Compute the Digit Difference Sum of a Number

Python 2, 73

Luckily, I managed to avoid any string operations.

t=lambda n:n>9and abs(n%10-n/10%10)+10*t(n/10)
g=lambda n:n and n+g(t(n))

g is the function that computes the answer.


Matlab, 101 105 bytes

Thanks a lot to @beaker for his suggestion to use polyval instead if base2dec. That allowed me to

  • save 4 bytes;
  • greatly simplify the generalization to arbitrary base (see below) and save 22 bytes there; and most of all,
  • helped me realize that the code for the general case was wrong (leading zeros were not being removed). The code and the graphs are correct now.

Code:

function y=f(y)
x=+num2str(y);while numel(x)>1
x=polyval(abs(diff(x)),10);y=y+x;x=+dec2base(x,10);end

Example:

>> f(8675309)
ans =
     8898683

Bonus: arbitrary base

A small generalization allows one to use an arbitrary number base, not necessarily decimal:

  • Arbitrary base from 2 to 10, 108 104 bytes

    function y=f(y,b)
    x=+dec2base(y,b);while numel(x)>1
    x=polyval(abs(diff(x)),b);y=y+x;x=+dec2base(x,b);end
    

    The reason why this works only for base up to 10 is that Matlab's dec2base function uses digits 0, 1, ..., 9, A, B, ..., and there's a jump in character (ASCII) codes from 9 to A.

  • Arbitrary base from 2 to 36, 124 146 bytes

    The jump from 9 to A referred to above needs special treatment. The maximum base is 36 as per Matlab's dec2base function.

    function y=f(y,b)
    x=+dec2base(y,b);x(x>57)=x(x>57)-7;while numel(x)>1
    x=abs(diff(x));x=x(find(x,1):end);y=y+polyval(x,b);end
    

This is how the dentist's staircases look for different bases:

enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here


CJam, 22 21 bytes

ri_{\s2ew::-:zsi_@+}h

Note that this program exits with an error, which is allowed by default.

With the Java interpreter, errors can be suppressed by closing STDERR. If you try this code online in the CJam interpreter, ignore all output before the last line.

Thanks to @Sp3000 for pointing out an error in the original revision.

Thanks to @MartinBüttner for golfing off 1 byte.

Example run

$ cjam digit-difference.cjam 2>&- <<< 8675309     
8898683

How it works

ri_   e# Read an integer (I) from STDIN and push a copy (A).
{     e# Do:
  \   e#   Swap I on top of A.
  s   e#   Cast I to string.
      e#   For example, 123 -> "123".
  2ew e#   Push the overlapping slices of length 2 (pair of adjacent digits).
  ::- e#   Replace each pair by its difference.
  :z  e#   Apply absolute value to each difference.
  si  e#   Cast to string, then to integer. This is the new I.
      e#   For example, [1 2 3] -> "123" -> 123.
  _   e#   Push a copy of I.
  @   e#   Rotate A on top of the copy of I.
  +   e#   Add I to A, updating A.
}h    e# While A is truthy, repeat the loop.

A will always be truthy when checked by h. However, once I is a single-digit integer, 2ew will fail with an error after consuming the array it was called on. This leaves only the desired result on the stack, which is printed before exiting.