RabbitFarm
2025-03-09
The Weekly Challenge 311 (Prolog Solutions)
The examples used here are from the weekly challenge problem statement and demonstrate the working solution.
Part 1: Upper Lower
You are given a string consists of english letters only. Write a script to convert lower case to upper and upper case to lower in the given string.
GNU Prolog defines a predicate lower_upper/2 which does pretty much what this problem is asking for. We could also just use the character code values instead of chars, but using chars seems a little more elegant as it avoids ASCII math.
-
upper_lower(S, UpperLower):-
atom_chars(S, C),
upper_lower(C, UL, _),
atom_chars(UpperLower, UL).
upper_lower([], [], _).
upper_lower([C|T], [L|UL], _):-
lower_upper(C, C0),
C == C0,
lower_upper(L, C),
upper_lower(T, UL, _).
upper_lower([C|T], [U|UL], _):-
lower_upper(C, U),
\+ C == U,
upper_lower(T, UL, _).
◇
-
Fragment referenced in 2.
The rest of the code just wraps this predicate into a file.
Sample Run
$ gprolog --consult-file prolog/ch-1.p | ?- upper_lower(’pERl’, UpperLower). UpperLower = ’PerL’ ? yes | ?- upper_lower(’rakU’, UpperLower). UpperLower = ’RAKu’ ? yes | ?- upper_lower(’PyThOn’, UpperLower). UpperLower = pYtHoN ? yes | ?-
Part 2: Group Digit Sum
You are given a string, $str, made up of digits, and an integer, $int, which is less than the length of the given string. Write a script to divide the given string into consecutive groups of size $int (plus one for leftovers if any). Then sum the digits of each group, and concatenate all group sums to create a new string. If the length of the new string is less than or equal to the given integer then return the new string, otherwise continue the process.
To solve this problem we need to do the following
- divide the list into groups of the given size
- compute the sums
- recombine
- repeat as needed
Let’s look at each of those pieces individually and then combine them together into one predicate.
-
group_list(S, Size, GroupedList):-
atom_chars(S, C),
maplist(char_number, C, N),
group_list(N, Size, [], [], GroupedList).
group_list([], _, Group, GroupedListAccum, GroupedList):-
length(Group, L),
((L > 0, append(GroupedListAccum, [Group], GroupedList));
(GroupedList = GroupedListAccum)).
group_list([H|T], Size, Group, GroupedListAccum, GroupedList):-
length(Group, L),
L < Size,
append(Group, [H], G),
GLA = GroupedListAccum,
group_list(T, Size, G, GLA, GroupedList).
group_list([H|T], Size, Group, GroupedListAccum, GroupedList):-
length(Group, L),
L == Size,
append(GroupedListAccum, [Group], GLA),
group_list([H|T], Size, [], GLA, GroupedList).
◇
-
char_number(C, N):-
number_chars(N, [C]).
◇
-
Fragment referenced in 9.
We can compute the sums using the GNU Prolog builtin predicate sum_list/2.
-
join([], ’’).
join([H|T], A):-
join(T, A0),
number_atom(H, A1),
atom_concat(A1, A0, A).
◇
-
Fragment referenced in 9.
Finally, let’s assemble our completed code into a single file.
Sample Run
$ gprolog prolog/ch-2.p | ?- group_digit_sum(’111122333’, 3, GroupDigitSum). GroupDigitSum = ’359’ yes | ?- group_digit_sum(’1222312’, 2, GroupDigitSum). GroupDigitSum = ’76’ yes | ?- group_digit_sum(’100012121001’, 4, GroupDigitSum). GroupDigitSum = ’162’ yes | ?-
References
posted at: 00:39 by: Adam Russell | path: /prolog | permanent link to this entry