Prolog
どう書く

オフラインリアルタイムどう書く過去問(第2回)

問題はこちら->http://nabetani.sakura.ne.jp/hena/ord2/
だいぶ前に書いていたのを修正したものです。
各列を8ビットの数として全部の列のandをとると(foldl/4)、横一列にそろっている位が1となります。
後は、それぞれの列で、該当の位より上位を右シフト(>>,drop/4)して一段下げます。

hatomtonum(X,Num):-(atom_concat('0x',X,Atom),atom_number(Atom,Num)).
numtohatom(Num,Atom):-
     Quot is Num div 16,Rem is Num mod 16,
     ntoha(Quot,A1),ntoha(Rem,A2),atom_concat(A1,A2,Atom).
ntoha(Q,S):-Q>9->
     member([S,Q],[[a,10],[b,11],[c,12],[d,13],[e,14],[f,15]]);atom_number(S,Q).

bittetris(In,Re):-
     concat_atom(Out, -, In),maplist(hatomtonum,Out,Nums),foldl(and,Nums,255,X),
     maplist(drop0(X),Nums,L),maplist(numtohatom,L,Atoms),atomics_to_string(Atoms,-,Re).

and(X,Y,Z):-Z is X /\ Y.

drop(X,_,0,X):-!.
drop(X,Y,Z,RX):-
     (Z is Y /\ Z->(R is X mod Z,X1 is ((X-R-Z) >>1)+R);X1=X),
     Z1 is Z >> 1,drop(X1,Y,Z1,RX).
drop0(Y,X,RX):-drop(X,Y,128,RX).

solve([]):-!.
solve([_,B,C|T]):-
     bittetris(B,R),(R==C->write("pass ");write(" fail ")),writeln(R),solve(T).

start:-str(S),split_string(S,"\s,\n","\s",L),solve(L),!.

%start.

str("#0      ff-2f-23-f3-77-7f-3b    1f-03-00-1c-0d-0f-06
#1      01      00
#2      00      00
#3      7a-4e   0c-02
#4      56-b6   08-14
#5      12-12-12        00-00-00
#6      de-ff-7b        0a-0f-05
#7      95-be-d0        05-1e-20
#8      7c-b0-bb        1c-20-2b
#9      7a-b6-31-6a     3a-56-11-2a
#10     32-0e-23-82     18-06-11-40
#11     ff-7f-bf-df-ef  0f-07-0b-0d-0e
#12     75-df-dc-6e-42  35-5f-5c-2e-02
#13     62-51-ef-c7-f8  22-11-6f-47-78
#14     0c-47-8e-dd-5d-17       04-23-46-6d-2d-0b
#15     aa-58-5b-6d-9f-1f       52-28-2b-35-4f-0f
#16     ff-55-d5-75-5d-57       0f-00-08-04-02-01
#17     fe-fd-fb-f7-ef-df-bf    7e-7d-7b-77-6f-5f-3f
#18     fd-fb-f7-ef-df-bf-7f    7e-7d-7b-77-6f-5f-3f
#19     d9-15-b5-d7-1b-9f-de    69-05-55-67-0b-4f-6e
#20     38-15-fd-50-10-96-ba    18-05-7d-20-00-46-5a
#21     fe-fd-fb-f7-ef-df-bf-7f fe-fd-fb-f7-ef-df-bf-7f").