tags:

views:

192

answers:

4

Given an arbitrary number, how can I process each digit of the number individually?

Edit I've added a basic example of the kind of thing Foo might do.

For example, in C# I might do something like this:

static void Main(string[] args)
{
    int number = 1234567890;
    string numberAsString = number.ToString();

    foreach(char x in numberAsString)
    {
        string y = x.ToString();
        int z = int.Parse(y);
        Foo(z);
    }
}

void Foo(int n)
{
    Console.WriteLine(n*n);
}
+4  A: 

Have you heard of div and mod? You'll probably want to reverse the list of numbers if you want to treat the most significant digit first. Converting the number into a string is an impaired way of doing things.

135 `div` 10 = 13
135 `mod` 10 = 5

Or, if you want the full code to get the digits:

digs 0 = []
digs x = digs (x `div` 10) ++ [x `mod` 10]

Or in reverse:

digs 0 = []
digs x = x `mod` 10 : digs (x `div` 10)

This treats 0 as having no digits. A simple wrapper function can deal with that special case if you want to.

Does it work for negative numbers? I haven't tried.

supercooldave
@supercooldave Care to give me an example?
Greg B
[quotRem](http://www.haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/Prelude.html#v%3AquotRem).
KennyTM
@supercooldave I've added an example to my code as I don't see how div and mod will help me walk over the digits of any arbitrary number. Could you expand on your thoughts please.
Greg B
@Greg B this is a haskell source code that does the exact same thing your algorithm does, but using @supercooldave algorithm => http://pastie.org/1231091
Roman Gonzalez
+2  A: 

Using the same technique used in your post, you can do:

digits :: Integer -> [Int]
digits n = map (\x -> read [x] :: Int) (show n)

See it in action:

Prelude> digits 123
[1,2,3]

Does that help?

Daniel
`digits = map (read . (:[])) . show`
sreservoir
+4  A: 
digits :: Integer -> [Int]
digits = map (read . (:[])) . show

or you can return it into []:

digits :: Integer -> [Int]
digits = map (read . return) . show

or, with Data.Char.digitToInt:

digits :: Integer -> [Int]
digits = map digitToInt . show

the same as Daniel's really, but pointless and uses Int, because a digit shouldn't really exceed maxBound :: Int.

sreservoir
maybe (digits = map (read . return) . show) ? or (read . pure)..
Ed'ka
the `digitToInt` version is probably better anyway, and `:[]` was slightly more obvious to me. eh, I'll edit it in. I have no idea where pure is from, so.
sreservoir
+3  A: 

You can use

digits = map (`mod` 10) . reverse . takeWhile (> 0) . iterate (`div` 10)

or for reverse order

rev_digits = map (`mod` 10) . takeWhile (> 0) . iterate (`div` 10)

The iterate part generates an infinite list dividing the argument in every step by 10, so 12345 becomes [12345,1234,123,12,1,0,0..]. The takeWhile part takes only the interesting non-null part of the list. Then we reverse (if we want to) and take the last digit of each number of the list.

I used point-free style here, so you can imagine an invisible argument n on both sides of the "equation". However, if you want to write it that way, you have to substitute the top level . by $:

digits n = map(`mod` 10) $ reverse $ takeWhile (> 0) $ iterate (`div`10) n
Landei