I have this function that generates a list of all words with a min length 0 and max length n, equals given as an input to the function:
import Data.List
words :: Int -> String -> [String]
words 0 alph = [[]]
words n alph = words (n-1) alph ++ [ ch:w | w <-words (n-1) alph, ch <- alph]
When I run this, the output is following:
> words 3 "AB"
["","A","B","A","B","AA","BA","AB","BB","A","B","AA","BA","AB","BB","AA","BA","AB","BB","AAA","BAA","ABA","BBA","AAB","BAB","ABB","BBB"]
The problem here is, that there are some words repeating, in this example, especially the words of length of 2 ("AA" is 3 times there). Can you see what am I doing wrong in my function, or do you have any idea how to solve it?
This is because the words (n-1) alph in the list comprehension does not only yield words of length n-1 but also n-2, n-3, etc., since that is how you defined the words function.
It might be better to make a helper function that only generates words of length n and then use that in an extra function that constructs strings with lengths up to n:
words :: Int -> String -> [String]
words 0 alph = [[]]
words n alph = [ ch:w | w <-words (n-1) alph, ch <- alph]
wordsUpTo :: Int -> String -> [String]
wordsUpTo n alph = concatMap (flip words alph) [0 .. n]
However words already exists, this is just a special case of replicateM :: Applicative m = > Int -> m a -> m [a], so we can write this as:
import Control.Monad(replicateM)
wordsUpTo :: Int -> String -> [String]
wordsUpTo n alph = [0 .. n] >>= (`replicateM` alph)
which will produce:
Prelude Control.Monad> wordsUpTo 3 "AB"
["","A","B","AA","AB","BA","BB","AAA","AAB","ABA","ABB","BAA","BAB","BBA","BBB"]
The Applicative instance for lists effectively computes a cross-product,
> (,) <$> ["A", "B"] <*> ["C", "D"]
[("A","C"),("A","D"),("B","C"),("B","D")]
elements of which can be joined with (++) instead of (,):
> (++) <$> ["A", "B"] <*> ["C", "D"]
["AC","AD","BC","BD"]
If you repeatedly apply this operation, you'll get the strings you want:
> (++) <$> ["A", "B"] <*> [""] -- base case
["A","B"]
> (++) <$> ["A", "B"] <*> ["A","B"]
["AA","AB","BA","BB"]
> (++) <$> ["A", "B"] <*> ["AA","AB","BA","BB"]
["AAA","AAB","ABA","ABB","BAA","BAB","BBA","BBB"]
The function you want to repeat is the section ((++) <$> ["A", "B"] <*>), which from now on we'll refer to as f:
> f = ((++) <$> ["A", "B"] <*>)
This repeated application is captured by the iterate function, which repeatedly feeds the output of one function application as the input of the next.
> take 3 $ iterate f [""]
[[""],["A","B"],["AA","AB","BA","BB"]]
We'll want to concatenate the results into a single list:
> take 7 $ concat $ iterate f [""]
["","A","B","AA","AB","BA","BB"]
So all combinations is just
allWords alph = concat $ iterate f [""]
where f = ((++) <$> alph <*>)
To get the elements with some maximum length, we can either
Use takeWhile (\x -> length x <= n), or
Use take (2^(n+1) - 1) (given the order in which items are generated, all the strings of a given length occur before longer strings, and we can compute the total number of strings with a given maximum length)
So we can define either
words n = takeWhile p . allWords
where p x = length x < 4
or
words n = take n' . allWords
Related
Hi I am new in Haskell and I came across an interesting problem but I was not really sure on how I would go about solving it. I am about to show you only two parts of the question as an example.
The question is that we are to input a number between 13 to 15 digits.
then from that number we remove the last number. such as 19283828382133 should out put the exact same number just without the final 3, 1928382838213.
Then every odd digit(not number) from these numbers will be doubled. So you will get 2,9,4,8,6 etc
This is my code so far. As you can see from the code I have been able to complete these two parts individually(working) but I am not sure how I would add them together.
lastdigit :: Integer -> Integer -- This Function removes the last number
lastdigit x = x`div`10
doubleOdd (x:xs) = (2*x):(doubleEven xs) -- This function doubles every odd digit not number.
doubleOdd [] = []
doubleEven (x:xs) = x:(doubleOdd xs)
doubleEven [] = []
So to further explain the program I am trying to build will first go through the step of taking in the number between 13 to 15 digits. Then it will first remove the last number then automatically go to the next step of doubling each odd digit(not number). Thanks
First, you need a way to break some large number into digits.
digits :: Integral x => x -> [x]
digits 0 = []
digits x = digits (x `div` 10) ++ [x `mod` 10]
Which gives you...
Prelude> digits 12345
[1,2,3,4,5]
You can then drop the last digit with init
Prelude> (init . digits) 12345
[1,2,3,4]
The a helper function to map over odd elements in a list.
mapOdd _ [] = []
mapOdd f (x:[]) = [f x]
mapOdd f (x:y:rest) = f x : y : mapOdd f rest
Giving you...
Prelude> mapOdd (+10) [1..10]
[11,2,13,4,15,6,17,8,19,10]
And a function to get back to a large number...
undigits = sum . zipWith (*) [10^n | n <- [0..]] . reverse
Resulting in...
Prelude> undigits [1, 2, 3, 4]
1234
And putting it all together
Prelude> undigits . mapOdd (*2) . init . digits $ 12345
2264
In functional languages particularly, always try to solve a problem by composing solutions to smaller problems :)
The missing component is a way to break down an integer into its digits, and build it back up from there. That's easy:
digits:: Int -> [Int]
digits = map (`mod` 10) . takeWhile (/= 0) . iterate (`div` 10)
undigits :: [Int] -> Int
undigits = foldr f 0 where f i r = 10 * r + i
Then it looks like you need to post-process those digits in two different ways, but only if they match a predicate. Let's build a combinator for that:
when :: (a -> Bool) -> (a -> a) -> a -> a
when p f a = if p a then f a else a
The first case appears when you want to double digits in odd position (from left to right). Again trivial, with the minor inconvenience that digits breaks down a number by increasing power of ten. Let's prefix each number by its position:
prefix :: [Int] -> [(Int, Int)]
prefix is = let n = length is in zip [n, n-1..1] is
doubleOdd can now be expressed as
doubleodd :: [Int] -> [Int]
doubleodd = map (snd . when (odd . fst) (id *** double)) . prefix
You mentioned in a comment that when the double number overflows, its digits must be added together. This is the second case I was referring to and is again simplicity itself:
double :: Int -> Int
double = when (>= 10) (sum . digits) . (* 2)
Here is your final program:
program = undigits . doubleodd . tail . digits
... assuming the "between 13 and 15 digits" part is verified separately.
I hope this helps and realize it could be cleaned up a lot. List indices start with 0 which is also an even number and the first element of a list. The list comprehension processes 0,2,4 ... the 1st,2nd and 3rd items.
let f n = [mod n 10] ++ f (div n 10)
let r = [if even i then d*2 else d|(i,d)<-zip [0..] (init.reverse.take 14.f$19283828382133)]
sum [b*(10^a)|(a,b) <- zip [12,11..0] r]
2948684868416
If you want it to handle any length number, the easiest way here is length $ show 19283828382133 but I do have a function somewhere that does that. Use the length as a value in 3 places, once at full value in thetake function in the composition.
Which function can I use to find its index of an element in an Array?
For example, I want to find the index of 'x' in an Array (Data.Array)
lowerCase = listArray ((0,0),(1,12)) ['a'..]
fst <$> find ((== 'a') . snd) $ assocs lowerCase
To get all the indices a certain element appears in your Data.Array the following list comprehension can be used:
results = [fst x | x <- (assocs lowerCase), snd x == 'a']
assocs has the following prototype:
assocs :: Ix i => Array i e -> [(i, e)]
It basically flattens a Data.Array in a List containing (i, e) pairs.
For:
a = listArray ((0,0),(2,2)) ['a'..]
assocs a will output
[((0,0),'a'),((0,1),'b'),((0,2),'c'),((1,0),'d'),((1,1),'e'),((1,2),'f'),((2,0),'g'),((2,1),'h'),((2,2),'i')]
Now, in our list comprehension, we have x <- (assocs a), so x is generated by the list assocs a.
The list outputed by the list comprehension will contain only fst x where
snd x == theElementWeAreLookingFor
Every x generated by assocs a is checked and if the condition snd x == 'a' is met then fst a (the index) will be inserted in the output list.
Once the list is generated, it can be checked whether there are none, one or more outputs.
getElementIndex :: Array (Int, Int) Char -> Char -> Maybe (Int, Int)
getElementIndex a e
| null results = Nothing
| othwerwise = Just $ head results
where results = [fst x | x <- (assocs a), snd x == e]
A imperative pseduocode could look like:
results = []
for_each x in a.toList():
if x.second == 'a':
results.append(x.first)
I have such code for creating permutations:
--unique permutation
perm :: [t] -> [[t]]
perm [] = [[]]
perm (x:xs) = [(y:zs) | (y,ys) <- views (x:xs), zs <- perm ys]
--create all possible views
views :: [t] -> [(t,[t])]
views [] = []
views (x:xs) = ((x,xs) : [ (y,(x:ys)) | (y,ys) <- views xs ])
However I want to limit the output to a certain length. For example, it should take a parameter specifying the number of elements in the ouput of the permutation. I want to create k distinct permutations drawn from a list [0..9].
So, for example, if k will be equal to 3, then the output should be something like this:[1,2,3], [9,8,7], [0,6,8] etc..
Right now if i pass [0..9] to the function it will generate a list with permutations of length 10. I am struggling to come up with a solution.
In the end, the function should look like perm k list
Thank you!
It is connected with this question: Verbal Arithmetics in Haskell (SEND + MORE = MONEY)
Do you mean something like this?
import Data.List (permutations)
choose n list = concatMap permutations $ choose' list [] where
choose' [] r = if length r == n then [r] else []
choose' (x:xs) r | length r == n = [r]
| otherwise = choose' xs (x:r)
++ choose' xs r
Output:
*Main> choose 2 [0..5]
[[1,0],[0,1],[2,0],[0,2],[3,0],[0,3],[4,0],[0,4],[5,0],[0,5],[2,1]
,[1,2],[3,1],[1,3],[4,1],[1,4],[5,1],[1,5],[3,2],[2,3],[4,2],[2,4]
,[5,2],[2,5],[4,3],[3,4],[5,3],[3,5],[5,4],[4,5]]
Will replicateM do what you need?
Prelude Control.Monad> take 10 $ replicateM 3 [0..9]
[[0,0,0],[0,0,1],[0,0,2],[0,0,3],[0,0,4],[0,0,5],[0,0,6],[0,0,7],[0,0,8],[0,0,9]]
Prelude Control.Monad> take 10 $ replicateM 4 [1,3,3,7]
[[1,1,1,1],[1,1,1,3],[1,1,1,3],[1,1,1,7],[1,1,3,1],[1,1,3,3],[1,1,3,3],[1,1,3,7],[1,1,3,1],[1,1,3,3]]
Prelude Control.Monad> take 10 $ replicateM 2 [4,2]
[[4,4],[4,2],[2,4],[2,2]]
I'm new in Haskell and I'm tring to write a simple function that counts the number of occurences of a substring in a string.
For example : "There is an apple" and I want to count how many times "is" in the sentence, in this case the result should be 1.
This is what I've tried:
countOf :: String -> Int
countOf x = length [n | n <- words x, filter "is" x]
According what I've studied it should work, but it doesn't. I really don't know how to solve the problem, and also don't know what the error message I get means:
input:1:41:
Couldn't match expected type `Bool' with actual type `[a0]'
In the return type of a call of `filter'
In the expression: filter "a" x
In a stmt of a list comprehension: filter "a" x
The function filter has the type
filter :: (a -> Bool) -> [a] -> [a]
This means that its first argument is another function, which takes an element and returns a Bool, and it applies this function to each element of the second argument. You're giving a String as the first argument instead of a function. Maybe you want something more like
countOf x = length [n | n <- words x, filter (\w -> w == "is") x]
But this won't work either! This is because any extra expression in a list comprehension has to be a Bool, not a list. filter returns a list of elements, not a Bool, and this is actually the source of your compiler error, it expects a Bool but it sees a list of type [a0] (it hasn't even gotten far enough to realize it should be [String]).
Instead, you could do
countOf x = length [n | n <- words x, n == "is"]
And this would be equivalent to
countOf x = length (filter (\w -> w == "is") (words x))
Or with $:
countOf x = length $ filter (\w -> w == "is") $ words x
Haskell will actually let us simplify this even further to
countOf x = length $ filter (== "is") $ words x
Which uses what is known as an operator section. You can then make it completely point free as
countOf = length . filter (== "is") . words
I would do like this:
countOf :: String -> Int
countOf x = length [n | n <- words x, compare "is" n == EQ]
Demo in ghci:
ghci> countOf "There is an apple"
1
You can put the comparison straight in the comprehension:
countOf x = length [n | n <- words x, n == "is"]
Actually, you try to count the number of occurences of a word in a string. In case you look for a substring:
import Data.List (inits, tails)
countOf = length . filter (=="is") . conSubsequences
where
conSubsequences = concatMap inits . tails
One could also try a foldr:
countOf :: String -> Int
countOf x = foldr count 0 (words x)
where
count x acc = if x == "is" then acc + 1 else acc
Just starting out with Haskell! As an exercise, the current problem I'm trying to implement is as follows:
We have n squares, print all possible world configurations where :
(1) Each square could have a "P" (pit) or not (2^n possibilities).
(2) There can be at most one "W" (wumpus) in all n squares (n+1 possibilities).
Representing two squares as two strings, here is an output example for n=2. We have (2^n)·(n+1) = (2^2)·(2+1) = 12 configurations.
[[" W"," "],[" "," W"],[" "," "],
[" W","P"],[" ","PW"],[" ","P"],
["PW"," "],["P"," W"],["P"," "],
["PW","P"],["P","PW"],["P","P"]]
Condition (1) is easily implemented. Looking around, I've found a few ways to express it :
p 0 = [[]]
p n = [x:xs | x <- [" ","P"], xs <- p (n-1)]
or
p n = mapM (\x -> [" ","P"]) [1..n]
or
p n = replicateM n [" ","P"]
I cannot claim to understand the last two yet, but here they are for completeness.
Question : How can I add condition (2)? Can it be done with list comprehension?
My not-so-good-looking novice solution involved these functions:
insertw :: Int -> [String] -> [String]
insertw n xs
| n < 0 = xs
| n >= lgth = xs
| otherwise = (take (n) xs) ++ [xs!!n++"W"] ++ (drop (n+1) xs)
where lgth = length xs
duplicate :: Int -> [String] -> [[String]]
duplicate i squares
| i > lgth = []
| otherwise = (insertw i squares) : duplicate (i+1) squares
where lgth = length squares
worlds :: Int -> [[String]]
worlds n = concat . map (duplicate 0) . p $ n
Condition 2 isn't an obvious candidate for a list comprehension, but the working code you have already written can be cleaned up.
The iteration from 0 to lgth in duplicate can be done with a map instead of explicit recursion:
duplicate squares = map (\i -> insertw i squares) [0 .. length squares]
duplicate no longer takes an index parameter, and concat . map is the same as concatMap:
worlds = concatMap duplicate . p
If you do both a drop and a take, then splitAt is often the better operation.
insertw n xs =
case splitAt n xs of
(as, []) -> as
(as, b : bs) -> as ++ ((b ++ "W") : bs)
Note that we got rid of the length xs and xs !! n operations too.
As an exercise, another short duplicate function can be written by zipping over the inits and tails of the squares list.
Seems obvious to me :). In list comprehensions, the later lists can depend on the values generated in the earlier ones. The second function generates your set by calling the first when it adds a wumpus..
p 0 = [[]]
p n = [[x,' ']:xs | x <- [' ','P'], xs <- p (n-1)]
pw 0 = [[]]
pw n = [[x,w]:xs | w <- [' ','W'], x <- [' ','P'], xs <- if w == 'W' then p (n-1) else pw (n-1)]
it isn't as clean as possible, but I always find list comprehensions bring an elegance to the problem :). Totally worth it.