RabbitFarm

2025-04-12

The Weekly Challenge 316 (Prolog Solutions)

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

Part 1: Circular

You are given a list of words. Write a script to find out whether the last character of each word is the first character of the following word.

We can do this in a single predicate which recursively examines the list of words, which we’ll take as a list of character code lists.

circular 1 ⟩≡


circular([]).
circular([_]).
circular([H0, H1|T]):-
last(H0, C0),
nth(1, H1, C1),
C0 = C1,
circular([H1|T]).

Fragment referenced in 2.

The rest of the code just wraps this predicate into a file.

"ch-1.p" 2


circular 1

Sample Run
$ gprolog --consult-file prolog/ch-1.p 
| ?- circular(["perl", "loves", "scala"]). 
 
true ? 
 
(1 ms) yes 
| ?- circular(["love", "the", "programming"]). 
 
no 
| ?- circular(["java", "awk", "kotlin", "node.js"]). 
 
true ? 
 
yes 
| ?-
    

Part 2: Subsequence

You are given two strings. Write a script to find out if one string is a subsequence of another.

This is going to be a quick one, seeing as GNU Prolog has a sublist/2 predicate which does exactly this! As in the previous part we’ll take the strings as lists of character codes.

subsequence 3 ⟩≡


subsequence(S, T):-
sublist(S, T).

Fragment referenced in 4.

Finally, let’s assemble our completed code into a single file.

"ch-2.p" 4


subsequence 3

Sample Run
$ gprolog --consult-file prolog/ch-2.p 
| ?- subsequence("uvw", "bcudvew"). 
 
true ? 
 
yes 
| ?- subsequence("aec", "abcde"). 
 
no 
| ?- subsequence("sip", "javascript"). 
 
true ? 
 
yes 
| ?-
    

References

The Weekly Challenge 316
Generated Code

posted at: 23:32 by: Adam Russell | path: /prolog | permanent link to this entry

Going Around in Sequential Circles

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

Part 1: Circular

You are given a list of words. Write a script to find out whether the last character of each word is the first character of the following word.

This seems straightforward enough. One question is whether we need to only consider the words in their given order. We’ll assume so.

Here’s our one subroutine, this problem requires very little code.

circular 1 ⟩≡


sub circular{
my $current = shift @_;
my $current_last = (split //, $current)[length($current) - 1];
do{
my $previous_last = $current_last;
$current = $_;
my $current_first = (split //, $current)[0];
$current_last = (split //, $current)[length($current) - 1];
return 0 if $previous_last ne $current_first;
} for @_;
return 1;
}

Fragment referenced in 2.

Putting it all together...

"ch-1.pl" 2


preamble 3
circular 1
main 4

preamble 3 ⟩≡


use v5.40;

Fragment referenced in 2, 8.

The rest of the code just runs some simple tests.

main 4 ⟩≡


MAIN:{
say circular(qw/perl loves scala/);
say circular(qw/love the programming/);
say circular(qw/java awk kotlin node.js/);
}

Fragment referenced in 2.

Sample Run
$ perl perl/ch-1.pl 
1 
0 
1
    

Part 2: Subsequence

You are given two strings. Write a script to find out if one string is a subsequence of another.

A subsequence of a string is a new string that is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters.

We’re going to do this in teh shortest way possible, via a regular expression.

We’re going to construct the regular expression dynamically each time

construct regex 5 ⟩≡


my $pattern = join q/.*/, split //, $s;
my $regex = qr/^.*$pattern.*$/;

Fragment referenced in 7.

Defines: $regex 7.

Uses: $s 6.

The shorter of the two strings will be what we test as the potential subsequence of the other longer one.

determine shortest/longest string 6 ⟩≡


my($s, $t) = length $s0 > length $s1? ($s1, $s0): ($s0, $s1);

Fragment referenced in 7.

Defines: $s 5, $t 7.

We’re going to have the work done in a single subroutine which determines which string to test, builds the regex, and runs it.

subsequence 7 ⟩≡


sub subsequence{
my($s0, $s1) = @_;
determine shortest/longest string 6
construct regex 5
return 0 + $t =~ $regex;
}

Fragment referenced in 8.

Uses: $regex 5, $t 6.

The rest of the code drives some tests.

"ch-2.pl" 8


preamble 3
subsequence 7
main 9

main 9 ⟩≡


MAIN:{
say subsequence q/uvw/, q/bcudvew/;
say subsequence q/aec/, q/abcde/;
say subsequence q/sip/, q/javascript/;
}

Fragment referenced in 8.

Sample Run
$ perl perl/ch-2.pl 
1 
0 
1
    

References

The Weekly Challenge 316
Generated Code

posted at: 22:58 by: Adam Russell | path: /perl | permanent link to this entry