% =========================================================================== % Deklaratív Programozás 2. gyakorlat, Prolog listakezelő eljárások % =========================================================================== % Examples of list handling predicates :- use_module(library(lists)). % Example 1: Inserting an element into a list % =========================================== % --------------------------------------------------------------- % insert_nth(N, L0, E, L): inserting element E into list L0 % before its Nth element gives list L. % If N is known, use versions 1 or 2 below. % If N in not known, then use version 3 if L0 is known and % version 4 if L is known. % :- mode insert_nth_1(+, ?, ?, ?). insert_nth_1(1, L0, E, [E|L0]). insert_nth_1(N, [X|L0], E, [X|L]) :- N > 1, N1 is N-1, insert_nth_1(N1, L0, E, L). % :- mode insert_nth_2(+, ?, ?, ?). insert_nth_2(N, L0, E, L) :- ( N =:= 1 -> L = [E|L0] ; N > 1 -> N1 is N-1, L0 = [X|L1], L = [X|L2], insert_nth_2(N1, L1, E, L2) ). % Calling insert_nth_2/4 produces the exactly same % answers as calling insert_nth_1/4, as shown above. % :- mode insert_nth_3(?, +, ?, ?). insert_nth_3(N, L0, E, L) :- append(L1, L2, L0), append(L1, [E|L2], L), length(L1, N1), N is N1+1. % :- mode insert_nth_4(?, ?, ?, +). insert_nth_4(N, L0, E, L) :- append(L1, [E|L2], L), append(L1, L2, L0), length(L1, N1), N is N1+1. % Examples using insert_nth: text("abrakadabra"). text("almakarika"). text("szilva"). text("fahej"). text("barnacukor"). text("haragosaik"). % find texts with letter `a' at 4th position, and print % the text without this letter `a': test1_slow :- ( text(Pat), insert_nth_1(4, SubPat, 0'a, Pat), % which other variants? format('~s\n', [SubPat]), fail ; true ). test1_fast :- insert_nth_1(4, SubPat, 0'a, Pat), % which other variants? ( text(Pat), format('~s\n', [SubPat]), fail ; true ). % | ?- test1_slow. % abrkadabra % almkarika % hargosaik % yes % | ?- test1_fast. % abrkadabra % almkarika % hargosaik % yes % % find positions on which a given letter occurs in a text and % print the text without this letter: test2 :- insert_nth_4(N, Txt, 0'a, "abrakadabra"), format('~d -- ~s\n', [N,Txt]), fail. test2. % | ?- test2. % 1 -- brakadabra % 4 -- abrkadabra % 6 -- abrakdabra % 8 -- abrakadbra % 11 -- abrakadabr % yes % insert a given letter into each even position of a text: test3 :- insert_nth_3(N, "krumpli", 0'a, Txt), N mod 2 =:= 0, format('~d -- ~s\n', [N,Txt]), fail. test3. % | ?- test3. % 2 -- karumpli % 4 -- kruampli % 6 -- krumpali % 8 -- krumplia % yes % Home Exercise 1.1: % ================== % Write a Prolog predicate replace_nth/5, according to the following % specification: % replace_nth(N, L0, E0, L, E): the Nth element of L0 is E0, % replacing the Nth element of L0 by E gives L. % In other words: the Nth element of L0 is E0, % the Nth element of L is E, all other elements of L0 and L are the same. % % :- mode replace_nth(+, ?, ?, ?, ?). % | ?- replace_nth(3, [a,b,c,d], E, L, 12). % E = c, % L = [a,b,12,d] ? ; % no % | ?- replace_nth(2, L0, a, L, b). % L = [_A,b|_B], % L0 = [_A,a|_B] ? ; % no % Example 2: Key-value maps % ========================= % --------------------------------------------------------------------------- % key_map_value(Key, Map, Value): Map associates Value with the key Key. % Map is a list of Key-Value pairs, where Keys are unique. % cf. the find_key Erlang function in the first practice session. % :- mode key_map_value_1(?, +, ?). key_map_value_1(Key, [Key-Value|_], Value). key_map_value_1(Key, [_|Map], Value) :- key_map_value_1(Key, Map, Value). % :- mode key_map_value_2(?, +, ?). key_map_value_2(Key, [K1-V1|Map], Value) :- ( Key = K1, Value = V1 ; key_map_value_2(Key, Map, Value) ). % :- mode key_map_value_3(?, +, ?). key_map_value_3(Key, Map, Value) :- member(Key-Value, Map). % from library(lists) % Versions 1, 2, and 3 are equivalent. % They make no use of the uniqueness of the keys. % :- mode key_map_value_4(+, +, ?). key_map_value_4(Key, [K1-V1|Map], Value) :- ( Key = K1 -> Value = V1 ; key_map_value_4(Key, Map, Value) ). % Version 4 is usable only when the Key argument is instantiated. It stops % scanning the list as soon as the given Key is found. % :- mode key_map_value_5(?, +, ?). key_map_value_5(Key, [K1-V1|Map], Value) :- ( Key = K1, Value = V1 -> true ; key_map_value_5(Key, Map, Value) ). % :- mode key_map_value_6(?, +, ?). key_map_value_6(Key, Map, Value) :- ( member(Key-Value, Map) -> true ). % :- mode key_map_value_7(+, +, ?). key_map_value_7(Key, Map, Value) :- memberchk(Key-Value, Map). % Example 3: Splitting a list % =========================== % --------------------------------------------------------------------------- % split_list(N, L, L1, L2): L can be split to L1 and L2 where the length of % L1 is N. % mode split_list_1(+, ?, ?, ?). split_list_1(0, L, [], L). split_list_1(N, [X|L], [X|L1], L2) :- N > 0, N1 is N-1, split_list_1(N1, L, L1, L2). % mode split_list_2(+, ?, ?, ?). split_list_2(N, L, L1, L2) :- ( N =:= 0 -> L1 = [], L2 = L ; N > 0, N1 is N-1, L = [X|RL], L1 = [X|RL1], split_list_2(N1, RL, RL1, L2) ). % Home Exercise 1.2 % ================= % % In the database of text/1 find strings with at least 5 characters % and print the first 5 characters and the rest separated by a space. % Try to be as efficient as in test1_fast. % mode split_list_3(?, +, ?, ?). % approx. split_list_3(N, L, L1, L2) :- append(L1, L2, L), length(L1, N). % mode split_list_4(+, +, ?, ?). % approx. split_list_4(N, L, L1, L2) :- length(L1, N), append(L1, L2, L).