Prologとリスト内包表記の対応関係
昨日の麻雀の待ちの問題、Prologのコードがほぼ1対1でリスト内包表記に書き換えられるような気がしたのでやってみた。
例えば、Prologでの順子の処理部(1行目)は、Haskellでは2行目のように記述できるはず。
(Prolog) tenpai(Xs, [[X,Y,Z]|Ys]) :- select(X,Xs,R1), Y is X+1, select(Y,R1,R2), Z is X+2, select(Z,R2,R3), tenpai(R3,Ys). (Haskell) tenpai xs = [[x,y,z]:ys | (x,r1)<-sel xs, (y,r2)<-sel r1, y==x+1, (z,r3)<-sel r2, z==x+2, ys<-tenpai r3]
なお、Prologでのselect(X,Xs,Y)に相当する関数を sel xs = [(x,delete x xs)|x<-xs] で用意する前提。
ソースコード
以上をふまえて出来るだけ直訳した全ソースコード
import Data.List sel xs = [(x,delete x xs)|x<-xs] tenpai [x] = [[[0,x]]] tenpai xs = nub $ [[[x,x1],[0,y,z]] | (x,r1)<-sel xs, (x1,[y,z])<-sel r1, x==x1, y<=z, z<=y+2] ++ [sort $ [x,x,x]:ys | (x,r1)<-sel xs, (y,r2)<-sel r1, y==x, (z,r3)<-sel r2, z==x, ys<-tenpai r3] ++ [sort $ [x,y,z]:ys | (x,r1)<-sel xs, (y,r2)<-sel r1, y==x+1, (z,r3)<-sel r2, z==x+2, ys<-tenpai r3]
実行結果
今回は待ちのところを0が入ったリストであらわすことにした
(Haskellのリストは型をそろえないといけないので)
Main> tenpai [1,1,2,2,3,3,5,5,5,6,7,9,9] [[[0,6,7],[1,2,3],[1,2,3],[5,5,5],[9,9]], [[0,9,9],[1,2,3],[1,2,3],[5,5],[5,6,7]], [[0,5,5],[1,2,3],[1,2,3],[5,6,7],[9,9]]]
おまけ
直訳をはなれて、少しシンプルにしてみたバージョン
import Data.List del x xs = if length xs == length((xs\\x)++x) then xs\\x else [] tenpai [x] = [[[0,x]]] tenpai xs = nub $ [[[x,x],[0,y,z]] | x<-xs, [y,z]<-[del [x,x] xs], y<=z, z<=y+2] ++ [sort $ [x,x,x ]:ys | x<-xs, ys<-tenpai $ del [x,x,x ] xs] ++ [sort $ [x..x+2]:ys | x<-xs, ys<-tenpai $ del [x..x+2] xs]