
Jerzy Karczmarczuk schreef op 6-2-2015 om 16:57:
Le 06/02/2015 16:48, Roelof Wobben a écrit :
Im only sure that somehow I take the wrong turn somewhere because I cannot figure out why I do not get the right answer.
I think I have the value of n wrong. Did you read my answer entirely? Do so, find the red fat line
You take n=1, and you write: n<10 not True. You don't need to be a specialist on recursion, to see the error.
Jerzy
oke, Another try : toDigits :: Integer -> [Integer] toDigits n | n < 0 = [] | n < 10 = [n] | otherwise = toDigits (n `div` 10) ++ [n `mod` 10] isDigits 1 n < 0 not true. n < 10 true so [1] IsDigits 12 n < 0 not true n < 10 not true toDigits 1 + [2] toDigits 1 + [2] n < 0 not true n < 10 true [1] ++ [2] 1 ++2 = [1,2] I think I understand it finnaly. Roelof

Here's a solution:
lastDigit x = mod x 10
remainingDigits x = (x - lastDigit x) `div` 10
listDigits x
| x < 10 = [x]
| otherwise = (listDigits $ remainingDigits x) ++ [lastDigit x]
Here's a faster one:
listDigits2 x
| x < 10 = [x]
| otherwise = (listDigits $ remainingDigits) ++ [lastDigit]
where lastDigit = mod x 10
remainingDigits = (x - lastDigit) `div` 10
On Fri, Feb 6, 2015 at 8:07 AM, Roelof Wobben
Jerzy Karczmarczuk schreef op 6-2-2015 om 16:57:
Le 06/02/2015 16:48, Roelof Wobben a écrit :
Im only sure that somehow I take the wrong turn somewhere because I cannot figure out why I do not get the right answer.
I think I have the value of n wrong.
Did you read my answer entirely? Do so, find the red fat line
You take n=1, and you write: n<10 not True. You don't need to be a specialist on recursion, to see the error.
Jerzy
oke,
Another try :
toDigits :: Integer -> [Integer] toDigits n | n < 0 = [] | n < 10 = [n] | otherwise = toDigits (n `div` 10) ++ [n `mod` 10]
isDigits 1
n < 0 not true. n < 10 true so [1]
IsDigits 12
n < 0 not true n < 10 not true toDigits 1 + [2]
toDigits 1 + [2]
n < 0 not true n < 10 true [1] ++ [2]
1 ++2 = [1,2]
I think I understand it finnaly.
Roelof
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Feb 6, 2015 3:41 PM, "Jeffrey Brown"
Here's a solution: lastDigit x = mod x 10 remainingDigits x = (x - lastDigit x) `div` 10 listDigits x | x < 10 = [x] | otherwise = (listDigits $ remainingDigits x) ++ [lastDigit x]
Here's a faster one: listDigits2 x | x < 10 = [x] | otherwise = (listDigits $ remainingDigits) ++ [lastDigit] where lastDigit = mod x 10 remainingDigits = (x - lastDigit) `div` 10
These give somewhat peculiar results when the argument is negative. That can be rectified, of course. Unfortunately, all of these proposed solutions have a serious performance problem: successively appending single elements to build a list of length n is O(n^2). There's an easy fix, which I'll let you come up with. David

Is it successively appending? My intention was to prepend. If it's
appending, Is that because the ++ operator always evaluates its left
argument first, then its right one?
On Fri, Feb 6, 2015 at 2:42 PM, David Feuer
On Feb 6, 2015 3:41 PM, "Jeffrey Brown"
wrote: Here's a solution: lastDigit x = mod x 10 remainingDigits x = (x - lastDigit x) `div` 10 listDigits x | x < 10 = [x] | otherwise = (listDigits $ remainingDigits x) ++ [lastDigit x]
Here's a faster one: listDigits2 x | x < 10 = [x] | otherwise = (listDigits $ remainingDigits) ++ [lastDigit] where lastDigit = mod x 10 remainingDigits = (x - lastDigit) `div` 10
These give somewhat peculiar results when the argument is negative. That can be rectified, of course. Unfortunately, all of these proposed solutions have a serious performance problem: successively appending single elements to build a list of length n is O(n^2). There's an easy fix, which I'll let you come up with.
David

Jeff,
An expression of the form xs ++ [x] appends the element to the end of the
list. In order to evaluate the result, the ++ function iterates through the
elements of the first list to find the end of the list then sets the tail
of the last element of the first list to the second list. This means that
on each recursive call (once per digit), your algorithm must traverse the
list of digits already produced to attach the newest element. You can avoid
this problem by instead consing the new digit onto the front of the list,
and then reverse the list at the end to produce the digits in the correct
order. Alternatively, you could try and compute the digits in the reverse
order.
Here's another solution, though it also will only work on positive integers
and will fail on negative inputs:
import Data.Char (digitToInt)
lastDigit :: Int -> [Int]
lastDigit x = map digitToInt (show x)
You can fix the issues with this implementation by replacing digitToInt
with a wrapper that checks if the character being analyzed is in fact a
digit and then providing something if it is not. What you should provide in
the failure case is up to the requirements of the problem.
Thanks,
Arjun
On Fri, Feb 6, 2015 at 8:01 PM, Jeffrey Brown
Is it successively appending? My intention was to prepend. If it's appending, Is that because the ++ operator always evaluates its left argument first, then its right one?
On Fri, Feb 6, 2015 at 2:42 PM, David Feuer
wrote: On Feb 6, 2015 3:41 PM, "Jeffrey Brown"
wrote: Here's a solution: lastDigit x = mod x 10 remainingDigits x = (x - lastDigit x) `div` 10 listDigits x | x < 10 = [x] | otherwise = (listDigits $ remainingDigits x) ++ [lastDigit x]
Here's a faster one: listDigits2 x | x < 10 = [x] | otherwise = (listDigits $ remainingDigits) ++ [lastDigit] where lastDigit = mod x 10 remainingDigits = (x - lastDigit) `div` 10
These give somewhat peculiar results when the argument is negative. That can be rectified, of course. Unfortunately, all of these proposed solutions have a serious performance problem: successively appending single elements to build a list of length n is O(n^2). There's an easy fix, which I'll let you come up with.
David
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

I see: what matters is that ++ has to traverse to the end of the first
list. The order in which its two arguments are evaluated is irrelevant.
Thank you, David and Arjun!
On Fri, Feb 6, 2015 at 5:38 PM, Arjun Comar
Jeff, An expression of the form xs ++ [x] appends the element to the end of the list. In order to evaluate the result, the ++ function iterates through the elements of the first list to find the end of the list then sets the tail of the last element of the first list to the second list. This means that on each recursive call (once per digit), your algorithm must traverse the list of digits already produced to attach the newest element. You can avoid this problem by instead consing the new digit onto the front of the list, and then reverse the list at the end to produce the digits in the correct order. Alternatively, you could try and compute the digits in the reverse order.
Here's another solution, though it also will only work on positive integers and will fail on negative inputs:
import Data.Char (digitToInt)
lastDigit :: Int -> [Int] lastDigit x = map digitToInt (show x)
You can fix the issues with this implementation by replacing digitToInt with a wrapper that checks if the character being analyzed is in fact a digit and then providing something if it is not. What you should provide in the failure case is up to the requirements of the problem.
Thanks, Arjun
On Fri, Feb 6, 2015 at 8:01 PM, Jeffrey Brown
wrote: Is it successively appending? My intention was to prepend. If it's appending, Is that because the ++ operator always evaluates its left argument first, then its right one?
On Fri, Feb 6, 2015 at 2:42 PM, David Feuer
wrote: On Feb 6, 2015 3:41 PM, "Jeffrey Brown"
wrote: Here's a solution: lastDigit x = mod x 10 remainingDigits x = (x - lastDigit x) `div` 10 listDigits x | x < 10 = [x] | otherwise = (listDigits $ remainingDigits x) ++ [lastDigit x]
Here's a faster one: listDigits2 x | x < 10 = [x] | otherwise = (listDigits $ remainingDigits) ++ [lastDigit] where lastDigit = mod x 10 remainingDigits = (x - lastDigit) `div` 10
These give somewhat peculiar results when the argument is negative. That can be rectified, of course. Unfortunately, all of these proposed solutions have a serious performance problem: successively appending single elements to build a list of length n is O(n^2). There's an easy fix, which I'll let you come up with.
David
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Le 07/02/2015 02:48, Jeffrey Brown a écrit :
I see: what matters is that ++ has to traverse to the end of the first list. The order in which its two arguments are evaluated is irrelevant.
Thank you, David and Arjun!
On Fri, Feb 6, 2015 at 5:38 PM, Arjun Comar
mailto:nrujac@gmail.com> wrote: Jeff, An expression of the form xs ++ [x] appends the element to the end of the list. In order to evaluate the result, the ++ function iterates through the elements of the first list to find the end of the list then sets the tail of the last element of the first list to the second list.
Gentlemen, don't forget that Haskell is lazy, and this traversal takes place only when the list is effectively traversed by a consumer, which stores everything (and doesn't get rid of elements read). This might be the case here if somebody wants to keep and use the "digit representation" of a number, but please do not consider this phenomenon as inherent to the list creation algorithm. Jerzy Karczmarczuk
participants (5)
-
Arjun Comar
-
David Feuer
-
Jeffrey Brown
-
Jerzy Karczmarczuk
-
Roelof Wobben