/* Local art theft in Picat. From Stack Overflow: "Local theft art in prolog program" http://stackoverflow.com/questions/16862293/local-theft-art-in-prolog-program """ I have to write program in prolog to solve this logic problem: After a local art theft, six suspects were being interviewed. Below is a summary of their statements. Police know that exactly four of them told one lie each and all of the other statements are true. From this information can you tell who committed the crime? Alan said: It wasn't Brian It wasn't Dave It wasn't Eddie Brian said: It wasn't Alan It wasn't Charlie It wasn't Eddie Charlie said: It wasn't Brian It wasn't Freddie It wasn't Eddie Dave said: It wasn't Alan It wasn't Freddie It wasn't Charlie Eddie said: It wasn't Charlie It wasn't Dave It wasn't Freddie Freddie said: It wasn't Charlie It wasn't Dave It wasn't Alan ... """ Model created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go => % The no blame table NoBlame = [ % A B C D E F [0,1,0,1,1,0], % Alan said .. [1,0,1,0,1,0], % Brian [0,1,0,0,1,1], % Charlie [1,0,1,0,0,1], % Dave [0,0,1,1,0,1], % Eddie [1,0,1,1,0,0] % Freddie ], N = NoBlame.length, Names = ["Alan", "Brian", "Charlie", "Dave", "Eddie", "Freddie"], B = new_list(N), B :: 0..1, Counts = new_list(N), Counts :: 2..3, foreach(I in 1..N) L = [B[J] : J in 1..N, NoBlame[I,J] == 1], C #= sum([(J #= 0) : J in L]), Counts[I] #= C, (B[I] #= 1) #=> C #= L.length end, count(2, Counts, #=, 4), solve(Counts ++ B), writeln(counts=Counts), writeln(b=B), foreach({BB, Name} in zip(B,Names)) if BB == 1 then printf("The thief is %s.\n", Name) end end, printf("The thief: %w.\n", [Name : {BB, Name} in zip(B,Names), BB == 1]), nl. % % Variant % go2 ?=> % truth values Truth = [Alan,Brian,Charlie,Dave,Eddie,Freddie], Truth :: 0..1, % counts Counts = [AlanC,BrianC,CharlieC,DaveC,EddieC,FreddieC], Counts :: 2..3, S = ["Alan", "Brian", "Charlie", "Dave", "Eddie", "Freddie"], % Alan said: It wasn't Brian It wasn't Dave It wasn't Eddie Alan #=> (#~(Brian) #/\ #~(Dave) #/\ #~(Eddie)), % Brian said: It wasn't Alan It wasn't Charlie It wasn't Eddie Brian #=> (#~(Alan) #/\ #~(Charlie) #/\ #~(Eddie)), % Charlie said: It wasn't Brian It wasn't Freddie It wasn't Eddie Charlie #=> (#~(Brian) #/\ #~(Freddie) #/\ #~(Eddie)), % Dave said: It wasn't Alan It wasn't Freddie It wasn't Charlie Dave #=> (#~(Alan) #/\ #~(Freddie) #/\ #~(Charlie)), % Eddie said: It wasn't Charlie It wasn't Dave It wasn't Freddie Eddie #=> (#~(Charlie) #/\ #~(Dave) #/\ #~(Freddie)), % Freddie said: It wasn't Charlie It wasn't Dave It wasn't Alan Freddie #=> (#~(Charlie) #/\ #~(Dave) #/\ #~(Alan)), % Police know that exactly four of them told one lie each and all % of the other statements are true. AlanC #= #~(Brian) + #~(Dave) + #~(Eddie), % Brian said: It wasn't Alan It wasn't Charlie It wasn't Eddie BrianC #= #~(Alan) + #~(Charlie) + #~(Eddie), % Charlie said: It wasn't Brian It wasn't Freddie It wasn't Eddie CharlieC #= #~(Brian) + #~(Freddie) + #~(Eddie), % Dave said: It wasn't Alan It wasn't Freddie It wasn't Charlie DaveC #= #~(Alan) + #~(Freddie) + #~(Charlie), % Eddie said: It wasn't Charlie It wasn't Dave It wasn't Freddie EddieC #= #~(Charlie)+ #~(Dave) + #~(Freddie), % Freddie said: It wasn't Charlie It wasn't Dave It wasn't Alan FreddieC #= #~(Charlie) + #~(Dave) + #~(Alan), count(2,Counts, 4), % From this information can you tell who committed % the crime? Vars = Truth ++ Counts, solve(Vars), println(truth=Truth), println(counts=Counts), printf("The thief is %w\n", [S[I] : I in 1..Truth.len, Truth[I] == 1]), nl, fail, nl. go2 => true.