RabbitFarm
2022-04-17
The Weekly Challenge 160 (Prolog Solutions)
The examples used here are from the weekly challenge problem statement and demonstrate the working solution.
Part 1
You are given a positive number, $n < 10. Write a script to generate english text sequence starting with the English cardinal representation of the given number, the word "is" and then the English cardinal representation of the count of characters that made up the first word, followed by a comma. Continue until you reach four.
Solution
cardinal(1, one).
cardinal(2, two).
cardinal(3, three).
cardinal(4, four).
cardinal(5, five).
cardinal(6, six).
cardinal(7, seven).
cardinal(8, eight).
cardinal(9, nine).
cardinal(10, ten).
four_is_magic(N) --> {between(1, 9, N), \+N == 4,
cardinal(N, Cardinal),
atom_codes(Cardinal, Codes),
length(Codes, Count)},
[N-Count], four_is_magic(Count).
four_is_magic(N) --> {between(1, 9, N), N == 4}, [N-magic].
print_magic([]):-
nl.
print_magic([H|T]):-
N-Count = H,
\+ N == 4,
cardinal(N, Cardinal),
cardinal(Count, CountCardinal),
format("~a is ~a, ", [Cardinal, CountCardinal]),
print_magic(T).
print_magic([H|T]):-
N-_ = H,
N == 4,
cardinal(N, Cardinal),
format("~a is ~a", [Cardinal, magic]),
print_magic(T).
main(N) :-
phrase(four_is_magic(N), FourIsMagic),
print_magic(FourIsMagic).
Sample Run
$ gprolog --consult-file prolog/ch-1.p
| ?- main(6).
six is three, three is five, five is four, four is magic
true ?
(1 ms) yes
| ?- main(_).
one is three, three is five, five is four, four is magic
true ? ;
two is three, three is five, five is four, four is magic
true ? ;
three is five, five is four, four is magic
true ? ;
five is four, four is magic
true ? ;
six is three, three is five, five is four, four is magic
true ? ;
seven is five, five is four, four is magic
true ? ;
eight is five, five is four, four is magic
true ?
(1 ms) yes
Notes
Prolog has an interesting history of generating text. This is one of the more simple applications I will admit. Here I use a DCG to generate the sequence and then a recursive set of predicates to print the associated text.
In typical Prolog fashion, as shown in the sample output, we can not only generate a sequence with a specified starting point, but all such sequences.
Part 2
You are give an array of integers, @n. Write a script to find out the Equilibrium Index of the given array, if found.
Solution
equilibrium_index(Numbers, I):-
member(N, Numbers),
append(Left, [N|Right], Numbers),
sum_list(Left, SumLeft),
sum_list(Right, SumRight),
SumLeft == SumRight,
nth(I, Numbers, N).
main:-
(equilibrium_index([1, 3, 5, 7, 9], I), format("~d~n", [I]); format("-1~n", _)),
(equilibrium_index([1, 2, 3, 4, 5], J), format("~d~n", [J]); format("-1~n", _)),
(equilibrium_index([2, 4, 2], K), format("~d~n", [K]); format("-1~n", _)), halt.
Sample Run
$ gprolog --consult-file prolog/ch-2.p
| ?- main.
4
-1
2
Notes
This problem was very "Prolog shaped" in my opinion! Just from reading the problem statement I could picture the standard Prolog predicates that could be used here. Prolog is not a language which naturally lends itself to code golf contests but in terms of simple elegance this is quite a compact solution!
References
posted at: 09:59 by: Adam Russell | path: /prolog | permanent link to this entry
Four is Equilibrium
The examples used here are from The Weekly Challenge problem statement and demonstrate the working solution.
Part 1
You are given a positive number, $n < 10. Write a script to generate english text sequence starting with the English cardinal representation of the given number, the word "is" and then the English cardinal representation of the count of characters that made up the first word, followed by a comma. Continue until you reach four.
Solution
use strict;
use warnings;
my %cardinals = (
1 => "one",
2 => "two",
3 => "three",
4 => "four",
5 => "five",
6 => "six",
7 => "seven",
8 => "eight",
9 => "nine"
);
sub four_is_magic{
my($n, $s) = @_;
$s = "" if !$s;
return $s .= "four is magic" if $n == 4;
$s .= $cardinals{$n} . " is " . $cardinals{length($cardinals{$n})} . ", ";
four_is_magic(length($cardinals{$n}), $s);
}
MAIN:{
print four_is_magic(5) . "\n";
print four_is_magic(7) . "\n";
print four_is_magic(6) . "\n";
}
Sample Run
$ perl perl/ch-1.pl
five is four, four is magic
seven is five, five is four, four is magic
six is three, three is five, five is four, four is magic
Notes
I was thinking of a clever way I might do this problem. I got nothing! Too much Easter candy perhaps? Anyway, I am not sure there is much tow rite about here as it's an otherwise straightforward use of hashes.
Part 2
You are give an array of integers, @n. Write a script to find out the Equilibrium Index of the given array, if found.
Solution
use strict;
use warnings;
sub equilibrium_index{
for my $i (0 .. @_ - 1){
return $i if unpack("%32I*", pack("I*", @_[0 .. $i])) == unpack("%32I*", pack("I*", @_[$i .. @_ - 1]));
}
return -1;
}
MAIN:{
print equilibrium_index(1, 3, 5, 7, 9) . "\n";
print equilibrium_index(1, 2, 3, 4, 5) . "\n";
print equilibrium_index(2, 4, 2) . "\n";
}
Sample Run
$ perl perl/ch-2.pl
3
-1
1
Notes
Like Part 1 above this problem allows for a pretty cut and dry solution. Also, similarly, I can't see a more efficient and/or creative way to solve this one. Maybe I should have just gone for obfuscated then?!?!? In any event, if nothing else, I always like using pack/unpack. I always considered it one of Perl's super powers!
References
posted at: 09:59 by: Adam Russell | path: /perl | permanent link to this entry