Good morning everyone!
I'm using the following function as a fitting example of a function that needs to have a simple input and output. In this case it's a function that converts a number from decimal to binary form, as a list of digits no less, just because it is convenient later on.
I chose to write it like this, because even though a number goes in and a list comes out, another structure is needed as an intermediate step, that will hold the digits found so far and hold the quotient of the division, as input for the next step of the loop. I will clean up the necessary mess before outputing anything, though, by selecting the part of the structure that I'm interested in, in this case the second one , and not counters or other stuff, that I'm done with. (As I mentioned this is an example only, and it's not unusual in other cases to initialize the until loop with a triplet like (a,b,c), only to pick one of them at the end, as I see fit, with the help of additional function, like pickXof3.)
So there,
dec2Bin :: Int -> [Int]
dec2Bin num = snd $ until
(\(n,l) -> n <=0) -- test
(\(n,l) -> (fst $ division n, (snd $ division n):l)) -- main function
(num,[]) -- initialization
where division a = divMod a 2
I find it very convenient that Haskell, although lacking traditional for/while loops has a function like until, which reminds me very much of Mathematica's NextWhile, that I'm familiar with.
In the past I would write sth even uglier, like two functions, a "helper" one and a "main" one, like so
dec2BinHelper :: (Int,[Int]) -> (Int,[Int])
dec2BinHelper (n,l)
| n <= 0 = (n,l)
| otherwise = dec2BinHelper (fst $ division n, (snd $ division n):l)
where division a = divMod a 2
-- a function with the sole purpose to act as a front-end to the helper function, initializing its call parameters and picking up its output
dec2Bin :: Int -> [Int]
dec2Bin n = snd $ dec2BinHelper (n,[])
which I think is unnecessarily bloated.
Still, while the use of until allows me to define just one function, I get the feeling that it could be done even simpler/easier to read, perhaps in a way more fitting to functional programming. Is that so? How would you write such a function differently, while keeping the input and output at the absolutely essential values?
I strongly prefer your second solution. I'd start a clean-up with two things: use pattern matching, and use where to hide your helper functions. So:
dec2Bin :: Int -> [Int]
dec2Bin n = snd $ dec2BinHelper (n, []) where
dec2BinHelper (n, l)
| n <= 0 = (n, l)
| otherwise = dec2BinHelper (d, m:l)
where (d, m) = divMod n 2
Now, in the base case, you return a tuple; but then immediately call snd on it. Why not fuse the two?
dec2Bin :: Int -> [Int]
dec2Bin n = dec2BinHelper (n, []) where
dec2BinHelper (n, l)
| n <= 0 = l
| otherwise = dec2BinHelper (d, m:l)
where (d, m) = divMod n 2
There's no obvious reason why you should pass these arguments in a tuple, rather than as separate arguments, which is more idiomatic and saves some allocation/deallocation noise besides.
dec2Bin :: Int -> [Int]
dec2Bin n = dec2BinHelper n [] where
dec2BinHelper n l
| n <= 0 = l
| otherwise = dec2BinHelper d (m:l)
where (d, m) = divMod n 2
You can swap the arguments to dec2BinHelper and eta-reduce; that way, you will not be shadowing the definition of n.
dec2Bin :: Int -> [Int]
dec2Bin = dec2BinHelper [] where
dec2BinHelper l n
| n <= 0 = l
| otherwise = dec2BinHelper (m:l) d
where (d, m) = divMod n 2
Since you know that n > 0 in the recursive call, you can use the slightly faster quotRem in place of divMod. You could also consider using bitwise operations like (.&. 1) and shiftR 1; they may be even better, but you should benchmark to know for sure.
dec2Bin :: Int -> [Int]
dec2Bin = dec2BinHelper [] where
dec2BinHelper l n
| n <= 0 = l
| otherwise = dec2BinHelper (r:l) q
where (q, r) = quotRem n 2
When you don't have a descriptive name for your helper function, it's traditional to name it go or loop.
dec2Bin :: Int -> [Int]
dec2Bin = go [] where
go l n
| n <= 0 = l
| otherwise = go (r:l) q
where (q, r) = quotRem n 2
At this point, the two sides of the conditional are short enough that I'd be tempted to put them on their own line, though this is something of an aesthetic choice.
dec2Bin :: Int -> [Int]
dec2Bin = go [] where
go l n = if n <= 0 then l else go (r:l) q
where (q, r) = quotRem n 2
Finally, a comment on the name: the input isn't really in decimal in any meaningful sense. (Indeed, it's much more physically accurate to think of the input as already being in binary!) Perhaps int2Bin or something like that would be more accurate. Or let the type speak for itself, and just call it toBin.
toBin :: Int -> [Int]
toBin = go [] where
go l n = if n <= 0 then l else go (r:l) q
where (q, r) = quotRem n 2
At this point I'd consider this code quite idiomatic.
I want to create a function as mentioned in the title. The specific is that it adds the digits in reversed order, you can see that in the test cases: 12 -> 1; 852369 -> 628; 1714 -> 11; 12345 -> 42; 891 -> 9; 448575 -> 784; 4214 -> 14
The main idea is that when the number is bigger than 99 it enters the helper function which has i - indicator if the the digit is on an even position, and res which stores the result. Helper begins to cycle n as it checks whether or not the current digit is on even position and adds it to the result.
So far I've tried the following code:
everyOther :: Int -> Int
everyOther n
| n < 10 = error "n must be bigger than 10 or equal"
| n < 100 = div n 10
| otherwise = helper n 0 0
where
helper :: Int -> Int -> Int -> Int
helper n i res
| n < 100 = res
| i == 1 = helper (div n 10) (i - 1) (res + (mod n 10)*10)
| otherwise = helper (div n 10) i res
Any help would be appreciated!
You can obtain the one but last digit of x with mod (div x 10) 10. You can use this with an accumulator that accumulates the value by each time multiplying with 10, so:
everyOther :: Int -> Int
everyOther = go 0
where go a v
| v < 10 = a
| otherwise = go (10*a + mod (div v 10) 10) (div v 100)
If v is thus less than 10, we can return the accumulator, since there is no "other digit" anymore. If that is not the case, we multiply a with 10, and add mod (div v 10) 10 to add the other digit to it, and recurse with the value divided by 100 to move it two places to the right.
We can improve this, as #Daniel Wagner says, by making use of quotRem :: Integral a => a -> a -> (a, a):
everyOther :: Int -> Int
everyOther = go 0
where go a v
| v < 10 = a
| otherwise = let (q, r) = v `quotRem` 100 in go (10*a + r `quot` 10) q
here we thus work with the remainder of a division by 100, and this thus avoids an extra modulo.
I am stuck with the variable not in scope: m error.
This is supposed to be a code to sum n numbers in a tail recursion way.
zum :: Integer-> Integer
zum n = add_sum m n where
add_sum :: Integer-> Integer-> Integer
add_sum m n
| n == 0 = m
| otherwise = add_sum (m+n) (n-1)
In the second line of your code
zum n = add_sum m n where
'm' is not defined. Perhaps it was intended that instead of an 'm', there needs to be 0 there.
perhaps cleaner this way?
sum n = go 0 n
where go m 0 = m
go m n = go (m+n) (n-1)
> sum 4
10
I am new to haskell and trying out some exercise.While trying to load the below code i am getting a binding error howmanytwoequal function.Can anyone please tell me as to what mistake i had done.
howmayoftwoequal :: Int->Int->Int
howmanyoftwoequal m n
|m==n =1
|otherwise =0
howmanyequal::Int->Int->Int->Int
howmanyequal m n o
| howmanyoftwoequal m n && howmanyoftwoequal n o =3
| howmanyoftwoequal m n || howmanyoftwoequal n o =2
|otherwise =1
You have several issues in your code:
Typo in howmanyoftwoequal type definition: you have 'howmayoftwoequal' instead of 'howmanyoftwoequal'
To use howmanyoftwoequal in boolean operations && and || its type should be Bool:
howmanyoftwoequal :: Int->Int->Bool
howmanyoftwoequal m n = m==n
Your definition of howManyEqual misses the case where m == o but m == n || n == o does not hold, which it seems should also be a valid case for it returning 2.
If you are trying to return the size of the largest equivalence class between m, n, and o, this can be achieved as follows:
largestEquivSize :: [Int] -> Int
largestEquivSize = maximum . map length . group . sort
howManyEqual :: Int -> Int -> Int -> Int
howManyEqual m n o = largestEquivSize [m, n, o]
With the added bonus that largestEquivSize is a lot more general (in fact its type is unnecessarily constrained here, and could be Ord a => [a] -> Int).
I have this code to work out the sum of squares of integers in the range of m:n
sumsquares :: Integral a=> Int -> Int -> Int -> Int
sumsquares m n middle
| m > n = error "First number cannot be bigger than second number"
|m==n = m*m
|otherwise = m*m + sumsquares (m+1)n
How would i redefine the function sumsquares for this purpose?
If there is more than one number in the range m:n, compute the middle of the range and add the sum of the squares of (m:middle) to sum of the squares (middle+1:n),
otherwise there is only one number in the range m:n, so m = = n, and the solution is just the square of m. (Note that with this approach the recursion combines two half- solutions: each sub-problem is approximately half in size of the overall problem).
In your original function, the class constraint Integral a in the type signature is obsolete (a is not mentioned anywhere else in the signature, is it?). Furthermore, the third parameter of the function (middle) remains unused. Hence, you could have written it as
sumsquares :: Int -> Int -> Int
sumsquares m n
| m > n = error "First number cannot be bigger than second number"
| m == n = m * m
| otherwise = m * m + sumsquares (m + 1) n
Rewriting it to move from a decrease-and-conquer scheme to a strict divide-and-conquer scheme then just involves adapting the recursive case accordingly:
sumsquares :: Int -> Int -> Int
sumsquares m n
| m > n = error "First number cannot be bigger than second number"
| m == n = m * m
| otherwise = let middle = (m + n) `div` 2
in sumsquares m middle + sumsquares (middle + 1) n
The question remains, of course, why you would want to make this change. One reason could be that you are preparing your algorithm to be adapted for parallelisation: then, indeed, divide-and-conquer is often a better fit than decrease-and-conquer.