I recently created a Code Golf challenge at www.code-golf.com called Digit Sum. At the time of writing this blog post, the challenge have gotten 14 answers, and I think it’s time to review the answers and crown a winner!
Introduction
Before we look at the entries let’s talk a bit about the challenge itself. The task at hand was to compute the sum of the individual digits of a whole number. So, for the number 19, the sum of it’s digits is 10 (1 + 9), and for the number 84001 the answer is 13. This last one was the example I used in the challenge, so all entries should output the number 13 to be the correct answer.
So how would we go about solving this problem? There are two strategies you could employ for this problem. The first one is the mathematical one, where you work with the number as a number and figure out the individual digits by dividing the number by 10 and keeping the remainder. You would repeat this until you get 0, and the sum of the remainders would be your answer.
The second approach is to convert the number to a string. You then get easy access to each individual number as a character in the resulting array of characters. You then convert the character back to an integer before you sum them.
After reviewing the answers to this challenge, we see that it is the second approach that is used by most of the answers. In fact, the only answer using the first approach is my own entry, which got last.
Before I start reviewing the entries, I let’s just go through my methodology. First of all, where multiple entries are submitted by the same user, I only care about the best one. Secondly, even though humorous, I have disqualified any answers that just tries to be funny, or are not in the spirit of the task. Luckily for me, I only had one of those, but that one is currently ranked 1 on the site though.
The entries
dburt667 – 9 characters
8+4+0+0+1
While this answer will give the correct output for the example used in the challenge, it will of course not produce the correct output for any other number, so this entry is disqualified 🙂
bjompen – 21 characters
$i-replace'','+0'|iex
This is the shortest answer in a string of answers that are just optimizations of the previous one to shorten down the total length. The idea here is pretty neat. We need to convert the integer to a string somehow, and by using the replace operator we are automatically casting the number as a string in the same process. The replace operation is just adding ‘+0’ in between all the numbers, so the resulting string is ‘+08+04+00+00+01+0‘. This is then piped to iex, which of course is an alias for Invoke-Expression. This just executes this a summing operation with the result being of course the answer we are after – 13.
ThmsRynr – 21 characters
$i-split''|measure -s
This entry tries another approach, and the answer is correct, just not in the correct form. Instead of outputting 13 as an integer, the output is a MeasureInfo object, where the value of the Sum property is 13. To modify this answer to give the correct type (($i-split”|measure -s).sum), we need to add 6 characters – we are then up to 27 characters for this entry. The technique used is to split the number into an array of digits and piping that to Measure-Object to get the sum.
KirkMunro – 23 characters
$i-split''-join'+0'|iex
Kirk’s solution is to first split the number into an array and joining it back together with +0 in between the numbers, before piping it to Invoke-Expression to calculate the sum. Kirk was actually the second person (after myself) to post an answer, and for the longest time I thought it would be impossible to beat him. Luckily I was proven wrong 😉
torgro – 24 characters
iex($i-split""-join'+0')
This solution is identical to the one from Kirk, it’s just organized in a slightly less optimized way, so it’s using 1 character more.
ChrisWarwick – 26 characters
iex($i-replace'(.)','+$1')
What Chris is doing here is similar to others in that he is using the replace operator to add characters in between the digits of the number. He is using a regular expression though, and the resulting string is ‘+8+4+0+0+1‘, which is then executed with Invoke-Expression.
lazywinadmin – 27 characters
[char[]]"$i"|%{$s+="$_"};$s
Here we see that the integer is cast to an array of chars before they are looped through and added to a variable, which is written out at the end. The only problem is that he forgot to convert the character back to an integer before adding it to the output collection, so the output of this is actually wrong. In fact, the output is identical to the input with the exception that it is now a string instead of an integer.
seanarmstrong – 28 characters
$x=0;$i-split''|%{$x+=$_};$x
This is another variant of splitting the integer into an array, looping though it and adding each number into a collection for output at the end. This one works though, as he is assigning 0 to the collection at the beginning, which means that the collection is of the correct type when the characters are added to it in the loop.
ocitrev – 39 characters
"$i".ToCharArray()|%{$r+=[int]$_-48};$r
This time the integer is implicitly cast to a string, and the ToCharArray method is used to get an array of characters. The characters are then cast back to an int before added to the output variable. But in the process of casting the character to an integer, you actually get the ASCII value of the number instead of the number it self. That’s why 48 is subtracted from the number before it is assigned to the collection. The ASCII value for 8 is 56, so by subtracting 48 we get 8 back. This holds true for all the numbers 0-9.
1RedOne – 53 characters
([string]$i).ToCharArray()|%{$s+=[int]::Parse($_)};$s
This approach is a more verbose way of doing the same as the one above, but the Parse method of the integer type is used so that he don’t have to do the -48 trick.
gravejester – 56 characters
$s=0;while($i-ne0){$s+=$i%10;$i=[math]::Floor($i/10)};$s
This was my own attempt, and the only one that actually uses math to get to the result. I initialize a variable by assigning 0 to it. This makes sure it have the correct type. I set up a loop that will continue as long as the variable i is not 0 and do my calculations. I divide the number by 10 to get the remainder, and add it to my output variable. I then update the number with the “new” number which is the floor of the original number divided by 10. After the loop I’m simply outputting the variable with the result of the calculation.
Conclusion
I hope you have learned something going through these different approaches to this simple problem. I know I have! And I also had a ton of fun doing it 🙂
So I guess the only thing left to do is to crown the winner, which of course is Björn Sundling – congratulations!
The challenge is still open on the Code Golf website, so if you figure out an ever shorter answer, please let me know and I’ll update this post.