Haskell : force evaluation/avoid garbage collecting when composing functions - haskell

I was looking for an elegant way to write this code :
import Data.List
import Data.Maybe
combi = [(x,y) | x <- [2..100], y <- [x..100]]
gsp = group (sort [x*y | (x,y) <- combi])
counts = zip (map head gsp) (map length gsp)
multipleProducts x = (fromJust (lookup x counts)) > 1
possibleComb1 = [(x,y) | (x,y) <- combi, multipleProducts (x*y)]
As I am reusing the same pattern multiple times but based on different input sets than [x*y | (x,y) <- combi], I came out with this code.
import Data.List
import Data.Maybe
combi = [(x,y) | x <- [2..100], y <- [x..100]]
onlyOneEl e x = (fromJust (lookup x counts)) == 1
where gs = group (sort e)
counts = zip (map head gs) (map length gs)
multipleProducts = not.(onlyOneEl [x*y | (x,y) <- combi])
possibleComb1 = [(x,y) | (x,y) <- combi, multipleProducts (x*y)]
However, Haskell seems to compute gs and count for every single time I call multipleProducts, taking a very big amount of time, instead of computing it only once, since the value of e is always the same with multipleProducts.
What is the most elegant way of avoiding the recalculation ?
Is there anything better than pre-calculating counts using one function and storing it in a local variable, and then passing it to onlyOneEl without the where ?
Because I'm later reusing onlyOneEl based on different sets, and I wanted to avoid having multiple counts variables.
I understood here why it did not evaluate it once per function, however, I do not use x as my last argument, and thus cannot do it exactly this way.
Thanks in advance !

You can rewrite it with little more goal oriented. Without getting into math, just with generation of data and filtering you can achieve the same with much less computation.
When you generate the product, add the multipliers to the tuple as well, i.e.
combi n = [((x,y),x*y) | x<-[2..n], y<-[x..n]]
now you can sort and group based on product
multi = filter ((>1) . length) . groupBy ((==) `on` snd) . sortBy (comparing snd) . combi
and extract the first element of the tuple, which will be the (x,y) pair to give same product more than once.
map (map fst) (multi 100)
if you don't care about the grouping, you can flatten the result, i.e.
concatMap (map fst) (multi 100)

The definition
onlyOneEl e x = fromJust (lookup x counts) == 1
where gs = group (sort e)
counts = zip (map head gs) (map length gs)
says "given e and x, set up the computations of gs and counts and use their (lazily calculated) results to calculate the expression fromJust (lookup x counts) == 1. You could write it completely equivalently as
onlyOneEl e x =
let gs = ...
counts = ...
in fromJust ...
On the other hand, if you move the x over to the other side with a lambda expression,
onlyOneEl e = \x -> fromJust ...
where ...
then you pull gs and counts into an outer scope. This code is equivalent to
onlyOneEl e =
let gs = ...
counts = ...
in \x -> fromJust ...
So gs and counts will only be calculated once per application of onlyOneEl to a single argument.
GHC supports a transformation called "full laziness" that does this kind of modification, which it applies when it thinks it will be a good idea. Apparently, GHC made the wrong judgement in this case.

Related

Count occurences in a list and return it in another list

I want to do a function called countAll. This function should get a list of numbers and return a list (element,number of occurences). For example :
countAll [1,2,3,4,4,4] should return
[(1,1),(2,1),(3,1),(4,3)]
I am forced to use function count which i posted below.
count :: Eq a=> a -> [a] -> Int
count e [] = 0
count e (x:xs)
| e == x = 1 + count e xs
| otherwise = count e xs
Using a fast data-structure, for example Data.IntMultiSet. Let ls = [1,2,3,4,4,4]
import qualified Data.IntMultiSet as IntMultiSet
IntMultiSet.fromList ls
An alternative using IntMap:
import qualified Data.IntMap.Strict as IntMap
IntMap.fromListWith (+) [(k,1) | k <- ls]
We can do better than nub (which is O(n^2)) if the list elements are also instances of Ord without requiring the heavy machinery of an IntMultiSet by putting like elements together with sort and then grouping them into sublists with group. For example, group . sort $ [1,2,3,4,4,4] gives [[1], [2], [3], [4,4,4]].
Once we have these items organized into sublists, we can count each sublist:
countAll = map (\(x:xs) -> (x, count x (x:xs))) . group . sort
(Note that group guarantees that there won't be any empty sublists so we know that we don't need to check the [] case in our mapped function even though the compiler does not.)
If we don't need to use count, we can instead use
countAll = map (\xs -> (head xs, length xs)) . group . sort
or, with the handy (&&&) combinator from Control.Arrow,
countAll = map (head &&& length) . group . sort
Since an association list of elements with their counts is a handy way to represent a bag, I like to call this
bag = map (head &&& length) . group . sort
bag is O(n log n), which is only a log factor worse than the IntMultiSet version.
One way of doing it is with list comprehension:
countAll xs = nub [(x, count x xs) | x <- xs]
nub removes the duplicates and you will need to import Data.List (nub) to use it.

How does listx2 = [x * 2 | x<- numberList] work?

So I m watching a very basic Tutorial, and I m at list comprehension where this comes up:
listx2 = [x * 2 | x<- numberList]
with numberList being a list of numbers
So this takes every number in the list and duplicates it, so numberList = [1,2] results in [2,4].
But HOW does the whole Syntax come together?
I know that x * 2 is the doubleing, but the rest just doesn't make sense to me.
| is the "or" Symbol as far as I know,and what does it do there?
x <- numberList gives x a number from the list, but why does it take just a number? and why so nicely one after the other? There is no recursion or anything that tells it to do one element at a time...
I learn stuff by understanding it, so is that even possible here or do I just have to accept this as "thats how it goes" and memorize the pattern?
List comprehensions use their own special syntax, which is
[ e | q1, q2, ..., qn ]
The | is not an "or", it's part of the syntax, just as [ and ].
Each qi can be of the following forms.
x <- list chooses x from the list
condition is a boolean expression, which discards the xs chosen before if the condition is false
let y = expression defines variable y accordingly
Finally, e is an expression which can involve all the variables defined in the qi, and which forms the elements in the resulting list.
What you see is syntactical sugar. So Haskell does not interpret the pipe (|) as a guard, etc. It sees the list comprehension as a whole.
This however does not mean that the <- are picked at random. Actually list comprehension maps nicely on the list monad. What you see is syntactical sugar for:
listx2 = do
x <- numberList
return x*2
Now a list type [] is actually a monad. It means that we have written:
listx2 = numberList >>= \x -> return (x*2)
Or even shorter:
listx2 = numberList >>= return . (*2)
Now the list monad is defined as:
instance Monad [] where
return x = [x]
xs >>= k = concat $ fmap k xs
So this means that it is equivalent to:
listx2 = numberList >>= return . (*2)
listx2 = concat (fmap (return . (*2)) numberList)
listx2 = concat (fmap (\x -> [2*x]) numberList)
Now for a list fmap is equal to map, so:
listx2 = concat $ map (\x -> [2*x]) numberList
listx2 = concatMap (\x -> [2*x]) numberList
so that means that for every element x in the numberList we will generate a singleton list [2*x] and concatenate all these singleton lists into the result.

generate binary one bit change between all members

ı have a question. ı want to generate binary list .but between members of the list will be only one bit change.
oneBitAll :: Integral a => a -> [[String]]
for n=2
Output:
["00","01","11","10"] ve ["00","10","11","01"]
n=3
oneBitAll 3
[["000","001","011","010","110","111","101","100"], ["000","001","011","111","101","100","110","010"], ["000","001","101","100","110","111","011","010"], ["000","001","101","111","011","010","110","100"], ["000","010","011","001","101","111","110","100"], .....]
only one bit change between members.
please help.
this gives only one
g 0 = [""]
g n = (map ('0':)) (g (n-1)) ++ (map ('1':)) (reverse (g (n-1)))
gray code is true for this.but ı want to find all combinations.
how can I generate all possible gray codes for given n number?
permute [] = [[]]
permute xs = concatMap (\x -> map (x:) $ permute $ delete x xs) xs
g 0 = [""]
g n = (map ('0':)) (g (n-1)) ++ (map ('1':)) (reverse (g (n-1)))
oneBitAll n = (map transpose . permute . transpose $ g n)
This code generate half of possibilities.What can ı add this code?this code generates;
[["000","001","011","010","110","111","101","100"],["000","010","011","001","101","111","110","100"],["000","001","101","100","110","111","011","010"],["000","010","110","100","101","111","011","001"],["000","100","101","001","011","111","110","010"],["000","100","110","010","011","111","101","001"]]
but must generate 12 members.
There is probably a smarter way to do this that exploits more of the structure of gray codes. This way is sort of quick and dirty, but it seems to work fairly well.
The basic idea is we'll generate all sequences of bitstrings, then filter out the ones that aren't gray codes. We'll be slightly more clever, though, in that we'll check prefixes of each sequence to make sure they could plausibly be extended to a gray code, and prune prefixes that can't be.
For our purposes, a gray code will have five properties:
Each pair of consecutive bitstrings differs in exactly one place.
The sequence is cyclic: the first and last bitstring also differ in exactly one place.
No two bitstrings in a sequence are equal.
A code with bitstring length n has 2^n elements.
To break the cyclic symmetry, every code will start with the all-zero bitstring.
Three of these properties can be expressed on code prefixes:
import Control.Monad
import Data.List
validCodePrefix xss = nearbyPairs && unique && endsWithZeros where
nearbyPairs = all (uncurry nearby) (zip xss (tail xss))
unique = all ((1==) . length) . group . sort $ xss
endsWithZeros = all (all (=='0')) (take 1 (reverse xss))
nearby xs xs' = length [() | (x, x') <- zip xs xs', x /= x'] == 1
The cyclic condition applies only to completed codes, and can be written as:
cyclic xss = nearby (head xss) (last xss)
We can implement the search and enforce the length condition at the same time, by repeatedly choosing from all appropriate length bitstrings, and keeping only those ones that are valid:
codes n = go (2^n) [] where
go 0 code = [reverse code | cyclic code]
go i code = do
continuation <- replicateM n "01"
guard (validCodePrefix (continuation:code))
go (i-1) (continuation:code)

Haskell - Most frequent value

how can i get the most frequent value in a list example:
[1,3,4,5,6,6] -> output 6
[1,3,1,5] -> output 1
Im trying to get it by my own functions but i cant achieve it can you guys help me?
my code:
del x [] = []
del x (y:ys) = if x /= y
then y:del x y
else del x ys
obj x []= []
obj x (y:ys) = if x== y then y:obj x y else(obj x ys)
tam [] = 0
tam (x:y) = 1+tam y
fun (n1:[]) (n:[]) [] =n1
fun (n1:[]) (n:[]) (x:s) =if (tam(obj x (x:s)))>n then fun (x:[]) ((tam(obj x (x:s))):[]) (del x (x:s)) else(fun (n1:[]) (n:[]) (del x (x:s)))
rep (x:s) = fun (x:[]) ((tam(obj x (x:s))):[]) (del x (x:s))
Expanding on Satvik's last suggestion, you can use (&&&) :: (b -> c) -> (b -> c') -> (b -> (c, c')) from Control.Arrow (Note that I substituted a = (->) in that type signature for simplicity) to cleanly perform a decorate-sort-undecorate transform.
mostCommon list = fst . maximumBy (compare `on` snd) $ elemCount
where elemCount = map (head &&& length) . group . sort $ list
The head &&& length function has type [b] -> (b, Int). It converts a list into a tuple of its first element and its length, so when it is combined with group . sort you get a list of each distinct value in the list along with the number of times it occurred.
Also, you should think about what happens when you call mostCommon []. Clearly there is no sensible value, since there is no element at all. As it stands, all the solutions proposed (including mine) just fail on an empty list, which is not good Haskell. The normal thing to do would be to return a Maybe a, where Nothing indicates an error (in this case, an empty list) and Just a represents a "real" return value. e.g.
mostCommon :: Ord a => [a] -> Maybe a
mostCommon [] = Nothing
mostCommon list = Just ... -- your implementation here
This is much nicer, as partial functions (functions that are undefined for some input values) are horrible from a code-safety point of view. You can manipulate Maybe values using pattern matching (matching on Nothing and Just x) and the functions in Data.Maybe (preferable fromMaybe and maybe rather than fromJust).
In case you would like to get some ideas from code that does what you wish to achieve, here is an example:
import Data.List (nub, maximumBy)
import Data.Function (on)
mostCommonElem list = fst $ maximumBy (compare `on` snd) elemCounts where
elemCounts = nub [(element, count) | element <- list, let count = length (filter (==element) list)]
Here are few suggestions
del can be implemented using filter rather than writing your own recursion. In your definition there was a mistake, you needed to give ys and not y while deleting.
del x = filter (/=x)
obj is similar to del with different filter function. Similarly here in your definition you need to give ys and not y in obj.
obj x = filter (==x)
tam is just length function
-- tam = length
You don't need to keep a list for n1 and n. I have also made your code more readable, although I have not made any changes to your algorithm.
fun n1 n [] =n1
fun n1 n xs#(x:s) | length (obj x xs) > n = fun x (length $ obj x xs) (del x xs)
| otherwise = fun n1 n $ del x xs
rep xs#(x:s) = fun x (length $ obj x xs) (del x xs)
Another way, not very optimal but much more readable is
import Data.List
import Data.Ord
rep :: Ord a => [a] -> a
rep = head . head . sortBy (flip $ comparing length) . group . sort
I will try to explain in short what this code is doing. You need to find the most frequent element of the list so the first idea that should come to mind is to find frequency of all the elements. Now group is a function which combines adjacent similar elements.
> group [1,2,2,3,3,3,1,2,4]
[[1],[2,2],[3,3,3],[1],[2],[4]]
So I have used sort to bring elements which are same adjacent to each other
> sort [1,2,2,3,3,3,1,2,4]
[1,1,2,2,2,3,3,3,4]
> group . sort $ [1,2,2,3,3,3,1,2,4]
[[1,1],[2,2,2],[3,3,3],[4]]
Finding element with the maximum frequency just reduces to finding the sublist with largest number of elements. Here comes the function sortBy with which you can sort based on given comparing function. So basically I have sorted on length of the sublists (The flip is just to make the sorting descending rather than ascending).
> sortBy (flip $ comparing length) . group . sort $ [1,2,2,3,3,3,1,2,4]
[[2,2,2],[3,3,3],[1,1],[4]]
Now you can just take head two times to get the element with the largest frequency.
Let's assume you already have argmax function. You can write
your own or even better, you can reuse list-extras package. I strongly suggest you
to take a look at the package anyway.
Then, it's quite easy:
import Data.List.Extras.Argmax ( argmax )
-- >> mostFrequent [3,1,2,3,2,3]
-- 3
mostFrequent xs = argmax f xs
where f x = length $ filter (==x) xs

Finding n such that f n is maximized in Haskell

I am using Project Euler problems to learn Haskell and I find a recurring theme in many of these problems where I need to find a value n that gives some property (usually minimum or maximum) to a function f n. As I build up a solution, I often find it convenient to create a list of pairs (n, f n). This helps me quickly see if I have any errors in my logic because I can check against the examples given in the problem statement. Then I "filter" out the single pair that gives the solution. My solution to problem 47 is an example:
-- Problem 47
import Data.List
import ProjectEuler
main = do
print (fst (head (filter (\(n, ds) -> (all (==consecutiveCount) ds))
(zip ns (map (map length)
(map (map primeDivisors) consecutives))))))
where consecutiveCount = 4
consecutive n start = take n [start..]
consecutives = map (consecutive consecutiveCount) ns
ns = [1..]
It seems to me that there's a more "haskelly" way to do this. Is there?
Use maximumBy from Data.List with comparing from Data.Ord, e.g.
maximumBy (comparing snd) [(n, f n) | n <- ns]
this will compute f once for each n. If f is cheap to compute, you can go with the simpler
maximumBy (comparing f) ns
Well, you could write your function as
main = print $ fst $ head
[ (x,ds) | x <- [1..]
, let ds=map primeDivisors [x..x+3], all ((==4).length) ds]
You could consider it "more Haskelly" to use Control.Arrow's (&&&), or "fan-out"
filter (all ((==4).length).snd)
. map (id &&& (\x-> map primeDivisors [x..x+3])) $ [1..]
To be able to tweak the code to try the simple examples first, you'd usually make it a function, abstracting over the variable(s) of interest, like so:
test n m = [ x | x <- [1..], all (==n) $ map (length.primeDivisors) [x..x+m-1]]
to search for m consequitive numbers each having n distinct prime factors. There is actually no need to carry the factorizations along in the final code.

Resources