Finding "gaps" in a list of numbers - haskell

I'm having trouble with going through a list. I made this code which gives me a list of numbers which are evenly divided by the sum of their digits. For example, consider the number 123: 123/6 = 20.5, so it will not be in the list. One the other hand 280 will be on the list, because 280/10 = 28.
let inaHelper x = (floor(x)`mod`10)+ (floor(x/10)`mod`10)+(floor(x/100)`mod`10)
let ina = [x | x <- [1..999] , x `mod` (inaHelper x) == 0 ]
[1,2,3,4,5,6,7,8,9,10,12,18,20,21,24,27,30,36,40,42,45,48,50,54,60,63,70,72,80,81,84,90,100,102,108,110,111,112,114,117,120,126,132,133,135,140,144,150,152,153,156,162,171,180,190,192,195,198,200,201,204,207,209,210,216,220,222,224,225,228,230,234,240,243,247,252,261,264,266,270,280,285,288,300,306,308,312,315,320,322,324,330,333,336,342,351,360,364,370,372,375,378,392,396,399,400,402,405,407,408,410,414,420,423,432,440,441,444,448,450,460,465,468,476,480,481,486,500,504,506,510,511,512,513,516,518,522,531,540,550,552,555,558,576,588,592,594,600,603,605,612,621,624,629,630,640,644,645,648,660,666,684,690,700,702,704,711,715,720,730,732,735,736,738,756,770,774,777,780,782,792,800,801,803,804,810,820,825,828,832,840,846,864,870,874,880,882,888,900,902,910,912,915,918,935,936,954,960,966,972,990,999]
But my problem now is: from the list above I only want the numbers that will not have a "neighbour" within a gap of 5 units. For example, the number 300 will be in the new list because it's neighbors (288 and 306) are not within the 5 unit gap.
I came up it this code:
let rare = [ x | x <- [ina] , ((x-5) >= [ina-1]) && ((x+5) <= [ina+1]) ]
I'm a beginner, can someone help?

An easy, though not very efficient, way would be to make a helper function which checks whether there is an element of a list within a certain range:
hasElemInRange :: (Int,Int) -> [Int] -> Bool
hasElemInRange (lo, hi) xs = -- left as exercise
(hint: you can use the any function)
and then you can include it in your list comprehension:
let rare = [ x | x <- ina, hasElemInRange (x-5,x+5) ina ]
Another idiom that you might consider is zipping a list with its own tail. So you can do:
ghci> let xs = [1,2,3,4,5,6,7]
ghci> zip3 xs (tail xs) (tail (tail xs))
[(1,2,3),(2,3,4),(3,4,5),(4,5,6),(5,6,7)]
Which will give you each element of the list with its "context", the element just before and after. Maybe you can figure out how to use that for what you need.

Related

How do you find the list of all numbers that are multiples of only powers of 2, 3, and 5? [duplicate]

This question already has answers here:
Generating integers in ascending order using a set of prime numbers
(4 answers)
Closed 4 years ago.
I am trying to generate a list of all multiples which can be represented by the form , where a, b, and c are whole numbers. I tried the following,
[ a * b * c | a <- map (2^) [0..], b <- map (3^) [0..], c <- map (5^) [0..] ]
but it only lists powers of 5 and never goes on to 2 or 3.
Edit: My apologies, it seems that I did not clarify the question enough. What I want is an ordered infinite list, and while I could sort a finite list, I feel as if there may be a solution that is more efficient.
The reason why there are only powers of 5 is that Haskell tries to evaluate every possible c for a = 2^0 and b = 3^0 and only when it is finished it goes for a = 2^0 and b = 3^1.
So this way you can only construct a finite list like this:
[ a * b * c | a <- map (2^) [0..n], b <- map (3^) [0..n], c <- map (5^) [0..n] ]
for a given n.
My first idea was starting from lists of powers of 2, 3 and 5, respectively:
p2 = iterate (2 *) 1
p3 = iterate (3 *) 1
p5 = iterate (5 *) 1
It's also easy to merge two sorted streams:
fuse [] ys = ys
fuse xs [] = xs
fuse xs#(x : xs') ys#(y : ys')
| x <= y = x : fuse xs' ys
| otherwise = y : fuse xs ys'
But then I got stuck because fuse p2 (fuse p3 p5) doesn't do anything useful. It only produces multiples of 2, or 3, or 5, never mixing factors.
I couldn't figure out a purely generative solution, so I added a bit of filtering in the form of a set accumulator. The algorithm (which is quite imperative) is:
Initialize the accumulator to {1}.
Find and remove the smallest element from the accumulator; call it n.
Emit n.
Add {2n, 3n, 5n} to the accumulator.
Go to #2 if you need more elements.
The accumulator is a set because this easily lets me find and extract the smallest element (I'm using it as a priority queue, basically). It also handles duplicates that arise from e.g. computing both 2 * 3 and 3 * 2.
Haskell implementation:
import qualified Data.Set as S
numbers :: [Integer]
numbers = go (S.singleton 1)
where
go acc = case S.deleteFindMin acc of
(n, ns) -> n : go (ns `S.union` S.fromDistinctAscList (map (n *) [2, 3, 5]))
This works, but there are things I don't like about it:
For every element we emit (n : ...), we add up to three new elements to the accumulator (ns `S.union` ... [2, 3, 5]). ("Up to three" because some of them may be duplicates that will be filtered out.)
That means numbers carries around a steadily growing data structure; the more elements we consume from numbers, the bigger the accumulator grows.
In that sense it's not a pure "streaming" algorithm. Even if we ignore the steadily growing numbers themselves, we need more memory and perform more computation the deeper we get into the sequence.
From your code:
[ a * b * c | a <- map (2^) [0..], b <- map (3^) [0..], c <- map (5^) [0..] ]
Since map (5^) [0..] is an infinite list, upon first iterations of a and b, it iterates over the said infinite list, which won't halt. That's why it is stuck at powers of 5.
Here is a solution apart from arithmetics. Note that map (2^) [0..], map (3^) [0..], and map (5^) [0..] are all lists sorted in ascending order. That means the usual merge operation is applicable:
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys
For convenience, let xs = map (2^) [0..]; let ys = map (3^) [0..]; let zs = map (5^) [0..].
To get multiples of 2 and 3, consider the following organization of said numbers:
1, 2, 4, 8, 16, ...
3, 6, 12, 24, 48, ...
9, 18, 36, 72, 144, ...
...
Judging by this, you might hope the following works:
let xys = foldr (merge . flip fmap xs . (*)) [] ys
But this doesn't work, because from the organization above, merge doesn't know which row contains the resulting head element, infinitely leaving it unevaluated. We know that the upper row contains said head element, so with following little tweak, it finally works:
let xys = foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xs . (*)) [] ys
Do the same against zs, and here comes the desired list:
let xyzs = foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xys . (*)) [] zs
Full code in summary:
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys) = if x <= y then x : merge xs (y:ys) else y : merge (x:xs) ys
xyzs = let
xs = map (2^) [0..]
ys = map (3^) [0..]
zs = map (5^) [0..]
xys = foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xs . (*)) [] ys
in foldr ((\(m:ms) ns -> m : merge ms ns) . flip fmap xys . (*)) [] zs
but it only lists powers of 5 and never goes on to 2 or 3.
Addressing only this bit.
To calculate numbers 2^a*3^0b*5^c you tried generating the triples (a,b,c), but got stuck producing those of the form (0,0,c). Which is why your numbers are all of the form 2^0*3^0*5^c, i.e. only powers of 5.
It's easier if you start with pairs. To produce all pairs (a,b) you can work along the diagonals of the form,
a+b = k
for each positivek. Each diagonal is easy to define,
diagonal k = [(k-x,x) | x <- [0..k]]
So to produce all pairs you'd just generate all diagonals for k<-[1..]. You want triples (a,b,c) though, but it's similar, just work along the planes,
a+b+c = k
To generate such planes just work along their diagonals,
triagonal k = [(k-x,b,c) | x <- [0..k], (b,c) <- diagonal x]
And there you go. Now just generate all 'triagonals' to get all possible triples,
triples = [triagonal k | k <- [0..]]
The other way to look at it is you wanted the numbers which are only divisible by 2,3 or 5. So check if each number starting from 1 satisfies this condition. If yes it is part of the list.
someList = [x| x<- [1..], isIncluded x]
where isIncluded is the function which decides whether x satisfies the above condition. To do this isIncluded divides the number first by 2 till it can not be divided any further by 2. Then same it does with new divided number for 3 and 5. It at ends there is 1 then we know this number is only divisible by 2,3 or 5 and nothing else.
This may not be the fastest way but still the simplest way.
isIncluded :: Int -> Bool
isIncluded n = if (powRemainder n 2 == 1) then True
else let q = powRemainder n 2
in if (powRemainder q 3 == 1) then True
else let p = powRemainder q 3
in if (powRemainder p 5 == 1) then True else False;
powRemainder is the function which takes number and base and returns the number which can not be further divided by base.
powRemainder :: Int -> Int -> Int
powRemainder 1 b = 1
powRemainder n b = if (n `mod` b) == 0 then powRemainder (n `div` b) b else n
with this when I run take 20 someList it returns [1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36].
As others already commented, your core does not work because it is analogous to the following imperative pseudocode:
for x in 0..infinity:
for y in 0..infinity:
for z in 0..infinity:
print (2^x * 3^y * 5^x)
The innermost for takes infinite time to execute, so the other two loops will never get past their first iteration. Consequently, x and y are both stuck to value 0.
This is a classic dovetailing problem: if we insist on trying all the values of z before taking the next y (or x), we get stuck on a subset of the intended outputs. We need a more "fair" way to choose the values of x,y,z so that we do not get stuck in such way: such techniques are known as "dovetailing".
Others have shown some dovetailing techniques. Here, I'll only mention the control-monad-omega package, which implements an easy to use dovetailing monad. The resulting code is very similar to the one posted in the OP.
import Control.Monad.Omega
powersOf235 :: [Integer]
powersOf235 = runOmega $ do
x <- each [0..]
y <- each [0..]
z <- each [0..]
return $ 2^x * 3^y * 5^z

Haskell 99 Questions #27

I'm having trouble conceptualizing given answer for problem 27 in haskell's 99 problems https://wiki.haskell.org/99_questions/Solutions/27.
The Problem:
"
Group the elements of a set into disjoint subsets.
a) In how many ways can a group of 9 people work in 3 disjoint subgroups of 2, 3 and 4 persons? Write a function that generates all the possibilities and returns them in a list.
Example:
* (group3 '(aldo beat carla david evi flip gary hugo ida))
( ( (ALDO BEAT) (CARLA DAVID EVI) (FLIP GARY HUGO IDA) )
... )
b) Generalize the above predicate in a way that we can specify a list of group sizes and the predicate will return a list of groups.
"
The answer they give is this:
combination :: Int -> [a] -> [([a],[a])]
combination 0 xs = [([],xs)]
combination n [] = []
combination n (x:xs) = ts ++ ds
where
ts = [ (x:ys,zs) | (ys,zs) <- combination (n-1) xs ]
ds = [ (ys,x:zs) | (ys,zs) <- combination n xs ]
group :: [Int] -> [a] -> [[[a]]]
group [] _ = [[]]
group (n:ns) xs =
[ g:gs | (g,rs) <- combination n xs
, gs <- group ns rs ]
I'm having a lot of trouble understanding how the first section (the section defining the function "combination") operates.
I'm pretty new to haskell too, so explain it to me like I'm in 5th grade.
Any feedback appreciated.
combination 0 xs = [([],xs)]
If we want to choose 0 elements from xs, there is only one way. No elements are taken [] and all the elements xs are left there.
combination n [] = []
Otherwise, we want to choose n (>0) elements. If we want to chose them from the empty list [], there are no ways to do that -- it's impossible.
combination n (x:xs) = ts ++ ds
where
ts = [ (x:ys,zs) | (ys,zs) <- combination (n-1) xs ]
ds = [ (ys,x:zs) | (ys,zs) <- combination n xs ]
Otherwise, we want to choose n (>0) elements from a nonempty list x:xs. There are many ways to do that, which we separate in two groups as follows:
we decide to take the element x among the chosen ones, and we are left with choosing n-1 from xs. This is done in ts, which considers all the ways to choose n-1 elements from xs, and then adds x to the list of "chosen" elements ys.
we decide to drop the element x from the input list, and we are left with choosing n from xs. This is done in ds, which considers all the ways to choose n elements from xs, and then adds x to the list of "dropped" elements zs.
We then output all such combinations using ts++ds.
Function combination takes list and one number. It creates the combination of the list considering the list has to be divided only in two parts. This is simply the original problem reduced only with 2 numbers k and n-k.
It does this using ts and ds lists.
ts is when the first element is in first part and then recursion occurs with remaining list and k-1. ds is where first element is in second part and recursion occurs with k and remaining part. Once remaining part is computed first element is added to it.

Enumerate All Finite Sequences of Integers?

I want to write a Haskell list comprehension to enumerate all finite sequences of integers.
I'm pretty sure that this set is countable.
This is what I have so far:
enumIntSeqs = [ (x, [ ( x, [0..x] ) | x <- [ x | x <- [0..x] ] ] ) | x <- [0..] ]
Another idea I have is to somehow list every finite path in the infinite array
Z* X Z* where Z* = {0, 1, -1, 2, -2,...}
This is, indeed, possible. But it is not easy. Imagine you have an enumeration of all integers, an enumeration of all pairs of integers, an enumeration of all triples of integers, etc. Then you need to choose "fairly" from those enumerations to be sure to hit each element of each. A similar problem will arise when you try even to enumerate all pairs of integers. I suggest you start with that problem, and then look into something like Control.Monad.Omega, or perhaps even Control.Monad.Logic.
I am not going to spoil your fun by attempting a full answer, so let me just demonstrate a handful of things through the simplified problem of enumerating all finite, non-empty, sequences of contiguous naturals starting from zero -- something that you seem close to achieving on your own already. The key steps are already amidst your enumIntSeqs, but you don't have to nest list comprehensions like that. If you begin with...
[ {- etc. -} | x <- [0..] ]
... you can generate a new list for each x simply by doing...
[ {- etc. -} | x <- [0..], let ys = [0..x] ]
... and then returning those lists:
[ ys | x <- [0..], let ys = [0..x] ]
(Note that I didn't write ys <- [0..x]. Try to predict what would happen in that case, and then check it in GHCi.)
The separate let definition isn't necessary, nor does it add anything in terms of clarity in this simple comprehension, so we can just write:
[ [0..x] | x <- [0..] ]
And that's it.
Prelude> take 4 $ [ [0..x] | x <- [0..] ]
[[0],[0,1],[0,1,2],[0,1,2,3]]
P.S.: Two other ways of writing the enumeration. Using do-notation...
someIntSeqs = do
x <- [0..]
return [0..x]
... and with a humble fmap (which in this case is the same as map):
Prelude> take 4 $ fmap (\x -> [0..x]) [0..]
[[0],[0,1],[0,1,2],[0,1,2,3]]
Prelude> -- Or, equivalently...
Prelude> take 4 $ (\x -> [0..x]) <$> [0..]
[[0],[0,1],[0,1,2],[0,1,2,3]]
I don't know if this is what you want, because your question wasn't very clear, but given the example that you provided [0,1,-1,-2,2..], I'm going to give a few examples of how to produce a sorted list of integers, and change it according to your needs.
numberline :: Integer -> [Integer]
numberline n = line (-abs n) (abs n) []
where
line 0 0 l = (0:l)
line r s t = r : line (r+1) (s-1) (s:t)
What it does is to ensure that there is a positive and negative number, with the use of -abs and abs as inputs, so that the line function returns them in that order. Then, you only need to map this function to a list of an arbitrary size to get a list of lists with integers ranging from a negative number to its symmetric end.
map numberline [1..2] -- [[-1,0,1],[-2,-1,0,1,2]]
map numberline [1..] -- [[-1,0,1],[-2,-1,0,1,2],[-3,-2,-1,0,1,2,3]..
So how do you change the above piece of code to generate an alternating path between integers as pairs of natural numbers in some array without repeating them?
countable :: Integer -> [Integer]
countable n = count (-abs n) (abs n) []
where
count 0 0 l = (0:l)
count r s t = count (r+1) (s-1) (s:r:t)
The end result being [0,1,-1,2,-2,3,-3] for countable 3. It's not very efficient for big numbers, so you may want to consider a list starting from the argument down to 0 instead of the other way around.
I hope that I helped.

Haskell Hamming numbers, works but shows duplicates

I am trying to generate hamming numbers in haskell, the problem is I get duplicate #'s in my output list and I cannot figure out why exactly. Should I just create a remove duplicates function or am I just missing something simple?
Also in the function hamming I would like to make sure the size of the input list is exactly 3, how do I find the size of a list so I can do the comparison?
{- Merge lists x&y of possibly infinite lengths -}
merge [] [] = []
merge [] ys = ys
merge xs [] = xs
merge xs ys = min x y : if x < y then merge (tail xs) ys
else merge xs (tail ys)
where x = head xs
y = head ys
{- multiply each element in y by x -}
times x [] = []
times x y = x * (head y) : times x (tail y)
{- find the hamming numbers of the input primes list -}
ham [] = []
ham x = 1 : merge (times (head x) (ham x))
(merge (times (x !! 1) (ham x)) (times (last x) (ham x)))
{- returns x hamming #'s based on y primes of size 3 -}
hamming x [] = []
hamming x y = take x (ham y)
{- hamming x y = if "y.size = 3" then take x (ham y)
else "Must supply 3 primes in input list" -}
You get duplicates because many of the hamming numbers are multiples of several of the base numbers, and you don't remove duplicates in your merge function. For example, for the classical 2, 3, 5 Hamming numbers, you obtain 6 as 2 * 3 as well as 3 * 2.
You could of course create a duplicate removal function. Since the list you create is sorted, that wouldn't even be very inefficient. Or you could remove the duplicates in the merge function.
how do I find the size of a list so I can do the comparison?
You can obtain the length of a list using the length function that is available from the Prelude, but let me warn you right now that calling length should only be done if the length is really required, since length has to traverse the entire list to calculate its length. If the list happens to be long, that takes a lot of time, and may cause huge memory usage if the list is referenced elsewhere so that it cannot be garbage-collected. If the list is even infinite, evaluating its length will of course never terminate.
What you want to do can also be achieved by pattern-matching,
ham [a, b, c] = list
where
list = 1 : merge (map (a*) list) (merge (map (b*) list) (map (c*) list))
ham _ = []
You could also use a guard with a length check
hamming x y
| length y == 3 = take x (ham y)
| otherwise = []
to make sure that your input list has exactly three elements, but you will regret that if you call hamming 10 [1 .. ].
In the List module, Haskell has a duplicate remover called nub. Here it is on hoogle: http://www.haskell.org/hoogle/?hoogle=nub. This is O(n^2) though, so you might be better off changing merge. But it may be worthwhile to first use a slow solution already written for you, before optimizing.
I suspect that you are trying to learn Haskell with this little exercise, but here's another way to write out the hamming numbers (no duplicates, but not in order) using the List monad:
uglyNumbers = do { n <- [0..]
; k <- [0..n]
; j <- [0..n-k]
; return $ (2^(n-k-j))*(3^j)*(5^k) }
This makes a lazy, infinite list of hamming numbers. You can equivalently write this using a list comprehension:
uglyNumbers' = [(2^(n-k-j))*(3^j)*(5^k) | n <- [0..], k <- [0..n], j <- [0..n-k]]

Sum of separated elements in a list [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Split list and make sum from sublist?
Im trying to solve this problem.
I need to do a sum of elements from a list which are separated from each other only with "0".
So for example I can have something like this as input: [1,2,3,0,3,4,0,2,1]
and the output should be [6,7,3].
So far I managed to do something like this:
cut (x:xs) | x > 0 = x : (cut xs)
| otherwise = []
first (xs) = ( (foldl (+) 0 (cut (xs))) ) : []
second (xs) = ( (foldl (+) 0 (cut (reverse (xs)))) ) : []
test (xs) = first(xs) ++ second(xs)
Problem is that this only works with only 1 instance of "0" in my list.
I was trying to solve this by editing my cut function:
cut [] = []
cut (x:xs) | x > 0 = foldl (+) 0 ( x : cut xs) : []
| x == 0 = (cut xs)
But I cant figure out how to adjust it, so it will separate the sums. Right now it just throws the sum of all the elements as the output.
You can divide your problem into two tasks
Split a list into parts on zeros.
Sum parts.
For the first task we have Data.List.Split module which exports splitOn function.
It does precisely what we need:
> splitOn [1] [0,0,0,1,0,0,0,1,0]
[[0,0,0],[0,0,0],[0]]
For the second task there is well-known map-function which applies a function to the each element of the list.
In our case this function is sum:
> map sum [[1,2,3],[4,5,6],[7,8,9]]
[6,15,24]
So:
> :m +Data.List.Split
> map sum . splitOn [0] $ [1,2,3,0,3,4,0,2,1]
[6,7,3]
For homework you should definitely follow dave's answer. However, here is a more advanced solution, employing groupBy as poor man's split:
import Data.List (groupBy)
map sum $ groupBy (const (/=0)) list
This might look cute, but note that there are still the zeros at the beginning of the sub-lists present, so you can't use this solution without changes if that matters (e.g if you need products instead of sums)
[Explanation]
groupBy looks if the first element of the current group "fits together" with the current element of the list. In that case the current element will be added to the group, else a new group starts. E.g.
groupBy (\x y -> x `mod` y == 0) [81,3,9,25,5]
--[[81,3,9],[25,5]]
Here the test ist successful for 81 'mod' 3 and 81 'mod' 9, but not for 81 'mod' 25, which starts a new group. Again, 25 'mod' 5 is successful.
But in our case all elements "fit" in the current group as long as they are not 0, so we don't even have to look at the first element. And if a 0 is found, a new group is started.
const (/=0) means just \_ y -> y /= 0, so regardless what the first argument is, it just tests that the second element isn't 0. To see why, look at the definition:
const :: a -> b -> a
const a _ = a
Now our lambda can be written as
\x y -> const (/= 0) x y
As from the const call only the first of the two arguments "survives", we have
\x y -> (/= 0) y
... or...
\_ y -> y /= 0
Even if you're unable to install to install the split package and use Data.List.Split as Matvey suggests, you can still use the general approach:
Split the weird list with 0 separators into a more conventional list of lists.
Sum each list.
So
yourFunction = map sum . split
Now we have to write split.
split :: [Int] -> [[Int]]
In general, when we want to pull a list apart to synthesise something new, we need to use a fold.
split = foldr cons nil where
nil here should be whatever you want split [] to be.
nil = --TODO: exercise for you; clue: NOT []
cons meanwhile combines one of your numbers, with the answer from the previous step of the fold. Obviously, you'll need to do different things depending on whether or not the number is 0.
cons 0 xss = --TODO
cons x (xs : xss) = --TODO; why will this pattern match never fail?

Resources