読者です 読者をやめる 読者になる 読者になる

project euler problem 8 answer

最近、ブログに回答を書くのがマナー違反なんじゃないかと思えて来た。

take(N, [Lcar | Lcdr], [Lcar | R]) :-
        N > 0, N1 is N - 1, take(N1, Lcdr, R).
take(0, _, []).

% 数字のアトムを数値に変換
numeric_to_number(List, NumberList) :- numeric_to_number_sub(List, [NumberList, []]).
numeric_to_number_sub([Head | Rest], [Result, Tail]) :-
        numeric_to_number_sub(Head, [Result, Appender]),
        numeric_to_number_sub(Rest, [Appender, Tail]).
numeric_to_number_sub([], [Tail, Tail]).
numeric_to_number_sub(Atom, [[Number | Appender], Appender]) :- number_atom(Number, Atom).

% リストの積(reduce)
product_list(List, Product) :- product_list_sub(List, 1, Product).
product_list_sub([], Acc, Acc).
product_list_sub([Head | Rest], Acc, Product) :-
        Acc1 is Head * Acc,
        product_list_sub(Rest, Acc1, Product).

% 最大の積を探す
find_max_product(NumericAtom, Length, Result) :-
        atom_chars(NumericAtom, Numbers),
        find_max_product_sub(Numbers, Length, 0, Result), !.
find_max_product_sub([Head | RestNumbers], Length, Max, Result) :-
        take(Length, [Head | RestNumbers], LengthNumbers),
        length(LengthNumbers, Length),
        numeric_to_number(LengthNumbers, Numbers),
        product_list(Numbers, Product),
        (Product > Max -> find_max_product_sub(RestNumbers, Length, Product, Result);
        find_max_product_sub(RestNumbers, Length, Max, Result)).
find_max_product_sub(_, _, Max, Max).

% アトムの連結
atom_concat_list(AtomList, ConcatedAtom) :- atom_concat_list_sub(AtomList, '', ConcatedAtom).
atom_concat_list_sub([], Acc, Acc).
atom_concat_list_sub([Atom | Rest], Acc, ConcatedAtom) :-
        atom_concat(Acc, Atom, Acc1),
        atom_concat_list_sub(Rest, Acc1, ConcatedAtom).

problem8(Result) :-
        atom_concat_list(
['73167176531330624919225119674426574742355349194934',
'96983520312774506326239578318016984801869478851843',
'85861560789112949495459501737958331952853208805511',
'12540698747158523863050715693290963295227443043557',
'66896648950445244523161731856403098711121722383113',
'62229893423380308135336276614282806444486645238749',
'30358907296290491560440772390713810515859307960866',
'70172427121883998797908792274921901699720888093776',
'65727333001053367881220235421809751254540594752243',
'52584907711670556013604839586446706324415722155397',
'53697817977846174064955149290862569321978468622482',
'83972241375657056057490261407972968652414535100474',
'82166370484403199890008895243450658541227588666881',
'16427171479924442928230863465674813919123162824586',
'17866458359124566529476545682848912883142607690042',
'24219022671055626321111109370544217506941658960408',
'07198403850962455444362981230987879927244284909188',
'84580156166097919133875499200524063689912560717606',
'05886116467109405077541002256983155200055935729725',
'71636269561882670428252483600823257530420752963450' ], ConcatedAtom),
        find_max_product(ConcatedAtom, 5, Result).