20
\$\begingroup\$

A triangular number is a number that can be expressed as the sum of consecutive positive integers, starting at 1. They can also be expressed with the formula n(n + 1) / 2, where n is some positive integer.

A number's digitangular counterpart is calculated in the following way:

  1. Split a number into an array of its digits e.g. 613 => [6 1 3]
  2. For each number in the array, calculate the nth triangular number; [6 1 3] => [21 1 6]
  3. Sum the resultant array; [21 1 6] => 28

Your task is, given an integer n, repeatedly calculate n's digitangular counterpart, until the result is equal to 1, then output all values that were calculated. You may output the values in any order, and with an optional inclusion of the original number at the start of the array. This is a so the shortest code wins.

Test cases

23 => 9 45 25 18 37 34 16 22 6 21 4 10 1
72 => 31 7 28 39 51 16 22 6 21 4 10 1
55 => 30 6 21 4 10 1
78 => 64 31 7 28 39 51 16 22 6 21 4 10 1
613 => 28 39 51 16 22 6 21 4 10 1
8392 => 90 45 25 18 37 34 16 22 6 21 4 10 1
11111 => 5 15 16 22 6 21 4 10 1
8592025 => 117 30 6 21 4 10 1
999999999 => 405 25 18 37 34 16 22 6 21 4 10 1
\$\endgroup\$
  • 1
    \$\begingroup\$ May we include the original number as first in the resultant array? \$\endgroup\$ – Uriel Nov 21 '17 at 23:28
  • 1
    \$\begingroup\$ How do we know it always goes down to 1? \$\endgroup\$ – Simply Beautiful Art Nov 21 '17 at 23:50
  • 5
    \$\begingroup\$ Let's suppose that a number is larger than 141 and has n digits. The maximum value its digitangular counterpart can have is 45n, so digi-△(x) ≤ 45n < 45(1+log_10(x)), and for x > 141, we have 45(1+log_10(x)) < x, hence digi-△(x) ≤ x-1 for x > 141, and once we pass the 141 limit, well, we brute force prove via programs. \$\endgroup\$ – Simply Beautiful Art Nov 22 '17 at 0:02
  • 1
    \$\begingroup\$ Can I have trailing 1's at the end of my output? \$\endgroup\$ – Simply Beautiful Art Nov 22 '17 at 12:10
  • 1
    \$\begingroup\$ Related: Digitangular numbers, seeking alternative proofs that this sequence goes to 1 eventually. \$\endgroup\$ – Simply Beautiful Art Nov 22 '17 at 12:33

33 Answers 33

10
\$\begingroup\$

Husk, 6 bytes

U¡(ṁΣd

Try it online!

Explanation

U¡(ṁΣd
 ¡(       Iterate the following function on the input:
     d       Split the number into digits
   ṁΣ        Map each digit to its triangular number, then sum the results
U         Take the results of iteration until before the first repeated one
\$\endgroup\$
7
\$\begingroup\$

05AB1E, 6 5 bytes

Δ=SLO

Try it online! Edit: Saved 1 byte thanks to @Emigna. Explanation:

Δ       Repeat until value doesn't change
 =      Print current value
  S     Split into characters
   L    Turn each character into range from 1 to N
    O   Sum
\$\endgroup\$
  • \$\begingroup\$ If you replace with S, you can skip one O. \$\endgroup\$ – Emigna Nov 22 '17 at 8:03
  • \$\begingroup\$ @Emigna ...why does L even behave that way? \$\endgroup\$ – Neil Nov 22 '17 at 8:44
  • \$\begingroup\$ If I recall correctly it was a bug that turned out to be useful and got to remain as a feature. I think it was one the first methods that vectorized. \$\endgroup\$ – Emigna Nov 22 '17 at 10:12
4
\$\begingroup\$

J, 20 19 bytes

(1#.2!1+,.&.":)^:a:

Try it online!

Outputs the original number, too.

Explanation

(1#.2!1+,.&.":)^:a:
               ^:a:  Apply until input converges, storing all results in an array
(1#.2!1+,.&.":)      Digitangular sum
        ,.&.":         Split to digits
          &.":           Convert to string, apply left function, then undo conversion
        ,.               Ravel items (make array of singleton arrays of items)
                         This ensures that when cast back to integers, the digits are split.
      1+               Add 1 to each
    2!                 Compute (n choose 2) on each (nth triangular number)
 1#.                   Sum (debase 1)
\$\endgroup\$
  • 1
    \$\begingroup\$ [:+/ ->1#. meow! \$\endgroup\$ – FrownyFrog Nov 22 '17 at 2:07
  • \$\begingroup\$ @FrownyFrog not an original trick, though I certainly make ample use of it when I remember to. \$\endgroup\$ – cole Nov 22 '17 at 2:08
4
\$\begingroup\$

APL (Dyalog), 23 20 17 bytes

3 bytes saved thanks to @ngn

{⍵∪⍨+/∊⍳¨⍎¨⍕⊃⍵}⍣≡

Try it online!

How?

⍵∪⍨ - prepend current array to the

+/ - sum of

- flattened

⍳¨ - ranges of each

⍎¨⍕ - digit of the

⊃⍵ - previous value

⍣≡ until convergence. The usage of (union) makes sure after the first 1 is joined, the next will be excluded due to set uniqueness, and the array will converge.

\$\endgroup\$
  • \$\begingroup\$ Out of curiosity, how long would it be if you weren't allowed to output the original value as well? \$\endgroup\$ – caird coinheringaahing Nov 21 '17 at 23:31
  • \$\begingroup\$ @cairdcoinheringaahing 2 bytes - 1↓ (drop first) \$\endgroup\$ – Uriel Nov 21 '17 at 23:56
  • \$\begingroup\$ @Uriel Here power limit (⍣≡) gives a shorter solution than recursion: {⍵∪⍨+/∊⍳¨⍎¨⍕⊃⍵}⍣≡ but it's a shame APL doesn't have a concise way to collect all iterations of a function until convergence: ⍵(f⍵)(f⍣2⊢⍵)(f⍣3⊢⍵)... \$\endgroup\$ – ngn Nov 22 '17 at 9:54
  • \$\begingroup\$ @ngn thanks! I did try to use the power operator, but I didn't think about the fact it converges after 1. Will update soon \$\endgroup\$ – Uriel Nov 22 '17 at 9:59
  • \$\begingroup\$ @ngn any idea on how to use {+/∊⍳¨⍎¨⍕⎕←⍵}⍣≡ without getting the last 1 printed? \$\endgroup\$ – Uriel Nov 22 '17 at 11:49
3
\$\begingroup\$

Haskell, 51 47 46 bytes

f 1=[1]
f x=x:f(sum$do d<-show x;[1..read[d]])

Try it online!

f 1=[1]                     -- if x == 1, return the singleton list [1]
f x=                        -- else
         do d<-show x       --  for each char 'd' in the string representation of x
                            --    (using the list monad)
           [1..read[d]]     --  make a list of [1..d]
                            --    (the list monad concatenates all those lists into a single list)
        sum                 --  sum those numbers
      f                     --  call f on it
    x:                      --  and put x in front of it 

Edit: @H.PWiz saved a byte. Thanks!

\$\endgroup\$
2
\$\begingroup\$

Python 2, 62 bytes

f=lambda x:x<2and[1]or[x]+f(sum(-~int(i)*int(i)/2for i in`x`))

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Wolfram Language (Mathematica), 43 41 bytes

Echo@#>1&&#0[#.(#+1)/2&@IntegerDigits@#]&

Try it online!

How it works

The expression #.(#+1)/2&@IntegerDigits@# gives the digitangular counterpart of #. We Echo the input, use short-circuit evaluation with && to stop if we've reached 1, and otherwise recurse on the digitangular counterpart.


-2 bytes thanks to Martin Ender for the . trick: we don't have to use Tr to sum the digits if we replace the multiplication #(#+1)/2 by the dot product #.(#+1)/2.

\$\endgroup\$
  • 2
    \$\begingroup\$ Only just saw your answer now. You can beat mine by using the scalar product trick to avoid the Tr: Echo@#>1&&#0[#.(#+1)/2&@IntegerDigits@#]& \$\endgroup\$ – Martin Ender Nov 22 '17 at 11:03
  • \$\begingroup\$ @MartinEnder Thanks, that's a neat trick. I wonder if there any even golfier ways to do "print all iterations of this function on the way to a fixed point" (essentially, reimplementing FixedPointList except for how that prints the fixed point twice). It seems like that should have come up before. \$\endgroup\$ – Misha Lavrov Nov 22 '17 at 17:31
2
\$\begingroup\$

Wolfram Language (Mathematica), 49 42 39 bytes

Thanks to Misha Lavrov for saving 3 bytes.

#//.x_:>(y=IntegerDigits@Echo@x).++y/2&

Try it online! (TIO needs parentheses around the ++y for some reason. In my local Mathematica installation it works without them, as it should.)

Prints each value on its own line, preceded by >>, and includes the starting number.

\$\endgroup\$
  • \$\begingroup\$ You can go back to beating my answer with #//.x_:>(y=IntegerDigits@Echo@x).++y/2&. (...maybe. For some reason, TIO doesn't like this, but Mathematica's fine with it?) \$\endgroup\$ – Misha Lavrov Nov 23 '17 at 1:16
  • \$\begingroup\$ Well, #//.x_:>(y=IntegerDigits@Echo@x).(++y)/2& is 41 bytes and works in TIO. But my copy of Mathematica doesn't think the parentheses are necessary. \$\endgroup\$ – Misha Lavrov Nov 23 '17 at 1:27
  • \$\begingroup\$ @MishaLavrov Thanks. Yeah, no clue why TIO needs the parentheses, but syntax in script files is sometimes a bit wonky. \$\endgroup\$ – Martin Ender Nov 23 '17 at 12:23
1
\$\begingroup\$

Ohm v2,  9  7 bytes

·Ω}#ΣΣu

Try it online!

Explanation

          Implicit input as a string
·Ω        Evaluate until the result has already been seen, pushing intermediate results
  }       Split digits
   #      Range from 0 to N
    ΣΣ    Sum
      u   Convert to string
\$\endgroup\$
  • \$\begingroup\$ Isn't u unnecessary? \$\endgroup\$ – Nick Clifford Nov 28 '17 at 0:02
  • \$\begingroup\$ It's necessary otherwise } won't split the digits \$\endgroup\$ – Cinaski Nov 28 '17 at 6:25
  • \$\begingroup\$ Hm. That might be a bug. I'll check it out. \$\endgroup\$ – Nick Clifford Nov 28 '17 at 13:34
1
\$\begingroup\$

Retina, 21 bytes

;{:G`
.
$*1¶
1
$%`1
1

Try it online! (The outputs of the individual cases aren't well separated, but each output ends with a 1.)

Prints each number on its own line, in order, including the starting number.

Explanation

;{:G`

This is just some configuration of the program. { makes the program loop until it fails to change the result (which happens once we get to 1), : prints number before each iteration, and ; prevents the final result from being printed twice at the end of the program. The G is just my usual way of creating a no-op stage.

.
$*1¶

Convert each digit to unary and put it on its own line.

1
$%`1

Compute the triangular number on each line, by replacing each 1 with its prefix. We could also use M!&`1+ here, which gives us all suffixes of each line.

1

Count all 1s, which sums up all the triangular numbers and converts the result back to decimal.

\$\endgroup\$
  • \$\begingroup\$ Is Retina a turing complete language? \$\endgroup\$ – user72349 Nov 22 '17 at 11:51
  • \$\begingroup\$ @ThePirateBay yes. \$\endgroup\$ – Martin Ender Nov 22 '17 at 11:54
1
\$\begingroup\$

Ruby, 60 47 42 bytes

-13 bytes by @JustinMariner

-5 bytes by @GB

->x{p x=x.digits.sum{|k|k*-~k/2}while x>1}

Try it online!

\$\endgroup\$
  • \$\begingroup\$ You can drop the array and splat ([*...]) and change (k+1) to -~k to save a total of 5 bytes: Try it online! Additionally, you can save 8 more by switching to an anonymous lambda function: Try it online! \$\endgroup\$ – Justin Mariner Nov 22 '17 at 2:32
  • \$\begingroup\$ Hm, no idea why I thought .map couldn't take arrays. \$\endgroup\$ – Simply Beautiful Art Nov 22 '17 at 2:54
  • \$\begingroup\$ You can use "sum{...}" instead of "map{...}.sum" and then remove the space before "while" \$\endgroup\$ – G B Nov 22 '17 at 11:55
1
\$\begingroup\$

Befunge-93, 51 bytes

p&>>:25*%:1+*2/v
  |:/*52p00+g00<
00<vp000_@#-1.::g

Try it online!

James Holderness cleverly reshaped my progarm into a 51-byte form. Thanks!

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

Pushy, 24 22 21 17 bytes

[sL:R{;Svc^#&1=?i

Try it online!

Explanation

[sL:R{;Svc^#&1=?i

[           &1=?i   \ Loop until result == 1:
 s                  \   Split last result into digits
  L:  ;             \   For each digit n:
    R{              \       Push the range (1, n) inclusive
       S            \   Sum the ranges
        vc^         \   Delete all stack items, except the sum
           #        \   Print result
\$\endgroup\$
1
\$\begingroup\$

Japt, 19 17 bytes

Takes input as a single element array.

_Ì¥1}a@pUÌì mò xx

Try it

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

R, 70 bytes

f=function(n)"if"(n-1,c(n,f((d=n%/%10^(nchar(n):0)%%10)%*%(d+1)/2)),n)

Try it online!

Returns the original value as well.

R, 80 bytes

function(n){o={}
while(n-1){n=(d=n%/%10^(nchar(n):0)%%10)%*%(d+1)/2
o=c(o,n)}
o}

Try it online!

Does not return the original value.

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

Lua, 91 bytes

function f(n)x=0 for d in((0|n)..""):gmatch"."do x=x+d*(d+1)/2 end print(x)c=x==1or f(x)end

Try it online!

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

05AB1E, 20 12 bytes

Saved 2 bytes thanks to caird coinheringaahing

ΔD,þ€iLO}O}}

Try it online!

Explanation

(old version)

Δþ€iD>*;}OD1›iD,}}1,  Main program
Δ                }    Repeat until there is no changes
 þ                    Push digits of the input number
  €i    }             Apply for each digit
    D>*;              Calculate the triangular number for given digit
         O            Sum all numbers
          D1›iD,}     Print if greater than 1
                  1,  Print 1 at the end
\$\endgroup\$
0
\$\begingroup\$

JavaScript, 61 57 bytes

f=a=>a-1?([...a+[]].map(b=>a+=b++*b/2,a=0),a)+' '+f(a):''

Try it online!

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

Python 2, 69 bytes

def f(x):
 while x>1:
  x=sum(-~int(z)*int(z)/2for z in`x`)
  print x

Try it online!

\$\endgroup\$
  • \$\begingroup\$ 64 \$\endgroup\$ – user72349 Nov 22 '17 at 0:32
0
\$\begingroup\$

Charcoal, 18 bytes

W⊖Iθ«≔IΣ⭆θΣ…·0κθθ⸿

Try it online! Link is to verbose version of code. Explanation:

   θ                Input
  I                 Cast to integer
 ⊖                  Decrement
W   «               Loop while not zero
         θ          Current value
        ⭆           Map over characters and concatenate
             0      Literal character 0
              κ     Current character
           …·       Inclusive range
          Σ         Concatenate
       Σ            Sum of digits
      I             Cast to string
     ≔         θ    Assign back to value
                θ   Output latest value
                 ⸿  Move to start of next line
\$\endgroup\$
0
\$\begingroup\$

dc, 62 bytes

?sj[0soljZ1-[dljr10r^/10%d1+*2/lo+sod1-r0<i]dsixlopdsj1<b]dsbx

Try it online!

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

k, 19 bytes

{+/(+/1+!"I"$)'$x}\

Unsurprisingly works similarly to the already posted APL and J solutions

               $x    cast x (implicit var of lambda) to string
   (         )'      apply composition (function train) to each character of string
    +/1+!"I"$        cast character to number, create list from 1 to n, sum it
 +/                  sum triangular numbers
{                }\  iterate lambda until result converges, appending each result
\$\endgroup\$
0
\$\begingroup\$

Jelly, 7 bytes

DRFSµÐĿ

Try it online!

  • DRFSµÐĿ: Full program / monadic link.

  • ÐĿ: Loop until results are no longer unique (if something other than 1 would occur twice, then the given input does not have a defined result, since it would never reach 1).

  • D: Convert from integer to decimal.

  • R: Range (1-indexed). Vectorizes.

  • F: Flatten and S: Sum (µ just creates a new monadic chain)

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

dc, 31 bytes

[[I~d1+*2/rd0<m+]dsmxpd1<f]dsfx

The function m computes the digitangular function of its input; f repeats this until the result reaches 1.

Note that we use the input radix to extract digits - this means it will work in any base system, not only decimal.

Demo

for i in 23 72 55 78 613 8392 11111 8592025 999999999
    do echo $i '=>' $(dc -e $i'[[I~d1+*2/rd0<m+]dsmxpd1<f]dsfx')
done
23 => 9 45 25 18 37 34 16 22 6 21 4 10 1
72 => 31 7 28 39 51 16 22 6 21 4 10 1
55 => 30 6 21 4 10 1
78 => 64 31 7 28 39 51 16 22 6 21 4 10 1
613 => 28 39 51 16 22 6 21 4 10 1
8392 => 90 45 25 18 37 34 16 22 6 21 4 10 1
11111 => 5 15 16 22 6 21 4 10 1
8592025 => 117 30 6 21 4 10 1
999999999 => 405 25 18 37 34 16 22 6 21 4 10 1
\$\endgroup\$
0
\$\begingroup\$

Python 2, 76 bytes

f=lambda k,s=0:k+s<2and[1]or[k]*(s<1)+f(*[k/10,s,s+k%10*(k%10+1)/2][k<1::2])

Try it online!

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

Neim, 8 bytes

ͻ𝐂t𝕕𝐬D÷D

Explanation:

ͻ             Start infinite loop
 𝐂            Split top of stack into each of its characters
  t           Push infinite list of triangular numbers
   𝕕          For each of the characters, get the nth element in the above list.
    𝐬          Sum.
     D         Duplicate.
      ÷        If top of stack is equal to 1, break.
       D       Duplicate.
               Implicitly print all elements in the stack, concatenated.

Try it online!

Formatted output

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

D, 140 bytes

import std.algorithm,std.range,std.conv,std.stdio;void f(T)(T n){n=n.text.map!(u=>u.to!T-48+(u.to!T-48).iota.sum).sum;n.writeln;if(n-1)n.f;}

Try it online!

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

PHP, 71+1 bytes

for(;1<$n="$s"?:$argn;print$s._)for($i=$s=0;$p--||~$p=$n[$i++];)$s+=$p;

Run as pipe with -nR or try it online. (requires PHP 5.3 or later for the Elvis operator)

\$\endgroup\$
  • \$\begingroup\$ What's the Elvis operator? \$\endgroup\$ – caird coinheringaahing Nov 24 '17 at 17:29
  • \$\begingroup\$ @cairdcoinheringaahing A?:B: if A is truthy then A else B \$\endgroup\$ – Titus Nov 24 '17 at 17:57
0
\$\begingroup\$

Add++, 32 bytes

D,f,@,EDBFEREss
+?
y:1
W!,$f>x,O

Try it online!

Doesn't output the first value

How it works

D,f,@,   - Create a monadic function, f.
         - Example argument: [613]
      ED - Digits;   STACK = [[6 1 3]]
      BF - Flatten;  STACK = [6 1 3]
      ER - Range;    STACK = [[1 2 3 4 5 6] [1] [1 2 3]]
      Es - Sum each; STACK = [21 1 6]
      s  - Sum;      STACK = [28]

           f calculates n's digitangular counterpart

+?       - Take input;     x = 613; y = 0
y:1      - Set y to 1;     x = 613; y = 1
W!,      - While x != y...
   $f>x, -   Call f;       x =  28; y = 1
   O     -   Print x;
\$\endgroup\$
0
\$\begingroup\$

Perl 6, 36 bytes

{$_,{sum map {sum 1..$_},.comb}...1}

Try it online!

Includes the input number in the output list.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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