46
\$\begingroup\$

This challenge is to write a program or script which counts the sum of all digits within the integers from 1 up to and including a given number.

Input, one positive integer. Output, the sum of digits in that number and all smaller numbers.

Examples:

Input: 5 
Integer Sequence: 1, 2, 3, 4, 5
Sum of Digits: 1 + 2 + 3 + 4 + 5 = 15

Input: 12
Integer Sequence: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 
Sum of Digits: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 1 + 0 + 1 + 1 + 1 + 2 = 51

To be clear, this is to count a sum of the digits - not the integers. For single-digit inputs, this will be the same. However, inputs larger than 10 will have different responses. This would be an incorrect response:

Input: 12
Output: 78

Another example, to show the difference:

Input: 10

Integer Sequence: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Sum of Integers (INCORRECT RESPONSE): 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 = 55

Digit Sequence: 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 0
Sum of Digits (CORRECT RESPONSE): 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 1 + 0 = 46

A larger test case (CORRECT RESPONSE):

Input: 1000000
Output: 27000001

Rules & Guidelines:

  • Submitted code must be a complete program or script - not just a function. If the code requires includes, imports, etc., they must be included in the posted code.
  • The number must be input by the user - not hard-coded. Input may be received as a command-line argument, file, stdin, or any other means by which your language can take user input.
  • The code must be able to properly handle inputs at least up to (2^64)-1.
  • The code should only output the sum.
  • Submitted programs & scripts should be user-friendly and not wasteful of computer resources (e.g.: they should not declare insanely-large arrays to hold every character). There is no strict bonus or penalty for this, but please be good programmers.

Scoring:

Primary scoring mechanism is by code length. Lower scores are better. The following bonuses and penalties also apply:

  • -25 Bonus if your code can handle all positive numbers, for example: 1234567891234567891234564789087414984894900000000
  • -50 Bonus if your code can handle simple expressions, for example 55*96-12. To qualify for this bonus, the code should handle + - / * (addition, subtraction, division, multiplication) operators and enforce order of operations. Division is regular integer division.
  • The given example (55*96-12) evaluates to 5268. Your code should return the same for either of those inputs - correct answer is 81393.
  • -10 Bonus if your code qualifies for the -50 bonus and can handle the ^ (exponent) operator.
  • -100 Bonus if your code qualifies for the -50 bonus and does not use eval or similar to handle expressions.
  • +300 Penalty if your code relies upon any web resources.
\$\endgroup\$
28
  • 2
    \$\begingroup\$ And what should 55*96-12 return? \$\endgroup\$
    – ProgramFOX
    Jan 15, 2014 at 18:04
  • 4
    \$\begingroup\$ Bonuses may be a bit on the big side, seems to be becoming a competition on the biggest negative score :) \$\endgroup\$ Jan 15, 2014 at 19:12
  • 9
    \$\begingroup\$ @ST3 if it's virtually impossible to win without the bonuses, then it's almost better to just make them requirements, or be worth less. \$\endgroup\$
    – Cruncher
    Jan 15, 2014 at 19:17
  • 3
    \$\begingroup\$ @flonk: This is wrong. Why people don't read tasks, I wonder. I decided to put a note in task (as an edit). Seriously, this is not task about summing numbers. \$\endgroup\$ Jan 16, 2014 at 12:35
  • 3
    \$\begingroup\$ -1 because this challenge uses the outdated (and awful) scoring incentive of "bonuses". \$\endgroup\$
    – mbomb007
    May 9, 2018 at 21:23

96 Answers 96

1
\$\begingroup\$

C# (80)

Its my another attempt.

double c(int n){double s=0;while(n>0)foreach(var c in n--+"")s+=c-48;return s;}

Pretty

double c(int n)
{
    double s = 0;
     while (n > 0)
        foreach(var c in n--+"") 
            s += c - 48;
    return s;
}
\$\endgroup\$
6
  • \$\begingroup\$ Is the whitespace between n-- and + needed? I don't think it is in other C-style languages. \$\endgroup\$
    – FireFly
    Jan 15, 2014 at 18:54
  • 1
    \$\begingroup\$ Does this work with the given range? The result for 2^64-1 doesn't fit in 64 bits. \$\endgroup\$
    – marinus
    Jan 15, 2014 at 19:38
  • 2
    \$\begingroup\$ It is not a valid answer as it is function and char count is kind a big. \$\endgroup\$
    – ST3
    Jan 15, 2014 at 20:49
  • \$\begingroup\$ @marinus Can you give us the result for 2^64-1 so that we can know what range we need to work with? I dare not test it in my language (PowerShell) since the processing time would be enormous. \$\endgroup\$
    – Iszi
    Jan 17, 2014 at 14:36
  • \$\begingroup\$ @Iszi: I'm not going to actually run it, but you can do some math: 1) the average value of a digit is 4.5; 2) the average sum of 20 digits is 90 (2^64 has 20 digits); so the expected value will be around 90 * 2^64 ≈ 1.66*10^21. So you'd need at least 71 bits, at most 72. \$\endgroup\$
    – marinus
    Jan 21, 2014 at 1:07
1
\$\begingroup\$

Ruby 69-50 = 19 (or -4)

This can definitely be golfed together but here is the first fifth try

p (1..eval(gets)).inject{|i,s|i+=s.to_s.chars.map(&:to_i).inject :+}

It also works for all numbers but is very slow for them as it runs slower than O(n), so I wouldn't add the -25. If slowness is fine, then it would be -4 though

Ruby 133-50-25 = 58

This is the faster version, that runs in less-than O(n) time (and uses actual math!), so it can provide results for large integers fast, thereby I added the -25:

n=eval(gets);p (d=->n,l{k=10**l;c,r=n.to_s[0].to_i,n%k;n<10?n*(n+1)/2:c*45*l*k/10+k*(c*(c-1)/2)+(r+1)*c+d[r,l-1]})[n,n.to_s.length-1]
\$\endgroup\$
2
  • \$\begingroup\$ We write exactly the same code (you golfed a little more)! \$\endgroup\$
    – Beterraba
    Jan 15, 2014 at 22:03
  • \$\begingroup\$ @Beterraba yup, and almost the same time, but you were a bit faster, so I have to figure out something different :) \$\endgroup\$
    – SztupY
    Jan 15, 2014 at 22:04
1
\$\begingroup\$

Haskell, 74-25=49

main=getLine>>=print.sum.map(\c->read[c]).concatMap show.(\x->[0..x]).read

\$\endgroup\$
2
  • \$\begingroup\$ Using interact and the fact that >>= for lists is the same as flip concatMap, you can golf this down to 63 chars like this: main=interact$show.sum.map(\c->read[c]). \x->[0..read x]>>=show \$\endgroup\$
    – Flonk
    Apr 15, 2014 at 12:35
  • \$\begingroup\$ One more byte to save: \c->read[c] is read.(:[]) \$\endgroup\$
    – nimi
    Jan 19, 2015 at 20:56
1
\$\begingroup\$

ECMAScript 6, 86 - 50 = 36

for(s="",i=eval(prompt());i;s+=i--)alert(s.replace(/\d/g,c=>Array(-~c).join()).length)
\$\endgroup\$
2
  • \$\begingroup\$ One character less: for(i=eval(prompt(s=""));i;s+=i--)alert(s.replace(/\d/g,c=>Array(-~c).join()).length). \$\endgroup\$
    – Toothbrush
    Feb 22, 2014 at 20:50
  • \$\begingroup\$ Quite a bit smaller (you don't need the .join()): for(i=eval(prompt(s=""));i;s+=i--)alert(s.replace(/\d/g,c=>Array(-~c)).length). 78 - 50 = 28! \$\endgroup\$
    – Toothbrush
    Feb 22, 2014 at 21:17
1
\$\begingroup\$

R (72 points)

f=function(n) sum(as.integer(strsplit(paste0(1:n,collapse=""),"")[[1]]))

Output:

> f(5)
[1] 15
> f(12)
[1] 51
> f(1000000)
[1] 27000001
\$\endgroup\$
2
  • \$\begingroup\$ In these challenges do you need to explicitily write "f=function(n) " or just the function with n? \$\endgroup\$
    – skan
    Dec 19, 2016 at 20:41
  • \$\begingroup\$ @skan, it depends on requirements. Usually it is not required to have an explicit function. \$\endgroup\$
    – djhurio
    Dec 20, 2016 at 6:47
1
\$\begingroup\$

Java(454 - 25 = 429) (super bad score, yep.)

It's not very fast, but it's working and eligible for the 25 Bonus. Just felt like doing a bit recursion.~

Ugly:

import static java.math.BigInteger.*;import java.math.BigInteger;public class Summy{public static void main(String[] args){if(args.length > 0){BigInteger n, s;n = new BigInteger(args[0]);s = ZERO;for(BigInteger i = ONE; i.compareTo(n.add(ONE)) == -1; i = i.add(ONE))s = s.add(m(i));System.out.println(s.toString());}}static BigInteger m(BigInteger n){return n.compareTo(valueOf(100))==-1?n.mod(TEN).add(n.divide(TEN)):m(n.divide(TEN)).add(n.mod(TEN));}}

Easier to read:

import static java.math.BigInteger.*;
import java.math.BigInteger;
public class Summy
{
    public static void main(String[] args)
    {
        if(args.length > 0)
        {
            BigInteger n, s;n = new BigInteger(args[0]);s = ZERO;
            for(BigInteger i = ONE; i.compareTo(n.add(ONE)) == -1; i = i.add(ONE))s = s.add(m(i));
            System.out.println(s.toString());
        }
    }
    static BigInteger m(BigInteger n){return n.compareTo(valueOf(100))==-1?n.mod(TEN).add(n.divide(TEN)):m(n.divide(TEN)).add(n.mod(TEN));}
}
\$\endgroup\$
3
  • \$\begingroup\$ You don't have call your class Summy. S will do. \$\endgroup\$ Jan 16, 2014 at 12:52
  • \$\begingroup\$ I liked the name, since I have many lines I felt like it wouldn't matter anyway. :D \$\endgroup\$
    – Leo Pflug
    Jan 16, 2014 at 13:03
  • \$\begingroup\$ When i started doing my java solution, i thought to get all bonus points, but in the middle, i realized it's not worth it. \$\endgroup\$
    – user902383
    Jul 28, 2016 at 13:14
1
\$\begingroup\$

K, 16 - 50 = -34

{+/"J"$',/$!1+x}
\$\endgroup\$
1
  • \$\begingroup\$ You can get shorter with .:' instead of "J"$' without losing the eval bonus because you're using it for parsing not evaluation. \$\endgroup\$
    – geocar
    Jul 31, 2016 at 12:02
1
\$\begingroup\$

Javascript (Paste it to your browser console):

i=eval(prompt());s=0;for(x=1;x<=i;x++){y=x;while(y>=10){s+=(t=y%10);y=(y-t)/10}s+=y}alert(s)

Eligible only for: "Can handle expressions: 50 bonus";

Code length: 92 bytes. Expected final score: 92-50=44

Ps: That's my first participation on this, so please tell me if I'm doing anything wrong.

\$\endgroup\$
0
1
\$\begingroup\$

PowerShell: 55

Mainly derived from this answer by microbian but with enough golfing and bug fixes I figured it was worth posting separately.

The script is 55 characters long. A previous version had claimed functionality for handling expressions, (thus a -50 bonus) but then I remembered that PowerShell doesn't do integer division by default. This would not meet the specification for the bonus, and would probably produce erroneous results whenever there is a remainder in a division operation. Adding the code needed to properly force integer division would probably not be worth the bonus.

Warning: This script should theoretically be able to handle any input for which the output is up to (2^96)-1. However, any input larger than about 5 digits is going to take a fairly long time to process.

This can be saved and run as a script, or run straight from the PowerShell console. The golfed version is a little "messy" - use rv x,y in between runs for variable cleanup.

Golfed Code:

for($x=read-host;$x;$x-=1){[char[]]"$x"|%{$y+=$_-48}}$y

Un-Golfed & Commented:

# Begin for loop definition.
for(
    # Take input from the user and store it in $x.
    # We don't need to explicitly force $x to any particular integer type, because PowerShell will automatically choose an appropriate type according to the result of an expression when math operators are used.
    # This piece should be able to handle inputs which evaluate as large as (2^96)-1.
    $x=read-host;
    # Loop runs so long as $x remains greater than zero since any non-zero values for $x are treated as $true.
    $x;
    # $x is decremented by one every time the loop runs.
    # I needed to use $x-=1 instead of $x-- because $x initially starts as a string, so the latter operator would not be available. $x-=1 will force $x into a number type.
    $x-=1
)
{
    # Convert $x to a string, then to a character array, and pass the array to ForEach-Object (%).
    [char[]]"$x"|%{
        # Increment $y by the integer value of the current character, minus 48.
        # Taking out 48 is needed to account for the difference in the digits' values and their ASCII codes.
        # We don't need to explicitly force a type on the current character, as the increment operator will automatically cast it to an integer.
        # We also don't need to explicitly force a type on $y, as the increment operator will do that appropriately for us so long as it is not hard-set otherwise.
        # This should be able to handle values of $y up to (2^96)-1.
        $y+=$_-48
    }
}
# After all loops are done, output $y.
$y

# Variables cleanup. Not included in golfed code.
rv x,y

I have tested this against the cases given in the question (inputs of 5, 10, 12, 5268, and 1000000) and they all gave the expected correct outputs. I dare not try testing it much higher due to performance issues.

\$\endgroup\$
6
  • \$\begingroup\$ Why not 1..(read-host|iex)|%... instead of the for loop? \$\endgroup\$ Jan 16, 2014 at 13:45
  • \$\begingroup\$ @DankoDurbić I tried that, but it requires that the result of (read-host|iex) fits within an int32. The question requires handling of values at least up to the maximum of a uint64. \$\endgroup\$
    – Iszi
    Jan 16, 2014 at 14:50
  • \$\begingroup\$ Oh, I see. Still, you can shorten the condition in the loop to just $x instead of $x-gt0. \$\endgroup\$ Jan 16, 2014 at 15:45
  • \$\begingroup\$ @DankoDurbić Good catch. Thanks. \$\endgroup\$
    – Iszi
    Jan 16, 2014 at 16:00
  • \$\begingroup\$ Shave off one character by using args[0] and parsing the value when calling the script, instead of read-host. for($x=$args[0];$x;$x-=1){[char[]]"$x"|%{$y+=$_-48}}$y \$\endgroup\$
    – unclemeat
    Jan 21, 2014 at 1:09
1
\$\begingroup\$

Golf, 38, 33-25=8

~,{1+}/]{''+[{-48+}/]{+}*}/]{+}*

This is my first (still very verbose) attempt at Golfscript.

Explanation:

~, -> converts input into a number (n), and creates an array of n elements starting at 0

{1+}/ -> adds one to all the elements of the previous array

] -> converts to an array

{''+[{-48+}/]{+}*}/ -> this is a function, applied to all the elements of the previous array, that:

''+ -> turns the array in an array of strings

{-48+}/ -> subtracts 48 ('0') from each element of the array

{+}* -> sums all the elements of the array

At the end, the {+}* sums all the results of the previous calculations, giving the correct output.

\$\endgroup\$
1
\$\begingroup\$

R5RS Scheme/Racket: 42 (227 - all bonuses)

(display(let l((s 0)(n(let e((x(read)))(if(pair? x)(apply(e(car x))(map e(cdr x)))(if(number? x)x(cadr(assoc x`((+,+)(-,-)(/,/)(*,*)(^,expt))))))))(c 0))(if(= 0 s)(if(= 0 n)c(l n(- n 1)c))(l(quotient s 10)n(+(modulo s 10)c)))))

Ungolfed:

(display 
 (let l ((s 0)
         (n (let e ((x (read)))
              (if (pair? x)
                  (apply (e (car x))
                         (map e(cdr x)))
                  (if (number? x)
                      x
                      (cadr (assoc x`((+,+)(-,-)(/,/)(*,*)(^,expt))))))))
         (c 0))
   (if (= 0 s)
       (if (= 0 n)
           c
           (l n (- n 1) c))
       (l (quotient s 10) n (+ (modulo s 10) c)))))

The mathematical expressions accepted are fully parenthesized polish prefix (LISP syntax) with the symbols demanded (^ neded rewriting). More than half the code is the interpreter.

Eg.

(+ (* 2 4) (^ 2 5)) ; == 40 ==> displays 244
\$\endgroup\$
1
\$\begingroup\$

Javascript, 79 points 35 points 29 points 25 points

for(i=1,e=eval(prompt()),s=1;i<e;i++,s+=+eval((''+i).split('').join('+')));

From @Collin Grady's comment, 24 points

for(t=0,x=1,m=+eval(prompt());x<=m;t+=+eval((""+x++).split("").join('+')));aler‌​t(t);

This is my first serious golf, so if anyone has tips for me, I'd be glad to hear them!

\$\endgroup\$
8
  • \$\begingroup\$ eval((''+prompt()).split('').join('+')) \$\endgroup\$
    – user12986
    Jan 16, 2014 at 3:28
  • \$\begingroup\$ @GabrielSantos where would I put that? \$\endgroup\$
    – scrblnrd3
    Jan 16, 2014 at 3:37
  • \$\begingroup\$ Just open the console with CTRL+SHIFT+K and paste that code. \$\endgroup\$
    – user12986
    Jan 16, 2014 at 3:43
  • \$\begingroup\$ That sums the number, not all the numbers up until that point, unless I'm misunderstanding you \$\endgroup\$
    – scrblnrd3
    Jan 16, 2014 at 3:50
  • 1
    \$\begingroup\$ Hey @scrblnrd3, hope you're enjoying the golf! I recently read a post on meta about JS IO standards and I think you need to add an alert of s to conform in this case... However you should be able to save a few chars in its place using s=i=1 instead of s=1,i=1 and remove the i++, changing the eval((''+i) to eval((''+i++)! \$\endgroup\$ Jan 16, 2014 at 8:43
1
\$\begingroup\$

Python 59-25-50-10 (-100): -26

(or -126, again: depending on how you see P2's input()) Oh wait, xrange supports things outside of range's scope. One character extra for 25 bonus points? Sure!

 sum(sum(int(a) for a in str(b+1)) for b in xrange(input()))

Old version:

Python 58-50-10(-100): -2

(or -102, depending on how you think of Python 2's input())

sum(sum(int(a) for a in str(b+1)) for b in range(input()))
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Make your generator expression nested to save some characters: sum(int(a)for b in xrange(input())for a in str(b+1)). \$\endgroup\$ Jun 20, 2016 at 16:55
1
\$\begingroup\$

Haskell - 67

f x=sum.map(read.(:[])).(=<<) show$[1..x]
main=interact$show.f.read

If you prepend f::Integer->Integer, it may qualify for a bonus (87 - 25 = 62), though it will probably OOM on large inputs.

\$\endgroup\$
1
\$\begingroup\$

Python2 - 75 (pure filesize, bonus stuff still uncounted)

The 'x' file:

N,i,d=input(),0,0
while i<N:
 i+=1
 n=i
 while n:
  d+=n%10
  n/=10
print d

Test runs:

$ python x
5
15
$ python x
12
51
$ python x
1000000
27000001
$ python x
5268
81393
$ python x
55*96-12
81393
$ python x
32
177
$ python x
2**5
177

Test runs I did not let finish because being impatient:

$ python x
2**(64-1)
### are you patient enough?
$ python x
1234567891234567891234564789087414984894900000000
### are you patient enough?

Python should handle these two test cases because it transparently switches to variable length long integers when the fixed lenghth integer range is insufficient.

\$\endgroup\$
1
\$\begingroup\$

Pyke, 4 - (50), -46 bytes, noncompeting

hmss

Try it here!

\$\endgroup\$
1
  • \$\begingroup\$ Oh, for god's sake. \$\endgroup\$
    – cat
    Jun 30, 2016 at 23:30
1
\$\begingroup\$

PHP, 110

$a=$argv[1];$b='0';do{$b=bcadd($b,(string)array_sum(str_split($a,1)));}while(($a=bcadd($a,-1))!='0');echo $b;

PHP is certainly not the easiest language for this, but the standard library has some nice stuff inside. The code relying on bcmath to do the job of working with very large numbers, and on two functions for string splitting and summing the contents of an array. It is certainly going to run with very large numbers, but that's gonna take some time (2 minutes 9 seconds for the number 100000000).

Here's an ungolfed version:

$a = $argv[1];
$b = '0';

do {
    $b = bcadd($b, (string) array_sum(str_split($a, 1)));
}
while(($a = bcadd($a, -1)) != '0');

echo $b;

And here's another shorter version (68 bytes), but this one is going to work only until an integer overflow occurs.

$a=$b=$argv[1];while($a--){$b.=$a;}echo array_sum(str_split($b,1));

P.S: Yes, I'm a necromancer, so feel free to burn me at the stake :)

\$\endgroup\$
1
\$\begingroup\$

Python 3, 76 bytes - (25 + 50 + 10) = -9

Put this as a separate answer because it's not anything fancy.

Also, ** is the exponentiation operator because ^ is XOR. I believe this still qualifies for the -10 bonus.

print(sum(map(int, list("".join(map(str, range(1,eval(str(input()))+1)))))))
\$\endgroup\$
1
\$\begingroup\$

PHP 4.1, 88-25-50=13 bytes

call in a web browser or with php-cgi; n as argument

<?for(eval('$i=$n;');$i;$i=bcsub($i,1))foreach(str_split($i)as$d)$s=bcadd($s,$d);echo$s;

Use PHP 4.1 to get off -6 of any of the current PHP versions by using $n instead of $argv[1].

current PHP: call from cli with number or calculation string as argument 1

PHP, 94-25-50=19 bytes

<?for(eval('$i=$argv[1];');$i;$i=bcsub($i,1))foreach(str_split($i)as$d)$s=bcadd($s,$d);echo$s;

69-50=19

<?for(eval('$i=$argv[1];');$i;)$s+=array_sum(str_split($i--));echo$s;

92-50-10=32 bytes

<?for(eval(str_replace('^','**',"\$i=$argv[1];"));$i;)$s+=array_sum(str_split($i--));echo$s;

201-50-10-100=41 bytes *

<?for($i=$argv[1];$p='^*/+-'[$k++];)while(preg_match("#(\d+)\\$p(\d+)#",$s,$m)){list(,$a,$b)=$m;$i=[42=>$a*$b,$a+$b,0,$a-$b,0,$a/$b,94=>$a**$b][ord($p)];}for(;$i;)$s+=array_sum(str_split($i--));echo$s;

60-0 bytes

<?for($i=$argv[1];$i;)$s+=array_sum(str_split($i--));echo$s;

260-25-50-10-100=75 bytes *

<?for($i=$argv[1];$p='^*/+-'[$k++];)while(preg_match("#(\d+)\\$p(\d+)#",$s,$m)){list(,$a,$b)=$m;$i=[42=>bcmul($a,$b),bcadd($a+$b),0,bcsub($a-$b),0,bcdiv($a,$b),94=>bcpow($a,$b)][ord($p)];}for(;$i;$i=bcsub($i,1))foreach(str_split($i)as$d)$s=bcadd($s,$d);echo$s;

x-25-50-10: yet to come ... find a golfable way to translate concatenated apbs to nested p(a,b)s. Or ... does preg_replace_callback qualify as eval?

* with PHP<5.3, you can use ereg("([0-9]+)\\$p([0-9]+)",$s,$m) instead of preg_match("#(\d+)\\$p(\d+)#",$s,$m) (-2 bytes)

breakdown for the last version

for($i=$argv[1];        # take string from argument 1
    $p='^*/+-'[$k++];)  # loop $p through operators in descending precedence
    # while operator (with two operands) is found in string ...
    while(preg_match("#(\d+)\\$p(\d+)#",$s,$m))
    {
        # get operators to $a and $b
        list(,$a,$b)=$m;
        # create an array of all operation results (key=ascii code of operator)
        # (may throw division by zero warnings)
        $i=[42=>bcmul($a,$b),bcadd($a+$b),0,bcsub($a-$b),0,bcdiv($a,$b),94=>bcpow($a,$b)]
        # and take the one matching the current operation
        [ord($p)];
    }
for(;$i;$i=bcsub($i,1))         # loop $i down to 1
    foreach(str_split($i)as$d)  # loop $d through digits
        $s=bcadd($s,$d);        # sum up
echo$s;                         # and print sum
\$\endgroup\$
1
\$\begingroup\$

Julia 0.6, -7 bytes (53 - 50 - 10) bytes

/ =÷
show(sum(sum.(digits.(1:eval(parse(ARGS[]))))))

Try it online!

Plain and simple - construct an array containing all the digits of the number in the range, sum the digits of individual numbers elementwise, then sum those digit sums together. The / =÷ reassigns / to be integer division, since otherwise eval will treat / in input as float division (and OP specifies "Division is regular integer division").

Because this constructs an array of array of all the digits in the range, this becomes very memory hungry for larger numbers. A better, much faster version is:

Julia 0.6, 39 (124 - 25 - 50 - 10) bytes, handles very large inputs

/ =÷
!n=n<=9?(n+1)n/2:(v=n/(t=10^(d=big(ndigits(n)-1))))*45d*10^~-d+t*(v-1)v/2+(1+n%t)v+!(n%t)
show(!(eval(parse(ARGS[]))))

Try it online!

This can handle inputs upto and above 1234567891234567891234564789087414984894900000000 very quickly.

julia> @btime !1234567891234567891234564789087414984894900000000
  282.726 μs (3167 allocations: 80.43 KiB)
265889343871444899381999757086453238874482500000214

I couldn't understand @ymbirtt's explanation of their Python code, and so set out to find a way of calculating this myself - and it looks like I rediscovered the method Wasi uses in their answer.

But because this uses BigInts and not floats, there's no loss of precision in large numbers - for eg., the Python code in ymbirtt's answer gives the same output for 999999999999999 and 1000000000000001 (67500000000000000), while this Julia version correctly returns 67500000000000000 and 67500000000000003 respectively. (This lead to some wall-meet-head moments while debugging my code before I realized what was happening, since I was using their Python code's output as the reference output to check against.) Two other answers with correct output for the very large number are duedl0r's Haskell answer (which I couldn't figure out how to run on TIO) and Wasi's Python answer (TIO).

Ungolfed with explanation:

# reassign float division to integer division (for the eval and to save bytes otherwise)
/ =÷
function f_(n::BigInt)
  # necessary as a base case for the recursion
  n <= 9 && return (n+1)n÷2
  d = big(ndigits(n)-1)
  # highest power of ten that's less than n
  # say n is 4895, then t = 1000
  t = 10^d
  # get first digit of n (v = 4 in this case)
  v = n÷t
  # initialize digit sum
  s = big(0)
  # there have been 1000 1's, 1000 2's, and 1000 3's as first digits of numbers so far,
  #  add those to the digit sum
  s += t*(v-1)v÷2
  # now that the first digits upto 3999 are taken care of, handle the other digits
  # digits in 0 to 3999 = digits in 0000 to 0999 + in 1000 to 1999 +
  # in 2000 to 2999 + in 3000 to 3999
  # once first digits are taken care of, that becomes four times the digits in 0 to 999
  # in 0 to 999, 6 occurs 100 times in hundreds digit (600-699),
  # 100 times in tens digit (x60 to x69, for x from 0 to 9),
  # 100 times in ones digit (xy6 for x from 0 to 9, for y from 0 to 9)
  # so 6 occurs 3*10^2 times in 0 to 999, or in general d*10^(d-1) times
  # so sum of 6s in 0 to 999 is 6d*10^(d-1), and since we have to consider
  # that range four times, sum in 0 to 3999 is 4*6d*10^(d-1)
  # same logic applies for the other digits, so the sum of all non-first digits
  # in this range (0 to 3999) is: 4*1d*10^(d-1) + 4*2d*10^(d-1) + ... 4*9d*10^(d-1)
  # = 4*(1+2+...+9)*d*10^(d-1) = 4*45d*10^(d-1)
  # or in general, v*45d*10^(d-1)
  s += v*45d*10^(d-1)
  #sum of digits up to 3999 has been taken care of

  # now sum from 4000 to 4895
  # there are 896 4s in the first digit in this range, so sum of those is 4*896
  # or in general, v*(1 + n%t)
  s += v*(1+n%t)
  # first digit taken care of, now call this function recursively to find sum of 
  # digits in 0 to 895 (which is all that remains to be summed)
  s += f_(n%t)
end
isinteractive() || show(f_(big(eval(parse(ARGS[])))))
\$\endgroup\$
1
\$\begingroup\$

Kotlin, 38 36 bytes

{(1..it).sumBy{"$it".sumBy{it-'0'}}}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

05AB1E, score: -55 (11 5 bytes -50-10 bonuses)

.ELSO

Inefficient, but it works.

Uses ** instead of ^.

Try it online.

Could be .VLSO if we take the input in Reverse Polish notation that 05AB1E uses, with m instead of ^:

Try it online.

Explanation:

.E     # Python-eval the (implicit) input
       #  i.e. "55*96-2**6+156/3" → 5268.0
       # OR
.V     # 05AB1E-eval the (implicit) input
       #  i.e. "55 96*2 6m-156 3/+" → 5268.0
  L    # Pop and push a list in the range [1,n]
       #  → [1,2,3,....,5266,5267,5268]
   S   # Convert it to a flattened list of digits
       #  → [1,2,3,...,5,2,6,6,5,2,6,7,5,2,6,8]
    O  # Sum
       #  → 81393
       # (after which the result is output implicitly)

Would be 3 bytes without any bonuses:

LSO

Try it online.

\$\endgroup\$
1
\$\begingroup\$

Ly, 10 - 50 = -40 bytes

ns[Sl,s]&+

Try it online!

I'm assuming that since Ly is writen in Python, it can handle arbitrarily large numbers. If that's wrong, then it's 10 bytes. Here's how it works:

ns         - read the ending number from STDIN, save to backup cell
  [    ]   - loop until the top of stack is 0
   S       - convert the top of stack codepoint to digits, push them
    l,s    - load the backup cell, decrement and re-save
        &+ - sum the entries on the stack, automatically prints as integer
\$\endgroup\$
1
\$\begingroup\$

Braingolf v2, 11 bytes

[.M1-]v&d&+

Try it online!

Doesn't work in v1 because the greedy & modifier is broken for d. Which is a shame because v1 is built on python and so supports arbitrarily large integers. v2 is built on JS and so uses doubles for everything.

Explanation

[.M1-]v&d&+ ; Implicit input to stack
[....]      ; While loop, loop while top of stack != 0
 .M         ; Duplicate top of stack and move it to next stack
   1-       ; Decrement top of stack
      v     ; Switch to next stack
       &    ; Greedy - apply next function to entire stack
        d   ; Split into digits
         &  ; Greedy - apply next function to entire stack
          + ; Sum
            ; Implicit output of top of stack
\$\endgroup\$
1
\$\begingroup\$

Vyxal, 8 bytes

ɾ(nf∑)W∑

Try it Online!

\$\endgroup\$
3
  • 1
    \$\begingroup\$ ɾ and f can both just be removed. you can easily get 3 bytes tho: v∑∑ (or ɾṠ∑), and they can be 2 bytes with s flag \$\endgroup\$
    – naffetS
    Oct 11, 2022 at 22:37
  • \$\begingroup\$ @Steffan what does v and Ṡ do? \$\endgroup\$ Oct 12, 2022 at 11:57
  • \$\begingroup\$ is sum each, v is vectorize \$\endgroup\$
    – naffetS
    Oct 12, 2022 at 17:26
1
\$\begingroup\$

Thunno 2 S, 2 - 160 = -158 bytes

Attempt This Online!

Just like the Vyxal answer, this qualifies for all the bounties. Uses ** for pow.

Explanation

Rʂ  # Implicit input
R   # Push the range [1..n]
 ʂ  # Sum the digits of each number
    # S flag sums this list
    # Implicit output
\$\endgroup\$
0
\$\begingroup\$

Squeak Smalltalk, fast version 111 octets - 25 bonus: 86

In class String, define method:

d|h s t|h:=self first:1.(s:=self size-1)>0or:[^h+1*h/2].t:=self last:s.^s*9+h-1*(5 raisedTo:s)<<(s-1)+t+1*h+t d

usage '1234567891234567891234564789087414984894900000000' d -> 265889343871444899381999757086453238874482500000214

This works because '1'+1 -> 2 dirtyness pay :)

The slow version 53 chars - 25 bonus: 18

In Integer, implement

d self=0or:[^('',self detectSum:[:d|'',d])+(self-1)d]

usage 12 d -> 51

It works for arbitrary long ints, but be patient...

It works because

  • '',12 -> '12' a String... dirty Squeakism :)
  • '',$1 -> '1' a String... dirty Squeakism :)
  • '1'+'2' -> 3 an Integer... dirty Squeakism :)
  • the method returns self by default (so 0)

A shame that detectSum: consumes so many chars, what a name!

The interpreter also works, but native integer division is //, not /, precedence of all binary operator is equal and expression is evaluated left to right, and unary message precedence requires (), so I did not count the 50 bonus...

(55*96-12)d -> 81393

How would cost an evaluator?
With unconventional precedence rules for * and /: 5*3/2*4 -> (5*(3/2))*4 rather than ((5*3)/2)*4 it is possible to make it in 118 chars - 150 bonus: -32

Define these two methods in String:

e:o o ifNotEmpty:[^((self findTokens:o first)collect:[:x|x e:o allButFirst])reduce:o first]

d^(0+(self e:#(+ - * //)))d

The string is split recursively against a list of operators o, around +, then - in inner loop, then *, then /

  • findTokens: performs the split on first operator '1+22+3' findTokens:#+ -> #('1' '22' '3')
  • collect: applies the recursion on remaining operators (allButFirst)
  • reduce: performs the operations (left to right)= #('1' '22' '3') reduce:#+ -> (1+22)+3->26

Given than selectors like allButFirst are rather long, manually nesting blocks and using splitBy: cost less 107 chars - 150 bonus: -43

f:o c:b^((self splitBy:o)collect:b)reduce:o

d^(self f:#+c:[:a|a f:#-c:[:b|b f:#*c:[:c|c f:#//c:[:d|d+0]]]])d

Reusing above Integer>>d, the total is 18-43 = -25

Usage is '55*96-12'd -> 81393

Note that it's not a program that takes a user input, but arguably in Squeak there is no such thing as a program, and user input happens everywhere, for example in any text pane of any window. You just press the 'do it' menu rather than press enter key...

previous slow version 58 chars - 25 bonus: 23

d self=0or:[^(#[],('',self)detectSum:[:d|d-48])+(self-1)d]

It works because

  • #[],'12' -> #[49 50] a ByteArray... dirty Squeakism :)
\$\endgroup\$
0
\$\begingroup\$

Ruby, 124 - (100 + 50 + 25) = -51

e=->((a,b,*c)){x=a.to_i;b ?x.send(b,e[c]):x}
p (1..e[gets.split /\s|\b/]).lazy.flat_map{|x|x.to_s.chars.map &:to_i}.reduce:+

Some tests:

$ ruby count.rb <<<12
51
$ ruby count.rb <<<1000000
27000001
$ ruby count.rb <<<'6 + 3 * 8/4'
51

Explanation:

e is a function that evaluates an expression given an array of numeric strings and operators:

e[%w(3 + 2 * 2)] # => 7

All operators have the same precedence and are right-associative.

e works by taking the first two tokens, a and b, from the array and sending b as a message to a (which i assume is not in the same level of magic as eval, as sending messages is all we can do in Ruby after all) passing the evaluation of the rest of the array as the parameter.

The rest of the code should be more straightforward.

\s is used to split the line read from stdin to allow spaces between operators and numbers, and to get rid of the pesky newline at the end of the string.

The lazy call allows flat_map to return a lazy enumerator, which is then lazily consumed by reduce, instead of creating a ginormous intermediate array, thus making it possible to handle very big numbers without exhausting the memory and making me feel like it deserves the 25 point bonus :) ... even though computing the result for 2^64 would take eons with this method:

$ time ruby count.rb <<<100_000_000
3600000001

real    6m40.998s
user    6m41.272s
sys 0m0.020s

If the slowness makes this solution non eligible for the 25 point bonus, then i propose an eval-less version of @Chron's "older" answer:

105 - (100 + 50) = -45

e=->((a,b,*c)){x=a.to_i;b ?x.send(b,e[c]):x}
p"#{[*1..e[gets.split /\s|\b/]]}".chars.map(&:to_i).inject:+
\$\endgroup\$
3
  • \$\begingroup\$ @ST3 :( why not? \$\endgroup\$
    – epidemian
    Feb 3, 2014 at 12:45
  • \$\begingroup\$ Sorry, have fast run through all posts, I'm not into ruby very well, now added this as a request for revision. Maybe you are winner. \$\endgroup\$
    – ST3
    Feb 3, 2014 at 13:13
  • \$\begingroup\$ @ST3, thanks. The code uses send to dynamically call methods on the numbers. It's not like eval in the sense that it doesn't need to parse code, or dynamically generate it. If you know JavaScript, it is analogous to using anObject[someMethodName](param1, param2) to call a method. If more clarification is needed, please let me know :) \$\endgroup\$
    – epidemian
    Feb 3, 2014 at 13:21
0
\$\begingroup\$

Gawk (115 - 50) = 65

{ "echo $(("$1"))"|getline x
  for(i=1;i<=x;i++){
   l=split(i,a,"")
   for(n=1;n<=l;n++) s+=a[n]
  } print s 
}

Requires GNU awk and a POSIX shell. Save the program as sum.awk and run it from the command line as:

% echo 55*96-12 | gawk -f sum.awk
81393
% echo 1000000 | gawk -f sum.awk
27000001
\$\endgroup\$
1
  • \$\begingroup\$ This should likely be listed as GAWK+SH \$\endgroup\$ Jan 15, 2018 at 15:02
0
\$\begingroup\$

Clojure, 104

(println (reduce (fn [a x] (+ a (apply + (map #(- (long %) 48) (seq (str x)))))) (range (inc (read)))))

Reads input on stdin and prints result to stdout.

To run, save to file sum.clj and call from shell (after installing Clojure):

echo 1000000 | java -jar clojure-1.5.1/clojure-1.5.1.jar sum.clj
27000001

You could also just paste the code into a lein repl (http://leiningen.org/) or run with lein exec plugin with echo 12 | lein exec sum.clj.

*Still waiting for results of 1234567891234567891234564789087414984894900000000 input for bonus points.

\$\endgroup\$
2
  • \$\begingroup\$ How would you call it? \$\endgroup\$
    – osvein
    Jan 16, 2014 at 6:45
  • \$\begingroup\$ Edit has shorter code and running instructions. \$\endgroup\$
    – ctrlrsf
    Jan 16, 2014 at 14:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.