Conditions in a list comprehension , finding possibilities - haskell

there are 3 keys and 3 locks, and i have to write a code to show the possible tries. Rules are:
Second key never can be placed before the first one.
No keys can be tried more than once.
First key cannot be placed as the first one.
and you can't place them in the order 3 - 2 - 1
and as a tip, this is given: [(x,y,z) | x <- [1..3], ]
I want to change this code in a way that, instead of " fst <- [3] " it says; " fst cannot be [1] "
and I also want to add that 2 cannot come before 1. I tried it with (elemIndex 2 (x,y,z)) > (elemIndex 1 (x,y,z))
but it didn't work. I would appreciate for some ideas.
d = [(x,y,z) | x <- [1..3], y <- [1..3], z <-[1..3], fst <- [3] , tail <- 1], x /= y, y /= z, x /= z]

You could use something like this:
d = [(3, y, z) | y <- [1..2], z <-[1..2], y /= z, y /= 2]
which gives
[(3,1,2)]
Explanation
First key cannot be placed as the first one.
and
Second key never can be placed before the first one.
imply that x cannot be 1 or 2, and hence must be 3. This gives
[(3, y, z) | y <- [1..2], z <-[1..2]
Since
No keys can be tried more than once.
we also have
, y != z
Finally
Second key never can be placed before the first one.
gives
, y /= 2]
In fact, with some thought, you could argue that you can just write
d = [(3, 1, 2)]

Related

Sorting a part of a list without using library functions

I want to sort the first three elements of a list, yet keep the other elements untouched. And I don't want to use any library functions because I am new to Haskell.
This is what I have so far:
{-# OPTIONS_GHC -Wincomplete-patterns #-}
sort2 (x, y) = if x > y then (y,x) else (x,y)
sort3 (x,y,z)
| x > y && y > z = (z,y,x)
| x > z && z > y = (y,z,x)
| y > x && x > z = (z,x,y)
| y > z && z > x = (x,z,y)
| z > x && x > y = (y,x,z)
| z > y && y > x = (x,y,z)
| otherwise = (0,0,0)
--sortfirst3 :: [Int] -> [Int]
sortfirst3 (x:y:z:v:xs) = sort3(x,y,z) : sortfirst3 (v:xs)
I'm trying to sort the first three elements, put them in a list, and then put the other elements in another list and then concatenate them with each other. However, this generates an error because of the type difference a tuple and a list. Is there another way I should be doing this?
You don't need to involve tuples. You can write what you wrote for tuples as patterns to match instead.
sortFirst3 [x, y] = if x > y then [y, x] else [x, y]
sortFirst3 [x, y, z]
| x >= y && y >= z = [z, y, x]
| x >= z && z >= y = [y, z, x]
| y >= x && x >= z = [z, x, y]
| y >= z && z >= x = [x, z, y]
| z >= x && x >= y = [y, x, z]
| z >= y && y >= x = [x, y, z]
sortFirst3 (x : y : z : ws) = sortFirst3 [x, y, z] ++ ws
sortFirst3 xs = xs
The last line catches what has not been matched, which are the singletons and empty lists, which remain the same when sorted. You should not have strict inequalities in your guards since elements may repeat. Also note that, in your code, even if you didn't have the type mismatch, the recursive call to sortFirst3 would be erroneous, since after sorting the first three terms, the first three of the rest would be sorted, and so on.
sortfirst3 (x:y:z:v:xs) = sort3(x,y,z) : sortfirst3 (v:xs)
This definition says, take the first 4 elements off the list, sort the first 3 into a tuple, then cons it onto the (recursive) result on the fourth element of the list with the rest of the list.
This reveals three changes to be made.
First, we only need to match the first 3 elements, not the first 4, but we should also probably deal with cases for when the list is <3 elements long. I've just made it an error, but you can use eg. sort2 instead.
sortfirst3 (x:y:z:xs) = sort3 (x,y,z) : sortfirst3 xs
sortfirst3 _ = error "Can't sort first 3 elements of list shorter than 3 elements"
Second, we intend to sort the first 3 elements ie. resulting in a 3 element list. (:) :: a -> [a] -> [a] ie. takes an element (not a list) in the first argument, what we want instead is concatentation (++) :: [a] -> [a] -> [a].
sortfirst3 (x:y:z:xs) = sort3 (x,y,z) ++ sortfirst3 xs
Third, we intend to leave the elements after the first 3 untouched, so we shouldn't actually make a recursive call on the rest of the list - otherwise we'll instead be sorting the list in 3 element chunks.
sortfirst3 (x:y:z:xs) = sort3 (x,y,z) ++ xs
This is now almost correct, but for sort3, which as you identified incorrectly returns a tuple rather than a 3-element list. kuoytfouy's answer helps with that.

Haskell List comprehensions infinite list problem

I'm trying to learn Haskell and comprehension lists but cannot find solution on this:
mylist = [x*y | x <- [1..], y <- [1..]]
After my trials the result is something like this
mylist = [1,2,3,4,5,...]
because in list comprehensions, x takes the value 1,and then y changes value repeatedly.
But my goal is to achieve a different assignment so as to have the following result:
mylist = [1,2,2,4,3,3,6.....]
I mean i want the combinations being mixed and not each one apart,because I have a serious problem to have the suitable result.
I will give a more specific example.
I want a list that will have all numbers of this form:
num = 2^x * 3^y
x and y must take all values >= 0.
My approach is the following:
powers = [2^x * 3^y | x <- [0..], y <- [0..]]
But in this way I only take powers of 3, because x is constantly 0.
I tried this one
multiples = nub (merge (<=) powers2 powers3)
powers3 = [2^x * 3^y | x <- [0..], y <- [0..]]
powers2 = [2^x * 3^y | y <- [0..], x <- [0..]]
so as to merge the different ones but again,the values 6,12,etc. are missing - the result is this:
mylist = [1,2,3,4,8,9,16,27,32,64,81...]
The code that you show,
multiples = nub (merge (<=) powers2 powers3)
powers3 = [2^x * 3^y | x <- [0..], y <- [0..]]
powers2 = [2^x * 3^y | y <- [0..], x <- [0..]]
is equivalent to
powers3 = [2^x * 3^y | x <- [0], y <- [0..]]
= [2^0 * 3^y | y <- [0..]]
= [3^y | y <- [0..]]
powers2 = [2^x * 3^y | y <- [0], x <- [0..]]
= [2^x * 3^0 | x <- [0..]]
= [2^x | x <- [0..]]
so you only produce the powers of 2 and 3, without any mixed multiples. As such, there are guaranteed to be no duplicates in the stream, and the nub was not necessary. And of course it's incomplete.
But let's look at it at another angle. It was proposed in the comments to create a 2D grid out of these numbers:
mults23_2D = [[2^x * 3^y | y <- [0..]] | x <- [0..]]
{-
1 3 9 27 81 ...
2 6 18 54 ...
4 12 36 108 ...
8 24 72 ...
16 ...
.......
-}
Now we're getting somewhere. At least now none are skipped. We just need to understand how to join them into one sorted, increasing stream of numbers. Simple concat of course won't do. We need to merge them in order. A well-known function merge does that, provided the arguments are already ordered, increasing lists.
Each row produced is already in increasing order, but there are infinitely many of them. Never fear, foldr can do it. We define
mults23 = foldr g [] [[2^x * 3^y | y <- [0..]] | x <- [0..]]
-- foldr g [] [a,b,c,...] == a `g` (b `g` (c `g` (....)))
where
g (x:xs) ys =
Here it is a little bit tricky. If we define g = merge, we'll have a run-away recursion, because each merge will want to know the head element of its "right" (second) argument stream.
To prevent that, we produce the leftmost element right away.
x : merge xs ys
And that's that.
Tool use
I needed an infinite Cartesian product function. An infinite function must take the diagonals of a table.
The pair pattern of a diagonal traversal is
0 0 – 0 1, 1 0 – 0 2, 1 1, 2 0 – 0 3, 1 2, 2 1, 3 0
I love the symmetries but the pattern is counting forward with first digit and backward with second which when expressed in an infinite function is
diag2 xs ys = [ (m,n) | i<- [1..], (m,n) <- zip (take i xs) (reverse.take i $ ys) ]
The infinite generation is just to take any amount however large to work with.
What may be important, also is taking a diagonal or triangular number for a complete set.
revt n makes a triangular number from you input. If you want 25 elements revt 25 will return 7. tri 7 will return 28 the parameter for take. revt and tri are
tri n = foldl (+) 1 [2..n]
revt n = floor (sqrt (n*2))
Making and using taket is good until you learn the first 10 or so triangular numbers.
taket n xs = take (tri $ revt n) xs
Now, with some tools in place we apply them (mostly 1) to a problem.
[ 2^a * 3^b | (a,b) <- sort.taket 25 $ diag2 [0..] [0..]]
[1,3,9,27,81,243,729, 2,6,18,54,162,486, 4,12,36,108,324, 8,24,72,216, 16,48,144, 32,96, 64]
And it’s a diagonal. The first group is 7 long, the second is 6 long, the second-to-the-last is 2 long and the last is 1 long. revt 25 is 7. tri 7 is 28 the length of the output list.

How to use list comprehension in Haskell?

I am trying to teach myself Haskell and I am doing random exercises.
I was supposed to write a code that will do this 6 = [1*1 + 3*3 + 5*5]= 35
So I had to filter out all odd numbers and then calculate the sum if I multiply every single one with itself.
sumquad n = (potenzsum(filter odd (ones n)))
where
potenzsum [x] = x*x
potenzsum [x,y] = x*x + y*y
potenzsum (x:xs) = x + potenzsum xs
ones 0 = []
ones x = [ 1 .. x]
This code works ;)
Now I am supposed to do the same thing but with list comprehension (I am allowed to use this list [1...n]
I could only think of this... Could someone help me?
power1 xs = [x*x | x <- xs]
Actually, you did half the job by [x * x | x <- xs], just replace xs by odd numbers from the previous example:
[x * x | x <- filter odd (ones 6))]
And you'll receive a list of squares: [1, 9, 25], which can be summed by function sum:
f n = sum [x * x | x <- filter odd (ones n))]
it evaluates to 35
One more note regarding list comprehension: the iterated elements can be filtered out by specifying conditions, which are called guards. Thus, the code above can be refactored into:
f n = sum [x * x | x <- [1..n], odd x]

Haskell: List comprehension predicate order

After reading about the Haskell syntax for List Comprehensions online, I got the feeling that predicates always come last. Eg:
[(x,y) | x <- [1..10000], y <- [1..100], x==2000, odd y]
But the following line accomplishes the same result:
[(x,y) | x <- [1..10000], x==2000, y <- [1..100], odd y]
Normally I would just take this as a hint that the order doesn't matter and be done with it. However this is a problem that comes from an old exam, and the answer to the problem says that while the results may be the same, the way in which they are computed may differ.
I'm assuming this is true but I can't find any information about it on the web. So my question is: How could the computations differ between the two list comprehensions and why? Are list comprehensions some form of syntactic sugar that I don't know about?
You can think of a list comprehension like
[(x,y) | x <- [1..10000], y <- [1..100], x==2000, odd y]
as corresponding to the imperative pseudo-code
for x in [1..10000]:
for y in [1..100];
if x == 2000:
if odd y:
yield (x,y)
and
[(x,y) | x <- [1..10000], x==2000, y <- [1..100], odd y]
as corresponding to
for x in [1..10000]:
if x == 2000;
for y in [1..100]:
if odd y:
yield (x,y)
Specifically, passing the list comprehension to something like mapM_ print is the same operationally as replacing yield by print in the imperative version.
Obviously, it's almost always better to "float" a guard/if out of a generator/for when possible. (The rare exception is when the generator is actually an empty list, and the guard condition is expensive to compute.)
They differ in the way of how many intermediary results/lists are generated.
You can visualize this with some trace - note that I modified this a bit to give reasonable results - also I replaced the return values by () to make it clearer:
comprehension1 = [ () | x <- [1..3], trace' 'x' x, y <- [1..3], trace' 'y' y, x==2, odd y]
comprehension2 = [ () | x <- [1..3], trace' 'x' x, x==2, y <- [1..3], trace' 'y' y, odd y]
trace' :: Show a => Char -> a -> Bool
trace' c x = trace (c : '=' : show x) True
here is the evaluation:
λ> comprehension1
x=1
y=1
y=2
y=3
x=2
y=1
[()y=2
y=3
,()x=3
y=1
y=2
y=3
]
λ> comprehension2
x=1
x=2
y=1
[()y=2
y=3
,()x=3
]
now do you notice something?
Obviously in the first example every (x,y) pair for x=1,2,3 and y=1,2,3 is generated before the filters are applied.
But in the second example the ys are only generated when x=2 - so you could say it's better/more performant

Pythagorean triple in Haskell without symmetrical solutions

I gotta do the Pythagorean triple in Haskell without symmetrical solutions. My try is:
terna :: Int -> [(Int,Int,Int)]
terna x = [(a,b,c)|a<-[1..x], b<-[1..x], c<-[1..x], (a^2)+(b^2) == (c^2)]
and I get as a result:
Main> terna 10
[(3,4,5),(4,3,5),(6,8,10),(8,6,10)]
As you can see, I´m getting symmetrical solutions like: (3,4,5) (4,3,5). I need to get rid of them but I don´t know how. Can anyone help me?
Every time you have a duplicate you have one version in which a is greater than b and one where b is greater than a. So if you want to make sure you only ever get one of them, you just need to make sure that either a is always equal to or less than b or vice versa.
One way to achieve this would be to add it as a condition to the list comprehension.
Another, more efficient way, would be to change b's generator to b <- [1..a], so it only generates values for b which are smaller or equal to a.
Speaking of efficiency: There is no need to iterate over c at all. Once you have values for a and b, you could simply calculate (a^2)+(b^2) and check whether it has a natural square root.
Don't know Haskell at all (perhaps you're learning it now?) but it seems like you could get rid of them if you could take only the ones for which a is less than or equal to b. That would get rid of the duplicates.
Try with a simple recursive generator:
http://en.wikipedia.org/wiki/Formulas_for_generating_Pythagorean_triples
(new article)
http://en.wikipedia.org/wiki/Tree_of_primitive_Pythagorean_triples
EDIT (7 May 2014)
Here I have made infinite generator that can generate primitive triplets ordered by perimeter (but can be modified to be ordered by other parameter - hypotenuses, area, ...) as long as it holds that any triplet is smaller that any generated from generator matrix according to provided compare function
import Data.List -- for mmult
merge f x [] = x
merge f [] y = y
merge f (x:xs) (y:ys)
| f x y = x : merge f xs (y:ys)
| otherwise = y : merge f (x:xs) ys
mmult :: Num a => [[a]] -> [[a]] -> [[a]]
mmult a b = [ [ sum $ zipWith (*) ar bc | bc <- (transpose b) ] | ar <- a ]
tpgen_matrix = [[[ 1,-2, 2],[ 2 ,-1, 2],[ 2,-2, 3]],
[[ 1, 2, 2],[ 2 , 1, 2],[ 2, 2, 3]],
[[-1, 2, 2],[-2 , 1, 2],[-2, 2, 3]]]
matrixsum = sum . map sum
tripletsorter x y = ( matrixsum x ) < ( matrixsum y ) -- compare perimeter
triplegen_helper b = foldl1
( merge tripletsorter )
[ h : triplegen_helper h | x <- tpgen_matrix , let h = mmult x b ]
triplets = x : triplegen_helper x where x = [[3],[4],[5]]
main = mapM print $ take 10 triplets
You can do the following:
pythagorean = [ (x,y,m*m+n*n) |
m <- [2..],
n <- [1 .. m-1],
let x = m*m-n*n,
let y = 2*m*n ]
This might work: Got it from this tutorial
triangles x = [(a,b,c) | c <- [1..x], b <- [1..c], a <- [1..b] , a^2 + b^2 == c^2]
List comprehension syntax makes this easy:
triplets :: Integer -> [(Integer, Integer, Integer)]
triplets d = [(a,b,c) | a <- [1..d], b <- [a..d], c <- [b..d], a^2 + b^2 == c^2]
This basically says than we build a list from as,bs and cs, where a changes from 1 to d, b changes from current a to d and etc. It also says that a^2 + b^2 == c^2 should hold.

Resources