Note: This solution marks my completion of 1- 50 in the project euler problem set. bringing the total number of problems I’ve solved to 64.
Problem #26 says
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.1Where 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.
The trick to this one is to realize that the decimals your going to end up dealing with are not going to fit into and standard decimal class. So you could go and try to find an arbitrary precision decimal class and then convert it to a string and hook that into some pattern detection. Or you can use a simple trick to build an array of quotients using nothing but integer math and check to see if you start going through the same sequence.
Solution provided below is in f# and requires .net 4. runs in under one second.
// Learn more about F# at http://fsharp.net
#light
open System
open System.Diagnostics
open System.Collections.Generic
//get some prime numbers
//set the limit and bound
let UpperLimit = 1000.
let UpperBound = 1000
//generate numbers to check
let LNums = ref [2..(int UpperLimit)] in
// loop through all numbers
// keep removing numbers that divide evenly
for div = 2 to UpperBound do
LNums := List.filter(fun num -> (num % div <> 0 || div >= num))
!LNums
done;
let Primes:list<int> = !LNums
let divby rem div =
let y =
[0..4]
|> Seq.filter (fun x -> (rem * int (float 10 ** float x)) > div)
if (y |> Seq.length) <> 0 then
let miny = Seq.min y
rem * int (float 10 ** float miny) % div
else
0
let rec patternlength init (rems:list<int>) d =
let rem = divby init d
if (List.exists (fun x -> x = rem) rems) then
(rems.Length - (List.findIndex (fun y -> y = rem) rems))
else
patternlength rem (List.append rems [rem]) d
Console.WriteLine("Starting check")
let watch = new Stopwatch()
watch.Start()
let Check =
let mutable Longest = 0
let mutable Nlongest = 0
for p in Primes do
let l = patternlength 1 [] p
if l > Longest then
Longest <- l
Nlongest <- p
Nlongest
watch.Stop()
Console.WriteLine(Check)
Console.WriteLine(watch.Elapsed)
Console.ReadKey() |> ignore