/* 3 digit passcode in Picat. From https://www.reddit.com/r/prolog/comments/14zi1gn/can_we_solve_this_using_prolog_lets_organize_a/ """ Can we solve this using Prolog? Let's organize a code golf challenge for it. Agent Monocle is hacking into a secret database and has one last chance to crack the code. Of the numbers she's tried below each guess has just one correct digit that's in the correct order. Knowing that, can you figure out the 3-digit passcode? Passcode: 896 X Passcode: 983 X Passcode: 246 X Passcode: 843 X Passcode: *** V """ All solutions output the single solution: [2,9,3] This program was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. go => passcodes(Passcodes), X = new_list(3), X :: 0..9, foreach(L in Passcodes) sum([X[I] #= L[I] : I in 1..3]) #= 1 end, solve(X), println(X), fail, nl. % Same CP approach, Prolog style go2 => passcodes(Passcodes), X = new_list(3), X :: 0..9, check(X,Passcodes), solve(X), writeln(X), fail, nl. % Another non CP approach go3 => passcodes(Passcodes), member(X1,0..9), member(X2,0..9), member(X3,0..9), X = [X1,X2,X3], Bs = [ 1 : Passcode in Passcodes, sum([cond(XI == P,1,0) : {XI,P} in zip(X,Passcode)]) == 1], sum(Bs) == length(Passcodes), println(X), fail, nl. % Another LP approach go4 => passcodes(Passcodes), Dom = flatten(Passcodes).sort_remove_dups, member(X1,Dom), member(X2,Dom), member(X3,Dom), X = [X1,X2,X3], check2(X,Passcodes), writeln(X), fail, nl. % Functional style go5 => passcodes(Passcodes), Dom = flatten(Passcodes).sort_remove_dups, member(X1,Dom), member(X2,Dom), member(X3,Dom), X = [X1,X2,X3], length(Passcodes) == check3(X,Passcodes), writeln(x=X), fail, nl. % CP (for go2/0) % Check the passcodes check(_,[]). check(X,[Passcode|Passcodes]) :- check(X,Passcode,Bs), sum(Bs) #= 1, check(X,Passcodes). % Check one passcode check([],[],[]). check([X|Xs],[P|Ps],[B|Bs]) :- X #= P #<=> B, check(Xs,Ps,Bs). % No CP (for go4/0) check2(_,[]). check2(X,[Passcode|Passcodes]) :- check2(X,Passcode,Bs), sum(Bs) == 1, check2(X,Passcodes). % Check one passcode check2([],[],[]). check2([X|Xs],[P|Ps],[B|Bs]) :- (X == P -> B = 1 ; B = 0), check(Xs,Ps,Bs). % Functional style (for go5/0) check3(_,[]) = 0. % We must ensure that check3_/2 returns 1 (1 match) check3(Xs,[Ps|Pss]) = cond(check3_(Xs,Ps) == 1, 1, 0) + check3(Xs,Pss). check3_([],[]) = 0. % Exactly one match check3_([X|Xs],[P|Ps]) = cond(X == P, 1,0) + check3_(Xs,Ps). passcodes(Passcodes) => Passcodes = [[8,9,6], [9,8,3], [2,4,6], [8,4,3]].