Search code examples
listrecursionprolog

Why is my prolog predicate returning 'true' rather than the desired list?


append_green([],[],X,X,5):-
    write('Final Green: '), 
    writeln(X).
append_green([CorrectHead|CorrectTail], [GuessHead|GuessTail], Grn, _FinalGreen, N):-
    N < 5,
    (    CorrectHead = GuessHead 
    ->   replace(Grn,N,GuessHead,FinalGrn),
         N1 is N + 1, 
         append_green(CorrectTail, GuessTail, FinalGrn, FinalGrn, N1)
    ;    N1 is N + 1, 
         append_green(CorrectTail, GuessTail, Grn, Grn, N1) ).

replace([_|T], 0, X, [X|T]).
replace([H|T], I, X, [H|R]):- 
    I > 0, 
    I1 is I-1, 
    replace(T, I1, X, R).

Hi, I'm trying to write a wordle solver using SWI prolog but I'm running into a few issues that I can't figure out. The code above is for a predicate that is supposed to update the list of green characters given the correct word and a guess.

The first parameter is the correct word that the program is attempting to guess in the format of a list, i.e. ['w','o','r','d','s'].

The second parameter is the "guess" in the same format. Grn is the existing list of green characters in the format ['.', '.', '.', '.', '.'] where the periods are placeholders for empty spots.

When called, the predicate is supposed to find the updated Green list, but instead just prints 'true' in console. The strange part is that the print statement in the base case displays the correct list.

Included below is what shows up when I trace it in SWI-prolog:

[trace]  ?- append_green([w,h,i,c,h],[h,i,t,c,h],[.,.,.,.,.],X,0).
   Call: (10) append_green([w, h, i, c, h], [h, i, t, c, h], ['.', '.', '.', '.', '.'], _25506, 0) ? creep
   Call: (11) 0<5 ? creep
   Exit: (11) 0<5 ? creep
   Call: (11) w=h ? creep
   Fail: (11) w=h ? creep
   Redo: (10) append_green([w, h, i, c, h], [h, i, t, c, h], ['.', '.', '.', '.', '.'], _25506, 0) ? creep
   Call: (11) _30726 is 0+1 ? creep
   Exit: (11) 1 is 0+1 ? creep
   Call: (11) append_green([h, i, c, h], [i, t, c, h], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], 1) ? creep
   Call: (12) 1<5 ? creep
   Exit: (12) 1<5 ? creep
   Call: (12) h=i ? creep
   Fail: (12) h=i ? creep
   Redo: (11) append_green([h, i, c, h], [i, t, c, h], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], 1) ? creep
   Call: (12) _36790 is 1+1 ? creep
   Exit: (12) 2 is 1+1 ? creep
   Call: (12) append_green([i, c, h], [t, c, h], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], 2) ? creep
   Call: (13) 2<5 ? creep
   Exit: (13) 2<5 ? creep
   Call: (13) i=t ? creep
   Fail: (13) i=t ? creep
   Redo: (12) append_green([i, c, h], [t, c, h], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], 2) ? creep
   Call: (13) _42854 is 2+1 ? creep
   Exit: (13) 3 is 2+1 ? creep
   Call: (13) append_green([c, h], [c, h], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], 3) ? creep
   Call: (14) 3<5 ? creep
   Exit: (14) 3<5 ? creep
   Call: (14) c=c ? creep
   Exit: (14) c=c ? creep
   Call: (14) replace(['.', '.', '.', '.', '.'], 3, c, _48146) ? creep
   Call: (15) 3>0 ? creep
   Exit: (15) 3>0 ? creep
   Call: (15) _50430 is 3+ -1 ? creep
   Exit: (15) 2 is 3+ -1 ? creep
   Call: (15) replace(['.', '.', '.', '.'], 2, c, _48914) ? creep
   Call: (16) 2>0 ? creep
   Exit: (16) 2>0 ? creep
   Call: (16) _54222 is 2+ -1 ? creep
   Exit: (16) 1 is 2+ -1 ? creep
   Call: (16) replace(['.', '.', '.'], 1, c, _52706) ? creep
   Call: (17) 1>0 ? creep
   Exit: (17) 1>0 ? creep
   Call: (17) _58014 is 1+ -1 ? creep
   Exit: (17) 0 is 1+ -1 ? creep
   Call: (17) replace(['.', '.'], 0, c, _56498) ? creep
   Exit: (17) replace(['.', '.'], 0, c, [c, '.']) ? creep
   Exit: (16) replace(['.', '.', '.'], 1, c, ['.', c, '.']) ? creep
   Exit: (15) replace(['.', '.', '.', '.'], 2, c, ['.', '.', c, '.']) ? creep
   Exit: (14) replace(['.', '.', '.', '.', '.'], 3, c, ['.', '.', '.', c, '.']) ? creep
   Call: (14) _63346 is 3+1 ? creep
   Exit: (14) 4 is 3+1 ? creep
   Call: (14) append_green([h], [h], ['.', '.', '.', c, '.'], ['.', '.', '.', c, '.'], 4) ? creep
   Call: (15) 4<5 ? creep
   Exit: (15) 4<5 ? creep
   Call: (15) h=h ? creep
   Exit: (15) h=h ? creep
   Call: (15) replace(['.', '.', '.', c, '.'], 4, h, _4622) ? creep
   Call: (16) 4>0 ? creep
   Exit: (16) 4>0 ? creep
   Call: (16) _6906 is 4+ -1 ? creep
   Exit: (16) 3 is 4+ -1 ? creep
   Call: (16) replace(['.', '.', c, '.'], 3, h, _5390) ? creep
   Call: (17) 3>0 ? creep
   Exit: (17) 3>0 ? creep
   Call: (17) _10698 is 3+ -1 ? creep
   Call: (17) replace(['.', c, '.'], 2, h, _9182) ? creep
   Call: (18) 2>0 ? creep
   Exit: (18) 2>0 ? creep
   Call: (18) _14490 is 2+ -1 ? creep
   Exit: (18) 1 is 2+ -1 ? creep
   Call: (18) replace([c, '.'], 1, h, _12974) ? creep
   Call: (19) 1>0 ? creep
   Exit: (19) 1>0 ? creep
   Call: (19) _18282 is 1+ -1 ? creep
   Exit: (19) 0 is 1+ -1 ? creep
   Call: (19) replace(['.'], 0, h, _16766) ? creep
   Exit: (19) replace(['.'], 0, h, [h]) ? creep
   Exit: (18) replace([c, '.'], 1, h, [c, h]) ? creep
   Exit: (17) replace(['.', c, '.'], 2, h, ['.', c, h]) ? creep
   Exit: (16) replace(['.', '.', c, '.'], 3, h, ['.', '.', c, h]) ? creep
   Exit: (15) replace(['.', '.', '.', c, '.'], 4, h, ['.', '.', '.', c, h]) ? creep
   Call: (15) _24376 is 4+1 ? creep
   Exit: (15) 5 is 4+1 ? creep
   Call: (15) append_green([], [], ['.', '.', '.', c, h], ['.', '.', '.', c, h], 5) ? creep
   Call: (16) write('Final Green: ') ? creep
Final Green: 
   Exit: (16) write('Final Green: ') ? creep
   Call: (16) writeln(['.', '.', '.', c, h]) ? creep
[.,.,.,c,h]
   Exit: (15) append_green([], [], ['.', '.', '.', c, h], ['.', '.', '.', c, h], 5) ? creep
   Exit: (14) append_green([h], [h], ['.', '.', '.', c, '.'], ['.', '.', '.', c, '.'], 4) ? creep
   Exit: (13) append_green([c, h], [c, h], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], 3) ? creep
   Exit: (12) append_green([i, c, h], [t, c, h], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], 2) ? creep
   Exit: (11) append_green([h, i, c, h], [i, t, c, h], ['.', '.', '.', '.', '.'], ['.', '.', '.', '.', '.'], 1) ? creep
   Exit: (10) append_green([w, h, i, c, h], [h, i, t, c, h], ['.', '.', '.', '.', '.'], _18, 0) ? creep
true 

Could anyone help me figure out what is wrong with the recursion that would cause it to do this? Thank you!


Solution

  • Although this is not the main cause of the error in your code, it is worth noting that there is no need to use the predicate replace/4 to solve the problem:

    % update_green(+Correct, +Guess, +gReen, -Updated)
    
      updated_green([], [], R, R).
      updated_green([C|Cs], [G|Gs], [R|Rs], [U|Us]):-
         (   C = G
         ->  U = G
         ;   U = R ),
         updated_green(Cs, Gs, Rs, Us).
    

    Example:

    ?- updated_green([w,h,i,c,h], [h,i,t,c,h], [.,.,.,.,.], UpdatedGreen).
    UpdatedGreen = ['.', '.', '.', c, h].
    

    Alternatively, you can define a predicate to update only one element of the list:

    updated_element(C, G, R, U) :-
        (   C = G
        ->  U = G
        ;   U = R ).
    

    And then use this predicate (with maplist/4) to map elements from the input lists to the desired output list.

    ?- maplist(updated_element, [w,h,i,c,h], [h,i,t,c,h], [.,.,.,.,.], UpdatedGreen).
    UpdatedGreen = ['.', '.', '.', c, h].