オフラインどう書くF01・第4回問題、CodeIQ:テトロミノの置き方を数えよう 

どう書くのパターンマッチで解いた問題と、それと同じ解き方をした
どう書くとCodeIQの類似問題で、いずれも@nabetaniさんの出題です。

ふたマスの領域の数　
問題はこちら->http://nabetani.sakura.ne.jp/hena/ordf01_twicel/

普通に探索を繰り返して、長さが2の場合のみを数えれば、解けると思いますが、
パターンマッチで解いてみました。
端の部分のパターンマッチのため、フィールドの上下左右にマスを足して、
10行10列のリストにします。
白または黒2マスの上下左右を含めたパターンを用意します。(pat/2)　
comp/3で10x10のリストの左上から下方向右方向に順に4x3のリストを切り取り、
(最初are/3で3行取り、そこから更にmaplist,are/3で4列ずつ取り,findallで集める。
　are(F:X,L,L1)ではリストLのF番目からX個の要素を集めたリストがL1）
patとパターンマッチさせて合致したものをfindallで集め、その数を得ます。
さらにrotete/2で10x10のリストを90度回転させ、同様の処理を行い、数を合計します。

```Prolog
%start.
%SWI-Prolog version 7.4.2
%:-initialization(start).   %ideone

pat(C,[[_,Y,Y,_],[Y,X,X,Y],[_,Y,Y,_]]):-C=b->(X=1,Y=0);(X=0,Y=1).

rotate(L,L1):-length(L,N),length(L2,N),maplist(=([]),L2),foldl(apall,L,L2,L1).   %90do kaiten

apall([],[],[]).
apall([H1|T1],[H2|T2],R):-apall(T1,T2,R1),L=[H1|H2],R=[L|R1].

are(1:LX,L,R):-are1(L,LX,[],R).
are(FX:LX,[_|T],R):-FX1 is FX-1,are(FX1:LX,T,R).
are1(_,0,L,R):-reverse(L,R).
are1([H|T],LX,L,R):-L1=[H|L],LX1 is LX-1,are1(T,LX1,L1,R).

comp(L,C,R):-
     findall(L2,(between(1,7,X),between(1,8,Y),are(Y:3,L,L1),
     maplist(are(X:4),L1,L2),pat(C,L2)),L3),length(L3,R).

add(N,L,R):-
     maplist(app(N),L,L1),length(L3,10),maplist(=(N),L3),
     append([L3],L1,L4),append(L4,[L3],R).

app(N,L,R):-append([N],L,L1),append(L1,[N],R).

che(L,C,R):-
     (C==b->N=0;N=1),add(N,L,L1),comp(L1,C,R1),rotate(L1,L2),
     comp(L2,C,R2),R is R1+R2.

solve(L,R):-che(L,b,NB),che(L,w,NW),R=[NW,NB].
            
start:-str(S),split_string(S,"\s\n","\s",L),pre(L),!.

pre([]).
pre([_,B,N|T]):-
     atomics_to_string(BL,"/",B),maplist(hatomtonum,BL,NL),
     maplist(hextolist,NL,L),solve(L,R),disp(R,N),pre(T).

disp(R,N):-
     maplist(atom_number,R1,R),atomics_to_string(R1,",",S),
     (S==N->Str=" yes ";Str=" no  "),write(Str),writeln(S).
        
hatomtonum(X,Num):-atom_concat('0x',X,Atom),atom_number(Atom,Num).

hextolist(X,R):-hextolist1(0,X,L),reverse(L,R).  %for use map
hextolist1(8,_,[]).
hextolist1(N,X,L):-N1 is N + 1,hextolist1(N1,X,L1), Bit=2^N /\ X,
          (Bit=\=0->L=[1|L1];L=[0|L1]).

 str("0         dc/bc/a7/59/03/d5/d4/ea         2,3
1       ff/ff/ff/ff/ff/ff/ff/ff         0,0
2       00/00/00/00/00/00/00/00         0,0
3       cc/33/cc/33/cc/33/cc/33         16,16
4       aa/aa/55/55/aa/aa/55/55         16,16
5       ac/a3/5c/53/ca/3a/c5/35         8,8
6       db/00/db/00/db/00/aa/aa         0,13
7       24/24/db/24/24/db/24/24         0,12
8       d7/d7/e9/f1/f7/de/60/56         3,2
9       17/7d/64/9b/a5/39/53/a6         2,2
10      bb/8f/18/fb/89/c2/c7/35         1,2
11      6d/63/20/08/54/cd/32/4f         2,2
12      a9/ca/cd/46/99/e6/f0/30         2,2
13      5b/70/fd/45/e2/a1/ab/9a         1,2
14      24/e4/a8/12/e1/a6/3f/f3         2,1
15      79/32/2e/07/d5/10/e7/9d         2,2
16      60/bc/ab/ec/1f/eb/63/2c         4,2
17      a5/dd/92/4e/67/c6/dc/34         6,1
18      aa/96/6d/67/d2/a8/ac/90         3,2
19      95/72/7d/5c/47/dc/ef/99         4,0
20      17/d6/6a/27/1f/25/26/b8         2,1
21      f0/f3/76/c5/31/ca/6b/ae         1,2
22      01/59/26/fa/8c/70/12/cd         1,4
23      1a/c3/1f/0b/83/b6/81/0d         0,5
24      4c/49/05/cf/54/bb/1f/da         1,2
25      eb/7c/d5/09/2a/c2/14/6b         0,7
26      b4/d3/4c/c4/ed/19/e8/63         1,3
27      bd/bc/6d/60/9b/00/9a/32         2,4
28      94/97/3f/e3/c7/06/15/c0         2,2
29      5f/1d/67/16/b8/f7/0a/2a         2,2
30      df/e6/f9/4f/59/e9/1f/ee         3,0
31      5a/53/9a/9a/73/b4/37/07         3,2
32      bd/87/7c/e7/c0/37/82/da         2,3
33      3d/c0/13/ac/57/3d/15/78         2,2
34      63/64/54/3a/40/28/4e/4e         0,3
35      f6/81/c9/15/00/4c/a0/a8         1,4
36      19/41/df/f8/e3/74/6b/9b         4,2
37      d5/0b/dd/35/3b/d2/0b/6b         1,5
38      08/b7/91/f3/6e/3c/74/a0         0,0
39      b8/a8/b4/a6/93/2c/94/3f         0,0
40      88/22/21/ee/dc/19/43/01         0,0
41      e1/ee/35/bc/fc/00/8e/fe         0,0
42      3c/42/63/5f/27/47/07/90         0,0").
```
テトロミノ認識 
問題はこちら->http://nabetani.sakura.ne.jp/hena/ord4tetroid/

前題と同様な解き方です。
ただしmakep/2でもとになるパターンのほうを回転や反転しています。
~~sort~~ list_to_setで重複がすべてなくなるわけではありませんが、
合致するものがあるかどうかですので、問題ありません。
comp/2でそれぞれのパターンの高さと幅を求め、それに従って、
前題と同様にパターンマッチします。マッチすれば記号を、なければ"-"を返します。

```Prolog
%start.
%SWI-Prolog version 7.4.2
%:-initialization(start).   %ideone

pat("I",[[0,0,0,0]]).
pat("L",[[0,_,_],[0,0,0]]).
pat("O",[[0,0],[0,0]]).
pat("S",[[_,0,0],[0,0,_]]).
pat("T",[[0,0,0],[_,0,_]]).

rotate(L,L1):-L=[H|T],maplist([A,B]>>(B=[A]),H,H1),foldl(apall,T,H1,L1).   %90do kaiten
apall([],[],[]).
apall([H1|T1],[H2|T2],R):-apall(T1,T2,R1),H3=[H1|H2],R=[H3|R1].

rot(0,_,L,L):-!.  
rot(N,L,R1,R):-N1 is N-1,rotate(L,L1),R2=[L1|R1],rot(N1,L1,R2,R).

makep(C,R):-pat(C,L),rot(4,L,[L],L1),reverse(L,L2),rot(4,L2,[L2|L1],R1),list_to_set(R1,R).   %pat wo kaiten

are(1:LX,L,R):-are1(L,LX,[],R).
are(FX:LX,[_|T],R):-FX1 is FX-1,are(FX1:LX,T,R).
are1(_,0,L,R):-reverse(L,R).
are1([H|T],LX,L,R):-L1=[H|L],LX1 is LX-1,are1(T,LX1,L1,R).

comp(L,L2):-
     length(L2,N1),L2=[H|_],length(H,N2),N3 is 11-N1,N4 is 11-N2,   %11=10+1
     between(1,N4,X),between(1,N3,Y),are(Y:N1,L,L1),
     maplist(are(X:N2),L1,L2).

makef(0,[]).
makef(N,R):-N1 is N-1,makef(N1,R1),length(L,10),R=[L|R1].

che(L,R):-makep(R,L1),member(L2,L1),comp(L,L2).
che(_,"-").

inp(_,_,-1).
inp(L1,DL,X):-X1 is X-1,inp(L1,DL,X1),inp(L1,DL,X,9).
inp(_,_,_,-1).

inp(L1,DL,X,Y):-
     Y1 is Y-1,inp(L1,DL,X,Y1),atom_number(SX,X),atom_number(SY,Y),
     (member([SX,SY],DL)->N=0;N=1),nth0(X,L1,L2),nth0(Y,L2,N).

solve(L,R):-makef(10,L1),inp(L1,L,9),che(L1,R).

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

go([]).
go([A|T]):-
     split_string(A,"\s","\s",L),L=[_,C,D],atomics_to_string(L1,",",C),
     maplist(atom_chars,L1,L2),solve(L2,R),disp(R,D),go(T).

disp(R,A):-(R==A->Str=" pass ";Str=" fail "),write(Str),writeln(R).


str("#1 55,55,55,55     -
#2      39,28,27,29     L
#3      63,62,43,53     L
#4      32,42,43,44     L
#5      81,72,91,71     L
#6      62,64,72,63     L
#7      45,25,35,24     L
#8      12,20,22,21     L
#9      66,46,67,56     L
#10     44,46,45,43     I
#11     04,24,14,34     I
#12     43,42,41,40     I
#13     48,38,58,68     I
#14     31,20,22,21     T
#15     69,79,78,89     T
#16     42,33,44,43     T
#17     16,25,05,15     T
#18     27,37,28,38     O
#19     13,24,23,14     O
#20     63,72,62,73     O
#21     73,63,62,74     S
#22     56,57,47,66     S
#23     88,99,98,87     S
#24     62,43,52,53     S
#25     86,95,87,96     S
#26     84,83,73,94     S
#27     32,33,41,42     S
#28     86,85,75,96     S
#29     97,76,96,77     -
#30     53,55,45,43     -
#31     73,93,94,84     -
#32     31,33,41,42     -
#33     21,32,11,12     -
#34     73,75,65,64     -
#35     64,65,45,54     -
#36     12,00,01,10     -
#37     94,85,75,74     -
#38     87,86,77,75     -
#39     56,56,56,56     -
#40     41,42,41,52     -
#41     61,60,63,61     -
#42     03,13,33,13     -
#43     92,96,94,93     -
#44     15,25,55,45     -
#45     17,14,16,13     -
#46     72,83,83,92     -
#47     40,40,42,51     -
#48     81,80,93,82     -
#49     51,61,30,41     -
#50     17,37,35,15     -").
```
CodeIQ19.テトロミノの置き方を数えよう
問題はこちら->http://nabetani.sakura.ne.jp/codeiq/codeiq_q1904.html
前題の類似問題ですが最初の問題の要素も含みます。

やはり元のパターンを回転や反転したパターンを作りますが、
パターンに重複がありますと結果が狂いますので、最初変数を同じにしておいて
list_to_setで重複を解消し、change/2で変数をすべて異なるものにします。
同じように矩形を次々に切り取ってパターンマッチさせ、
マッチしたものをfindallで集めてリストに入れ、リストの要素数を数えます。

```Prolog
%start.
%SWI-Prolog version 7.4.2
%:-initialization(start).   %ideone

pat(i,[[0,0,0,0]]).
pat(l,[[0,X,X],[0,0,0]]).
pat(o,[[0,0],[0,0]]).
pat(s,[[X,0,0],[0,0,X]]).
pat(t,[[0,0,0],[X,0,X]]).

tenton(0,_,L,L):-!.
tenton(X,B,L,RL):-X1 is X div B,R1 is X-(X1*B),tenton(X1,B,[R1|L],RL).

rotate(L,L1):-L=[H|T],maplist([A,B]>>(B=[A]),H,H1),foldl(apall,T,H1,L1).   %90do kaiten
apall([],[],[]).
apall([H1|T1],[H2|T2],R):-apall(T1,T2,R1),H3=[H1|H2],R=[H3|R1].

rot(0,_,L,L):-!.   
rot(N,L,R1,R):-N1 is N-1,rotate(L,L1),R2=[L1|R1],rot(N1,L1,R2,R).

change([],[]).      
change([H|T],R):-   
     change(T,R1),
     (is_list(H)->(change(H,R2),append(R1,[R2],R));(var(H)->R=[_|R1];R=[H|R1])).

makep(C,R):-
     pat(C,L),rot(4,L,[L],R1),reverse(L,L1),rot(4,L1,[L1|R1],L2),
     list_to_set(L2,L3),change(L3,R).   %pat wo kaiten
     
are(1:LX,L,R):-are1(L,LX,[],R).
are(FX:LX,[_|T],R):-FX1 is FX-1,are(FX1:LX,T,R).
are1(_,0,L,R):-reverse(L,R).
are1([H|T],LX,L,R):-L1=[H|L],LX1 is LX-1,are1(T,LX1,L1,R).

comp(L,L2,R):-
     length(L2,N1),L2=[H|_],length(H,N2),N3 is 9-N1,N4 is 9-N2,
     findall(L2,(between(1,N4,X),between(1,N3,Y),are(Y:N1,L,L1),
     maplist(are(X:N2),L1,L2)),L3),length(L3,R).

makef([],[]).
makef([H|T],R):-
     makef(T,R1),hex_bytes(H,X),tenton(X,2,[],L),length(L,N),
     N1 is 8-N,length(L1,N1),maplist(=(0),L1),append(L1,L,L2),R=[L2|R1].

count(L,L3,R):-findall(R1,(member(L2,L3),comp(L,L2,R1)),R2),sumlist(R2,R).

solve(L,R):-makef(L,L1),findall(R1,(makep(_,L2),count(L1,L2,R1)),R).

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

go([]).
go([A,B|T]):-atomics_to_string(L," ",A),solve(L,R),disp(R,B),go(T).

disp(R,A):-
     maplist(atom_number,R1,R),atomics_to_string(R1,",",S),
     (S==A->Str=" pass ";Str=" fail "),write(Str),writeln(S).


str("00 00 00 00 00 00 00 00
80,336,49,168,168
00 ff 42 7e 42 7e ff 00
14,0,0,0,0
bb 88 ee 22 bb 88 ee 22
0,21,0,0,0
92 24 49 92 24 49 92 24
0,0,0,28,0
a2 15 a8 45 2a 51 8a 54
0,0,0,0,22
26 55 99 66 2c d3 4a 34
0,0,0,0,0
44 7a 49 d6 72 4e 77 88
0,0,0,0,0
aa 00 55 00 aa 00 55 00
20,84,0,21,21
00 7f 41 5d 55 5d 41 7f
18,10,0,0,0
10 88 44 22 91 88 44 32
2,42,11,40,36
93 1e 26 b2 72 d8 ae 96
5,15,3,9,8
da 4e ce 0f cb f5 ba 9b
4,14,3,7,8").
```