RabbitFarm

2026-07-25

The Weekly Challenge 383 (Prolog Solutions)

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

Part 1: Similar List

You are given three list of strings. Write a script to find out if the first two list are similar with the help the third list. The third list contains the similar words map.

Our solution is short and will be contained in a single file that has the following structure.

"ch-1.p" 1


utilities 2
similar 3
similar DCG 4

First we’ll define a couple of helper predicates for constructing pairs from the given input lists. These pairs will be used as a data structure for the given mappings.

utilities 2 ⟩≡


make_kv(K, V, K-V).
make_kv(L, KV):-
L = [H|T],
maplist(make_kv(H), T, KV1),
reverse(L, LR),
LR = [HR|TR],
maplist(make_kv(HR), TR, KVR),
append(KV1, KVR, KV).
make_kvs([], []).
make_kvs([H|T], [KV|KVs]):-
make_kvs(T, KVs),
make_kv(H, KV).

Fragment referenced in 1.

Now we’ll compare the lists. First is just a small predicate for calling the DCG using phrase/2.

similar 3 ⟩≡


similar(L1, L2, M):-
make_kvs(M, KV1),
flatten(KV1, KVs),
phrase(similar(KVs, L1), L2).

Fragment referenced in 1.

This makes use of the following DCG definition.

similar DCG 4 ⟩≡


similar(_, []) --> [].
similar(_, []) --> [_], {!, fail}.
similar(KVs, L) --> [W], {L = [H|T], (H == W; member(H-W, KVs);
member(W-H, KVs))}, similar(KVs, T).

Fragment referenced in 1.

Sample Run
% gprolog --consult-file prolog/ch-1.p 
| ?- similar([great, acting], [fine, drama], [[great, fine], [acting, drama]]). 
 
true ? 
 
yes 
| ?- similar([apple, pie], [banana, pie], [[apple, peach], [peach, banana]]). 
 
no 
| ?- similar([perl4, python], [raku, python], [[perl4, perl5, raku]]). 
 
true ? 
 
yes 
| ?- similar([enjoy, challenge], [love, weekly, challenge], [[enjoy, love]]). 
 
no 
| ?- similar([fast, car], [quick, vehicle], [[quick, fast], [vehicle, car]]). 
 
true ? 
 
yes 
| ?-
    

Part 2: Nearest RGB

You are given a 6-digit hex color. Write a script to round the RGB channels to the nearest web-safe value and return the nearest RGB color.

This will proceed in a way very similar to Part 1, but this is a short enough problem so we won’t bother writing DCG rules.

"ch-2.p" 5


utilities 10
compute the nearest RGB values 11

We’ll define a few helper predicates first.

remove leading octothorpe 6 ⟩≡


leading_octothorpe(Hex, Hex1):-
nth(1, Hex, 35),
Hex = [_|Hex1].

Fragment referenced in 10.

code to hex conversion 7 ⟩≡


codes_nearest_hex(Codes, Hex):-
atom_codes(A, Codes),
atom_concat(’0x’, A, A1),
number_atom(Decimal, A1),
N is truncate((Decimal + 25.5) / 51) * 51,
Offset is N + 256,
format_to_atom(Temp, ’~16R’, [Offset]),
sub_atom(Temp, 1, 2, _, Hex).

Fragment referenced in 10.

split into RGB 8 ⟩≡


rgb(Hex, R, G, B):-
length(R, 2),
length(G, 2),
length(B, 2),
append(R, GB, Hex),
append(G, B, GB).

Fragment referenced in 10.

compute nearest 9 ⟩≡


nearest_rgb(R, G, B, Nearest):-
maplist(codes_nearest_hex, [R, G, B], [R1, G1, B1]),
atom_concat(’#’, R1, H1),
atom_concat(H1, G1, H2),
atom_concat(H2, B1, Nearest).

Fragment referenced in 10.

utilities 10 ⟩≡


remove leading octothorpe 6
code to hex conversion 7
split into RGB 8
compute nearest 9

Fragment referenced in 5.

Finally we’ll have a small predicate for tying everything together.

compute the nearest RGB values 11 ⟩≡


nearest_rgb(Hex, Nearest):-
leading_octothorpe(Hex, Hex1),
rgb(Hex1, R, G, B),
nearest_rgb(R, G, B, Nearest).

Fragment referenced in 5.

Sample Run
% gprolog --consult-file prolog/ch-2.p 
| ?- nearest_rgb("#F4B2D1", Nearest). 
 
Nearest = ’#FF99CC’ 
 
yes 
| ?- nearest_rgb("#15E6E5", Nearest). 
 
Nearest = ’#00FFCC’ 
 
yes 
| ?- nearest_rgb("#191A65", Nearest). 
 
Nearest = ’#003366’ 
 
yes 
| ?- nearest_rgb("#2D5A1B", Nearest). 
 
Nearest = ’#336633’ 
 
yes 
| ?- nearest_rgb("#00FF66", Nearest). 
 
Nearest = ’#00FF66’ 
 
yes 
| ?-
    

References

The Weekly Challenge 383
Generated Code

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