I wanted to create the function genAllSize ::[a] -> [[a]], that receives a list l and generates all the lists sorted by size that can be built with the elements of the list l; i.e.
> genAllSize [2,4,8]
[[],[2],[4],[8],[2,2],[4,2],[8,2],[2,4],[4,4],[8,4],[2,8],[4,8],[8,8],[2,2,2],[4,2,2],[8,2,2], ...
How would you do it? I came up with a solution using permutations from Data.List but I do not want to use it.
Given an input list xs, select a prefix of that in a non deterministic way
For each element in the prefix, replace it with any element of xs, in a non deterministic way
Result:
> xs = [2,4,8]
> inits xs >>= mapM (const xs)
[[],[2],[4],[8],[2,2],[2,4],[2,8],[4,2],[4,4],[4,8],[8,2],[8,4],
[8,8],[2,2,2],[2,2,4],[2,2,8],[2,4,2],[2,4,4],[2,4,8],[2,8,2],
[2,8,4],[2,8,8],[4,2,2],[4,2,4],[4,2,8],[4,4,2],[4,4,4],[4,4,8],
[4,8,2],[4,8,4],[4,8,8],[8,2,2],[8,2,4],[8,2,8],[8,4,2],[8,4,4],
[8,4,8],[8,8,2],[8,8,4],[8,8,8]]
The other answers seem sort of complicated. I'd do it this way:
> [0..] >>= flip replicateM "abc"
["","a","b","c","aa","ab","ac","ba","bb","bc","ca","cb","cc","aaa","aab",...
Hmm I guess you a need a lazy infinite list of cycling subsequences. One naive way could be like
Prelude> take 100 $ nub . subsequences . cycle $ [2,4,8]
[[],[2],[4],[2,4],[8],[2,8],[4,8],[2,4,8],[2,2],[4,2],[2,4,2],[8,2],[2,8,2],[4,8,2],[2,4,8,2],[4,4],[2,4,4],[8,4],[2,8,4],[4,8,4],[2,4,8,4],[2,2,4],[4,2,4],[2,4,2,4],[8,2,4],[2,8,2,4],[4,8,2,4],[2,4,8,2,4],[8,8],[2,8,8],[4,8,8],[2,4,8,8],[2,2,8],[4,2,8],[2,4,2,8],[8,2,8],[2,8,2,8],[4,8,2,8],[2,4,8,2,8],[4,4,8],[2,4,4,8],[8,4,8],[2,8,4,8],[4,8,4,8],[2,4,8,4,8],[2,2,4,8],[4,2,4,8],[2,4,2,4,8],[8,2,4,8],[2,8,2,4,8],[4,8,2,4,8],[2,4,8,2,4,8],[2,2,2],[4,2,2],[2,4,2,2],[8,2,2],[2,8,2,2],[4,8,2,2],[2,4,8,2,2],[4,4,2],[2,4,4,2],[8,4,2],[2,8,4,2],[4,8,4,2],[2,4,8,4,2],[2,2,4,2],[4,2,4,2],[2,4,2,4,2],[8,2,4,2],[2,8,2,4,2],[4,8,2,4,2],[2,4,8,2,4,2]]
A simple and highly efficient option:
genAllSize [] = [[]]
genAllSize [a] = iterate (a:) []
genAllSize xs =
[] : [x:q|q<-genAllSize xs,x<-xs]
(Thanks to Will Ness for a small but very nice simplification.)
This solution takes advantage of the fact that a valid solution list is either empty or an element of the argument list consed onto a shorter valid solution list. Unlike Daniel Wagner's solution, this one doesn't resort to counting. My tests suggest that it performs extremely well under typical conditions.
Why do we need a special case for a one-element list? The general case performs extremely badly for that, because it maps over the same list over and over with no logarithmic slowdown.
But what's the deal with that call to genAllSizes with the very same argument? Wouldn't it be better to save the result to increase sharing?
genAllSize [] = [[]]
genAllSize xs = p
where
p = [] : [x:q|q<-p,x<-xs]
Indeed, on a theoretical machine with unlimited constant-time memory, this is optimal: walking the list takes worst-case O(1) time for each cons. In practice, it's only a good idea if a great many entries will be realized and retained. Otherwise, there's a problem: most of the list entries will be retained indefinitely, dramatically increasing memory residency and the amount of work the garbage collector needs to do. The non-bold sharing version above still offers amortized O(1) time per cons, but it needs very little memory (logarithmic rather than linear).
Examples
genAllSize "ab" =
["","a","b","aa","ba"
,"ab","bb","aaa","baa"
,"aba","bba","aab","bab"
,"abb","bbb","aaaa",...]
genAllSize "abc" =
["","a","b","c","aa","ba"
,"ca","ab","bb","cb","ac"
,"bc","cc","aaa","baa"
,"caa","aba","bba","cba"
,"aca",...]
An explicit option
You can also use two accumulators:
genAllSize [] = [[]]
genAllSize [a] = iterate (a:) []
genAllSize (x:xs) = go ([], []) where
go (curr, remain) = curr : go (step curr remain)
step [] [] = ([x], [xs])
step (_:ls) ((r:rs):rss) =
(r:ls, rs:rss)
step (_:ls) ([] : rs) =
(x : ls', xs : rs')
where
!(ls', rs') = step ls rs
This version keeps track of the current "word" and also the remaining available "letters" in each position. The performance seems comparable in general, but a bit better with regard to memory residency. It's also much harder to understand!
This produces the elements in a different order within each length than your example, but it meets the definition of the text of your question. Changing the order is easy - you have to replace <*> with a slightly different operator of your own making.
import Control.Applicative
import Control.Monad
rinvjoin :: Applicative both => both a -> both (both a)
rinvjoin = fmap pure
extendBranches options branches = (<|>) <$> options <*> branches
singletonBranchExtensions = rinvjoin
genAllSize [] = []
genAllSize xs = join <$> iterate (extendBranches extensions) $ initialBranches
where extensions = singletonBranchExtensions xs
initialBranches = pure empty
I have two strings
a :: [String]
a = ["A1","A2","B3","C3"]
and
b :: [String]
b = ["A1","B2","B3","D5"]
And I want to calculate the difference between two strings based on the first character and second character and combination of two characters.
If the combination of two elements are the same, it would be calculate as 1
The function I declared is
calcP :: [String] -> [String] -> (Int,[String])
calcP (x:xs) (y:ys) = (a,b)
where
a = 0 in
???
b = ????
I know that I should have a increment variable to count the correct element, and where I should put it in? For now I totally have no idea about how to do that, can anyone give me some hint??
The desired result would be
(2,["B2","D5"])
How should I do that?
I assume that the lists have the same size.
The differences between the two lists
Let's focus on the main part of the problem:
Prelude> a=["A1","A2","B3","C3"]
Prelude> b=["A1","B2","B3","D5"]
First, notice that the zip method zips two lists. If you use it on a and b, you get:
Prelude> zip a b
[("A1","A1"),("A2","B2"),("B3","B3"),("C3","D5")]
Ok. It's now time to compare the terms one to one. There are many ways to do it.
Filter
Prelude> filter(\(x,y)->x/=y)(zip a b)
[("A2","B2"),("C3","D5")]
The lambda function returns True if the elements of the pair are different (/= operator). Thus, the filter keeps only the pairs that don't match.
It's ok, but you have to do a little more job to keep only the second element of each pair.
Prelude> map(snd)(filter(\(x,y)->x/=y)(zip a b))
["B2","D5"]
map(snd) applies snd, which keeps only the second element of a pair, to every discordant pair.
Fold
A fold is more generic, and may be used to implement a filter. Let's see how:
Prelude> foldl(\l(x,y)->if x==y then l else l++[y])[](zip a b)
["B2","D5"]
The lambda function takes every pair (x,y) and compares the two elements. If they have the same value, the accumulator list remains the identical, but if the values are different, the accumulator list is augmented by the second element.
List comprehension
This is more compact, and should seem obvious to every Python programmer:
Prelude> [y|(x,y)<-zip a b, x/=y] -- in Python [y for (x,y) in zip(a,b) if x!= y]
["B2","D5"]
The number of elements
You want a pair with the number of elements and the elements themselves.
Fold
With a fold, it's easy but cumbersome: you will use a slightly more complicated accumulator, that stores simultaneously the differences (l) and the number of those differences (n).
Prelude> foldl(\(n,l)(x,y)->if x==y then (n,l) else (n+1,l++[y]))(0,[])$zip a b
(2,["B2","D5"])
Lambda
But you can use the fact that your output is redundant: you want a list preceeded by the length of that list. Why not apply a lambda that does the job?
Prelude> (\x->(length x,x))[1,2,3]
(3,[1,2,3])
With a list comprehension, it gives:
Prelude> (\x->(length x,x))[y|(x,y)<-zip a b, x/=y]
(2,["B2","D5"])
Bind operator
Finally, and for the fun, you don't need to build the lambda this way. You could do:
Prelude> ((,)=<<length)[y|(x,y)<-zip a b,x/=y]
(2,["B2","D5"])
What happens here? (,) is a operator that makes a pair from two elements:
Prelude> (,) 1 2
(1,2)
and ((,)=<<length) : 1. takes a list (technically a Foldable) and passes it to the length function; 2. the list and the length are then passed by =<< (the "bind" operator) to the (,) operator, hence the expected result.
Partial conclusion
"There is more than than one way to do it" (but it's not Perl!)
Haskell offers a lot of builtins functions and operators to handle this kind of basic manipulation.
What about doing it recursively? If two elements are the same, the first element of the resulting tuple is incremented; otherwise, the second element of the resulting tuple is appended by the mismatched element:
calcP :: [String] -> [String] -> (Int,[String])
calcP (x:xs) (y:ys)
| x == y = increment (calcP xs ys)
| otherwise = append y (calcP xs ys)
where
increment (count, results) = (count + 1, results)
append y (count, results) = (count, y:results)
calcP [] x = (0, x)
calcP x [] = (0, [])
a = ["A1","A2","B3","C3"]
b = ["A1","B2","B3","D5"]
main = print $ calcP a b
The printed result is (2,["B2","D5"])
Note, that
calcP [] x = (0, x)
calcP x [] = (0, [])
are needed to provide exhaustiveness for the pattern matching. In other words, you need to provide the case when one of the passed elements is an empty list. This also provides the following logic:
If the first list is greater than the second one on n elements, these n last elements are ignored.
If the second list is greater than the first one on n elements, these n last elements are appended to the second element of the resulting tuple.
I'd like to propose a very different method than the other folks: namely, compute a "summary statistic" for each pairing of elements between the two lists, and then combine the summaries into your desired result.
First some imports.
import Data.Monoid
import Data.Foldable
For us, the summary statistic is how many matches there are, together with the list of mismatches from the second argument:
type Statistic = (Sum Int, [String])
I've used Sum Int instead of Int to specify how statistics should be combined. (Other options here include Product Int, which would multiply together the values instead of adding them.) We can compute the summary of a single pairing quite simply:
summary :: String -> String -> Statistic
summary a b | a == b = (1, [ ])
| otherwise = (0, [b])
Combining the summaries for all the elements is just a fold:
calcP :: [String] -> [String] -> Statistic
calcP as bs = fold (zipWith summary as bs)
In ghci:
> calcP ["A1", "A2", "B3", "C3"] ["A1", "B2", "B3", "D5"]
(Sum {getSum = 2},["B2","D5"])
This general pattern (of processing elements one at a time into a Monoidal type) is frequently useful, and spotting where it's applicable can greatly simplify your code.
I have two lists in Haskell.
Original list containing string values:
["Hello", "HELLO", "", "WORLD", "xxx", "world"]
Index list containing integer values where the strings are all upper case in the original list:
[1,3]
I incremented all the values in the index list with a function I created and make index2 list, overall it looks like this:
My code:
import Data.List
import Data.Char
import Data.Maybe
main = do
contents <- readFile "h.txt"
let original = lines (contents)
let allUpper = lines (map toUpper contents)
let onlyUpper = filter(/="") (intersect original allUpper)
let upperIndex = findIndices ('elem' onlyUpper) original
let index2 = (map increment upperIndex)
print index2
increment :: Int -> Int
increment x = x+1
I have managed to came this far with the help of yours. However, since I am a beginner I do not seem to understand how iteration over lists works.
The thing I want to accomplish is to check whether the corresponding index values (in index2) are empty or not in the original list, if they are empty, I want to remove them in index2.
Filtering empty elements
The thing I want to accomplish is to check whether the corresponding
index values (in index2) are empty or not in the original list, if
they are empty, I want to remove them in index2.
The code already filters out empty elements! Look at the following line:
let onlyUpper = filter(/="") (intersect original allUpper)
This line does two things:
it keeps only elements which are constituted only with uppercase letters(intersect original allUpper),
it filters out empty elements (filter(/="")).
If by empty elements you mean strings which contains only space characters or nothing, you can use instead:
filter (all isSpace)
Iterating over lists
I do not seem to understand how iteration over lists works.
In Haskell, lists are single chained lists: each element contains a value and a reference to the next value.
Therefore lists are not indexed: the !! operator have to go through each element to access a specific element making lists completely inefficient when dealing with direct access.
When you’re submitting a list to a function, you simply give it the first element.
With these considerations, when you work on lists, you have to avoid accessing elements via their index.
The idea is to create functions which do their job on simple values and mapping them to list of elements. Take a look at the toUpper function:
toUpper :: Char -> Char
It takes a Char and returns its uppercased version (also a Char).
Haskell does not have a toUpper function which works on String, you have to use something like map or <$> to apply toUpper to a list of char (a String):
map toUpper "ab" -- "AB"
toUpper <$> "ab" -- "AB"
The idea is to have functions which does only one specific thing. Upercasing and iterating over a list are two different things. Does the toUpper function need to know the index of the element it will uppercase? No!
Iterating over a list with index
You may ask: but what if my function REALLY need to consider the index of the elements? (ie: for filtering out even or odd elements).
You have two way of considering it:
a List is not the type you need to work with. Maybe Data.Map, Data.IntMap or Data.Vector are better suited for the task (see these modules for more information),
you need to use an intermediate type which will hold the index.
For example:
let string = "abcde"
let indexedString = zip [1..] string
print indexedString -- [(1, 'a'), (2, 'b), (3, 'c), (4, 'd), (5, 'e)]
Note that this also solves your need of an increment function since the index is started at whatever value you want.
To go back to the original string, you write:
map snd indexedString -- "abcde"
You need to use the fst and snd functions to work with the intermediate type, or to use pattern matching:
filter (\x -> snd x == 'b') indexedString -- [(2, 'b')]
map (\(i,s) -> (i, toUpper s)) indexedString -- [(1,'A'),(2,'B'),(3,'C'),(4,'D'),(5,'E')]
Taking the index into account:
let string = "abcde"
indexedString = zip [1..] string
upperEven (i, c) | even i = (i, toUpper c)
| otherwise = (i, c)
print $ map upperEven indexedString -- [(1,'a'),(2,'B'),(3,'c'),(4,'D'),(5,'e')]
print $ map snd $ map upperEven indexedString -- "aBcDe"
Notes
The increment function already exists in Haskell, it’s called succ (it is also a more generic function which works on every types supporting the Enum class like Int, Char…)
Why not use words :: String -> [String] on the contents you get from a file? Using lines :: String -> [String] would be an alternative if you had one word per line.
Then if i get your problem right, you could write the following to solve your problem:
import Data.List (findIndices)
import Data.Char (isUpper)
allUpperOneBasedIndices :: String -> [Int]
allUpperOneBasedIndices = map succ . findIndices (all isUpper) . words
Problem
i have list of int as [123,123] which i required to be as [1,2,3,1,2,3]
Current Code
i tried out the following code using recursion
fat::[Int]->[Int]
fat [] = []
fat (a,b,c:xs) = a : b : c : fat xs
Conclusions
i have no idea how to acess values as '1' , '2 , '3 in a list [123,123] separetly
I suggest to use the digs function given in this answer on each element of your list. It splits an Int into a list of digits ([Int]). Then you just need to concatenate the resulting lists. This 'map and concatenate results' requirement is a perfect job for concatMap
fat :: [Int] -> [Int]
fat = concatMap digs
This gives:
*Main> fat [123,123]
[1,2,3,1,2,3]
Which is what you want, if I understood correctly.
splitNum :: Int -> [Int]
splitNum n | n <= 9 = [n]
| otherwise = (splitNum (n `div` 10)) ++ [n `mod` 10]
fat :: [Int] -> [Int]
fat x = concatMap splitNum x
splitNum is used to convert an Int to a [Int] by splitting it into the division by ten reminders and appending the resulting Int to the splitted rest (recursion!)
Now, having a function that converts numbers into lists, go through input, apply splitNum to any Number in the inner list and concat all resulting lists (list comprehension!)
As a new Haskell programmer I will give you my thoughts of this problem. Just because I think it's good to have many alternatives, especially from different people with different experience.
Here's my take on the problem:
For each item in the list, convert that item to a char list using read.
Send that char list into a function which converts each item of that list into an int, then return an list of ints.
Concat that list of ints into the main list.
To clarify:
[123, 234]
123 turns into ['1', '2', '3']
['1', '2', '3'] turns into [1, 2, 3]
[1, 2, 3] gets concat in the main list
the cycle repeats for 234.
The util function would look something like this:
import Char
charsToInts :: [Char] -> [Int]
charsToInts [] = []
charsToInts (x:xs) = digitToInt x : charsToInts xs
Coming from a imperative background that's how I would have solved it. Probably slower than just splitting the number mathematically, but I thought it would be interesting to show a alternative.
To pinpoint the problem bluntly, you have no idea how to access the digits separately because you do not understand Haskell types and pattern matching. Let me try to help dispel some of your misconceptions.
Let's look at your list:
[123, 123]
What is its type? It is clearly a list of ints, or [Int]. With lists, you can pattern match on the constructor :, known to lispers as "cons", or "list constructor". You put a single element on the left side of the :, and another list on the right side. The list on the right side can be the empty list [], which basically indicates the end of the list. Haskell provides "syntactic sugar" to make lists easier to write, but [123,456] actually gets desugared into 123:(456:[]). So when you pattern match (x:y:z), you can now see that x will be assigned 123 and y will be assigned 456. z will be the rest of the list after x and y; in this case only [] is left.
Now then, pattern matching with : works for lists. Ints are not lists, so you can't use : to pattern match on the digits of an Int. However, Strings are lists, because String is the same as [Char]. So if you turn your Int into a String then you can pattern match on each character.
map show [123, 123]
map applies a function to all elements of a list. show can take an Int and turn it into a String. So we map show over the list of Ints to get a list of Strings.
["123", "123"]
Now let's turn those Strings into lists of Ints. Since String is simply [Char], we will again make use of map.
map digitToInt "123" -- this requires that you import Data.Char (digitToInt)
This will give us [1,2,3]; each Char in the list is turned into an Int. This is what we want to do to each String in our list ["123", "123"]. We want to map digitToInt to each String. But we have a list of Strings. So what do we do? We map it!
map (map digitToInt) ["123", "123"]
This will give us [[1,2,3], [1,2,3]]. Almost what we wanted. Now we just have to flatten the list of list of Ints ([[Int]]) into just a list of Int ([Int]). How can we do that? Stop...Hoogle time! Hoogling [[a]] -> [a] we find the very first hit, concat, is exactly what we wanted.
Let's put it all together. First we do map show to get from [Int] to [String]. Then we do map (map digitToInt) to get from [String] to [[Int]]. Then we do concat to get from [[Int]] to [Int]. Then we'll just print it out!
import Data.Char (digitToInt)
main = print $ concat $ map (map digitToInt) $ map show $ [123, 123]
Now let's pull most of that out into a function fat
import Data.Char (digitToInt)
main = print $ fat [123, 123]
fat :: [Int] -> [Int]
fat xs = concat $ map (map digitToInt) $ map show $ xs
From here you could make it prettier in a few different ways. concat $ map is the same as concatMap, and since we map both (map digitToInt) and show in sequence, we can merge those. Also making it pointfree, we can end up with quite a terse definition:
fat = concatMap (map digitToInt . show)
For the sake of completeness, I wrote it as suggested by #Ancide
Implementation
fat' :: [Int] -> [Int]
fat' l = map (read) [[z] | z <- [x | k <- (map (show) l), x <- k]]
Explanation:
{- last result -} stands for the result of the last code explained.
map (show) l
This takes every element inside l and converts it to [String].
[x | k <- {- last result -}, x <- k]
While k goes through all elements inside the last result, x enumerates all character in each k. All those are added to a list. Now you have a String, respectively a [Char] with all digits next to each others.
[[z] | z <- {- last result -}]
This part takes each Char from the String and puts it into an empty String. Notice the [z] part! This make a list around z, which is (see above) the same as String. Now you have a list of String with a String for each digit.
map (read) {- last result -}
This takes every item in the last result and converts it back to Int and joins them to [Int]. Now you have a list of type [Int] of the wanted result.
Resumé
Although this implementation is possible, it's neither fast, due to all the type conversions, nor readable.
Playing around with the list monad I came up with this. Pretty much the same #Ankur's solution, except using the list monad:
fat :: [Int] -> [Int]
fat is = is >>= show >>= return . digitToInt
If you had two numbers, a and b then you could turn them into a single number by doing 10*a + b. The same principles apply for three.
It sounds like one way of doing this would be to splitEvery into lumps of three and then map a function to turn a list of three into a single number.
Does that help?
You need a function to convert Integer to string... which is obviously Show function
Another function to convert a Char to Integer which is "digitToInt" in module Char
And here we go :
fat::[Int]->[Int]
fat [] = []
fat ls = concat $ map (map digitToInt) (map show ls)
Please let me know if it works :)