Last active
December 20, 2015 22:38
-
-
Save controlflow/6206209 to your computer and use it in GitHub Desktop.
99 Prolog problems :: solutions 1.01 - 1.28
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% problem 1.01 | |
my_last(X, [X]). | |
my_last(X, [_|TL]) :- my_last(X, TL). | |
% problem 1.02 | |
last_but_one(X, [X, _]). | |
last_but_one(X, [_,Y|TL]) :- last_but_one(X, [Y|TL]). | |
% problem 1.03 | |
element_at(X, [X|_], 1). | |
element_at(X, [_|TL], N) :- | |
U is N - 1, element_at(X, TL, U). | |
% problem 1.04 | |
my_count(0, []). | |
my_count(N, [_|TL]) :- my_count(U, TL), N is U + 1. | |
% problem 1.05 | |
my_reverse(XS, [], XS). | |
my_reverse(XS, [Y|YS], ACC) :- my_reverse(XS, YS, [Y|ACC]). | |
my_reverse(XS, YS) :- my_reverse(XS, YS, []). | |
% problem 1.06 | |
is_palindrome(XS) :- reverse(XS, XS). | |
% problem 1.07 | |
my_flatten(XS, [], XS). | |
my_flatten(XS, [H|TL], ACC) :- | |
is_list(H), | |
my_flatten(YS, H), | |
append(YS, ACC, BS), | |
my_flatten(XS, TL, BS). | |
my_flatten(XS, [H|TL], ACC) :- | |
my_flatten(XS, TL, [H|ACC]). | |
my_flatten(XS, YS) :- | |
my_flatten(TS, YS, []), | |
reverse(TS, XS). | |
% problem 1.08 | |
compress([], XS, XS). | |
compress([H,H|TL], ACC, XS) :- | |
compress([H|TL], ACC, XS). | |
compress([H|TL], ACC, XS) :- | |
compress(TL, [H|ACC], XS). | |
compress(XS, YS) :- | |
compress(XS, [], TS), reverse(TS, YS). | |
% problem 1.09 | |
pack([], YS, YS). | |
pack([H|TL], [[H|HS]|ACC], XS) :- | |
pack(TL, [[H,H|HS]|ACC], XS). | |
pack([H|TL], ACC, XS) :- | |
pack(TL, [[H]|ACC], XS). | |
pack(XS, YS) :- | |
pack(XS, [], TS), reverse(TS, YS). | |
% problem 1.10 | |
encode([], YS, YS). | |
encode([[X|XS]|TL], ACC, YS) :- | |
my_count(N, [X|XS]), | |
encode(TL, [[N,X]|ACC], YS). | |
encode(XS, YS) :- | |
pack(XS, TS), | |
encode(TS, [], ZS), | |
reverse(ZS, YS). | |
% problem 1.11 | |
encode_modified([], YS, YS). | |
encode_modified([[X]|TL], ACC, YS) :- | |
encode_modified(TL, [X|ACC], YS). | |
encode_modified([[X|XS]|TL], ACC, YS) :- | |
my_count(N, [X|XS]), | |
encode_modified(TL, [[N,X]|ACC], YS). | |
encode_modified(XS, YS) :- | |
pack(XS, TS), | |
encode_modified(TS, [], ZS), | |
reverse(ZS, YS). | |
% problem 1.12 | |
decode([], YS, YS). | |
decode([[0,_]|TL], ACC, YS) :- | |
decode(TL, ACC, YS). | |
decode([[N,X]|TL], ACC, YS) :- | |
U is N - 1, decode([[U,X]|TL], [X|ACC], YS). | |
decode([X|TL], ACC, YS) :- | |
decode(TL, [X|ACC], YS). | |
decode(XS, YS) :- | |
decode(XS, [], TS), reverse(TS, YS). | |
% problem 1.13 | |
encode_direct([], YS, YS). | |
encode_direct([H|TL], [H|ACC], YS) :- | |
encode_direct(TL, [[2,H]|ACC], YS). | |
encode_direct([H|TL], [[N,H]|ACC], YS) :- | |
U is N + 1, encode_direct(TL, [[U,H]|ACC], YS). | |
encode_direct([H|TL], ACC, YS) :- | |
encode_direct(TL, [H|ACC], YS). | |
encode_direct(XS, YS) :- | |
encode_direct(XS, [], TS), reverse(TS, YS). | |
% problem 1.14 | |
dupli([], YS, YS). | |
dupli([H|TL], ACC, YS) :- dupli(TL, [H,H|ACC], YS). | |
dupli(XS, YS) :- dupli(XS, [], TS), reverse(TS, YS). | |
% problem 1.15 | |
dupli_n([], _, _, YS, YS). | |
dupli_n([_|TL], N, 0, ACC, YS) :- | |
dupli_n(TL, N, N, ACC, YS). | |
dupli_n([H|TL], N, I, ACC, YS) :- | |
U is I - 1, dupli_n([H|TL], N, U, [H|ACC], YS). | |
dupli_n(XS, N, YS) :- | |
dupli_n(XS, N, N, [], TS), reverse(TS, YS). | |
% problem 1.16 | |
drop([], _, _, YS, YS). | |
drop([_|TL], N, 1, ACC, YS) :- | |
drop(TL, N, N, ACC, YS). | |
drop([H|TL], N, I, ACC, YS) :- | |
U is I - 1, drop(TL, N, U, [H|ACC], YS). | |
drop(XS, N, YS) :- | |
drop(XS, N, N, [], TS), reverse(TS, YS). | |
% problem 1.17 | |
split(L2, 0, ACC, L1, L2) :- reverse(ACC, L1). | |
split([H|TL], N, ACC, L1, L2) :- | |
U is N - 1, split(TL, U, [H|ACC], L1, L2). | |
split(XS, N, L1, L2) :- split(XS, N, [], L1, L2). | |
% problem 1.18 | |
slice(_, _, 0, ACC, YS) :- | |
reverse(ACC, YS). | |
slice([H|TL], 1, U, ACC, YS) :- | |
V is U - 1, | |
slice(TL, 1, V, [H|ACC], YS). | |
slice([_|TL], N, U, _, YS) :- | |
V is N - 1, W is U - 1, | |
slice(TL, V, W, [], YS). | |
slice(XS, N, U, YS) :- | |
U > N, slice(XS, N, U, [], YS). | |
% problem 1.19 | |
rotate(XS, 0, XS). | |
rotate(XS, N, YS) :- | |
N > 0, split(XS, N, L1, L2), | |
append(L2, L1, YS). | |
rotate(XS, N, YS) :- | |
length(XS, L), V is L + N, | |
rotate(XS, V, YS). | |
% problem 1.20 | |
remove_at(X, [X|TL], 0, ACC, YS) :- | |
reverse(ACC, TS), append(TS, TL, YS). | |
remove_at(X, [H|TL], N, ACC, YS) :- | |
U is N - 1, remove_at(X, TL, U, [H|ACC], YS). | |
remove_at(X, XS, N, YS) :- | |
remove_at(X, XS, N, [], YS). | |
% problem 1.21 | |
insert_at(X, XS, 0, ACC, YS) :- | |
reverse(ACC, TS), append(TS, [X|XS], YS). | |
insert_at(X, [H|TL], N, ACC, YS) :- | |
U is N - 1, insert_at(X, TL, U, [H|ACC], YS). | |
insert_at(X, XS, N, YS) :- | |
insert_at(X, XS, N, [], YS). | |
% problem 1.22 | |
range(X, Y, ACC, YS) :- X > Y, reverse(ACC, YS). | |
range(X, Y, ACC, YS) :- U is X + 1, range(U, Y, [X|ACC], YS). | |
range(X, Y, XS) :- range(X, Y, [], XS). | |
% problem 1.23 | |
rnd_select(_, 0, _, YS, YS). | |
rnd_select(XS, N, L, ACC, YS) :- | |
N =< L, I is random(L), | |
U is N - 1, V is L - 1, | |
remove_at(R, XS, I, TS), | |
rnd_select(TS, U, V, [R|ACC], YS). | |
rnd_select(XS, N, YS) :- | |
length(XS, L), | |
rnd_select(XS, N, L, [], YS). | |
% problem 1.24 | |
rnd_select2(N, X, XS) :- | |
range(1, X, TS), | |
rnd_select(TS, N, XS). | |
% problem 1.25 | |
rnd_permu(XS, YS) :- | |
length(XS, L), rnd_select(XS, L, YS). | |
% problem 1.26 | |
combination(0, _, ACC, YS) :- reverse(ACC, YS). | |
combination(N, [H|TL], ACC, YS) :- | |
U is N - 1, combination(U, TL, [H|ACC], YS). | |
combination(N, [_|TL], ACC, YS) :- | |
N > 0, combination(N, TL, ACC, YS). | |
combination(N, XS, YS) :- combination(N, XS, [], YS). | |
% problem 1.27 | |
combination2(0, TL, AS, BS, YS, ZS) :- | |
reverse(AS, YS), reverse(BS, TS), append(TL, TS, ZS). | |
combination2(N, [H|TL], AS, BS, YS, ZS) :- | |
U is N - 1, combination2(U, TL, [H|AS], BS, YS, ZS). | |
combination2(N, [H|TL], AS, BS, YS, ZS) :- | |
N > 0, combination2(N, TL, AS, [H|BS], YS, ZS). | |
combination2(N, XS, YS, TL) :- | |
combination2(N, XS, [], [], YS, TL). | |
group(_, [], YS, YS). | |
group(XS, [N|TL], ACC, YS) :- | |
combination2(N, XS, H, ZS), | |
group(ZS, TL, [H|ACC], YS). | |
group(XS, NS, YS) :- | |
group(XS, NS, [], TS), reverse(TS, YS). | |
% problem 1.28 | |
my_partition(_, [], AS, BS, L1, L2) :- | |
reverse(AS, L1), reverse(BS, L2). | |
my_partition(P, [H|TL], AS, BS, L1, L2) :- | |
call(P, H), my_partition(P, TL, [H|AS], BS, L1, L2). | |
my_partition(P, [H|TL], AS, BS, L1, L2) :- | |
my_partition(P, TL, AS, [H|BS], L1, L2). | |
my_partition(P, XS, L1, L2) :- | |
my_partition(P, XS, [], [], L1, L2). | |
qsort(_, [], []). | |
qsort(P, [H|TL], YS) :- | |
partition(call(P, H), TL, L1, L2), | |
qsort(P, L1, S1), qsort(P, L2, S2), | |
append(S1, [H|S2], YS). | |
cmp_length(XS, YS) :- | |
length(XS, X), length(YS, Y), X > Y. | |
lsort(XS, YS) :- qsort(cmp_length, XS, YS). | |
% problem 1.28b | |
my_map(_, [], ACC, YS) :- reverse(ACC, YS). | |
my_map(F, [H|TL], ACC, YS) :- | |
call(F, H, X), | |
my_map(F, TL, [X|ACC], YS). | |
my_map(F, XS, YS) :- | |
my_map(F, XS, [], YS). | |
get_key(K, [[K, V]|_], V). | |
get_key(K, [_|TL], V) :- get_key(K, TL, V). | |
set_key(K, [], V, Map, [[K,V]|Map]). | |
set_key(K, [[K,_]|TL], V, ACC, Map) :- | |
append(ACC, [[K,V]|TL], Map). | |
set_key(K, [H|TL], V, ACC, Map) :- | |
set_key(K, TL, V, [H|ACC], Map). | |
set_key(K, Map, V, Map2) :- | |
set_key(K, Map, V, [], Map2). | |
group_by_counts([], Map, Map). | |
group_by_counts([H|TL], Map, Mres) :- | |
get_key(H, Map, V), N is V + 1, | |
set_key(H, Map, N, Map2), | |
group_by_counts(TL, Map2, Mres). | |
group_by_counts([H|TL], Map, Mres) :- | |
set_key(H, Map, 1, Map2), | |
group_by_counts(TL, Map2, Mres). | |
group_by_counts(XS, M) :- | |
group_by_counts(XS, [], M). | |
cmp_freq(Map, XS, YS) :- | |
length(XS, L1), get_key(L1, Map, F1), | |
length(YS, L2), get_key(L2, Map, F2), | |
F1 > F2. | |
lfsort(XS, YS) :- | |
my_map(length, XS, Lens), | |
group_by_counts(Lens, Map), | |
qsort(call(cmp_freq, Map), XS, YS). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment