I'm pretty proud of the following, but would welcome any comments from experts:
%% Provide with a Goal and it will iterate towards it. guess(Goal, Res) :- guessIterate(Goal, , Res). guessIterate(Goal, Guesses, Res) :- makeGuess(Guess), check_against_guesses(Guess, Guesses), score(Guess, Goal, ThisScore), ( %% if completely correct,... ThisScore == [4, 0] -> Res = Guess ; write(Guess), write(' '), write(ThisScore),nl, NewGuesses = [guess(Guess, ThisScore) | Guesses], guessIterate(Goal, NewGuesses, Res) ). /* If this Guess is correct, it will pedict the right results for previous guesses */ check_against_guesses(_, ). check_against_guesses(Guess, [guess(Code, Score) | TGuesses]) :- score(Code, Guess, Score), check_against_guesses(Guess, TGuesses). makeGuess(Guess) :- Colours = [red, blue, green, yellow, orange, purple, pink], member(G1, Colours), member(G2, Colours), member(G3, Colours), member(G4, Colours), Guess = [G1, G2, G3, G4]. /* Score a guess, [#Black, #White], by first looking for exact matches - black - and then look for inexaxct matches - white. It is not possible for a guess of [...red, red...] to match twice with a single 'red' in the Goal */ score(Guess, Goal, Res) :- pass1(Guess, Goal, , Pass1Res), pass2(Guess, Pass1Res, Pass2Res), countUp(Pass2Res, [0,0], Res). pass1(_, , Acc, AccRev) :- reverse(Acc, AccRev). pass1([HGuess | TGuess], [HGoal | TGoal], Acc, Res) :- ( HGuess == HGoal -> AccNew = [black | Acc] ; AccNew = [HGoal | Acc] ), pass1(TGuess, TGoal, AccNew, Res). %% check each Guess element with Goal and change Goal element to 'white' if there is a match pass2(, Goal, GoalRev) :- reverse(Goal, GoalRev). pass2([HGuess | TGuess], Goal, Res) :- pass2Helper(HGuess, Goal, , ModifiedGoal), pass2(TGuess, ModifiedGoal, Res). pass2Helper(_, , Acc, AccRev) :- reverse(Acc, AccRev). pass2Helper(Guess, [HGoal | TGoal], Acc, Res) :- ( Guess == HGoal -> reverse(TGoal, TGoalRev), %% Res = [white | TGoalRev] append(TGoalRev, [white | Acc], Res) ; AccNew = [HGoal | Acc], pass2Helper(Guess, TGoal, AccNew, Res) ). countUp(, Acc, Acc). countUp([HRes|TRes], [AccB, AccW|_], Res) :- ( HRes == black -> AccBNew is AccB + 1, countUp(TRes, [AccBNew, AccW], Res) ; ( HRes == white -> AccWNew is AccW + 1, countUp(TRes, [AccB, AccWNew], Res) ; countUp(TRes, [AccB, AccW], Res) ) ).