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 //
- include <iostream>
- 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
PARI/GP
<lang parigp>dsum(n,base)=my(s); while(n, s += n%b; n \= b); s</lang>
Also the built-in sumdigits
can be used for base 10.
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>