tags:

views:

108

answers:

4
dreiNplusEins :: Integer -> [Integer]
dreiNplusEins n = if n == 1 then [1] else if n `mod` 2 == 0 then
                        [n] ++ dreiNplusEins (n `div` 2)
                                        else
                        [n] ++ dreiNplusEins (n * 3 + 1)

maxZyklus :: UntereGrenze -> ObereGrenze -> (UntereGrenze,ObereGrenze,MaxZyklaenge)
maxZyklus m n = if m > n then (m,n,0) else if m == n then 
                         (m,n,length(dreiNplusEins m))
                         else 
                         (m,n,0)
type UntereGrenze = Integer
type ObereGrenze  = Integer
type MaxZykLaenge = Integer

this is my program and this gives error as Not in scope: type constructor or class `MaxZyklaenge' how can i fix it ?

+6  A: 

You have a typo in the type name:

In the type signature of maxZyklus you write MaxZyklaenge (lower case l), but in the type definition you write MayZykLaenge (capital L).

sepp2k
... do you mean "You have a typo"? ;)
KennyTM
@KennyTM: Hehe, I typoed "typo" ;-)
sepp2k
+1  A: 

Haskell is case sensitive.

In the type signature of maxZyklus:

 ... ,MaxZyklaenge)
-- #        ^

But you have:

 type MaxZykLaenge = Integer
-- #        ^
KennyTM
A: 

It's defined as MaxZykLaenge (note the "L"), whereas you wrote the type as "MaxZyklaenge". Haskell is case-sensitive.

Chuck
+3  A: 

Even if you fix the typo you'll still get an error, since length returns an Int where you need an Integer. The following is one way to fix this (I've also rewritten your code to use guards):

import Data.List (genericLength)

dreiNplusEins :: Integer -> [Integer]
dreiNplusEins 1 = [1]
dreiNplusEins n
  | n `mod` 2 == 0 = n : dreiNplusEins (n `div` 2)
  | otherwise      = n : dreiNplusEins (n * 3 + 1)

maxZyklus :: UntereGrenze -> ObereGrenze -> (UntereGrenze, ObereGrenze, MaxZyklaenge)
maxZyklus m n
 | m == n    = (m, n, genericLength $ dreiNplusEins m)
 | otherwise = (m, n, 0)

type UntereGrenze = Integer
type ObereGrenze  = Integer
type MaxZyklaenge = Integer

You could also use fromIntegral . length if you don't want the extra import, but I personally think genericLength is a little clearer.


Also, if you're interested, here's an arguably nicer way to write the first function:

dreiNplusEins :: Integer -> [Integer]
dreiNplusEins = (++[1]) . takeWhile (/=1) . iterate f
  where
    f n | even n    = n `div` 2
        | otherwise = n * 3 + 1

This just says "iteratively apply f until you hit a 1, and then tack a 1 on the end".


To find the number in a given range that produces the longest chain, you can use the following function:

longestBetween :: (Enum a, Integral b) => (a -> [b]) -> (a, a) -> (a, b)
longestBetween f (m, n)
  = maximumBy (comparing snd)
  . zip [m..n] $ map (genericLength . f) [m..n]

The first argument is the function that creates the list and the second is the range. The return value is a tuple containing the desired number in the range and the length of its list. Note that we need these additional imports:

import Data.List (genericLength, maximumBy)
import Data.Ord (comparing)

We can test as follows:

*Main> longestBetween dreiNplusEins (100, 1000) 
(871,179)

Implementing the maxZyklus function you specify in the comments just takes a couple of minor changes at this point:

maxZyklus m n = (m, n, maximum $ map (genericLength . dreiNplusEins) [m..n])

maxZyklus 11 22 gives the desired (11, 22, 21).

Travis Brown
do you know how can i let the program to search for the maximum length of deriNplusEins from the given intervall m to n? for example maxZyklus 11 22 here the program has to calcualte the maximum length of dreiNplusEins for each value (11,12,13,14,..22) and give the maximum length back.
marco
@marco: Something like `maximumBy (comparing snd) $ zip [m..n] $ map (length . dreiNplusEins) [m..n]` (where `maximumBy` is from `Data.List` and `comparing` is from `Data.Ord`) should do the trick.
Travis Brown
you can add it in the code I get error messages
marco
I'm really new in this language
marco
@marco: I've added a working example.
Travis Brown
this program muss with command maxZyklus 11 22 call and gives (11,22, and the longest list betweetn 11..22) when your programlongestBestween give Integer (longest list length) back then it is true
marco
for example *Main> length(dreiNplusEins 11) 15*Main> length(dreiNplusEins 12)10*Main> length(dreiNplusEins 13)10*Main> length(dreiNplusEins 14)18*Main> length(dreiNplusEins 15)18*Main> length(dreiNplusEins 16)5*Main> length(dreiNplusEins 17)13*Main> length(dreiNplusEins 18)21*Main> length(dreiNplusEins 19)21*Main> length(dreiNplusEins 20)8*Main> length(dreiNplusEins 21)8*Main> length(dreiNplusEins 22)16 we muss save the result length in a list and take the maximum this is what am i looking for
marco
this example maxZyklus 11 22 muss give (11,22,21) back
marco
@marco: I've updated with your `maxZyklus`, but I don't understand why you want the function to return its arguments—there is almost certainly a better way to accomplish whatever goal you have in mind.
Travis Brown