Learn A New Language
March 4, 2014
In today’s exercise you are challenged to write a program in a language you’ve never used before. We’ve done this before, and it’s fun; the idea is to get you out of your comfort zone, so you’re thinking about programming, not just blindly following habit.
Your task is to write a program in a language you’ve never used before. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.
Project Euler problem 3 in Erlang using a 2,3,5,7 factor wheel. The main routine is pretty much like how to factor a number in any functional programming language.
wheel2357() -> Start = [1, 2, 2, 4], Wheel = [ 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6, 6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4, 2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6, 4, 2, 4, 6, 2, 6, 4, 2, 4, 2, 10, 2, 10], cycle:new(Start, Wheel). factorize(N) -> lists:reverse(factorize(abs(N), wheel2357(), 2, [])). factorize(N, Wheel, Fac, Factors) -> if Fac*Fac > N -> [N | Factors]; N rem Fac =:= 0 -> factorize(N div Fac, Wheel, Fac, [Fac | Factors]); true -> factorize(N, Wheel, Fac + cycle:next(Wheel), Factors) end. main(_) -> test_wheel(), io:format("The factors of 600,051,475,143 are ~p~n", [factorize(600851475143)]).Erlang does not have a facility to create a cirular list, so to create the wheel I create a new process (actually a very lightweight thread) to simulate a generator that can yield a new value each time it is called.
-module(cycle). -export([new/2, next/1, loop/2]). -spec new([any()], [any()]) -> pid(). new(Pfx, Seq) -> spawn_link(?MODULE, loop, [Pfx, Seq]). -spec next(pid()) -> any(). next(ProcID) -> ProcID ! {self(), next}, receive {ProcID, Response} -> Response end. loop(Prefix, Cycle) -> receive {From, next} -> case Prefix of [First | Rest] -> From ! {self(), First}, loop(Rest, Cycle); [] -> [First | Rest] = Cycle, From ! {self(), First}, loop(Rest, Cycle) end; {From, _} -> From ! {self(), message_not_understood}, loop(Prefix, Cycle) end.