オフラインどう書くE14・CodeIQ:展開図の反対側の解答

@mtsmfmさんのどう書くE14と@NabetaniさんのCodeIQ:展開図の反対側の解答です。
まずE14の問題をヒントに従って解き、次いでCodeIQの問題を解き、
さらにCodeIQの問題の解き方を応用してE14の問題を解きます。

どう書くE14。
問題はこちら->http://mtsmfm.github.io/2017/06/03/doukaku-e14.html

出題者のヒントに甘えて、展開図の11種類のパターンを用意し、
それと問題図とのパターンマッチで解きました。
展開図は3行x4列または2行x5列なので、check1/1で3x4と2x5に類別し、
check2/3のare/4で切り分けdat/1でパターンマッチ。
che/2でサイコロを作れるかの判定と問題図の回転を行います。
判定部分にnotを使用していますので、マッチすれば失敗でそこで終了します（判定はtrue）。
solve/2でche/2の呼び出しと問題図の反転を行います。
最後までマッチしなければ成功です(判定はfalse)。

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

rule(X1,X2,Y1,Y2,Z1,Z2):-plus(X1,X2,7),plus(Y1,Y2,7),plus(Z1,Z2,7),
                         X1\==Y1,X1\==Y2,Y1\==Z1,Y1\==Z2,Z1\==X1,Z1\==X2.
                         
ht([H|T],H,T).

rot([[]|_],[]).
rot(L,R):-maplist(ht,L,LH,LT),reverse(LH,LH1),rot(LT,R1),R=[LH1|R1].

data([[X1,_,_,_],[Y1,Z1,Y2,Z2],[X2,_,_,_]]):-rule(X1,X2,Y1,Y2,Z1,Z2).
data([[X1,_,_,_],[Y1,Z1,Y2,Z2],[_,X2,_,_]]):-rule(X1,X2,Y1,Y2,Z1,Z2).
data([[X1,_,_,_],[Y1,Z1,Y2,Z2],[_,_,X2,_]]):-rule(X1,X2,Y1,Y2,Z1,Z2).
data([[X1,_,_,_],[Y1,Z1,Y2,Z2],[_,_,_,X2]]):-rule(X1,X2,Y1,Y2,Z1,Z2).     %180度回転対称
data([[_,X1,_,_],[Y1,Z1,Y2,Z2],[_,X2,_,_]]):-rule(X1,X2,Y1,Y2,Z1,Z2).
data([[_,X1,_,_],[Y1,Z1,Y2,Z2],[_,_,X2,_]]):-rule(X1,X2,Y1,Y2,Z1,Z2).     %180度回転対称
data([[X1,Y1,_,_],[_,Z1,X2,Z2],[_,_,Y2,_]]):-rule(X1,X2,Y1,Y2,Z1,Z2).
data([[X1,Y1,_,_],[_,Z1,X2,Z2],[_,Y2,_,_]]):-rule(X1,X2,Y1,Y2,Z1,Z2).
data([[X1,Y1,_,_],[_,Z1,X2,_],[_,_,Y2,Z2]]):-rule(X1,X2,Y1,Y2,Z1,Z2).     %180度回転対称
data([[X1,Y1,_,_],[_,Z1,X2,Z2],[_,_,_,Y2]]):-rule(X1,X2,Y1,Y2,Z1,Z2).
data([[X1,Y1,X2,_,_],[_,_,Z1,Y2,Z2]]):-rule(X1,X2,Y1,Y2,Z1,Z2).          %180度回転対称

check1(L):-length(L,N1),L=[H|_],length(H,N2),check2(L,N1,N2),!.

check2(L,N1,N2):-N1>2,N2>3,are(3,4,L,L1),data(L1).
check2(L,N1,N2):-N1>1,N2>4,are(2,5,L,L1),data(L1).

delh([_|T],T).

are(N1,N2,L,R):-(are2(N1,L,L1),are1(N2,L1,R));(delh(L,L2),are(N1,N2,L2,R)).

are1(N,L,R):-maplist(are2(N),L,R);(maplist(delh,L,L1),are1(N,L1,R)).

are2(N,L,R):-length(R,N),append(R,_,L).

che(0,_):-!.
che(N,L):-not(check1(L)),N1 is N-1,rot(L,L1),che(N1,L1).
 
solve(L,"false"):-che(4,L),maplist(reverse,L,L4),che(4,L4).
solve(_,"true").

aton(L,L1):-maplist(atom_number,L,L1).

test(In, Out) :-
     split_string(In,"\s,\n","\s",L),maplist(atom_chars,L,L1), maplist(aton,L1,L2),
     solve(L2, R),(R==Out->Str=pass;Str=fail),writeln(Str->R),!.

start:-
  test("44165,44516", "false"),
  test("26265,31436", "true"),
  test("46345,54215", "true"),
  test("62143,11152", "false"),
  test("4242,4314,1562", "false"),
  test("5612,3656,4523", "false"),
  test("5514,1311,5252", "false"),
  test("5262,4631,2644", "true"),
  test("6626,3324,2644", "false"),
  test("4645,6314,2564", "true"),
  test("54,65,23,21,14", "true"),
  test("5325,3641,1335", "true"),
  test("4163,2156,2553", "true"),
  test("3126,6543,4352", "false"),
  test("4464,5423,5216", "true"),
  test("3564,3634,5631", "false"),
  test("4363,3454,2126", "true"),
  test("25,25,33,12,52", "false"),
  test("1551,4542,3624", "true"),
  test("6623,4126,6331", "false"),
  test("2432,6215,1623", "true"),
  test("1151,6555,3616", "false"),
  test("2466,1242,4444", "false"),
  test("5646,1463,4244", "true"),
  test("1255,6413,4534", "true"),
  test("1325,2312,2425", "false"),
  test("2544,6413,4656", "true"),
  test("1656,4131,3235", "true"),
  test("6332,3631,4113", "false"),
  test("4525,2151,2336", "true"),
  test("1645,2356,4314", "true"),
  test("3334,6215,1553", "true"),
  test("2622,5251,5165", "false"),
  test("1111,5613,3451", "false"),
  test("6146,4512,6353", "true"),
  test("2455,3312,6461", "false"),
  test("1221,1325,1422", "false"),
  test("1562,2236,5212", "false"),
  test("6622,3324,5155", "true"),
  test("2352,4631,1236", "true"),
  test("4645,2252,6554", "false"),
  test("3542,6515,1231", "true"),
  test("12,61,56,45,23", "false"),
  test("4643,6522,3625", "false"),
  test("1151,1642,4512", "false"),
  test("5423,5146,2212", "false"),
  test("6224,3412,5653", "true"),
  test("3122,5423,6231", "true"),
  test("5421,2351,6513", "false"),
  test("5652,3542,3313", "true"),
  test("5524,3335,1146", "false"),
  test("5311,4126,6425", "true"),
  test("15,43,62,42,14", "true"),
  test("3631,3542,3265", "true"),
  test("1232,5364,6135", "true"),
  test("2441,4644,5433", "false"),
  test("2213,5621,3412", "true"),
  test("6644,1264,1235", "true"),
  test("5613,1423,6315", "true"),
  test("6552,1546,2141", "false"),
  test("5623,1461,5645", "true"),
  test("1442,1436,6362", "false"),
  test("3443,5145,4546", "false"),
  test("1244,1313,2316", "false"),
  test("2152,1463,2114", "true"),
  test("1211,6234,5561", "false"),
  test("4152,1252,3142", "false"),
  test("6645,1231,6122", "false"),
  test("353,241,121,536", "true"),
  test("224,444,651,234", "true"),
  test("643,214,244,343", "false"),
  test("624,542,214,333", "true"),
  test("441,426,536,656", "true"),
  test("564,642,513,364", "true"),
  test("422,136,414,416", "false"),
  test("463,356,113,662", "true"),
  test("464,515,435,462", "true"),
  test("531,145,364,525", "false"),
  test("623,564,153,633", "false"),
  test("335,462,531,424", "false"),
  test("131,111,535,436", "false"),
  test("435,414,423,365", "true"),
  test("144,512,332,346", "true"),
  test("342,246,342,634", "false"),
  test("246,566,431,415", "true"),
  test("444,554,234,621", "true"),
  test("313,624,165,652", "true"),
  test("563,262,545,315", "true"),
  test("213,264,154,264", "false"),
  test("364,434,246,113", "false"),
  test("411,656,325,225", "false"),
  test("624,234,115,443", "true"),
  test("252,214,635,154", "false"),
  test("146,213,525,164", "false"),
  test("456,423,112,352", "true"),
  test("253,156,111,355", "false"),
  test("252,161,562,365", "false"),
  test("136,553,544,524", "true"),
  test("414,351,161,525", "true"),
  test("261,442,111,531", "true"),
  test("323,664,454,133", "true"),
  test("213,415,225,165", "false"),
  test("363,162,165,533", "false"),
  test("346,441,315,241", "false"),
  test("121,312,155,164", "true"),
  test("123,311,452,365", "true"),
  test("361,145,212,431", "true"),
  test("451,264,412,513", "false"),
  test("311,456,263,226", "true"),
  test("343,442,624,635", "false"),
  test("534,644,234,251", "false"),
  test("515,346,462,435", "true"),
  test("445,126,165,636", "false"),
  test("343,355,126,353", "false"),
  test("623,533,256,144", "true"),
  test("125,341,566,416", "false"),
  test("354,434,621,411", "true"),
  test("356,435,253,114", "false"),
  test("141,265,533,514", "true"),
  test("613,426,142,535", "true"),
  test("366,322,413,325", "true"),
  test("331,542,343,545", "false"),
  test("261,512,563,123", "false"),
  test("242,132,656,164", "true"),
  test("133,545,441,665", "false"),
  test("111,151,621,545", "false"),
  test("132,154,234,653", "false"),
  test("114,455,635,511", "false"),
  test("14366,64254,66664,42611,41245", "false"),
  test("41114,53116,13122,66613,35111", "false"),
  test("22146,34244,16154,62531,51426", "true"),
  test("464316,136563,136326,535655,641161,252655", "true"),
  test("166255,615452,261224,533566,323335,556213", "false"),
  test("126665,245653,343553,254661,365415,361154", "false"),
  test("1512663,1525531,5456426,6336325,4324465,6512242,4112466", "true"),
  test("2236563,6644542,4425515,6641142,4214543,1156426,3225413", "false"),
test("5545354,6566343,3525411,5356165,4625265,1535435,5522665", "false"),
test("16161,61616,16161", "false"),
test("2431,6354,2341", "false"),
test("00000,00000,12600,00453", "true").  %my test case
```

CodeIQ:展開図の反対側。
問題とテストケースはこちらのお世話になりました。解答もあります。
->https://blog.goo.ne.jp/r-de-r/e/5031cf50cc74ee160226523846cec208

対面はある升から一升進みそこから直角方向に0-3升進んでさらに最初の方向に一升進んだ升。
この関係が三組できれば展開図は正しい。
dat76/2は直角方向のデータ。move76/5でdat76/2を利用して実際に0-3升進みます。
solve76/4では最初と最後の升を扱い、途中dat76とmove76をよびだします。
これを三回繰り返します。
atoc/2はアルファベットを座標にctoa/2は座標をアルファベットに変換します。

```Prolog
%SWI-Prolog (version 7.4.2,version 7.6.4)
%:-initialization(start76).  %ideone
%start76.

dat76(_,[[0,0]]).               %tyokkaku houkou ni 0ko kara 3ko
dat76([X,Y],[B]):-B=[Y,X];B=[-Y,-X].
dat76([X,Y],[B,B]):-B=[Y,X];B=[-Y,-X].
dat76([X,Y],[B,B,B]):-B=[Y,X];B=[-Y,-X].

mov76(X,Y,[],_,[X,Y]).           %0 kara 3 masu ugoku
mov76(X,Y,[[DX,DY]|T],L,R):-X1 is X+DX,Y1 is Y+DY,member([X1,Y1],L),mov76(X1,Y1,T,L,R).

solve76([],_,[A,B|_],B).
solve76([[X,Y]|T],L,TL,R):-
     member([DX,DY],[[1,0],[-1,0],[0,1],[0,-1]]),X1 is X+DX,Y1 is Y+DY,member([X1,Y1],L),
     dat76([DX,DY],M),mov76(X1,Y1,M,L,[NX,NY]),X2 is NX+DX,Y2 is NY+DY,select([X2,Y2],T,L1),
     append(TL,[[X,Y],[X2,Y2]],TL1),solve76(L1,L,TL1,R).
solve76(_,_,_,[]).

solve760(S,R):-atom_chars(S,L),maplist(atoc,L,L1),solve76(L1,L1,[],R),!.

start76:-f76(S,A),solve760(S,R),disp(R,A),fail.
start76.

disp(R,A):-(R=[]->S='-';ctoa(R,S)),(A==S->Str=" pass ";Str=" fail "),write(Str),writeln(S).

atoc(A,C):-atom_codes(A,N),N1 is N-92,divmod(N1,5,Y,X),X1 is X+1,C=[X1,Y].

ctoa([X,Y],A):-N is Y*5+X+91,atom_codes(A,[N]).

f76("ngmbah",g).
f76("rdmgch",h).
f76("imdsen",s).
f76("nuqprs",u).
f76("gmknlr",r).
f76("jbhaci",h).
f76("ijcmbh",b).
f76("gmlnrf",r).
f76("nagihb",b).
f76("pwrtsq",-).
f76("fgbach",-).
f76("mihgsn",-).

```

「展開図の反対側」を解いた時これを利用してE14の問題を解けることに気が付きました。
「展開図の反対側」ではsolve76/4で条件にに合致する升を探しましたが、
E14問題ではsolve76/3で与えられた升の組が条件に合致するかどうか調べます。
まずacc/2でX座標またはY座標の差が2で升の値の和が7である2升の組を集めます。
（2升の和が7だけでも正解は出ますが時間がかかります）
それから、その中から小さいほうの升の値が1,2,3である三組をmember/2を三回使って選び、
solve76 に送り、展開図の反対側の解法を少し変えた方法で立方体になるかどうか調べます。
立法体になる組が一つでもあれば成功です。

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

data(N1,N2,L,[X,Y,V]):-between(1,N1,X),nth1(X,L,L1),between(1,N2,Y),nth1(Y,L1,V).
acc(L,R):-
     L=[H|_],length(H,N2),length(L,N1),
     findall(V1:[X1,Y1]:[X2,Y2],(data(N1,N2,L,[X1,Y1,V1]),data(N1,N2,L,[X2,Y2,V2]),
     (abs(X2-X1)=:=2;abs(Y2-Y1)=:=2),V1<V2,V1+V2=:=7),R).

dat76(_,[[0,0]]).
dat76([X,Y],[B]):-B=[Y,X];B=[-Y,-X].
dat76([X,Y],[B,B]):-B=[Y,X];B=[-Y,-X].
dat76([X,Y],[B,B,B]):-B=[Y,X];B=[-Y,-X].

mov76(X,Y,[],_,[X,Y]).
mov76(X,Y,[[DX,DY]|T],L,R):-X1 is X+DX,Y1 is Y+DY,member([X1,Y1],L),mov76(X1,Y1,T,L,R).

solve76([],_,"true").
solve76([[X1,Y1]:[X2,Y2]|T],L,R):-
     member([DX,DY],[[1,0],[-1,0],[0,1],[0,-1]]),X10 is X1+DX,Y10 is Y1+DY,member([X10,Y10],L),
     dat76([DX,DY],M),mov76(X10,Y10,M,L,[NX,NY]),X2=:=NX+DX,Y2=:=NY+DY,solve76(T,L,R).

solve(L,R):-
     acc(L,L1),member(1:[X1,Y1]:[X2,Y2],L1),member(2:[X3,Y3]:[X4,Y4],L1),member(3:[X5,Y5]:[X6,Y6],L1),
     solve76([[X1,Y1]:[X2,Y2],[X3,Y3]:[X4,Y4],[X5,Y5]:[X6,Y6]],[[X1,Y1],[X2,Y2],[X3,Y3],[X4,Y4],[X5,Y5],[X6,Y6]],R).
solve(_,"false").

aton(L,L1):-maplist(atom_number,L,L1).

test(In, Out) :-
     split_string(In,"\s,\n","\s",L),maplist(atom_chars,L,L1), maplist(aton,L1,L2),
     solve(L2,R),(R==Out->Str=pass;Str=fail),writeln(Str->R),!.
```