/* Sum digits of an integer (Rosetta code ) in Picat. http://rosettacode.org/wiki/Sum_digits_of_an_integer """ This task is to take a Natural Number in a given Base and return the sum of its digits: 1[base=10] sums to 1; 1234[base=10] sums to 10; fe[base=16] sums to 29; f0e[base=16] sums to 29. """ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ % import util. % import cp. main => go. go => println(1=sum_digits(1)), println(1234=sum_digits(1234)), println('"1234"'=sum_digits("1234")), println(1234=sum_digits(1234)), println('"fe(16)"'=sum_digits("fe", 16)), % -> 29 println('"f0e(16)"'=sum_digits("f0e", 16)), % -> 29 println('"FOE(16)"'=sum_digits("F0E", 16)), % -> 29 println('123(16)'=sum_digits(123, 16)), % -> 6 println('"123"(16)'=sum_digits("123", 16)), % -> 6 println('"1110010101"(2)'=sum_digits("1110010101", 2)), println('"picat"(36)'=sum_digits("picat", 36)), Alpha = "0123456789abcdefghijklmnopqrstuvwxyz", Rand = [Alpha[1+random2() mod Alpha.length] : _ in 1..40], println(rand=Rand), println(rand_sum_digits=sum_digits(Rand, 36)), println("\nTesting exceptions"), catch(println(sum_digits(Rand, 10)), E, println(exception=E)), % bad_base catch(println(sum_digits("picat_is_fun!", 36)), E2, println(exeption=E2)), % bad_digit catch(println(sum_digits("11100101", 1)),E3,println(exception=E3)), % bad base catch(println(sum_digits("hi", 100)), E4, println(exception=E4)), % bad base nl. % base 10 sum_digits(N) = sum([D.to_integer() : D in N.to_string()]), integer(N) => true. sum_digits(N) = sum([D.to_integer() : D in N]), string(N) => true. % base Base sum_digits(N,Base) = sum_digits(N.to_string(), Base), integer(N) => true. sum_digits(N,Base) = sum_digits(N,Base,10), string(N) => true. sum_digits(N,Base,OutputBase) = Sum, string(N) => N := to_lowercase(N), Alpha = "0123456789abcdefghijklmnopqrstuvwxyz", Map = new_map([A=I : {A,I} in zip(Alpha,0..length(Alpha)-1)]), M = [Map.get(I,-1) : I in N], if max(M) >= Base ; Base < 2; Base > Alpha.length then throw $bad_base('N'=N,base=Base) elseif min(M) == -1 then throw $bad_digits('N'=N,bad=[D : D in N, not Map.has_key(D) ]) else if OutputBase != 10 then Sum = dec_to_base(sum(M),OutputBase) else Sum = sum(M) end end. dec_to_base(N, Base) = [Alpha[D+1] : D in reverse(Res)] => Alpha = "0123456789abcdefghijklmnopqrstuvwxyz", Res = [], while (N > 0) R := N mod Base, N := N div Base, Res := Res ++ [R] end. base_to_dec(N, Base) = base_to_dec(N.to_string(), Base), integer(N) => true. base_to_dec(N, Base) = Res => println($base_to_dec(N, Base)), Alpha = "0123456789abcdefghijklmnopqrstuvwxyz", Map = new_map([A=I : {A,I} in zip(Alpha,0..length(Alpha)-1)]), Len = N.length, Res = sum([Map.get(D)*Base**(Len-I) : {D,I} in zip(N,1..N.length)]).