List-comprehension output not what I assumed - haskell

I assume its simple as its in a past paper of my university but the function is:
[(x,y) | x <- [0..2], y<-[0,x])
and the output
[(0,0),(0,0),(1,0), (1,1), (2,0), (2,2)]
The (2,0) confuses me, if y maps to 0 to x whilst x is equal to 1 = (1,1) wouldnt it be
[(0,0),(0,0),(1,0), (1,1), **(2,1)**, (2,2)]
or is it because due to the y using all its numbers in its list [0,1] it reverts back to 0?

case [(x,y) | x <- [0..2], y<-[0,x]]
[0,x] is:
[0,0] for x=0
[0,1] for x=1
[0,2] for x=2
so if you pair each of those ys up with the corresponding x you get:
[(0,0),(0,0)] -- x = 0
++ [(1,0),(1,1)] -- x = 1
++ [(2,0),(2,2)] -- x = 2
which yields your given output
note: [0,2] has length 2 and is quite different from [0..2] which has length 3 and contains 1
case [(x,y) | x <- [0..2], y<-[0..x]]
it's not that different - [0..x] is:
[0] for x=0
[0,1] for x=1
[0,1,2] for x=2
and if you pair each of those ys up with the corresponding x you get
[(0,0))] -- x = 0
++ [(1,0),(1,1)] -- x = 1
++ [(2,0),(2,1),(2,2)] -- x = 2
which then would give you the result
[(0,0),(1,0),(1,1),(2,0),(2,1),(2,2)]

Related

generate a list of numbers with increasing digit order

Hi I am trying to generate a list with
All possible n digit numbers
And their digits are in decreasing order
For example, if n = 3 the output will be [111 .. 321 .. 543 ..999].
My initial attempt was
--attempt1
digits n = map (\x -> read [x] :: Int) (show n)
sorted [] = True
sorted [x] = True
sorted (x:y:xs) = if x <= y then sorted (y:xs) else False
[ x | x <- [ 10^(n-1) .. 10^n ] , sorted $ digits $ x]
However this approach got slower exponentially as the variable n got bigger.
My second approach was (if n == 3)
joiner :: [Integer] -> Integer
joiner = read . concatMap show
[ joiner [z,y,x] |
x <- [1..9],
y <- [9,8..x],
z <- [9,8..y]]
However now the problem is how I can generalise this code to an arbitrary n
joiner :: [Integer] -> Integer
joiner = read . concatMap show
[ joiner [a_n,...,a_1] |
a_1 <- [1..9],
a_2 <- [9,8..x],
.
.
.
a_n <- [9,8..a_n-1]
]
Thank you!
Every time you need to combine N of something (where N is unknown upfront), the answer is always recursion. After all, that's the only way to iterate in Haskell.
First, we'll need a way to append another digit to a given number. Simple enough:
appendDigit x = [ x*10 + d | d <- [0..9] ]
Let's test it out:
λ appendDigit 2
[20,21,22,23,24,25,26,27,28,29]
λ appendDigit 3
[30,31,32,33,34,35,36,37,38,39]
But not good enough: we only need to append digits that are less than the last one. Well, easy to modify:
appendDigit x = [ x*10 + d | d <- [0..(lastDigit-1)] ]
where lastDigit = x `mod` 10
Try it out:
λ appendDigit 2
[20,21]
*Main Lib
λ appendDigit 3
[30,31,32]
*Main Lib
λ appendDigit 8
[80,81,82,83,84,85,86,87]
And now all that remains is just to do it N times, concatenating resulting lists along the way:
decDigits 0 = [] -- degenerate case: when N = 0, there are no such numbers
decDigits 1 = [0..9] -- base case: N = 1
decDigits n = concatMap appendDigit $ decDigits (n-1)

Haskell: Generating k-itemsets for apriori

I am trying to generate all k-item sets for use in apriori, I am following this pseudocode:
L1= {frequent items};
for (k= 2; Lk-1 !=∅; k++) do begin
Ck= candidates generated from Lk-1 (that is: cartesian product Lk-1 x Lk-1 and eliminating any
k-1 size itemset that is not frequent);
for each transaction t in database do
increment the count of all candidates in
Ck that are contained in t
Lk = candidates in Ck with min_sup
end
return U_k Lk;
,here is the code I have:
-- d transactions, threshold
kItemSets d thresh = kItemSets' 2 $ frequentItems d thresh
where
kItemSets' _ [] = [[]]
kItemSets' k t = ck ++ (kItemSets' (k+1) ck)
where
-- those (k-1) length sets that meet the threshold of being a subset of the transactions in d
ck = filter (\x->(countSubsets x d) >= thresh) $ combinations k t
-- length n combinations that can be made from xs
combinations 0 _ = [[]]
combinations _ [] = []
combinations n xs#(y:ys)
| n < 0 = []
| otherwise = case drop (n-1) xs of
[ ] -> []
[_] -> [xs]
_ -> [y:c | c <- combinations (n-1) ys]
++ combinations n ys
-- those items of with frequency o in the dataset
frequentItems xs o = [y| y <- nub cs, x<-[count y cs], x >= o]
where
cs = concat xs
isSubset a b = not $ any (`notElem` b) a
-- Count how many times the list y appears as a subset of a list of lists xs
countSubsets y xs = length $ filter (isSubset y ) xs
count :: Eq a => a -> [a] -> Int
count x [] = 0
count x (y:ys) | x == y = 1+(count x ys)
| otherwise = count x ys
transactions =[["Butter", "Biscuits", "Cream", "Newspaper", "Bread", "Chocolate"],
["Cream", "Newspaper", "Tea", "Oil", "Chocolate"] ,
["Chocolate", "Cereal", "Bread"],
["Chocolate", "Flour", "Biscuits", "Newspaper"],
["Chocolate", "Biscuits", "Newspaper"] ]
But when I compile I get the error:
apriori.hs:5:51:
Occurs check: cannot construct the infinite type: a0 = [a0]
Expected type: [a0]
Actual type: [[a0]]
In the second argument of kItemSets', namely `ck'
In the second argument of `(++)', namely `(kItemSets' (k + 1) ck)'
Failed, modules loaded: none.
But when I run from ghci:
*Main> mapM_ print $ filter (\x->(countSubsets x transactions ) >= 2 ) $ combinations 2 $ frequentItems transactions 2
["Biscuits","Newspaper"]
["Biscuits","Chocolate"]
["Cream","Newspaper"]
["Cream","Chocolate"]
["Newspaper","Chocolate"]
["Bread","Chocolate"]
Which is correct, since it's those 2-item sets that meet the occurrence threshold in the set of transactions. But what I need for the 3-item sets is
[["Biscuits", "Chocolate", "Newspaper" ],
["Chocolate", "Cream", "Newspaper"]]
and for this to be appended to the list of 2-item sets. How would I change my current code to achieve this? I know it can be built from the 2-item set, but I'm not sure how to go about it.
Had to use this for line 5:
kItemSets' k t = ck ++ (kItemSets' (k+1) $ nub $ concat ck)
Not the most efficient but it works.

Haskell program that gives pretty prime numbers

I've made a haskell program that computes pretty prime numbers. Pretty primes are primes that are very close to a power of 2. You give 2 numbers for example: 10 and 20 then it returns 17 because 17 is the closest to a power of 2. 17 - 16 = 1 so it is the closest.
I've made this:
EDIT: I've rewrote the primefunction like this and e verw function but still getting -1.
-- Geeft priemgetallen terug tussen de 2 grenzen
-- English: Gives primenumbers between 2 numbers
priemgetallen :: Int->[Int]
priemgetallen b = take b (zeef [2..])
where zeef (p:xs) = p : zeef [x | x<-xs, (mod x p) /= 0]
-- Geeft machten terug tussen de 2 grenzen
-- English: Gives powers of 2 between 2 numbers
machten :: Int->Int->[Int]
machten a b
| a <= 2 = 2:[2^x| x<-[2..b], (2^x) `mod` 2 == 0, 2^x < b, 2^x > a]
| otherwise = [2^x| x<-[2..b], (2^x) `mod` 2 == 0, 2^x < b, 2^x > a]
-- English: the start of the function
prettyprime :: Int->Int->Int
prettyprime a b = vergelijk ( verw a (priemgetallen b)) (machten a b)
-- Filter the list
verw :: Int->[Int]->[Int]
verw _ [] = []
verw k (x:xs)
| x > k = [x] ++ verw k xs
| otherwise = verw k xs
-- Vergelijkt alle priemgetallen en geeft welke korste bij het ander ligt
-- English this function must see what primenumber is the closest to a power of 2 but I can't fix it
vergelijk :: [Int]->[Int]->Int
vergelijk [] _ = -1
vergelijk _ [] = -1
vergelijk (x:xs) (y:ys)
| x - y < vergelijk (x:xs) ys = x
| x - y > vergelijk (x:xs) ys = vergelijk xs (y:ys)
| x - y == vergelijk (x:xs) ys = x
main = do
print $ prettyprime 14 20
Can someone help me?
Kind regards,
The incomplete pattern is because you've omitted the case when x - y == vergelijk (x:xs) ys. The compiler is capable of warning you about this if you add -fwarn-incomplete-patterns and convert your guards into a real case:
vergelijk (x:xs) (y:ys) = case compare (x - y) (vergelijk (x:xs) ys) of
LT -> x
-- you will get a warning about having no case for EQ
GT -> vergelijk xs (y:ys)
As a bonus, this version is much less likely to recompute the recursive call, especially on low optimization levels.

Comparing Bool Value in Matrix

t = True
f = False
anzNachbarn :: [[Bool]] -> (Integer,Integer) -> Integer
anzNachbarn a (x,y)
| x < 0 || y < 0=-1
| otherwise ... here comes the comparison
This is an example matrix:
[[True,False,False],
[True,False,False],
[False,True,False]]
here i need an algorithm, where it calculates (for given x and y position in matrix) its neighbours (only "true" neighboors) and increase it by 1 for each true neighboor.
For example: anzNachbarn [[True,False,False],[True,False,False],[False,True,False]] (0,1)
returns 2 back.
:Edit
I still have a question how can I now implement each component of the result matrix, the number of named elements with True neighboring fields indicates the corresponding component of the argument matrix Applies to
[[True, False, False],
[True, False, False],
[False, True , False]]
the function func returns the results matrix [[1,2,0], [2,3,1], [2,1,1]]
with signature func :: [[Bool]] -> [[Integer]]
have you got any idea about this ?
You almost certainly want to use an array (from Data.Array) in this situation, since looking up an item in a list by its index is very slow.
Here's a quick implementation using Array:
countNeighbors :: Array (Int, Int) Bool -> (Int, Int) -> Int
countNeighbors board (x, y) = length
[ (x', y')
| x' <- [x - 1, x, x + 1]
, y' <- [y - 1, y, y + 1]
, x' /= x || y' /= y
, inRange (bounds board) (x', y')
, board ! (x', y')
]
This is a list comprehension with two generators and three guards. The generators simply give us the indices of the nine positions in a three-by-three square centered at (x, y) (you'll need a minor change if you don't want neighbors at the corners to be considered).
The first guard (x' /= y') ignores (x, y) itself. The second throws out positions that aren't within the bounds of the array. The final guard throws out positions that are in the array but have a False value.
So we now have a list of indices for the neighbors with True values. The length of this list is the desired count.
This is ugly, but seems to work...
anzNachbarn :: [[Bool]] -> (Int,Int) → Integer
anzNachbarn a (x,y)
| x < 0 || y < 0 = -1
| otherwise = sum [v x' y' | x' <- [max 0 (x-1)..x+1],
y' <- [max 0 (y-1)..y+1],
x ≠ x' || y ≠ y' ]
where v i j = if j >= length a
|| i >= length (a !! 0)
|| not (a !! j !! i)
then 0 else 1
[Edit]
In order to convert the whole array, you can write the equally ugly
conv a = [line y | y <- [0 .. (length a) - 1]]
where line y = [anzNachbarn a (x,y) | x <- [0 .. ((length (a !! 0) - 1)]]
Note that the performance of this is terrible.

Detecting cyclic behaviour in Haskell

I am doing yet another projecteuler question in Haskell, where I must find if the sum of the factorials of each digit in a number is equal to the original number. If not repeat the process until the original number is reached. The next part is to find the number of starting numbers below 1 million that have 60 non-repeating units. I got this far:
prob74 = length [ x | x <- [1..999999], 60 == ((length $ chain74 x)-1)]
factorial n = product [1..n]
factC x = sum $ map factorial (decToList x)
chain74 x | x == 0 = []
| x == 1 = [1]
| x /= factC x = x : chain74 (factC x)
But what I don't know how to do is to get it to stop once the value for x has become cyclic. How would I go about stopping chain74 when it gets back to the original number?
When you walk through the list that might contain a cycle your function needs to keep track of the already seen elements to be able to check for repetitions. Every new element is compared against the already seen elements. If the new element has already been seen, the cycle is complete, if it hasn't been seen the next element is inspected.
So this calculates the length of the non-cyclic part of a list:
uniqlength :: (Eq a) => [a] -> Int
uniqlength l = uniqlength_ l []
where uniqlength_ [] ls = length ls
uniqlength_ (x:xs) ls
| x `elem` ls = length ls
| otherwise = uniqlength_ xs (x:ls)
(Performance might be better when using a set instead of a list, but I haven't tried that.)
What about passing another argument (y for example) to the chain74 in the list comprehension.
Morning fail so EDIT:
[.. ((length $ chain74 x x False)-1)]
chain74 x y not_first | x == y && not_first = replace_with_stop_value_:-)
| x == 0 = []
| x == 1 = [1]
| x == 2 = [2]
| x /= factC x = x : chain74 (factC x) y True
I implemented a cycle-detection algorithm in Haskell on my blog. It should work for you, but there might be a more clever approach for this particular problem:
http://coder.bsimmons.name/blog/2009/04/cycle-detection/
Just change the return type from String to Bool.
EDIT: Here is a modified version of the algorithm I posted about:
cycling :: (Show a, Eq a) => Int -> [a] -> Bool
cycling k [] = False --not cycling
cycling k (a:as) = find 0 a 1 2 as
where find _ _ c _ [] = False
find i x c p (x':xs)
| c > k = False -- no cycles after k elements
| x == x' = True -- found a cycle
| c == p = find c x' (c+1) (p*2) xs
| otherwise = find i x (c+1) p xs
You can remove the 'k' if you know your list will either cycle or terminate soon.
EDIT2: You could change the following function to look something like:
prob74 = length [ x | x <- [1..999999], let chain = chain74 x, not$ cycling 999 chain, 60 == ((length chain)-1)]
Quite a fun problem. I've come up with a corecursive function that returns the list of the "factorial chains" for every number, stopping as soon as they would repeat themselves:
chains = [] : let f x = x : takeWhile (x /=) (chains !! factC x) in (map f [1..])
Giving:
take 4 chains == [[],[1],[2],[3,6,720,5043,151,122,5,120,4,24,26,722,5044,169,363601,1454]]
map head $ filter ((== 60) . length) (take 10000 chains)
is
[1479,1497,1749,1794,1947,1974,4079,4097,4179,4197,4709,4719,4790,4791,4907,4917
,4970,4971,7049,7094,7149,7194,7409,7419,7490,7491,7904,7914,7940,7941,9047,9074
,9147,9174,9407,9417,9470,9471,9704,9714,9740,9741]
It works by calculating the "factC" of its position in the list, then references that position in itself. This would generate an infinite list of infinite lists (using lazy evaluation), but using takeWhile the inner lists only continue until the element occurs again or the list ends (meaning a deeper element in the corecursion has repeated itself).
If you just want to remove cycles from a list you can use:
decycle :: Eq a => [a] -> [a]
decycle = dc []
where
dc _ [] = []
dc xh (x : xs) = if elem x xh then [] else x : dc (x : xh) xs
decycle [1, 2, 3, 4, 5, 3, 2] == [1, 2, 3, 4, 5]

Resources