Sum digits of an integer: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Perl 6}}: Added Perl 6 solution)
Line 381: Line 381:


=={{header|Perl 6}}==
=={{header|Perl 6}}==
This will handle input numbers in any base fron 2 to 36. The results are in base 10.
This will handle input numbers in any base from 2 to 36. The results are in base 10.
<lang perl6>
<lang perl6>
say Σ $_ for <1 1234 1020304 fe f0e DEADBEEF>;
say Σ $_ for <1 1234 1020304 fe f0e DEADBEEF>;

Revision as of 02:34, 25 July 2012

Task
Sum digits of an integer
You are encouraged to solve this task according to the task description, using any language you may know.

This task takes a Natural Number in a given Base and returns the sum of it digits:

1 sums to 1;
1234 sums to 10;
0xfe sums to 29;
0xf0e sums to 29.

Ada

<lang Ada>with Ada.Integer_Text_IO;

procedure Sum_Digits is

  -- sums the digits of an integer (in whatever base)
  -- outputs the sum (in base 10)
  function Sum_Of_Digits(N: Natural; Base: Natural := 10) return Natural is
     Sum: Natural := 0;
     Val: Natural := N;
  begin
     while Val > 0 loop
        Sum := Sum + (Val mod Base);
        Val := Val / Base;
     end loop;
     return Sum;
  end Sum_Of_Digits;
  use Ada.Integer_Text_IO;

begin -- main procedure Sum_Digits

  Put(Sum_OF_Digits(1));            --   1
  Put(Sum_OF_Digits(12345));        --  15
  Put(Sum_OF_Digits(123045));       --  15
  Put(Sum_OF_Digits(123045,  50));  -- 104
  Put(Sum_OF_Digits(16#fe#,  10));  --  11
  Put(Sum_OF_Digits(16#fe#,  16));  --  29
  Put(Sum_OF_Digits(16#f0e#, 16));  --  29

end Sum_Digits;</lang>

Output:
          1         15         15        104         11         29         29

AWK

MAWK only support base 10 numeric constants, so a conversion function is necessary.

Will sum digits in numbers from base 2 to base 16.

The output is in decimal. Output in other bases would require a function to do the conversion because MAWK's printf() does not support bases other than 10.

Other versions of AWK may not have these limitations.

<lang AWK>#!/usr/bin/awk -f

BEGIN {

   print sumDigits("1")
   print sumDigits("12")
   print sumDigits("fe")
   print sumDigits("f0e")

}

function sumDigits(num, nDigs, digits, sum, d, dig, val, sum) {

   nDigs = split(num, digits, "")
   sum = 0
   for (d = 1; d <= nDigs; d++) {
       dig = digits[d]
       val = digToDec(dig)
       sum += val
   }
   return sum

}

function digToDec(dig) {

   return index("0123456789abcdef", tolower(dig)) - 1

} </lang>

Example output:

1
3
29
29

C++

<lang cpp> // Sum the digits of an Integer // // Nigel Galloway. July 16th., 2012 //

  1. include <iostream>
  2. include <cmath>

int SumDigits(const unsigned long long int digits, const int BASE = 10) {

   int sum = 0;
   unsigned long long int x = digits;
   for (int i = log(digits)/log(BASE); i>0; i--){
       const double z = std::pow(BASE,i);

const unsigned long long int t = x/z; sum += t; x -= t*z;

   }
   return x+sum;

}

int main() {

       std::cout << SumDigits(1) << ' '
                 << SumDigits(12345) << ' '
                 << SumDigits(123045) << ' '
                 << SumDigits(0xfe, 16) << ' '
                 << SumDigits(0xf0e, 16) << std::endl;
       return 0;

}</lang>

Output:
1 15 15 29 29

Erlang

<lang erlang> -module(sum_digits). -export([sum_digits/2, sum_digits/1]).

sum_digits(N) ->

   sum_digits(N,10).

sum_digits(N,B) ->

   sum_digits(N,B,0).

sum_digits(0,_,Acc) ->

   Acc;

sum_digits(N,B,Acc) when N < B ->

   Acc+N;

sum_digits(N,B,Acc) ->

   sum_digits(N div B, B, Acc + (N rem B)).

</lang>

Example usage:

2> sum_digits:sum_digits(1).
1
3> sum_digits:sum_digits(1234).
10
4> sum_digits:sum_digits(16#fe,16).
29
5> sum_digits:sum_digits(16#f0e,16).
29

J

<lang j>digsum=: 10&$: : (+/@(#.inv))</lang>

Example use:

<lang J> digsum 1234 10

  10 digsum 254

11

  16 digsum 254

29</lang>

Illustration of mechanics:

<lang j> 10 #. 1 2 3 4 1234

 10 #.inv 1234

1 2 3 4

 10 +/ 1 2 3 4

10

 10 +/@(#.inv) 1234

10</lang>

So #.inv gives us the digits, +/ gives us the sum, and @ glues them together with +/ being a "post processor" for #.inv or, as we say in the expression: (#.inv). We need the parenthesis or inv will try to look up the inverse of +/@#. and that's not well defined.

The rest of it is about using 10 as the default left argument when no left argument is defined. A J verb has a monadic definition (for use with one argument) and a dyadic definition (for use with two arguments) and : derives a new verb where the monadic definition is used from the verb on the left and the dyadic definition is used from the verb on the right. $: is a self reference to the top-level defined verb.

Full examples:

<lang j> digsum 1 1

  digsum 1234

10

  16 digsum 16bfe

29

  16 digsum 16bf0e

29</lang>

Note that J implements numeric types -- J tries to ensure that the semantics of numbers match their mathematical properties. So it doesn't matter how we originally obtained a number.

<lang j> 200+54 254

  254

254

  2.54e2

254

  16bfe

254</lang>

Java

<lang java>import java.math.BigInteger; public class SumDigits {

   public static int sumDigits(long num) {

return sumDigits(num, 10);

   }
   public static int sumDigits(long num, int base) {

String s = Long.toString(num, base); int result = 0; for (int i = 0; i < s.length(); i++) result += Character.digit(s.charAt(i), base); return result;

   }
   public static int sumDigits(BigInteger num) {

return sumDigits(num, 10);

   }
   public static int sumDigits(BigInteger num, int base) {

String s = num.toString(base); int result = 0; for (int i = 0; i < s.length(); i++) result += Character.digit(s.charAt(i), base); return result;

   }
   public static void main(String[] args) {

System.out.println(sumDigits(1)); System.out.println(sumDigits(12345)); System.out.println(sumDigits(123045)); System.out.println(sumDigits(0xfe, 16)); System.out.println(sumDigits(0xf0e, 16)); System.out.println(sumDigits(new BigInteger("12345678901234567890")));

   }

}</lang>

Output:
1
15
15
29
29
90

NetRexx

Strings

Processes data as text from the command line. Provides a representative sample if no input is supplied: <lang NetRexx>/* NetRexx */ options replace format comments java crossref symbols nobinary

parse arg input inputs = ['1234', '01234', '0xfe', '0xf0e', '0', '00', '0,2' '1', '070', '77, 8' '0xf0e, 10', '070, 16', '0xf0e, 36', '000999ABCXYZ, 36', 'ff, 16', 'f, 10', 'z, 37'] -- test data if input.length() > 0 then inputs = [input] -- replace test data with user input loop i_ = 0 to inputs.length - 1

 in = inputs[i_]
 parse in val . ',' base .
 dSum = sumDigits(val, base)
 say 'Sum of digits for integer "'val'" for a given base of "'base'":' dSum'\-'
 -- Carry the exercise to it's logical conclusion and sum the results to give a single digit in range 0-9
 loop while dSum.length() > 1 & dSum.datatype('n')
   dSum = sumDigits(dSum, 10)
   say ',' dSum'\-'
   end
 say
 end i_

-- Sum digits of an integer method sumDigits(val = Rexx, base = Rexx ) public static returns Rexx

 rVal = 0
 parse normalizeValue(val, base) val base .
 loop label digs for val.length()
   -- loop to extract digits from input and sum them
   parse val dv +1 val
   do
     rVal = rVal + Integer.valueOf(dv.toString(), base).intValue()
   catch ex = NumberFormatException
     rVal = 'NumberFormatException:' ex.getMessage()
     leave digs
   end
   end digs
 return rVal

-- Clean up the input, normalize the data and determine which base to use method normalizeValue(inV = Rexx, base = Rexx ) private static returns Rexx

 inV = inV.strip('l')
 base = base.strip()
 parse inV xpref +2 . -
        =0 opref +1 . -
        =0 . '0x' xval . ',' . -
        =0 . '0'  oval . ',' . -
        =0 dval .
 select
   when xpref = '0x' & base.length() = 0 then do
     -- value starts with '0x' and no base supplied.  Assign hex as base
     inval = xval
     base = 16
     end
   when opref = '0'  & base.length() = 0 then do
     -- value starts with '0' and no base supplied.  Assign octal as base
     inval = oval
     base = 8
     end
   otherwise do
     inval = dval
     end
   end
 if base.length() = 0 then base = 10 -- base not set.  Assign decimal as base
 if inval.length() <= 0 then inval = 0 -- boundary condition.  Invalid input or a single zero
 rVal = inval base
 return rVal

</lang> Output

Sum of digits for integer "1234" for a given base of "": 10, 1
Sum of digits for integer "01234" for a given base of "": 10, 1
Sum of digits for integer "0xfe" for a given base of "": 29, 11, 2
Sum of digits for integer "0xf0e" for a given base of "": 29, 11, 2
Sum of digits for integer "0" for a given base of "": 0
Sum of digits for integer "00" for a given base of "": 0
Sum of digits for integer "0" for a given base of "2": 0
Sum of digits for integer "070" for a given base of "": 7
Sum of digits for integer "77" for a given base of "8": 14, 5
Sum of digits for integer "070" for a given base of "16": 7
Sum of digits for integer "0xf0e" for a given base of "36": 62, 8
Sum of digits for integer "000999ABCXYZ" for a given base of "36": 162, 9
Sum of digits for integer "ff" for a given base of "16": 30, 3
Sum of digits for integer "f" for a given base of "10": NumberFormatException: For input string: "f"
Sum of digits for integer "z" for a given base of "37": NumberFormatException: radix 37 greater than Character.MAX_RADIX

Type int

Processes sample data as int arrays: <lang NetRexx>/* NetRexx */ options replace format comments java crossref symbols binary

inputs = [[int 1234, 10], [octal('01234'), 8], [0xfe, 16], [0xf0e,16], [8b0, 2], [16b10101100, 2], [octal('077'), 8]] -- test data loop i_ = 0 to inputs.length - 1

 in = inputs[i_, 0]
 ib = inputs[i_, 1]
 dSum = sumDigits(in, ib)
 say 'Sum of digits for integer "'Integer.toString(in, ib)'" for a given base of "'ib'":' dSum'\-'
 -- Carry the exercise to it's logical conclusion and sum the results to give a single digit in range 0-9
 loop while dSum.length() > 1 & dSum.datatype('n')
   dSum = sumDigits(dSum, 10)
   say ',' dSum'\-'
   end
 say
 end i_

-- Sum digits of an integer method sumDigits(val = int, base = int 10) public static returns Rexx

 rVal = Rexx 0
 sVal = Rexx(Integer.toString(val, base))
 loop label digs for sVal.length()
   -- loop to extract digits from input and sum them
   parse sVal dv +1 sVal
   do
     rVal = rVal + Integer.valueOf(dv.toString(), base).intValue()
   catch ex = NumberFormatException
     rVal = 'NumberFormatException:' ex.getMessage()
     leave digs
   end
   end digs
 return rVal

-- if there's a way to insert octal constants into an int in NetRexx I don't remember it method octal(oVal = String) private constant returns int signals NumberFormatException

 iVal = Integer.valueOf(oVal, 8).intValue()
 return iVal

</lang> Output

Sum of digits for integer "1234" for a given base of "10": 10, 1
Sum of digits for integer "1234" for a given base of "8": 10, 1
Sum of digits for integer "fe" for a given base of "16": 29, 11, 2
Sum of digits for integer "f0e" for a given base of "16": 29, 11, 2
Sum of digits for integer "0" for a given base of "2": 0
Sum of digits for integer "10101100" for a given base of "2": 4
Sum of digits for integer "77" for a given base of "8": 14, 5

Perl 6

This will handle input numbers in any base from 2 to 36. The results are in base 10. <lang perl6> say Σ $_ for <1 1234 1020304 fe f0e DEADBEEF>;

sub Σ { [+] $^n.comb.map: { :36($_) } }; </lang>

Output:
1
10
10
29
29
104

PHP

<lang php><?php function sumDigits($num, $base = 10) {

   $s = base_convert($num, 10, $base);
   foreach (str_split($s) as $c)
       $result += intval($c, $base);
   return $result;

} echo sumDigits(1), "\n"; echo sumDigits(12345), "\n"; echo sumDigits(123045), "\n"; echo sumDigits(0xfe, 16), "\n"; echo sumDigits(0xf0e, 16), "\n"; ?></lang>

Output:
1
15
15
29
29

PicoLisp

<lang PicoLisp>(de sumDigits (N Base)

  (or
     (=0 N)
     (+ (% N Base) (sumDigits (/ N Base) Base)) ) )</lang>

Test: <lang PicoLisp>: (sumDigits 1 10) -> 1

(sumDigits 1234 10)

-> 10

(sumDigits (hex "fe") 16)

-> 29

(sumDigits (hex "f0e") 16)

-> 29</lang>

Ruby

<lang ruby>>> def sumDigits(num, base = 10) >> num.to_s(base).split(//).inject(0) {|z, x| z + x.to_i(base)} >> end => nil >> sumDigits(1) => 1 >> sumDigits(12345) => 15 >> sumDigits(123045) => 15 >> sumDigits(0xfe, 16) => 29 >> sumDigits(0xf0e, 16) => 29 </lang>