Wednesday, April 02, 2008

Long Division

Earlier this week, I solved another problem from Project Euler. This was #26. Here is the description:

A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:

1/2= 0.5
1/3= 0.(3)
1/4= 0.25
1/5= 0.2
1/6= 0.1(6)
1/7= 0.(142857)
1/8= 0.125
1/9= 0.(1)
1/10= 0.1

Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.

Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.

I knew this problem was related to the totient function, but I went a brute force route instead. The brute force route required writing a long division algorithm, which just seemed like a fun thing to do anyways. So I solved the problem, and the solution was plenty fast (0.185s for the calculation.)

I was ready to post my solution to the forums. I was also planning on reading the forums to see if anyone had a clever solution using the totient function. So I was greatly disappointed to see that the forms were down. Still my ego required me to publish my long division algorithm, so here it is:


def cycle(d)

m,i = 1,1
arr = Hash.new

while m > 0
while m < d
m *= 10

i += 1
end
m = m % d

if arr[m]
return i - arr[m]

end
arr[m] = i
end
return 0

end

max = 0
m = 2
3.upto(ARGV[0].to_i){|n|
c = cycle(n)

if c > max
max = c
m = n

end
}
puts m

Obviously this is in Ruby. The cycle calculates the length of the recurring cycle. The m variable is essentially the digits in the decimal representation of 1/d. The algorithm doesn't capture it, since it is not needed for the problem, but you could easily capture it (append to a string or array or whatever) and return it for a true long division algorithm.

No comments: