Erlang: Running time = 9.1s
+-%digit_split
digit_split(N)->
lists:map(fun(X)->X-48 end,integer_to_list(N)).
+-%echo
echo(Message,Sender)->Sender ! Message.
+-%prime_list
prime_list()->
case whereis(primeList) of
undefined->
Pid=spawn(euler,prime_list,[initialize]),
register(primeList, Pid),
Pid;
Exists->
Exists
end.
prime_list(initialize)->
put(primes,array:from_list([2,3,5,7,11,13,17,19])),
put(total,8),
prime_list(idle);
prime_list(idle)->
Size=get(total),
receive
{get,FromZero,Reply} when FromZero < Size ->
Reply ! {prime,FromZero,array:get(FromZero,get(primes))};
{get,FromZero,Reply} ->
echo({get,FromZero,Reply},self()),
prime_list(gen);
{all_below,What,Reply} ->
case array:get(Size-1,get(primes)) < What of
true->
prime_list(gen),
echo({all_below,What,Reply},self());
false->
Reply ! {primes_below,What,prime_list(below,What,0,[])}
end;
{is_prime,What,Reply}->
Skirt=math:sqrt(What),
Largest=array:get(Size-1,get(primes)),
case Largest < What of
true->
case Largest < Skirt of
true->
prime_list(gen),
echo({is_prime,What,Reply},self());
false->
Reply ! {is_prime,What,prime_list(check_factors,0,What,Skirt)}
end;
false->
Reply ! {is_prime,What,prime_list(binary_search,What,0,Size-1)}
end
end,
prime_list(idle);
prime_list(gen)->
Size=get(total),
Start=array:get(Size-1,get(primes))+2,
End=Start*10+1,
Sqrt=math:sqrt(End),
AsList=array:to_list(get(primes)),
[2|Odds]=AsList,
RelevantOdds=lists:takewhile(fun(N)->N =< Sqrt end,Odds),
Newbs=prime_list(gen,Size,Start,End,RelevantOdds,ordsets:from_list(lists:seq(Start,End,2))),
put(primes,array:from_list(lists:append(AsList,ordsets:to_list(Newbs)))),
put(total,get(total)+ordsets:size(Newbs)).
prime_list(check_factors,NextIndex,N,Sqrt)->
NextPrime=array:get(NextIndex,get(primes)),
case NextPrime > Sqrt of
true->true;
false->
case N rem NextPrime ==0 of
true->false;
false->
prime_list(check_factors,NextIndex+1,N,Sqrt)
end
end;
prime_list(binary_search,What,Low,High) when High-Low < 2 ->
H=array:get(High,get(primes)),
L=array:get(Low,get(primes)),
if
H == What; L == What ->
true;
true->false
end;
prime_list(binary_search,What,Low,High)->
Mid=Low+((High-Low) div 2),
Got=array:get(Mid,get(primes)),
if
What > Got->prime_list(binary_search,What,Mid+1,High);
What < Got->prime_list(binary_search,What,Low,Mid-1);
true->true
end;
prime_list(below,What,Index,SoFar)->
Next=array:get(Index,get(primes)),
if
Next >= What->
lists:reverse(SoFar);
true->
prime_list(below,What,Index+1,[Next|SoFar])
end.
prime_list(gen,_,_,_,[],Survivors)->Survivors;
prime_list(gen,Total,Lowest,Highest,[MyPrime|RestPrimes],Survivors)->
prime_list(gen,Total,Lowest,Highest,RestPrimes,
ordsets:subtract(Survivors,
ordsets:from_list(
lists:seq(Lowest-(Lowest rem MyPrime),Highest,MyPrime)))).
p35()->
A=prime_list(),
A!{all_below,1000000,self()},
Primes=lists:filter(fun(2)->true;(5)->true;
(X)->
DS=digit_split(X),
L=length(DS),
L==length(lists:subtract(DS,[0,2,5])) end,
receive {primes_below,1000000,V}->V end),
put(prime_set,sets:from_list(Primes)),
put(circular,[]),
put(done,sets:new()),
p35(Primes),
io:format("~w~n",[length(get(circular))]).
p35([])->ok;
p35([NextPrime|Others])->
case sets:is_element(NextPrime,get(done)) of
true->
p35(Others);
false->
DS=digit_split(NextPrime),
All=p35(DS,DS,[]),
case lists:all(fun(X)->sets:is_element(X,get(prime_set)) end,All) of
true->
put(circular,lists:append(get(circular),All));
false-> ok
end,
put(done,sets:union(get(done),sets:from_list(All))),
p35(Others)
end.
p35(OrigDigs,OrigDigs,All)when length(All)>0 ->All;
p35(OrigDigs,NextDigs,All)->
N=list_to_integer(lists:append(lists:map(fun integer_to_list/1,NextDigs))),
{First,Tail}=lists:split(length(NextDigs)-1,NextDigs),
p35(OrigDigs,lists:append(Tail,First),[list_to_integer(lists:append(lists:map(fun integer_to_list/1,NextDigs)))|All]).