RabbitFarm
2025-04-06
The Weekly Challenge 315 (Prolog Solutions)
The examples used here are from the weekly challenge problem statement and demonstrate the working solution.
Part 1: Find Words
You are given a list of words and a character. Write a script to return the index of word in the list where you find the given character.
This can be done with a basic predicate with findall. Or we can use maplist! maplist is more fun in my opinion, so we’ll go with that.
First off a small utility predicate to see if a word contains a given letter.
-
contains_letter(Letter, Index-Word, Index):-
atom_chars(Word, C),
member(Letter, C).
contains_letter(_, _, -1).
◇
-
Fragment referenced in 4.
You can see that we are sending that previous predicate a pair. The first element in that pair is an index. Let’s build a word index, mainly for the sake of avoiding the use of between and findall. Those builtin predicates are fine, but aesthetically to me it seems nicer to not use them if we absolutely don’t have to.
-
word_index(Words, Index):-
word_index(Words, 0, Index).
word_index([], _, []).
word_index([H|T], N, [I-H|Index]):-
succ(N, I),
word_index(T, I, Index).
◇
-
Fragment referenced in 4.
Now we’ll use maplist to find the words.
-
find_words(Words, Letter, Indices):-
word_index(Words, Index),
maplist(contains_letter(Letter), Index, I),
delete(I, -1, Indices).
◇
-
Fragment referenced in 4.
The rest of the code just wraps this predicate into a file.
Sample Run
$ gprolog --consult-file prolog/ch-1.p | ?- find_words([the, weekly, challenge], e, Indices). Indices = [1,2,3] ? yes | ?- find_words([perl, raku, python], p, Indices). Indices = [1,3] ? yes | ?- find_words([abc, def, bbb, bcd], b, Indices). Indices = [1,3,4] ? yes | ?-
Part 2: Find Third
You are given a sentence and two words. Write a script to return all words in the given sentence that appear in sequence to the given two words.
In the first part I mentioned the between and findall predicates. Here we will use them to find successive words.
-
find_third(Words, One, Two, Thirds):-
length(Words, WordLength),
N is WordLength - 2,
findall(Third, (
between(1, N, I),
succ(I, J),
nth(I, Words, One),
nth(J, Words, Two),
succ(J, K),
nth(K, Words, Third)
), Thirds).
◇
-
Fragment referenced in 6.
Finally, let’s assemble our completed code into a single file.
Sample Run
$ gprolog --consult-file prolog/ch-2.p | ?- find_third([’Perl’, is, a, my, favourite, language, but, ’Python’, is, my, favourite, too], my, favourite, Thirds). Thirds = [language,too] yes | ?- find_third([’Barbie’, is, a, beautiful, doll, also, also, a, beautiful, princess], a, beautiful, Thirds). Thirds = [doll,princess] yes | ?- find_third([we, will, we, will, rock, you, rock, you], we, will, Thirds). Thirds = [we,rock] yes | ?-
References
posted at: 17:41 by: Adam Russell | path: /prolog | permanent link to this entry