オフラインどう書くF04・CodeIQ:正六角形の分割の解答


リアルタイムオフラインどう書くF04問題(正八角形の分割)と同じ出題者の類題、
CodeIQの正六角形の分割の解答です。

まずF04の解答です。
問題はこちら->http://nabetani.sakura.ne.jp/hena/ordf04octsp/

線分の番号は2の累乗で表せるのでその指数に変換します。すると
二つの線分で挟まれる多角形の辺（角）の数は二つの線分の指数の差に2を足したものです。
辺が直径になる場合は例外なので、弥縫策をほどこします。
cal/4で入力値を2の累乗の和に分解しその指数を集めてリストにします。
cor/2で1の線を256ともみなし2^8の8を指数の集まりに加えます。
ext1/3ではリストのすべての隣り合う二数の組み合わせで二数の差を計算して集めます。
ext2で指数の差に、辺が直径になる場合1それ以外は2を足します。

```Prolog
:-initialization(start).

cal(0,_,L,L):-!.
cal(N,M,L,R):-(N>=2^M->(N1 is N-2^M,L1=[M|L]);(N1=N,L1=L)),M1 is M-1,cal(N1,M1,L1,R).

cor([H|T],L):-H1 is H+8,append([H|T],[H1],L).

ext1([_],L,L):-!.
ext1([H1,H2|T],L,R):-X is H2-H1,ext1([H2|T],[X|L],R).

ext2([],[]):-!.                          % 直径が辺になる場合のための弥縫的修正
ext2([H|T],[H1|L]):-ext2(T,L),(H==4->H1 is H+1;H1 is H+2).

solve(N,S):-
     cal(N,7,[],L),cor(L,L1),ext1(L1,[],L2),ext2(L2,L3),
     msort(L3,R),atomics_to_string(R,"",S).

disp(S,Q):-
        (S==Q->Str=" yes ";Str=" no  "),write(Str),write(S),write("\n").

start:-str(S),split_string(S,"\n,\s","\s",L0),pre(L0).

pre([]).
pre([_,B,N|T]):-
    number_chars(NB,B),solve(NB,S),disp(S,N),pre(T).

str("0       165     3445
1       80      48
2       255     33333333
3       68      55
4       200     355
5       82      455
6       164     455
7       73      455
8       146     455
9       37      455
10      74      455
11      148     455
12      41      455
13      38      355
14      76      355
15      152     355
16      49      355
17      98      355
18      196     355
19      137     355
20      19      355
21      20      48
22      9       57
23      209     3345
24      121     33345
25      239     3333334
26      26      347
27      111     333344
28      95      333344
29      85      4444
30      24      39
31      97      347
32      234     33444
33      59      33345
34      187     333344
35      34      55
36      249     333335
37      43      3445
38      143     33335
39      28      338
40      79      33345
41      173     33444
42      55      33345
43      77      3445
44      35      355
45      153     3355
46      30      3337
47      228     3355
48      177     3345
49      162     445
50      184     3345").
```
CodeIQ64 正六角形の分割
問題とテストケースについてこちらのお世話になりました。解答もあります。
->https://blog.goo.ne.jp/r-de-r/e/014046b2dd1b27f9e957d9f896a89f45

どう書くの「正八角形の分割」と同様に2の累乗の和に分けます。
cor64/2で1と同じ線は2^12ですので12を付け加えます。
ext64/3でH1,H2が指数、X1=H2-H1として多角形の辺（角）の数をXとします。
H1,H2が奇数の時それぞれX1に1を足していったX3が、
多角形の辺を含む六角形の辺（数が同じ）を挟む二線分の値の差になります。
一つの辺を挟む線分間の値の差は2なのでX4=X3 div 2が六角形の辺に沿った多角形の辺の数、
六角形の中の多角形の辺の数はX1=6の時は六角形の長短径なので1、他は2ですので、
其々X=X4+1,X=X4+2となります。

```Prolog
%:-initialization(start).  %ideone
%start.
cal64(0,_,L,L):-!.
cal64(N,M,L,R):-
     (N>=2^M->(N1 is N-2^M,L1=[M|L]);(N1=N,L1=L)),M1 is M-1,cal64(N1,M1,L1,R).

cor64([H|T],L):-H1 is H+12,append([H|T],[H1],L).

ext64([_],L,R):-reverse(L,R),!.
ext64([H1,H2|T],L,R):-
     X1 is H2-H1,(H1 mod 2 =:=1->X2 is X1+1;X2=X1),(H2 mod 2=:=1->X3 is X2+1;X3 =X2),
     X4  is X3 div 2,(X1=:=6->X is X4+1;X is X4+2),ext64([H2|T],[X|L],R).

solve64(N,R):-cal64(N,11,[],L),cor64(L,L1),ext64(L1,[],L2),msort(L2,R).

disp64(R,A):-
        (R==A->Str=" yes ";Str=" no  "),write(Str),write(R),write("\n").


start:-f64(N,AL),solve64(N,R),disp64(R,AL),fail.

f64(4095,[3,3,3,3,3,3,3,3,3,3,3,3]).
f64(3,[3,8]).
f64(5,[3,7]).
f64(10,[4,8]).
f64(260,[4,4]).
f64(520,[5,5]).
f64(132,[5,6]).
f64(1898,[3,3,3,3,4,4,4]).
f64(268,[3,4,5]).
f64(2176,[5,7]).
f64(1088,[4,6]).
f64(72,[4,7]).
```