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
maximumpart. To get the list (that’s what Haskell’s []s are, arrays are different structures) you need to use themaphigher-order function, like this:Essentially,
maptakes 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
chainLengthfunction to return the number as well, like this: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
maximumByfunction comes in. It works just likemaximumbut 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 typeOrdering. 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:
I used the default
comparefunction that compares numbers (well, not just numbers).Now we only need to get the maximum using this function:
That gets you a pair of the number with the longest chain and the corresponding length. Feel free to apply
fstandsndas you please.Note that this could be more much more concisely using
zipand composition, but since you tagged the question as newbie, I thought it better to break it down like this.