RabbitFarm

2022-05-08

The Weekly Challenge 163 (Prolog Solutions)

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

Part 1

You are given a list of numbers. Write a script to calculate the sum of the bitwise & operator for all unique pairs.

Solution


and(N, X, And):-
    And is N /\ X.
sum_and([], 0).
sum_and([H|T], SumAnd):-
    sum_and(T, Sum),
    maplist(and(H), T, Ands),
    sum_list(Ands, AndSum),
    SumAnd is Sum + AndSum.

Sample Run


$ gprolog --consult-file prolog/ch-1.p 
| ?- sum_and([1, 2, 3], SumAnd).

SumAnd = 3

yes
| ?- sum_and([2, 3, 4], SumAnd).   

SumAnd = 2

yes
| ?- sum_and([1, 2, 3], 99).    

no
| ?- sum_and([1, 2, 3], 3). 

yes

Notes

It is not too often you see the bitwise operators used in Prolog code! I am kind of a fan of the /\ operator, I mean, it even looks like an upper case 'A', right?

Other than the novelty of the bitwise and I found this task to be well suited for the use of maplist/3 for computing the pairwise and operations across the list of numbers. This is something of a "nested loop" in the sense that recursively the head of the list of numbers is removed and upon each recursive step the maplist is re-performed on the increasingly shorter list.

Part 2

Given a list of numbers, generate the skip summations.

Solution


skip_sum(Numbers, N, Sum):-
    append(Left, [N|_], Numbers),
    sum_list(Left, SumLeft),
    Sum is N + SumLeft.

skip_summations(Numbers, Summations):-
    skip_summations(Numbers, [Numbers], Summations).
skip_summations([], Summations, Summations).
skip_summations([_|T], SummationsAccum, Summations):-
    maplist(skip_sum(T), T, Sums),
    skip_summations(Sums, [Sums|SummationsAccum], Summations).

print_summation(S):-
    write(S),
    write(' ').
print_summations([]).
print_summations([H|T]):-
    print_summations(T),
    maplist(print_summation, H), nl.

Sample Run


$ gprolog --consult-file prolog/ch-2.p 
| ?- skip_summations([1, 2, 3, 4, 5], Summations), print_summations(Summations).
1 2 3 4 5 
2 5 9 14 
5 14 28 
14 42 
42 


Summations = [[],[42],[14,42],[5,14,28],[2,5,9,14],[1,2,3,4,5]] ? 

yes
| ?- skip_summations([1, 3, 5, 7, 9], Summations), print_summations(Summations).      
1 3 5 7 9 
3 8 15 24 
8 23 47 
23 70 
70 


Summations = [[],[70],[23,70],[8,23,47],[3,8,15,24],[1,3,5,7,9]] ? 

yes
| ?- skip_summations([1, 3, 5, 7, 9], [[],[70],[23,70],[8,23,47],[3,8,15,24],[1,3,5,27,9]]).

no
| ?- skip_summations([1, 3, 5, 7, 9], [[],[70],[23,70],[8,23,47],[3,8,15,24],[1,3,5,7,9]]). 

true ? 

yes

Notes

Much like the task above we use a maplist/3 within a recursive step. Here the maplist/3 is used to do the partial sums for each "line" of the output. There is also a maplist/2 used to print the output lines with a space between each element.

Satisfyingly, as shown above, the same code not only generates the skip summations but also validates them as well. This sort of intrinsic Prolog behavior brings joy!

References

Challenge 163

posted at: 13:52 by: Adam Russell | path: /prolog | permanent link to this entry