Related
I am pretty new to Prolog, actually 4 days into it and I came across an exercise that states :
Given a list of N lists with N size each implement a predicate called reshape(X,Y)
so that it :
Collects the first elements of all lists into a list.
Collects the second elements of all lists lists into a list.
...
Collects the N elements of all lists into a list.
Collects all lists mentioned above into a new list.
An example would be :
reshape([[1,2,3],[4,5,6],[7,8,9]],X)
X = [[1,4,7],[2,5,8],[3,6,9]]
So here is my implementation :
% Insert at the end of a list
insert([],X,[X]).
insert([H|T1],X,[H|T2]) :- insert(T1,X,T2).
% Length of list
len([],L,L).
len([_|T],L,X) :-
L1 is L + 1,
len(T,L1,X).
len(L,X) :- len(L,0,X).
% Create a list of N empty lists
init_list(L,0,L) :- !.
init_list(L,N,X) :-
N1 is N-1,
insert(L,[],Y),
init_list(Y,N1,X).
init_list(N,X) :- init_list([],N,X).
% Assign each element of a list to the corresponding list.
assign([],[],[]).
assign([H1|T1],[H2|T2],[Y|T3]) :-
insert(H2,H1,Y),
assign(T1,T2,T3).
% Reshape :
reshape([],L,L).
reshape([H1|T1],X,Result):-
assign(H1,X,Y),
reshape(T1,Y,Result).
reshape(Input,Result) :-
len(Input,N),
init_list(N,X),
reshape(Input,X,Result).
So the basic idea is that I start by creating a list of N empty lists and then for each list say L of the input I assign/add each element of L to the corresponding list.
Now I would appreciate some input as I already said I am new to Prolog and can't even tell what the time complexity of my predicate is.The only thing I know for a fact is that it works.
Howerever is there a better way I can implement it?
What's the time complexity of my implementation ? It seems like polynomial time but I can't really tell.
Thanks in advance.
You can code an O(N) algorithm that just goes through each element once:
reshape([[]|Tail], []):-
maplist(=([]), Tail).
reshape(Input, [Result|RTail]):-
reshape(Input, LTail, Result),
reshape(LTail, RTail).
reshape([], [], []).
reshape([[Item|Tail]|LTail], [Tail|MTail], [Item|RTail]):-
reshape(LTail, MTail, RTail).
reshape/3 gets the list with every first element of the list of lists. Then reshape/2 builds all such lists recursively.
Test case:
?- reshape([[1,2,3],[4,5,6],[7,8,9]],X).
X = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] ;
false.
I want to create a predicate shift(List1,List2) where List2 is List1 shifted rotationally by one element to the left.
Example:
?- shift([1,2,3,4],L1), shift(L1,L2), shift(L2,L3).
L1 = [2, 3, 4, 1],
L2 = [3, 4, 1, 2],
L3 = [4, 1, 2, 3].
I created the predicate
conc([],L,L).
conc([X|T],L2,[X|T1]) :-
conc(T,L2,T1).
shift([H|T],L2) :-
conc(T,H,L2).
However, it's wrong & I don't understand why... It works only if the H is surrounded by [H].
shift([H|T],L2) :-
conc(T,[H],L2).
The predicate without the [ ] only works with 1 shift & it outputs the following:
?- shift([1,2,3,4],L1).
L1 = [2, 3, 4|1].
Obviously, there's a basic concept I'm confused with, but I can't seem to pin-point what's wrong alone. I'm new at Prolog, so any help would be appreciated.
It works only if the H is surrounded by [H]
As I noted before, conc/3 is really the standard predicate append/3 which takes in two list and creates a third list.
append/3 says:
append(?List1, ?List2, ?List1AndList2)
List1AndList2 is the concatenation of List1 and List2
A single term is not a list, e.g. 1 is not a list, but [1] is a list.
A list starts with [ and ends with ].
This is the empty list: []
A list can have one item: [a]
or more than one item: [a,b] and so on. Notice how they always have square brackets.
When you use conc/3 or append/3 all three values have to be list, so even if you want to concatenate or append a single item you have to convert it to a list first by surrounding it with [] to turn it into a list. So the single item 1 is converted to a list as [1].
the Nested List can exist in Scheme, but is it legal to use nested-list in SML? or we can only use simple list in SML?
and if legal,
1) how to check wether the two input list have the same list structure. algorithm the atoms in the list are not equal.
2) Whatever the deep of the input list, how to delete all the atoms in the nested-list that equals to the input value: a. should use the original list and not create a new list.
There's no problem in having nested lists in Standard ML. For an example:
val foo = [ [1, 2, 3], [4, 5], [6] ]
is an example of an int list list, i.e., a list of lists of integers.
As for your additional questions.
1
If by same structure you mean whether the sublists contain the same number of elements, i.e, you want
val bar = [ [34, 4, 6], [2, 78], [22] ]
val baz = [ [1], [4, 6, 2], [3, 6] ]
val cmp_foo_bar = structureEq (foo, bar) (* gives true, since the lengths of the sublists match up *)
val cmp_foo_baz = structureEq (foo, baz) (* gives false, since they don't *)
Then you can simply make a recursive function on the lists, that compares the length of each sublist in turn.
Note, if the lists are nested more than once, you'll need a function for each level. (i.e., one for 'a list lists, one for 'a list list lists, etc.
2
You cannot make a function that "however deep the input list" does something to the elements in the list. The type system will not let you do this. This is similar to how you cannot make the following list:
val illegal_list = [ [1, 2], [ [1, 4], [2, 3] ] ]
This is due to a list only being allowed to contain one type of elements, so if you have an 'a list list, each element in the list must be an 'a list. You cannot have 'as directly.
You'll have to settle on how nested the lists are, and make a function specific to that depth.
There is no problem with nesting lists in SML, e.g. [[1, 2], [3, 4]] works just fine.
However, I suspect you actually mean something more general, namely the ability to nest "lists" in heterogeneous ways: [[1, [3]], 2]. This is not legal as such in SML. However, this is because such a thing is not really a list, it is a tree.
You can define trees easily as well, but you need a more general type definition than the one for list:
datatype 'a tree = L of 'a | T of 'a tree list
Then T[T[L 1, T[L 3]], L 2] is a representation of the "list" above. A function for computing the depth (or height) of such a tree looks like
fun depth (L _) = 0
| depth (T ts) = 1 + max (List.map depth ts)
where max needs to be defined in the obvious manner.
Hi all im new to programming and im doing a problem for learning and enjoyment. Im a bit stuck at this point.. The problem is from Introduction to Programming using Sml 5.9
I want to split a list of [x1, x2, x3, ... ,xn] = ([x1, x3,....], [x2, x4,...])
This is what I have made so far:
fun split [] = []
| split (x1::x2::x3::x4::xs) = ([x1, x3], [x2, x4])::split xs
val test1split = split [1, 1, 2, 3];
From this I get:
[([1, 2], [1, 3])].... (I want a tuple with splitting list and not this obviously)
If there are more than 4 elements then the function doesn't work. Maybe I need a helper function to sort even and odd elements in a list first? I hope someone can help me with tracking my mind in the correct direction, until then I keep trying.
fun split [] = ([], [])
| split [x] = ([x], [])
| split (x1::x2::xs) =
let
val (ys, zs) = split xs
in
((x1::ys), (x2::zs))
end;
val test1split = split [1, 1, 2, 3, 5, 6] = ([1, 2, 5], [1, 3, 6])
val test2split = split [8, 7, 6, 5, 4, 3] = ([8, 6, 4], [7, 5, 3])
val test3split = split [8, 7] = ([8], [7])
val test4split = split [8] = ([8], [])
Solved it... Not completely sure how lol, need alot more practice to master it. Couldn't have done it without the pointers... Thx alot for the help Nick Barnes.
I'll try not to give too much away, but here are some tips:
You need two base cases - one for [], one for [x].
Your general case only needs to deal with two elements, not four (putting one in the first list, and one in the second)
At the moment, you've got split returning a list, rather than a tuple. The result of your first base case should be ([],[]).
In the general case, the recursive split xs will return a tuple (ys,zs). You need to extract these values, and build the resulting tuple in terms of ys, zs, x1 and x2.
(Edit) A couple of points on your revised solution:
You only need to deal with two elements at a time - the general case should be split x1::x2::xs
split [x,y] is handled by the general case - no need for another base case.
You're missing the recursive call! Elements are ending up in both lists because you're putting xs directly into both halves of your output - you need to split it first. Start with
let (ys, zs) = split xs in ...
I am creating a sequence as a [Integer] in Haskell. The mathematical definition of the sequence is such that it repeats for some positive integers. In such a situation, I want to terminate the sequence and determine the length of the finite list.
My attempt at a solution is to first create an infinite list from the mathematical sequence. Then I want to filter the list for all elements until the first element repeats. The result should not include the repeating head of the list.
I have two questions/concerns here:
1) How do I match the head of the list to an element later in the list?
2) Is this an efficient method of solving my problem? (I will add more details about the exact sequence later if needed. For now I am looking for general comments.)
The algorithm that you described can simply be implemented like this:
findPeriodic :: Eq a => [a] -> [a]
findPeriodic [] = error "there are no periodic sequences in the empty list"
findPeriodic (x : xs) = x : takeWhile (/= x) xs
It does exactly what you describe: it takes the head of some list, and collects the part of the list up until that head element appears again in the list. So, for example:
list = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, ...]
findPeriodic list => [1, 2, 3, 4, 5]
The first element might never repeat in a sequence like 1,2,3,4,5,3,4,5,3,4, ... , where (a !! i) == (a !! j) ==> (a !! (i+1)) == (a !! (j+1)) (like you added in a comment, which is different from what you've asked for in the question).
This is known as cycle detection and was recently discussed e.g. here.