I want to create a function that given two lists (of floats, but could be anything) gives a list with all the combinations of taking two elements from the first list and putting it in the last and all the combinations of the former putting one of the elements from the last (now with more elements) and putting it back on the first.
For every movement it also gives the greatest value that moved (in the second movement only one moves, that is the value). It should all end when the first list is empty (there would be no second movement).
I can't expect anyone to understand that so, examples:
next [1,2,3,4] [] -> [(([1,2], [3,4], 4), ([1,2,3],[4],3)), (([1,2], [3,4], 4), ([1,2,4],[3],4)), (([1,3], [2,4], 4), ([1,2,3],[4],2)), (([1,3], [2,4], 4), ([1,3,4],[2],4)).....
next [1,2] [3,4] -> [(([], [1,2,3,4],2),)], ())
What I have so far:
module Test where
next :: [Float] -> [Float] -> [(([Float],[Float], Float),([Float],[Float], Float))]
next [] _ = []
next (a:b:[]) s
|a>b = [([],a:b:s, a)]
|otherwise = [([],a:b:s, b)]
next d s = [([x,z], i:j:s, j), b | i <- d, j <- d, i < j, x <- d, z <- d, x < z, z /= i, z /= j, x /= z, x /= i, x /= j, b <- (back [x,z] i:j:s)]
where
back d s = [(i:d, [x,z], i) | i <- s, x <- s, z <- s, x < z, z /= i, x /= z]
Compiling that code gives back an error on the first comprehension list at the | character. I'd kind of understand an error in the back function. Why won't that compile?
The comprehension syntax is
[ <expression> | ... ]
For <expression> you have ([x,z], i:j:s, j), b which is syntactically wrong. Did you mean ([x,z], i:j:s, b)?
Related
I am new to Prolog, and have been having some problems figuring out the syntax of the language. I want to create a method which takes 3 arguements of (X,Y,Z).
X is a list of all of the numbers in between Y and Z. I know that the base case should only return Y since Y+1 = Z. Then the recursive should keep incrementing Y until it is equal to Z while putting the numbers into a list.
Since I am new, I wanted to avoid using built-in libraries and predicates.
This is what I am working off of right now.
range(X,Y,Z):-
%If Y + 1 == Z, X is just Y
range(X,Y,Z) :-
Y =< Z,
D is Y+1,
range(X,D,Z).
%use recursion to go from Y to Z, then collect it in X
I realized a bit later that my expected results should look like this:
range(X,1,10) should return [1,2,3,4,5,6,7,8]
Here a simple solution:
range([],A,B):-
A > B.
range([A|T],A,B):-
A =< B,
A1 is A + 1,
range(T,A1,B).
First clause: if A is greater than B, the resulting list is empty ([]). Second clause: if A is less or equal than B, increment A by 1 and store the result in A1, unify the head of the list with A (see [A|T]), and recursively call the predicate with the remaining part of the list (T), A1, and B.
?- range(L,1,10).
L = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
false
?- range(L,10,1).
L = []
false
There are multiple use cases for something like this:
testing that an integer lies within a given range, and
generating a specified sequence of integers.
This covers both ascending ranges and descending ranges, so
range(1,5,X) will, on backtracking, unify X with 1,2,3,4,5.
range(5,1,X) will, on backtracking, unify X with 5,4,3,2,1.
range(1,5,9) tests whether or not 9 lies within the ascending range 1-5 (it does not).
range(5,1,3) tests whether or not 3 lies within the descending range 5-1 (it does).
% ==========================================================
% range/3: Tests that Z lies with the range X-Y,
% or generates the sequence of integers X-Y.
% Both ascending ranges (1-5) and descending ranges (5-1)
% are supported. X and Y must both be integers. Z must be
% either an integer or an unbound variable.
% ==========================================================
range( X , Y , Z ) :-
integer(X),
integer(Y),
range0(X,Y,Z).
% ==========================================================
% Private (helper) predicates)
% ==========================================================
% --------------------------
% range0/3: Traffic director
% --------------------------
range0( X , Y , Z ) :- integer(Z), !, range1(X,Y,Z) .
range0( X , Y , Z ) :- var(Z), !, range2(X,Y,Z) .
% ----------------------------------
% range1/3: Z is bound to an integer
% ----------------------------------
range1(Lo,Hi,N) :- N >= Lo, N =< Hi, !.
range1(Hi,Lo,N) :- N >= Lo, N =< Hi, !.
% --------------------------------------------
% range2/3: Z is unbound. Generate a sequence.
% --------------------------------------------
range2(X,Y,N) :- X =< Y, !, range_asc(Lo,Hi,N) .
range2(X,Y,N) :- X > Y, !, range_dsc(Lo,Hi,N) .
% --------------------------------------------------------
% range_asc/3: Generates an ascending sequence of integers
% --------------------------------------------------------
range_asc( Hi , Hi , Hi ) :- !.
range_asc( Lo , _ , Lo ) .
range_asc( Lo , Hi , N ) :- L1 is Lo+1, range_asc(L1,Hi,N) .
% --------------------------------------------------------
% range_dsc/3: Generates a descending sequence of integers
% --------------------------------------------------------
range_dsc( Lo , Lo , Lo ) :- !.
range_dsc( Hi , _ , Hi ) .
range_dsc( Hi , Lo , N ) :- H1 is Hi-1, range_dsc(H1,Lo,N) .
I am trying to compare and retrieve values from corresponding lists. My Predicate is correspond_elements(V1, Xs, V2, Ys), where I expect the following behavior:
?- correspond_elements(a, [a,b,b,a], X, [1,2,3,4]).
X = 1;
X = 4.
Where V1 is checked in the first list Xs, and the corresponding values in Ys are given to V2 to return. So far I have this:
% checks if the argument is a list
is_list([]).
is_list([_|T]) :-
is_list(T).
% predicate
correspond_elements(V1, [X|Xs], V2, [Y|Ys]) :-
is_list([X|Xs]),
is_list([Y|Ys]),
( V1 == X ->
V2 is Y
;
correspond_elements(V1, Xs, V2, Ys)
).
Which only gets the first value:
?- correspond_elements(a, [a,b,b,a], X, [1,2,3,4]).
X = 1.
I know that once the -> clause becomes true, then anything after the ; is not executed. It is clear that my code will only get the first answer it finds for X and stop, but I am unsure of how to keep recursing through the list and return all the possible answers for X, even after the first answer has been found.
As you have found out yourself, the if-then-else of Prolog A -> B; C will check the condition A, and if true it will execute B (and not C). Otherwise it will execute C (and not B).
You however want to execute C as an additional option in case A is true. This can be done, by transforming:
foo(Some,Parameters) :-
A
-> B
; C.
into:
foo(Some,Parameters) :-
A,
B.
foo(Some,Parameters) :-
C.
Since now A works as a guard for B, but regardless whether A succeeds or fails, Prolog will backtrack and execute the second foo/2 clause.
If we remove the is_list(..) predicates (which are a bit verbose in my opinion), we can produce the predicate:
correspond_elements(X, [X|_], Y, [Y|_]).
correspond_elements(V1, [_|Xs], V2, [_|Ys]) :-
correspond_elements(V1, Xs, V2, Ys).
We do not have to write the condition V1 == X here, since we used unification in the head for this. Because we use unification, it is V1 = X (one equation sign), so that means we can use the predicate in a more multi-directional way.
Querying the elements in the second list X:
?- correspond_elements(a, [a,b,b,a], X, [1,2,3,4]).
X = 1 ;
X = 4 ;
false.
Querying all tuples A and X of both lists (some sort of "zip"):
?- correspond_elements(A, [a,b,b,a], X, [1,2,3,4]).
A = a,
X = 1 ;
A = b,
X = 2 ;
A = b,
X = 3 ;
A = a,
X = 4 ;
false.
Obtain the elements in the first list:
?- correspond_elements(A, [a,b,b,a], 1, [1,2,3,4]).
A = a ;
false.
Generate a list such that 1 is in the list:
?- correspond_elements(A, [a,b,b,a], 1, L).
A = a,
L = [1|_G1285] ;
A = b,
L = [_G1284, 1|_G1288] ;
A = b,
L = [_G1284, _G1287, 1|_G1291] ;
A = a,
L = [_G1284, _G1287, _G1290, 1|_G1294] .
I have a type called image which holds a set of tuples, which are coordinates. I am trying to make a list comprehension where I can print out max and min of the list of either the x or y coordinates.
example :: Image -> (Int,Int)
example e = [ (j,k) | (x,y) <- e, j <- (maximum x), k <- (minimum y)]
I want to print (max x, min x) as a starter.
I keep getting an error, could someone please show me the correct way of doing this.
edit: Thanks to the answer, I have changed the second line to:
example e = [ (j,k) | (x,y) <- e, let j = maximum x, let k = minimum y]
however get this error:
Couldn't match expected type ‘[a]’ with actual type ‘Int’
Relevant bindings include j :: a (bound at image.hs:69:39)
In the first argument of ‘maximum’, namely ‘x’
In the expression: maximum x
for both j and k
Updated answer:
Here are the definitions of Image and Point:
type Image = [Point]
type Point = (Int,Int)
And how example should be written:
example :: Image -> (Int,Int)
example e = (maximum xs, minimum xs)
where xs = map fst e -- xs = list of the x coordinates
ys = map snd e -- ys = list of the y coordinates
Original answer:
Use let:
example e = [ (j,k) | (x,y) <- e, let j = maximum x, let k = minimum y]
Well, I have a list, say [a,b,c,c,d], and I want to generate a list [[a,1],[b,1],[c,2],[d,1]]. But I'm having trouble with generating my list. I can count how many times the element occur but not add it into a list:
% count how much the element occurs in the list.
count([], _, 0).
count([A|Tail], A, K) :-
count(Tail, A, K1),
K is K1 + 1.
count([_|Tail], X, K) :-
count(Tail, X, K1),
K is K1 + 0.
% Give back a list with each element and how many times is occur
count_list(L, [], _).
count_list(L, [A|Tail], Out) :-
count(L, A, K),
write(K),
count_list(L, Tail, [K|Out]).
I'm trying to learn Prolog but having some difficulties... Some help will be much appreciated... Thanks in advance!
Let me first refer to a related question "How to count number of element occurrences in a list in Prolog" and to my answer in particular.
In said answer I presented a logically-pure monotone implementation of a predicate named list_counts/2, which basically does what you want. Consider the following query:
?- list_counts([a,b,c,c,d], Xs).
Xs = [a-1,b-1,c-2,d-1]. % succeeds deterministically
?- list_counts([a,b,a,d,a], Xs). % 'a' is spread over the list
Xs = [a-3,b-1,d-1]. % succeeds deterministically
Note that the implementation is monotone and gives logically sound answers even for very general queries like the following one:
?- Xs = [_,_,_,_],list_counts(Xs,[a-N,b-M]).
Xs = [a,a,a,b], N = 3, M = 1 ;
Xs = [a,a,b,a], N = 3, M = 1 ;
Xs = [a,a,b,b], N = M, M = 2 ;
Xs = [a,b,a,a], N = 3, M = 1 ;
Xs = [a,b,a,b], N = M, M = 2 ;
Xs = [a,b,b,a], N = M, M = 2 ;
Xs = [a,b,b,b], N = 1, M = 3 ;
false.
I cannot follow your logic. The easy way would be to use library(aggregate), but here is a recursive definition
count_list([], []).
count_list([H|T], R) :-
count_list(T, C),
update(H, C, R).
update(H, [], [[H,1]]).
update(H, [[H,N]|T], [[H,M]|T]) :- !, M is N+1.
update(H, [S|T], [S|U]) :- update(H, T, U).
the quirk: it build the result in reverse order. Your code, since it uses an accumulator, would give the chance to build in direct order....
Create an infinite list pairs :: [(Integer, Integer)] containing pairs of the form (m,n),
where each of m and n is a member of [0 ..]. An additional requirement is that if (m,n)
is a legit member of the list, then (elem (m,n) pairs) should return True in finite time.
An implementation of pairs that violates this requirement is considered a non- solution.
****Fresh edit Thank you for the comments, Lets see if I can make some progress****
pairs :: [(Integer, Integer)]
pairs = [(m,n) | t <- [0..], m <- [0..], n <-[0..], m+n == t]
Something like this? I just don't know where it's going to return True in finite time.
I feel the way the question is worded elem doesn't have to be part of my answer. Just if you call (elem (m,n) pairs) it should return true. Sound right?
Ignoring the helper method, the list comprehension you have will list out all pairs but the order of elements is a problem. You'll have a infinitely many pairs like (0, m) which are followed by infinitely many pairs like (1, m). Of course elem will forever iterate all the (0, m) pairs never reaching (1, m) or (2, m) etc.
I'm not sure why you have the helper method -- with it, you are only building a list of pairs like [(0,0), (1,1), (2,2), ...] because you've filtered on m = n. Was that part of the requirements?
Like #hammar suggested, start with 0 = m + n and list out the pairs (m, n). Then list pairs (m, n) where 1 = m + n. Then your list will look like [(0,0), (0,1), (1,0), (0,2), (1,1), (2,0), ...].
The helper function ensures that pairs is a list of the form [ (0,0) , (1,1) , (2,2) ... ].
So elem ( m , n ) pairs can be implemented as:
elem (m , n) _ | m == n = True
| otherwise = False
This is a constant time implementation.
I first posted
Prelude> let pairs = [(m, n) | t <- [0..]
, let m = head $ take 1 $ drop t [0..]
, let n = head $ take 1 $ drop (t + 1) [0..]]
Which, I believed answered the three conditions set by the professor. But hammar pointed out that if I chose this list as an answer, that is, the list of pairs of the form (t, t+1), then I might as well choose the list
repeat [(0,0)]
Well, both of these do seem to answer the professor's question, considering there seems to be no mention of the list having to contain all combinations of [0..] and [0..].
That aside, hammer helped me see how you can list all combinations, facilitating the evaluation of elem in finite time by building the infinite list from finite lists. Here are two other finite lists - less succinct than Hammar's suggestion of the diagonals - that seem to build all combinations of [0..] and [0..]:
edges = concat [concat [[(m,n),(n,m)] | let m = t, n <- take m [0..]] ++ [(t,t)]
| t <- [0..]]
*Main> take 9 edges
[(0,0),(1,0),(0,1),(1,1),(2,0),(0,2),(2,1),(1,2),(2,2)]
which construct the edges (t, 0..t) (0..t, t), and
oddSpirals size = concat [spiral m size' | m <- n] where
size' = if size < 3 then 3 else if even size then size - 1 else size
n = map (\y -> (fst y * size' + div size' 2, snd y * size' + div size' 2))
[(x, t-x) | let size' = 5, t <- [0..], x <- [0..t]]
spiral seed size = spiral' (size - 1) "-" 1 [seed]
spiral' limit op count result
| count == limit =
let op' = if op == "-" then (-) else (+)
m = foldl (\a b -> a ++ [(op' (fst $ last a) b, snd $ last a)]) result (replicate count 1)
nextOp = if op == "-" then "+" else "-"
nextOp' = if op == "-" then (+) else (-)
n = foldl (\a b -> a ++ [(fst $ last a, nextOp' (snd $ last a) b)]) m (replicate count 1)
n' = foldl (\a b -> a ++ [(nextOp' (fst $ last a) b, snd $ last a)]) n (replicate count 1)
in n'
| otherwise =
let op' = if op == "-" then (-) else (+)
m = foldl (\a b -> a ++ [(op' (fst $ last a) b, snd $ last a)]) result (replicate count 1)
nextOp = if op == "-" then "+" else "-"
nextOp' = if op == "-" then (+) else (-)
n = foldl (\a b -> a ++ [(fst $ last a, nextOp' (snd $ last a) b)]) m (replicate count 1)
in spiral' limit nextOp (count + 1) n
*Main> take 9 $ oddSpirals 3
[(1,1),(0,1),(0,2),(1,2),(2,2),(2,1),(2,0),(1,0),(0,0)]
which build clockwise spirals of length 'size' squared, superimposed on hammar's diagonals algorithm.
I believe the solution to your task is:
pairs = [(x,y) | u <- [0..], x <- [0..u], y <-[0..u] , u == x+y]