Prolog - Why does my definition for append_list not return the combined list? - prolog

% appends an element to the beginning of a list.
append_element(X, T, [X|T]).
% append a list to another list to create a combined list,
% by breaking the first list apart, and using append_element.
append_list([], L, L).
append_list([H|T], L, NewList) :-
append_element(H, L, NL),
append_list(T, NL, NL).
When I try to run append_list,
?- append_list([1,2], [3, 4, 5], NL).
I get back false. Instead of
NL = [2, 1, 3, 4, 5].
Why?

Related

Predicate concat in Prolog

I'm trying to write a predicate concat/3 with header concat(whole, part1, part2) that succeeds if part1 and part2 are two not-empty subsequences which when concatenated form the sequence whole. For example concat(A, [12, a, z],[1, 2, 3, 4]) answers with A = [12, a, z, 1, 2, 3, 4]. I've looked at append/3, but when I change it putting the whole as the first parameter it fails.
That is the modification I have done:
append(L, [], L).
append([H|R], [H|T], L) :-
append(R, T, L).

Create a list of adjacencies by adjacency matrix

I need to write a program that will create a list of adjacencies based on the representation of the graph, given in the form of an adjacency matrix.
Examples
input - a list with lists of elements
[[0,1,1],[1,0,1],[1,1,0]].
output
[[0,2,3],[1,0,3],[1,2,0]]
I've tried this one:
indexof(Index, Item, List):-
nth1(Index, List, Item).
replace(I, L, E, K) :-
nth1(I, L, _, R),
nth1(I, K, E, R).
f([], []).
f([H|Tail], [Z|RezTail]):-
member(E,H),
E =:= 1,
indexof(X, E, H),
replace(X, H, X, Z),
f(Tail, RezTail).
Input - f([[0,1,1],[1,0,1],[1,1,0]], Z).
Output - Z = [[0, 2, 1], [1, 0, 1], [1, 1, 0]]
As you can see the problem is that after finding the first " 1 " the program goes into recursion and skips further items in the list. Is there any option how to avoid this?
How about
fh([], [], _).
fh([0|T1], [0|T2], I) :-
Ip is I+1,
fh(T1, T2,Ip).
fh([_|T1], [I|T2], I) :-
Ip is I+1,
fh(T1, T2, Ip).
f([], []).
f([H1|T1], [H2|T2]) :-
fh(H1, H2, 1),
f(T1, T2).
so:
?- f([[0,1,1],[1,0,1],[1,1,0]],X).
evaluates to:
X = [[0, 2, 3], [1, 0, 3], [1, 2, 0]]

prolog implement custom flatten

Hello I have a list of list in prolog and I want to flatten them. I've made a preidacate that flatten lists as I wanted but I have this case:
[[2,2,3],[3,2]] to be flattened like this: [2,2,3,0,3,2]
i.e., I want to add a 0 to the new list if the last element of the previous list is the same as the first element of the next list. Can you help me?
here is my work so far:
myflat([],[]) :- !.
myflat([H|T],Z) :- myflat(H,K), myflat(T,L), append(K,L,Z),!.
myflat(H,[H]) :- not(H = [K]).
but I cannot think how to check the equality of elements stated above
Not perfect but works:
myflat([[A,B|List]|ListOfLists], [A|Output]) :-
myflat([[B|List]|ListOfLists], Output).
myflat([[A],[A|List]|ListOfLists], [A,0|Output]) :-
myflat([[A|List]|ListOfLists], Output).
myflat([[A],[B|List]|ListOfLists], [A|Output]) :-
A =\= B,
myflat([[B|List]|ListOfLists], Output).
myflat([[A]], [A]).
Sample input/output:
?- myflat([[1,2,1],[1,2],[2,1]], X).
X = [1, 2, 1, 0, 1, 2, 0, 2, 1] .
?- myflat([[2,2,3],[3,2]],X).
X = [2, 2, 3, 0, 3, 2] ;
false.

Create a newlist with elements of the sublists by my List

I have this list :
C = [[1,0],[2,3],[1,2],[1,3]]
I'll like find if the number 1 included in a sublist inside my list in position [1,_ ] and i like to save to a list Newlist the number of X ..... [1,X].
I will give an example... i have the list C and i am searching for sublist which first element it's 1 and give me the Newlist.
The Newlist must be : Newlist=[0,2,3]
It had the second element of the sublists who has the number 1 at the first element.
If you use SWI-Prolog with module lambda.pl, (you can find it at http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl) you can write
:- use_module(library(lambda)).
my_filter(V, L, R) :-
foldl(V+\X^Y^Z^(X = [V,W]
-> append(Y, [W], Z)
; Z = Y),
L, [], R).
nth0/3 allows to access list' elements by index:
?- C = [[1,0],[2,3],[1,2],[1,3]], findall(P, nth0(P, C, [1,_]), NewList).
C = [[1, 0], [2, 3], [1, 2], [1, 3]],
NewList = [0, 2, 3].
edit I'm sorry I didn't read the question right. nth0 is misleading. Could be instead
findall(E, member([1,E], C), NewList)
You need a "filter". This is what it could look like:
filter_1_at_pos_1([], []). % The new list is empty when the input list is empty
filter_1_at_pos_1([[1,X]|Sublist], [X|Xs]) :- % The first element is 1 so the
% second element belongs to the
% new list
!, filter_1_at_pos_1(Sublist, Xs). % filter the remainder of the list
filter_1_at_pos_1([[N,_]|Sublist], Xs) :-
N \== 1, % The first element is not 1, ignore the second element
!, filter_1_at_pos_1(Sublist, Xs).
As #mbratch suggested, just define the solution for one element of the input list for each possible condition, in this case 1) empty list 2) first element is 1 and 3) first element is not 1.
?- C = [[1,0],[2,3],[1,2],[1,3]], filter_1_at_pos_1(C, NewList).
C = [[1, 0], [2, 3], [1, 2], [1, 3]],
NewList = [0, 2, 3].
The cuts make the predicate deterministic. The cut in the last clause is not necessary.

Find repeating sublists in list using Prolog

I want to write a prolog predicate with the following output:
?- all_match([1,2,3,2,3,1,2],L).
L = [[], [1], [1, 2], [2], [2, 3], [3]].
?- all_match([1,1,1,2],L).
L = [[], [1], [1, 1]].
The purpose is to find the sublists that repeat more than once.
So far I found the solution to find all sublists in a list-
subSet(_, []).
subSet(L, [S|T]) :- append(_, L2,L), append([S|T], _, L2).
But I can't figure out how to repeat the search for every element.
Thanks in advance.
This code is a little different from your requirements, in that all_match/2 will omit the empty sequence and fail if there where no repeated subsequences in the input.
repeated(List, Sublist) :-
% For all prefixes, suffixes:
append(Sublist, Tail, List), Sublist \= [],
% For all suffixes of the former suffixes:
append(_, TailTail, Tail),
% Is the head of the latter suffix equal to the head of the input?
append(Sublist, _, TailTail).
repeated([_|List], Sublist) :-
% Strip leading character and continue
repeated(List, Sublist).
all_match(List, Lists) :-
% Aggregate all repeated sequences or fail if there weren't any.
setof(L, repeated(List, L), Lists).
A sketch of the idea of the first clause of repeated/2:
|----------------List------------------| repeated(List, Sublist)
|--Sublist--|------------Tail----------| append(Sublist, Tail, List)
|--Sublist--| |-----TailTail-----| append(_, TailTail, Tail)
|--Sublist--| |--Sublist--| | append(Sublist, _, TailTail)
Result:
?- all_match([1,2,3,2,3,1,2],L).
L = [[1], [1, 2], [2], [2, 3], [3]].
Update to allow overlapping sequences:
repeated([H|List], Sublist) :-
append(Sublist, _, [H|List]), Sublist \= [],
append(_, Tail, List),
append(Sublist, _, Tail).
repeated([_|List], Sublist) :-
repeated(List, Sublist).
I like Kay's answer (+1). Here a variation on thema
all_match(L, M) :-
take(L, M, R),
take(R, M, _).
take(L, [A|B], R) :- % use [A|B] to remove empties
append(_, T, L),
append([A|B], R, T).
yields
?- setof(L,all_match([1,2,3,2,3,1,2],L),R).
R = [[1], [1, 2], [2], [2, 3], [3]].

Resources