パズルの問題で1枚の上に書いた「数字」の個数に言及するタイプのものがある。
問題:□の中に数字を1個ずつ、入れて成り立つようにしてください。
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
この紙の上には
1が□個
2が□個
3が□個
4が□個
5が□個 あります。
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
というようなもの。この問題自体は答えが唯一解。(*1)
この手の問題を作ろうとした。プログラムの世話になるわけだが、今回はprologを使ってみることに。(*2)
「あてはめてはあってるかどうか調べる」的な問題はprologがあってるような気がしたので。
上記の問題を変形して1行減らした、
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
この紙の上には
1が□個
2が□個
3が□個
4が□個 があります。
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
を解いてみることにした。これでも唯一解だったか?
prologのソースを書いていく。たぶん約20年ぶり。(*3)
「文の最後はピリオドだっけ?」「countって作ってみたがこれでいいのか」「カット(!)マークの使った方がいいんだっけか」「表示ってどうやるんだっけprintf? print? write? writeln?」「ワーニング出てるじゃん、直しておこうねぇ、やっぱり」「試してみよう、げっ動かない」・・・。
と格闘して、書き上げたのがこのソース。ちゃんと動いているようなので、まずまずOKということで。(*4)
test1:-acheck(3,1,3,1).
test2:-kouho(A),kouho(B),kouho(C),kouho(D),acheck(A,B,C,D),print(A),print(B),print(C),print(D),print('\n'),fail.
mklist(A,B,C,D,[1,A,2,B,3,C,4,D]).
acheck(A,B,C,D):-
mklist(A,B,C,D,LIST),
count(1,LIST,A),
count(2,LIST,B),
count(3,LIST,C),
count(4,LIST,D).
kouho(0).
kouho(1).
kouho(2).
kouho(3).
kouho(4).
kouho(5).
kouho(6).
kouho(7).
kouho(8).
kouho(9).
count(_,[],0).
count(X,[X|L],C):-!,count(X,L,C2),C is C2+1.
count(X,[H|L],C):-not(X = H),count(X,L,C).
いざ、実行してみると、
1 ?- test2.
2321
3131
どうやら答えは2つあるようだ。「3131」の方は手で解いて知ってたけど、「2321」でも成立してることが判明。(*5)
次回はソースを使いまわせるように改良して、もう少しゴツイ問題を解いてみたい意向。
(*1)~(*5) プ:何が何個をprologで 補足 参照のこと。