Iterating a function and analysing the result in haskell - haskell

Ok, referring back to my previous question, I am still working on learning haskell and solving the current problem of finding the longest chain from the following iteration:
chain n | n == 0 = error "What are you on about?"
| n == 1 = [1]
| rem n 2 == 0 = n : chain (n `div` 2)
| otherwise = n : chain (3 * n + 1)
I have this bit sorted, but I need to find the longest chain from a starting number below 1,000,000. So how do I make it do each starting number up to 1,000,000 and then print the one with the longest chain length.
I can do it for one example with:
Main> length (chain n)
I assume I need the output as an array and then use the maximum function to find the value largest chain length and then see how far along it is in the array of answers.
Is this a good way to go about finding a solution or is there a better way (perhaps with better efficiency)?

You are right about the maximum part. To get the list (that's what Haskell's []s are, arrays are different structures) you need to use the map higher-order function, like this:
chainLength n = length (chain n)
lengths = map chainLength [1..1000000]
Essentially, map takes as arguments a function and a list. It applies the function to each element in the list and returns the list of the results.
Since you will be needing the number whose chain has that length, you may want change the chainLength function to return the number as well, like this:
chainLength n = (n, length (chain n))
That way you will have an array of pairs, with each number and its chain length.
Now you need to get the pair with the largest second component. That's where the maximumBy function comes in. It works just like maximum but takes a function as a parameter to select how to compare the values. In this case, the second component of the pair. This comparison function takes two numbers and returns a value of type Ordering. This type has only three possible values: LT, EQ, GT, for less than, equal, and greater than, respectively.
So, we need a function that given two pairs tells us how the second components compare to each other:
compareSnd (_, y1) (_, y2) = compare y1 y2
-- Or, if you import Data.Function, you can write it like this (thanks alexey_r):
compareSnd = compare `on` snd -- reads nicely
I used the default compare function that compares numbers (well, not just numbers).
Now we only need to get the maximum using this function:
longestChain = maximumBy compareSnd lengths
That gets you a pair of the number with the longest chain and the corresponding length. Feel free to apply fst and snd as you please.
Note that this could be more much more concisely using zip and composition, but since you tagged the question as newbie, I thought it better to break it down like this.

SPOILER (solving the problem for positive integers under 100):
module Test where
import Data.List -- this contains maximumBy
chain n
| n == 0 = error "What are you on about?"
| n == 1 = [1]
| rem n 2 == 0 = n : chain (n `div` 2)
| otherwise = n : chain (3 * n + 1)
chains = map (\x -> (x,chain x)) [1..100]
cmpSnd (a,b) (c,d)
| length b > length d = GT
| length b == length d = EQ
| otherwise = LT
solve = (fst . maximumBy cmpSnd) chains
The chains function makes use of map. It applies a function to every element of a list of a values, so
map succ [1,2]
is the same as
[succ 1,succ 2]
The cmpSnd function is a comparison function that probably exists somewhere deep in the Hierarchical Libraries, but I could not find it, so I created it. GT means "the first value is greater than the second", the rest is trivial.
Solve takes the maximum (by utilizing the comparison function we defined earlier) of the list. This will be a pair of an integer and a list. It will return the integer only (because of the fst).
A comment: Your chain function is not tail-recursive. This means that large chains will inevitably result in a Stack Overflow. You shall add an explicit accumulator variable and make it tail-recursive.

Something like
fst $ maximumBy (length . snd) $ zip [1..1000000] $ map chain [1..1000000]
(untested)
i.e. don't work out how far along the longest chain is in the list of longest chains, but carry around the seed values with the chains instead.

I studied Haskell years ago, so I don't remember it that well. On the other hand I've tested this code and it works. You will get the max chain and the number that generates it. But as fiships has stated before, it will overflow for big values.
chain :: Int -> [Int]
chain n
| n == 0 = []
| n == 1 = [1]
| rem n 2 == 0 = n : chain (n `div` 2)
| otherwise = n : chain (3 * n + 1)
length_chain :: Int -> Int
length_chain n = length (chain n)
max_pos :: (Int,Int) -> Int -> [Int] -> (Int,Int)
max_pos (m,p) _ [] = (m,p)
max_pos (m,p) a (x:xs)
| x > m = max_pos (x,a) (a+1) xs
| otherwise = max_pos (m,p) (a+1) xs
The instruction will be
Main> max_pos (0,0) 1 (map length_chain [1..10000])
(262,6171)

Related

Get the minimum value

I have a function 'getMin' which should return the minimum value. This function uses another function 'urvalFun' in order to determine this minimim value. Here is a demonstration of 'urvalFun'
get1:: (String,String,Double ) -> String
get1 (x,_,_ ) = x
get2 :: (String,String,Double)-> String
get2 (_,x,_) = x
get3:: (String,String,Double)->Double
get3 (_,_,x) = x
distDiff:: String-> String->[(String,String,Double)] ->Double
distDiff a b diMat = sum [z |(x,y,z)<- diMat, (x == a && y /= b)
|| (y == a && x /= b) ]
urvalFun:: Int -> (String,String,Double)->[(String,String,Double) ]->Double
urvalFun size triple diMat = ((fromIntegral size)-2)*(get3 triple)
- ( (distDiff (get1 triple) (get2 triple) diMat ) + (distDiff (get2 triple)
(get1 triple) diMat ))
Its not necessary to understand this chunck of code, the only thing that is important is that if i evaluate:
urvalFun 3 ("a","b",0.304) [("a","b",0.304),("a","d",0.52),("a","e",0.824)]
this will evaluate to -1.03999
urvalFun 3 ("a","d",0.52) [("a","b",0.304),("a","d",0.52),("a","e",0.824)]
this will evaluate to - 0.60799
urvalFun 3 ("a","e",0.824) [("a","b",0.304),("a","d",0.52),("a","e",0.824)]
this will evaluate to 1.1e^-16
now we know that calling urvalFun with ("a","b",0.304) and [("a","b",0.304),("a","d",0.52),("a","e",0.824)] will get the value which is the smallest. I want to create a function 'getMin' which will return this minimum value (with the same vector as in the above examples as a parameter) ,as shown above. The problem is that it won't work I have no clue why
getMin:: [(String,String,Double)]->Double
getMin diMat = inner 0 diMat 2000
where
inner 3 diMat min = min
inner n diMat min
|current > min = inner (n + 1) (diMatMinus ++ [(head diMat) ]) min
|otherwise = inner (n+1) (diMatMinus ++ [(head diMat) ]) current
current = urvalFun (length diMat) (head diMat) diMat
diMatMinus = tail diMat
try to evaluate for example
getMin [("a","e",0.824),("a","d",0.52),("a","b",0.304)]
which will evaluate to -1.1e^-16
which is not want i intended because I want this to return -1.03999
Could someone help me out here?
(this code is a little bit ad hoc but it is under construction, I am just doing some tests right now)
notice that i have rearranged the vector so that the triple ("a","b",0.304) is the last element in the vector.
First you need a way to get the minimum element to pass to urvalFun. This can be done with minimumBy.
Observe the following
λ> let ls = [("a","d",0.52),("a","e",0.824),("a","b",0.304)]
λ> let min = minimumBy (\(_,_,c) (_,_,c') -> compare c c') ls
λ> urvalFun 3 min ls
-1.0399999999999998
Or maybe this is what you intended:
λ> minimum [ urvalFun 3 x ls | x <- ls]
-1.0399999999999998
If you also want to alter n from 0 to 3 or something, then this can be further modified. I'd suggest stating in english what you want your function to do.
You want to find the value in a given list which minimizes your function.
I'll work with a simpler example than yours: finding the string with minimum length. You'll be able to adapt this to your case by replacing the length function.
> import Data.Foldable
> let list = ["hello", "world!", "here", "is", "fine"]
> minimumBy (comparing length) list
"is"
The above works, but it will call length every time it performs a comparison, i.e. roughly twice the length of the list. It is also possible to avoid this, and use length only once per element, by precomputing it:
> snd $ minimumBy (comparing fst) [ (length x, x) | x <- list ]
We first pair each string with its length, take the minimum length-string pair according to the length only, and finally take only the string in such pair.
By the way, I'd recommend you avoid functions such as get1 to access tuples: they are not idiomatic in Haskell code, which usually exploits pattern matching for the same effect: for instance
urvalFun:: Int -> (String,String,Double)->[(String,String,Double) ]->Double
urvalFun size (s1,s2,d) diMat =
(fromIntegral size - 2)*d - distDiff s1 s2 diMat + distDiff s2 s1 diMat
looks more readable.
head,tail are also particularly dangerous since they are partial: they will crash your program if you ever use them on a empty list, without providing much explanation.
In general, when working with lists, using indexes, or counter variables to count up to the length of the list, is typically not needed and not idiomatic. One can often simply resort to pattern matching and recursion, or even to standard fold/map functions.
Note that for a list of size 3 your getMin function may be written:
getMin' [x,y,z]
= minimum [ urvalFun 3 x [x,y,z]
, urvalFun 3 y [y,z,x]
, urvalFun 3 z [z,x,y]
]
You can create the sequence of arguments to the urvalFun function with zip and and a helper function:
rotate (x:xs) = xs ++ [x]
zip "xyzw" (iterate rotate "xyzw")
= [ ('x', "xyzw"),
('y', "yzwx"),
('z', "zwxy"),
('w', "wxyz") ]
Thus:
import Data.List
getMin tuples = minimum (zipWith go tuples (iterate rotate tuples))
where n = length tuples
go (x,xs) = urvalFun n x xs

Is it possible to exit a generator?

Consider the following:
list = [1,3..]
generate n = [compute y | y <- list , (compute y) < n ]
compute a = ... whatever ...
Is it possible to exit the generator before getting to the last element of my list
(e.g. if (compute y > 20)?
I want to save computing power. I only need the elements smaller than n.
I'm new to Haskell. A simple answer might be the best answer.
The wonderful thing about Haskell is that it's lazy. If you said
> let x = generate 100000
then Haskell doesn't immediately calculate generate 100000, it just creates a promise to start calculating it (we normally call this a thunk).
If you want only elements only until compute y > 20, then you can do
> takeWhile (<= 20) (generate 100000)
This is the same semantics that let you do something like
> let nums = [1..] :: [Integer]
This makes a lazy reference to all Integer values from 1 to infinity. You can then do things like
> take 10 $ map (* 10) $ drop 12345 $ map (\x -> x ^ 2 + x ^ 3 + x ^ 4) $ filter even nums
[3717428823832552480,3718633373599415160,3719838216073150080,3721043351301172120,3722248779330900000,3723454500209756280,3724660513985167360,3725866820704563480,3727073420415378720,3728280313165051000]
And while tihs seems like a lot of work, it only calculates the bare minimum necessary to return the 10 elements you requested. The argument to take 10 in this example is still an infinite list, where we first grabbed all the evens, then mapped an algebraic expression to it, then dropped the first 12345 elements, then multiplied all remaining (infinite) elements by 10. Working with infinite structures in Haskell is very common and often advantageous.
As a side note, your current definition of generate will do extra work, you'd want something more like
generate n = [compute_y | y <- list, let compute_y = compute y, compute_y < n]
This way compute y is only calculated once and the value is shared between your filter compute_y < n and the left hand side of the | in the comprehension. Also be aware that when you have a condition in a comprehension, this gets translated to a filter, not a takeWhile:
> -- filter applies the predicate to all elements in the list
> filter (\x -> x `mod` 5 == 0) [5,10,15,21,25]
[5,10,15,20]
> -- takeWhile pulls values until the predicate returns False
> takeWhile (\x -> x `mod` 5 == 0) [5,10,15,21,25]
[5,10,15]

Dovetail iteration over infinite lists in Haskell

I want to iterate 2 (or 3) infinite lists and find the "smallest" pair that satisfies a condition, like so:
until pred [(a,b,c) | a<-as, b<-bs, c<-cs]
where pred (a,b,c) = a*a + b*b == c*c
as = [1..]
bs = [1..]
cs = [1..]
The above wouldn't get very far, as a == b == 1 throughout the run of the program.
Is there a nice way to dovetail the problem, e.g. build the infinite sequence [(1,1,1),(1,2,1),(2,1,1),(2,1,2),(2,2,1),(2,2,2),(2,2,3),(2,3,2),..] ?
Bonus: is it possible to generalize to n-tuples?
There's a monad for that, Omega.
Prelude> let as = each [1..]
Prelude> let x = liftA3 (,,) as as as
Prelude> let x' = mfilter (\(a,b,c) -> a*a + b*b == c*c) x
Prelude> take 10 $ runOmega x'
[(3,4,5),(4,3,5),(6,8,10),(8,6,10),(5,12,13),(12,5,13),(9,12,15),(12,9,15),(8,15,17),(15,8,17)]
Using it's applicative features, you can generalize to arbitrary tuples:
quadrupels = (,,,) <$> as <*> as <*> as <*> as -- or call it liftA4
But: this alone does not eliminate duplication, of course. It only gives you proper diagonalization. Maybe you could use monad comprehensions together with an approach like Thomas's, or just another mfilter pass (restricting to b /= c, in this case).
List comprehensions are great (and concise) ways to solve such problems. First, you know you want all combinations of (a,b,c) that might satisfy a^2 + b^2 = c^2 - a helpful observation is that (considering only positive numbers) it will always be the case that a <= c && b <= c.
To generate our list of candidates we can thus say c ranges from 1 to infinity while a and b range from one to c.
[(a,b,c) | c <- [1..], a <- [1..c], b <- [1..c]]
To get to the solution we just need to add your desired equation as a guard:
[(a,b,c) | c <- [1..], a <- [1..c], b <- [1..c], a*a+b*b == c*c]
This is inefficient, but the output is correct:
[(3,4,5),(4,3,5),(6,8,10),(8,6,10),(5,12,13),(12,5,13),(9,12,15)...
There are more principled methods than blind testing that can solve this problem.
{- It depends on what is "smallest". But here is a solution for a concept of "smallest" if tuples were compared first by their max. number and then by their total sum. (You can just copy and paste my whole answer into a file as I write the text in comments.)
We will need nub later. -}
import Data.List (nub)
{- Just for illustration: the easy case with 2-tuples. -}
-- all the two-tuples where 'snd' is 'n'
tuples n = [(i, n) | i <- [1..n]]
-- all the two-tuples where 'snd' is in '1..n'
tuplesUpTo n = concat [tuples i | i <- [1..n]]
{-
To get all results, you will need to insert the flip of each tuple into the stream. But let's do that later and generalize first.
Building tuples of arbitrary length is somewhat difficult, so we will work on lists. I call them 'kList's, if they have a length 'k'.
-}
-- just copied from the tuples case, only we need a base case for k=1 and
-- we can combine all results utilizing the list monad.
kLists 1 n = [[n]]
kLists k n = do
rest <- kLists (k-1) n
add <- [1..head rest]
return (add:rest)
-- same as above. all the klists with length k and max number of n
kListsUpTo k n = concat [kLists k i | i <- [1..n]]
-- we can do that unbounded as well, creating an infinite list.
kListsInf k = concat [kLists k i | i <- [1..]]
{-
The next step is rotating these lists around, because until now the largest number is always in the last place. So we just look at all rotations to get all the results. Using nub here is admittedly awkward, you can improve that. But without it, lists where all elements are the same are repeated k times.
-}
rotate n l = let (init, end) = splitAt n l
in end ++ init
rotations k l = nub [rotate i l | i <- [0..k-1]]
rotatedKListsInf k = concatMap (rotations k) $ kListsInf k
{- What remains is to convert these lists into tuples. This is a bit awkward, because every n-tuple is a separate type. But it's straightforward, of course. -}
kListToTuple2 [x,y] = (x,y)
kListToTuple3 [x,y,z] = (x,y,z)
kListToTuple4 [x,y,z,t] = (x,y,z,t)
kListToTuple5 [x,y,z,t,u] = (x,y,z,t,u)
kListToTuple6 [x,y,z,t,u,v] = (x,y,z,t,u,v)
{- Some tests:
*Main> take 30 . map kListToTuple2 $ rotatedKListsInf 2
[(1,1),(1,2),(2,1),(2,2),(1,3),(3,1),(2,3),(3,2),(3,3),(1,4),(4,1),(2,4),(4,2),(3,4),
(4,3),(4,4),(1,5),(5,1),(2,5),(5,2),(3,5),(5,3),(4,5),(5,4),(5,5),(1,6),(6,1),
(2,6), (6,2), (3,6)]
*Main> take 30 . map kListToTuple3 $ rotatedKListsInf 3
[(1,1,1),(1,1,2),(1,2,1),(2,1,1),(1,2,2),(2,2,1),(2,1,2),(2,2,2),(1,1,3),(1,3,1),
(3,1,1),(1,2,3),(2,3,1),(3,1,2),(2,2,3),(2,3,2),(3,2,2),(1,3,3),(3,3,1),(3,1,3),
(2,3,3),(3,3,2),(3,2,3),(3,3,3),(1,1,4),(1,4,1),(4,1,1),(1,2,4),(2,4,1),(4,1,2)]
Edit:
I realized there is a bug: Just rotating the ordered lists isn't enough of course. The solution must be somewhere along the lines of having
rest <- concat . map (rotations (k-1)) $ kLists (k-1) n
in kLists, but then some issues with repeated outputs arise. You can figure that out, I guess. ;-)
-}
It really depends on what you mean by "smallest", but I assume you want to find a tuple of numbers with respect to its maximal element - so (2,2) is less than (1,3) (while standard Haskell ordering is lexicographic).
There is package data-ordlist, which is aimed precisely at working with ordered lists. It's function mergeAll (and mergeAllBy) allows you to combine a 2-dimensional matrix ordered in each direction into an ordered list.
First let's create a desired comparing function on tuples:
import Data.List (find)
import Data.List.Ordered
compare2 :: (Ord a) => (a, a) -> (a, a) -> Ordering
compare2 x y = compare (max2 x, x) (max2 y, y)
where
max2 :: Ord a => (a, a) -> a
max2 (x, y) = max x y
Then using mergeAll we create a function that takes a comparator, a combining function (which must be monotonic in both arguments) and two sorted lists. It combines all possible elements from the two lists using the function and produces a result sorted list:
mergeWith :: (b -> b -> Ordering) -> (a -> a -> b) -> [a] -> [a] -> [b]
mergeWith cmp f xs ys = mergeAllBy cmp $ map (\x -> map (f x) xs) ys
With this function, it's very simple to produce tuples ordered according to their maximum:
incPairs :: [(Int,Int)]
incPairs = mergeWith compare2 (,) [1..] [1..]
Its first 10 elements are:
> take 10 incPairs
[(1,1),(1,2),(2,1),(2,2),(1,3),(2,3),(3,1),(3,2),(3,3),(1,4)]
and when we (for example) look for the first pair whose sum of squares is equal to 65:
find (\(x,y) -> x^2+y^2 == 65) incPairs
we get the correct result (4,7) (as opposed to (1,8) if lexicographic ordering were used).
This answer is for a more general problem for a unknown predicate. If the predicate is known, more efficient solutions are possible, like others have listed solutions based on knowledge that you don't need to iterate for all Ints for a given c.
When dealing with infinite lists, you need to perform breadth-first search for solution. The list comprehension only affords depth-first search, that is why you never arrive at a solution in your original code.
counters 0 xs = [[]]
counters n xs = concat $ foldr f [] gens where
gens = [[x:t | t <- counters (n-1) xs] | x <- xs]
f ys n = cat ys ([]:n)
cat (y:ys) (x:xs) = (y:x): cat ys xs
cat [] xs = xs
cat xs [] = [xs]
main = print $ take 10 $ filter p $ counters 3 [1..] where
p [a,b,c] = a*a + b*b == c*c
counters generates all possible counters for values from the specified range of digits, including a infinite range.
First, we obtain a list of generators of valid combinations of counters - for each permitted digit, combine it with all permitted combinations for counters of smaller size. This may result in a generator that produces a infinite number of combinations. So, we need to borrow from each generator evenly.
So gens is a list of generators. Think of this as a list of all counters starting with one digit: gens !! 0 is a list of all counters starting with 1, gens !! 1 is a list of all counters starting with 2, etc.
In order to borrow from each generator evenly, we could transpose the list of generators - that way we would get a list of first elements of the generators, followed by a list of second elements of the generators, etc.
Since the list of generators may be infinite, we cannot afford to transpose the list of generators, because we may never get to look at the second element of any generator (for a infinite number of digits we'd have a infinite number of generators). So, we enumerate the elements from the generators "diagonally" - take first element from the first generator; then take the second element from the first generator and the first from the second generator; then take the third element from the first generator, the second from the second, and the first element from the third generator, etc. This can be done by folding the list of generators with a function f, which zips together two lists - one list is the generator, the other is the already-zipped generators -, the beginning of one of them being offset by one step by adding []: to the head. This is almost zipWith (:) ys ([]:n) - the difference is that if n or ys is shorter than the other one, we don't drop the remainder of the other list. Note that folding with zipWith (:) ys n would be a transpose.
For this answer I will take "smallest" to refer to the sum of the numbers in the tuple.
To list all possible pairs in order, you can first list all of the pairs with a sum of 2, then all pairs with a sum of 3 and so on. In code
pairsWithSum n = [(i, n-i) | i <- [1..n-1]]
xs = concatMap pairsWithSum [2..]
Haskell doesn't have facilities for dealing with n-tuples without using Template Haskell, so to generalize this you will have to switch to lists.
ntuplesWithSum 1 s = [[s]]
ntuplesWithSum n s = concatMap (\i -> map (i:) (ntuplesWithSum (n-1) (s-i))) [1..s-n+1]
nums n = concatMap (ntuplesWithSum n) [n..]
Here's another solution, with probably another slightly different idea of "smallest". My order is just "all tuples with max element N come before all tuples with max element N+1". I wrote the versions for pairs and triples:
gen2_step :: Int -> [(Int, Int)]
gen2_step s = [(x, y) | x <- [1..s], y <- [1..s], (x == s || y == s)]
gen2 :: Int -> [(Int, Int)]
gen2 n = concatMap gen2_step [1..n]
gen2inf :: [(Int, Int)]
gen2inf = concatMap gen2_step [1..]
gen3_step :: Int -> [(Int, Int, Int)]
gen3_step s = [(x, y, z) | x <- [1..s], y <- [1..s], z <- [1..s], (x == s || y == s || z == s)]
gen3 :: Int -> [(Int, Int, Int)]
gen3 n = concatMap gen3_step [1..n]
gen3inf :: [(Int, Int, Int)]
gen3inf = concatMap gen3_step [1..]
You can't really generalize it to N-tuples, though as long as you stay homogeneous, you may be able to generalize it if you use arrays. But I don't want to tie my brain into that knot.
I think this is the simplest solution if "smallest" is defined as x+y+z because after you find your first solution in the space of Integral valued pythagorean triangles, your next solutions from the infinite list are bigger.
take 1 [(x,y,z) | y <- [1..], x <- [1..y], z <- [1..x], z*z + x*x == y*y]
-> [(4,5,3)]
It has the nice property that it returns each symmetrically unique solution only once. x and z are also infinite, because y is infinite.
This does not work, because the sequence for x never finishes, and thus you never get a value for y, not to mention z. The rightmost generator is the innermost loop.
take 1 [(z,y,x)|z <- [1..],y <- [1..],x <- [1..],x*x + y*y == z*z]
Sry, it's quite a while since I did haskell, so I'm going to describe it with words.
As I pointed out in my comment. It is not possible to find the smallest anything in an infinite list, since there could always be a smaller one.
What you can do is, have a stream based approach that takes the lists and returns a list with only 'valid' elements, i. e. where the condition is met. Lets call this function triangle
You can then compute the triangle list to some extent with take n (triangle ...) and from this n elements you can find the minium.

List comprehension: making lists of lists

hi im trying to make a function in haskell that takes a number a makes a partion of it using lists i.e. for number 4 it would create [[1,1,1,1],[1,1,2],[1,3],[2,2],[4]]. I was thinking of using list comprehension for this where it would create list x and then create further lists using numbers from [1...n] (n being the partition number I would want) where the sum of the list created would be equal to n.
The code I have created so far is-
partions (n:xs) = [[x|x<-[1...n], sum[x]==n]]|xs<-[1..]]
but obiviously it doesnt work, any suggestions?
thanks.
I suggest trying recursion: To obtain the partitions of n, iterate over the numbers i = 1 to n, and recursively generate the partitions of (n-i), the base case being that the only partition of 1 is 1 itself, and the partition of 0 is the empty list.
How about this...
import Data.List (nub, sort)
parts :: Int -> [[Int]]
parts 0 = []
parts n = nub $ map sort $ [n] : [x:xs | x <- [1..n`div`2], xs <- parts(n - x)]
Trying it:
*Main Control.Monad> forM [1..5] (print . parts)
[[1]]
[[2],[1,1]]
[[3],[1,2],[1,1,1]]
[[4],[1,3],[1,1,2],[1,1,1,1],[2,2]]
[[5],[1,4],[1,1,3],[1,1,1,2],[1,1,1,1,1],[1,2,2],[2,3]]
I think it's correct, if not efficient.
I found it helpful to define an auxiliary function, partitionsCap, which does not let any of the items be larger than a given value. Used recursively, it can be used to only produce the monotonically decreasing results you want (i.e. no [1,3,1] when you already have [1,1,3]):
partitions :: Int -> [[Int]]
partitions n = partitionsCap n n
partitionsCap :: Int -> Int -> [[Int]]
partitionsCap cap n
| n < 0 = error "partitions: negative number"
| n == 0 = [[]]
| n > 0 = [i : p | i <- [hi,hi-1..1], p <- partitionsCap i (n-i)]
where hi = min cap n
At the heart of the algorithm is the idea that, when partitioning N, you take i from n down to 1, and prepend i to the partitions of n-i. Simplified:
concat [map (i:) $ partitions (n-i) | i <- [n,n-1..1]]
but wrong:
> partitions 3
[[3],[2,1],[1,2],[1,1,1]]
We want that [1,2] to go away. Hence, we need to cap the partitions we're prepending to so they won't go above i:
concat [map (i:) $ partitionsCap i (n-i) | i <- [hi,hi-1..1]]
where hi = min cap n
Now, to clean it up: that concat and map so close together got my attention. A little background: list comprehensions and the list monad are very closely related, and concatMap is the same as >>= with its arguments flipped, in the list monad. So I wondered: can those concat and map somehow turn into a >>=, and can that >>= somehow sweet-talk its way into the list comprehension?
In this case, the answer is yes :-)
[i : p | i <- [hi,hi-1..1], p <- partitionsCap i (n-i)]
where hi = min cap n
I'm a little rusty with Haskell, but maybe the following code can guide you to find the solution.
parts :: Int -> Int -> [[Int]]
parts 0 p = [[]]
parts x p = [(y:ys) | y <-[p..x], ys <- (parts (x - y) y)]
And then you would have to call parts with x = n, and p = 1.
EDIT
I've fixed the base case when x equals 0 to return a list with a single item, being that item an empty list. Now it works fine :)

Haskell: recursion with array arguments

Disclaimer: I'm new to Haskell and I don't remember a lot about FP from university, so there may be more than one or two errors in my code. This is also my code for Euler Problem 3.
I'm trying to recursively call a function with two arrays as arguments and an array as a result.
The goal:
assume n is 10 for this question
create a list of all natural numbers from 1 to n (variable is 'allNumbers' is code)
create another list of all natural numbers from 1 to n (variable is 'allFactors' is code)
take the first element in 'allFactors' and multiply the rest of the numbers of 'allFactors' by this number. (this generates an array of numbers)
remove all these numbers from 'allNumbers'
continue from 1 to n until 'allFactors' is empty.
Here is my code:
mkList :: Int -> [Int]
mkList n = [1..n-1]
modArray :: Int -> Int -> [Int]
modArray a b = [ x*b | x <- [1..a], x `mod` b == 0]
modArrayAll :: [Int] -> [Int] -> [Int]
modArrayAll [] [] = []
modArrayAll (x:xs) (y:ys) = (e)
where
m = head( ys)
n = length( xs)
e = (modArrayAll xs ys ) \\ modArray n m
(in main)
let allNumbers = mkList (first + 1)
let allFactors = mkList (first + 1)
let mainList2 = modArrayAll allNumbers allFactors
This results in a null list. However, if I have:
e = xs \\ modArray n m --WORKS for one iteration
I get all the odd numbers from 1 to 10.
My Question: Why isn't this working the way I would expect it? I would expect that the recursive stack would hit the empty array condition and just return an empty array which would not be removed from the calling array and it would continue on returning just the prime numbers?
I copied your goal notes:
-- assume n is 10 for this question
n=10
-- create a list of all natural numbers from 1 to n (variable is 'allNumbers' is code)
allNumbers = [1..n]
-- create another list of all natural numbers from 1 to n (variable is 'allFactors' is code)
allFactors = [2..n] -- i suspect you really wanted this rather than [1..n]
-- take the first element in 'allFactors' and
-- multiply the rest of the numbers of 'allFactors' by this number.
-- (this generates an array of numbers)
-- continue from 1 to n until 'allFactors' is empty
factorProducts = [ x*y | x <- allFactors, y <- allFactors]
-- remove all these numbers from 'allNumbers'
whatYouWanted = allNumbers \\ factorProducts
At the moment you seem to still be thinking in a fairly imperative mindset. Try thinking more about what you want, not how to get it :)
modArray n m creates a list of multiples of m, which you then remove from the "main list" of integers. But modArray n m includes 1*m, so each number is removed because it is a "multiple" of itself. In your test case you get only the odd numbers as a result, while you would want 2 to still be in the resulting list. Additionally 1 is included in your list of factors, which will eliminate all numbers, since they are all multiples of 1.
The terminating case of the recursion is modArrayAll [] [] = [], so there an empty list is returned. Then in the surrounding recursive calls this return value is used here:
(modArrayAll xs ys) \\ modArray n m
This tries to remove further elements (those returned by modArray n m) from the already empty list returned by modArrayAll xs ys. No new elements are added anywhere and the result list stays empty. With your algorithm you want the []-case to return the whole list of numbers, not an empty one. Then the \\ modArray n m in the surrounding recursive function calls can filter out more and more of the non-prime factors.

Resources