I have the following data type
data Tree a -> Node a [Tree a]
and would like to find the labels of all the Nodes and height of the tree.
Here is what I did:
height:: Tree a -> Integer height
(Node _ (x:xs)) = 1 + maximum height' (x:xs)
height' (x:xs) = map height (x:xs)
I was hoping that height' would return a list of height mapped over x:xs and try to find the max of that value but ghci does not approve of the map function here.
You can write this in a one liner with:
height :: Integral i => Tree a -> i
height (Node _ cs) = 1 + maximum (0 : map height cs)
Here for every node, we thus return 1 + … where … is the maximum of 0 and the heights of the children of these nodes. We here use 0 to prevent that, if the Node hase no children, the maximum will work over an empty list, and thus raise an error.
Taking in account I defined the Tree as:
data GenTree a = NodeG a [GenTree a] deriving (Show)
Well, in this one you where a little closer:
height:: GenTree a -> Integer
height (NodeG _ []) = 0 -- Deep 0
height (NodeG _ trees) = 1 + (maximum $ heightLs trees) -- take the max
-- (maximum $ heightLs trees) == (maximum (heightLs trees))
heightLs (x:xs) = map height (x:xs) -- here is perfect
genTree1 = NodeG "1" [NodeG "2" [],
NodeG "3" [NodeG "4" [],
NodeG "5" [NodeG "6" [],
NodeG "7" [],
NodeG "8" [
NodeG "9" []
]
]
]
]
Example
$> height genTree1
=> 4
Related
For example if we have two strings "abc" and "1234" i want result "abc4" (the first string masks second). (If we draw them vertical it's like a wave comes from left and tuch chars)
"a" "1" "a"
wave -> "b" "2" result "b"
"c" "3" "c"
"4" "4"
I start with this solution with Haskell
slice from to xs = take (to - from + 1) (drop from xs)
merge l1 l2 = if length l2 > length l1
then l1 ++ slice (length l1) (length l2) l2
else l1
Can you please provide some more elegant\compact solutions.
You just need a special merge function
> let merge [] ys = ys
| merge xs [] = xs
| merge (x:xs) (y:ys) = x : merge xs ys
or using drop
> let merge2 x y = x ++ drop (length x) y
You want kind of a "zipLongest", and transpose is kind of like that:
maskMerge1 :: [b] -> [b] -> [b]
maskMerge1 as bs = map head $ transpose [as,bs]
-- or:
-- head <$> transpose [as,bs]
This is pretty compact and elegant (with big thanks to #leftaroundabout for the comments!).
Looking from above,
[ "abc" , [ ['a' ,'b' ,'c' ] ,
"1234" ] ['1' ,'2' ,'3' ,'4'] ]
---------- --------------------------
[ "a1","b2","c3","4" ] -- transpose
---------- --------------------------
"abc4" [ 'a' ,'b' ,'c' ,'4' ] -- map head
The code with length in the other answer also works, and even for an infinite x despite calling the dreaded length on it, but it will retain the whole of x in memory because of calling the length on it.
I have the following datatype:
data Tree a = Node [Tree a]
and I want to count how many nodes are in such a tree so I defined the following:
count:: Tree a -> Integer
count [] = 0
count Node label [childrenTree a] = 1 + count a
which gives me an error saying "Parse error in pattern: true". If I change childrenTree a to Tree a it says that the data constructor is not in scope.
How do I solve this?
This specifies that function count has three arguments, which is not what you want:
count Node label [childrenTree a] = ...
-- ^1 ^2 ^3
Further,
count [] = ...
specifies that there is a single argument, which must be a list (an empty list, to be exact). You want count to take trees as argument, not lists.
The right way to write the code is:
count:: Tree a -> Integer
count (Node subtrees) = ... -- here, we have subtrees :: [Tree a]
Alternatively:
count:: Tree a -> Integer
count (Node []) = ...
count (Node (t:ts)) = ...
--here t is the first tree in the list, ts is the list of remaining ones
Here's a complete working program:
data Tree a = Node [Tree a]
count:: Tree a -> Integer
count (Node []) = 1
count (Node (t:ts)) = count t + count (Node ts)
-- a little test
main :: IO ()
main = print (count (Node [Node [], Node [Node[], Node[]]]))
The output is 5, which is the number of Nodes in the input.
There is a tricky part in General Trees to take account, you have the function in the Tree itself, and you have the recursion over the list of tree so.
Another thing is, you tree as it is, doesn't save any valuable information, you can change it a little bit as:
data Tree a = Node a [Tree a] deriving (Show)
and the two functions will be like:
count:: Tree a -> Integer
count (Node _ trees) = 1 + countLs trees
countLs [] = 0
countLs (t:ts) = (count t) + (countLs ts)
and a little demo:
genTree1 = NodeG "1" [NodeG "2" [],
NodeG "3" [NodeG "4" [],
NodeG "5" [NodeG "6" [],
NodeG "7" [],
NodeG "8" []
]
]
]
runing example:
$> count genTree1
8
I have a list of 9 integers with values 1, -1, 0 such as:
[-1, 0, 0, 1, -1, -1, 1, 1, 0]
What I am trying to do is that from this one list create list of lists where each one of them contain only one change and all the time different. For each -1 I want to change it into 0.
Example:
From the list:
[-1,0,0,1,-1,-1,1,1,0],
I want to get the result:
[ [ 0, 0, 0, 1, -1, -1, 1, 1, 0]
, [-1, 0, 0, 1, 0, -1, 1, 1, 0]
, [-1, 0, 0, 1, -1, 0, 1, 1, 0]
]
So each list has only one value changed and each has a different one. I have no idea how to even start.
First thing you always need is to figure out the type signature of your function. In your case you want
lister :: [Int] -> [[Int]]
Then, as you want to loop through the list but keeping track of the indexes you have changed, an easy way would be to list a list of your list (hard to follow, just look at the code) and then zip it with its index. Then for each list you switch the element in that position. This is you code
lister :: [Int] -> [[Int]]
lister ls = [switch i l | (i,l) <- zip [0..9] (repeat ls)]
You then need a switch function, to switch the element in the ith position accordingly to your rule:
switch :: Int -> [Int] -> [Int]
switch 0 ls = ls
switch n ls = [if i == n && x == -1 then 0 else x | (i,x) <- zip [1..] ls]
Note that this returns 9 lists, one for each element in your original list. Therefore it contains some duplicates. You can eliminate them using nub from Data.List, watch out because it is O(n^2)
This is your complete code:
import Data.List
lister :: [Int] -> [[Int]]
lister ls = nub [switch i l | (i,l) <- zip [0..9] (repeat ls)]
switch :: Int -> [Int] -> [Int]
switch 0 ls = ls
switch n ls = [if i == n && x == -1 then 0 else x | (i,x) <- zip [1..] ls]
Clearly this is a very specific problem. It is often useful to look at the bigger picture: what more general problem is this a special case of? Clearly, here, we are looking through a list, and may see an element that we wish to replace, in zero or more ways. Further, we wish to see how many ways it is possible to make a limited number of such replacements. So, let us implement the general case before thinking about how to specialize to our original problem:
import Control.Applicative (Alternative, empty, (<|>))
replaceNTimes :: Alternative f => (a -> f a) -> Int -> [a] -> f [a]
replaceNTimes _ 0 xs = pure xs
replaceNTimes _ _ [] = empty
replaceNTimes f n (x:xs) = replaceHere <|> keepLooking
where replaceHere = (:) <$> f x <*> replaceNTimes f (n - 1) xs
keepLooking = (x:) <$> replaceNTimes f n xs
If we have a "budget" of zero replacements remaining, we simply return the remainder of the list. If we have budget remaining but the list is empty, we abort, because we failed to make the expected number of replacements. Otherwise, we consult our replacement-suggester function to see which replacements are legal at the current position, and choose to either make one of them and recurse with a smaller N, or to make none and recurse with the same N.
With this tool at our disposal, the original problem is easy: we just specialize N to 1 (make exactly one replacement), and supply a replacing function that only suggests replacing -1 with 0:
replaceSingleNegativeOneWithZero :: [Int] -> [[Int]]
replaceSingleNegativeOneWithZero = replaceNTimes go 1
where go (-1) = [0]
go _ = []
And test to ensure that we get the expected output:
*Main> replaceSingleNegativeOneWithZero [-1,0,0,1,-1,-1,1,1,0]
[ [0,0,0,1,-1,-1,1,1,0]
, [-1,0,0,1,0,-1,1,1,0]
, [-1,0,0,1,-1,0,1,1,0]]
Another try:
zeros :: [Int] -> [Int] -> [[Int]]
zeros _ [] = []
zeros h (x:xs) = [h ++ newX:xs] ++ zeros nextH xs
where newX = if x == (-1) then 0 else x
nextH = h ++ [x]
switch xs = ((filter (/= xs)) . (zeros [])) xs
Usage:
main = print $ switch [-1, 0, 0, 1, -1, -1, 1, 1, 0]
How I can iterate a list of elements four by four and then add these four card to a tuple?.
Basically this a function that receives the Suit that it was to be killed, the cards played by order and the player who has played first.
That game is played by pairs, so it returns a tuple with the cards won for the first couple and the cards won for the second couple.
winnedCards:: Suit-> [Card] -> Int -> ([Card],[Card])
winnedCards [] _ = ([],[])
winnedCards (Suit type) cardsPlayed positionFirstPlayPerson
| snd(xs) == 3 = (take 4 (cardsPlayed),[])
| snd(xs) == 1 = (take 4 (cardsPlayed),[])
| otherwise = ([],take 2 (cardsPlayed))
where xs = whoHasWon (take 4 (cardsPlayed)) (Suit type)
whoHasWon returns the position of the player who has won. I think I have to it recursevily because I have to iterate 4 by 4, and then add the result to the tuple after each iteration.
As Willem Van Onsem mentions in the comments, your function appears to do entirely too much work. If you're trying to split a list into groups of four-tuples, do that separately from the rest of the logic.
toFourTuple :: [a] -> [(a, a, a, a)]
toFourTuple [] = []
toFourTuple (a:b:c:d:rest) = (a, b, c, d) : toFourTuple rest
toFourTuple _ = error "list not divisible by four"
-- how should this be handled?
For the rest, it might be useful to know that the Monoid instance of Monoid a => (a, a) implements mappend as mappend (x, y) (x', y') = (x <> x', y <> y'), so if you generate a list of (leftside, rightside) sublists, you can mconcat them together.
xs = [ ([1] , [3])
, ([2, 4], [5])
, ([6] , [7, 9, 11, 13])
]
mconcat xs = ([1,2,4,6],[3,5,7,9,11,13])
Of course this works incrementally too.
-- |Separates [Int] into ([odds], [evens])
splitByMod2 :: [Int] -> ([Int], [Int])
splitByMod2 [] = ([], [])
splitByMod2 (x:xs)
| odd x = ([x], []) `mappend` splitByMod2 xs
| even x = ([], [x]) `mappend` splitByMod2 xs
| otherwise = error "This cannot happen"
This is for a class
We're supposed to write 3 functions :
1 : Prints list of fibbonaci numbers
2 : Prints list of prime numbers
3 : Prints list of fibonacci numbers whose indexes are prime
EG : Let this be fibbonaci series
Then In partC - certain elements are only shown
1: 1
*2: 1 (shown as index 2 is prime )
*3: 2 (shown as index 3 is prime )
4: 3
*5: 5 (shown )
6: 8
*7: 13 (shown as index 7 prime and so on)
I'm done with part 1 & 2 but I'm struggling with part 3. I created a function listNum that creates a sort of mapping [Integer, Integer] from the Fibbonaci series - where 1st Int is the index and 2nd int is the actual fibbonaci numbers.
Now my function partC is trying to stitch snd elements of the fibonaci series by filtering the indexes but I'm doing something wrong in the filter step.
Any help would be appreciated as I'm a beginner to Haskell.
Thanks!
fib :: [Integer]
fib = 0 : 1 : zipWith (+) fib (tail fib)
listNum :: [(Integer, Integer)]
listNum = zip [1 .. ] fib
primes :: [Integer]
primes = sieve (2 : [3,5 ..])
where
sieve (p:xs) = p : sieve [x | x <- xs , x `mod` p > 0]
partC :: [Integer] -- Problem in filter part of this function
partC = map snd listNum $ filter (\x -> x `elem` primes) [1,2 ..]
main = do
print (take 10 fib) -- Works fine
print (take 10 primes) --works fine
print (take 10 listNum) --works fine
print ( take 10 partC) -- Causes error
Error :
prog0.hs:14:9: error:
• Couldn't match expected type ‘[Integer] -> [Integer]’
with actual type ‘[Integer]’
• The first argument of ($) takes one argument,
but its type ‘[Integer]’ has none
In the expression:
map snd listNum $ filter (\ x -> x `elem` primes) [1, 2 .. ]
In an equation for ‘partC’:
partC
= map snd listNum $ filter (\ x -> x `elem` primes) [1, 2 .. ]
|
14 | partC = map snd listNum $ filter (\x -> x `elem` primes) [1,2 ..]
Here's what I think you intended as the original logic of partC. You got the syntax mostly right, but the logic has a flaw.
partC = snd <$> filter ((`elem` primes) . fst) (zip [1..] fib)
-- note that (<$>) = fmap = map, just infix
-- list comprehension
partC = [fn | (idx, fn) <- zip [1..] fib, idx `elem` primes]
But this cannot work. As #DanRobertson notes, you'll try to check 4 `elem` primes and run into an infinite loop, because primes is infinite and elem tries to be really sure that 4 isn't an element before giving up. We humans know that 4 isn't an element of primes, but elem doesn't.
There are two ways out. We can write a custom version of elem that gives up once it finds an element larger than the one we're looking for:
sortedElem :: Ord a => a -> [a] -> Bool
sortedElem x (h:tl) = case x `compare` h of
LT -> False
EQ -> True
GT -> sortedElem x tl
sortedElem _ [] = False
-- or
sortedElem x = foldr (\h tl -> case x `compare` h of
LT -> False
EQ -> True
GT -> tl
) False
Since primes is a sorted list, sortedElem will always give the correct answer now:
partC = snd <$> filter ((`sortedElem` primes) . fst) (zip [1..] fib)
However, there is a performance issue, because every call to sortedElem has to start at the very beginning of primes and walk all the way down until it figures out whether or not the index is right. This leads into the second way:
partC = go primeDiffs fib
where primeDiffs = zipWith (-) primes (1:primes)
-- primeDiffs = [1, 1, 2, 2, 4, 2, 4, 2, 4, 6, ...]
-- The distance from one prime (incl. 1) to the next
go (step:steps) xs = x:go steps xs'
where xs'#(x:_) = drop step xs
go [] _ = [] -- unused here
-- in real code you might pull this out into an atOrderedIndices :: [Int] -> [a] -> [a]
We transform the list of indices (primes) into a list of offsets, each one building on the next, and we call it primeDiffs. We then define go to take such a list of offsets and extract elements from another list. It first drops the elements being skipped, and then puts the top element into the result before building the rest of the list. Under -O2, on my machine, this version is twice as fast as the other one when finding partC !! 5000.