<!-- canonical: https://efficientnewlanguage.org/eml-p/projects/P113-number-curiosities/ | updated: 2026-10-16 -->

# P113 Number curiosities

What a number's digits do: happy numbers and the cycle every other number falls into, Armstrong numbers, the digital root beside its formula, and Kaprekar's routine to 6174 and 495, step by step.

EML-P project `projects/number-curiosities` in the EML language repo: 2 module(s), entry `main.eml`, terminal UI. There, `eml project run projects/number-curiosities` runs it and `eml project verify projects/number-curiosities` replays every session under CPython (two hash seeds) and in the interpreter; the site build replays every session in the interpreter again and publishes a session only if its screen matches.

Built on verified corpus cases: happy-number (https://efficientnewlanguage.org/cases/087-happy-number/), armstrong-number-checker (https://efficientnewlanguage.org/cases/012-armstrong-number-checker/), digital-root-recursive (https://efficientnewlanguage.org/cases/068-digital-root-recursive/).

## Sessions

### bad-input - interpreter: byte-equal to the golden

Input:

```text
0
x
1
0
1000000000
abc

2
0
1001

3
10001

4

4
12
4
12345
4
abc
4
000
5
```

Screen:

```text
== Number curiosities ==
What a number's digits do: happy numbers, Armstrong numbers, the digital root and Kaprekar's routine.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 0
Pick a number from 1 to 5.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> x
Pick a number from 1 to 5.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 1
number (1 to 999999999)> 0
Type a whole number from 1 to 999999999.
number (1 to 999999999)> 1000000000
Type a whole number from 1 to 999999999.
number (1 to 999999999)> abc
Type a whole number from 1 to 999999999.
number (1 to 999999999)> 
Cancelled.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 2
up to (1 to 1000)> 0
Type a whole number from 1 to 1000.
up to (1 to 1000)> 1001
Type a whole number from 1 to 1000.
up to (1 to 1000)> 
Cancelled.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 3
up to (1 to 10000)> 10001
Type a whole number from 1 to 10000.
up to (1 to 10000)> 
Cancelled.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 4
a number of 3 or 4 digits, zeros in front allowed (such as 0021)> 
Cancelled.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 4
a number of 3 or 4 digits, zeros in front allowed (such as 0021)> 12
Type 3 or 4 digits.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 4
a number of 3 or 4 digits, zeros in front allowed (such as 0021)> 12345
Type 3 or 4 digits.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 4
a number of 3 or 4 digits, zeros in front allowed (such as 0021)> abc
Type 3 or 4 digits.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 4
a number of 3 or 4 digits, zeros in front allowed (such as 0021)> 000
Kaprekar's routine needs at least two different digits; 000 goes straight to 000.
Every number from 100 to 999 whose digits are not all the same reaches 495 within 6 steps.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 5
Bye.
```

### basic - interpreter: byte-equal to the golden

Input:

```text
1
7
1
4
1
153
1
3087
1
9474
1
999999999
2
100
3
10000
4
0021
4
495
4
2111
4
5555
5
```

Screen:

```text
== Number curiosities ==
What a number's digits do: happy numbers, Armstrong numbers, the digital root and Kaprekar's routine.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 1
number (1 to 999999999)> 7
Happy: 7 -> 49 -> 97 -> 130 -> 10 -> 1.
Armstrong: 7^1 = 7, the number itself.
Digital root 7: 7; and 1 + (7 - 1) mod 9 = 7.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 1
number (1 to 999999999)> 4
Not happy: 4 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4, round the cycle of 4, 16, 37, 58, 89, 145, 42 and 20.
Armstrong: 4^1 = 4, the number itself.
Digital root 4: 4; and 1 + (4 - 1) mod 9 = 4.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 1
number (1 to 999999999)> 153
Not happy: 153 -> 35 -> 34 -> 25 -> 29 -> 85 -> 89 -> 145 -> 42 -> 20 -> 4 -> 16 -> 37 -> 58 -> 89, round the cycle of 4, 16, 37, 58, 89, 145, 42 and 20.
Armstrong: 1^3 + 5^3 + 3^3 = 153, the number itself.
Digital root 9: 153 -> 9; and 1 + (153 - 1) mod 9 = 9.
Kaprekar's routine on 3 digits:
  531 - 135 = 396
  963 - 369 = 594
  954 - 459 = 495
  954 - 459 = 495
It reaches 495 in 3 steps, and 495 gives itself again.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 1
number (1 to 999999999)> 3087
Not happy: 3087 -> 122 -> 9 -> 81 -> 65 -> 61 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4 -> 16 -> 37, round the cycle of 4, 16, 37, 58, 89, 145, 42 and 20.
Not Armstrong: 3^4 + 0^4 + 8^4 + 7^4 = 6578.
Digital root 9: 3087 -> 18 -> 9; and 1 + (3087 - 1) mod 9 = 9.
Kaprekar's routine on 4 digits:
  8730 - 0378 = 8352
  8532 - 2358 = 6174
  7641 - 1467 = 6174
It reaches 6174 in 2 steps, and 6174 gives itself again.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 1
number (1 to 999999999)> 9474
Not happy: 9474 -> 162 -> 41 -> 17 -> 50 -> 25 -> 29 -> 85 -> 89 -> 145 -> 42 -> 20 -> 4 -> 16 -> 37 -> 58 -> 89, round the cycle of 4, 16, 37, 58, 89, 145, 42 and 20.
Armstrong: 9^4 + 4^4 + 7^4 + 4^4 = 9474, the number itself.
Digital root 6: 9474 -> 24 -> 6; and 1 + (9474 - 1) mod 9 = 6.
Kaprekar's routine on 4 digits:
  9744 - 4479 = 5265
  6552 - 2556 = 3996
  9963 - 3699 = 6264
  6642 - 2466 = 4176
  7641 - 1467 = 6174
  7641 - 1467 = 6174
It reaches 6174 in 5 steps, and 6174 gives itself again.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 1
number (1 to 999999999)> 999999999
Not happy: 999999999 -> 729 -> 134 -> 26 -> 40 -> 16 -> 37 -> 58 -> 89 -> 145 -> 42 -> 20 -> 4 -> 16, round the cycle of 4, 16, 37, 58, 89, 145, 42 and 20.
Not Armstrong: 9^9 + 9^9 + 9^9 + 9^9 + 9^9 + 9^9 + 9^9 + 9^9 + 9^9 = 3486784401.
Digital root 9: 999999999 -> 81 -> 9; and 1 + (999999999 - 1) mod 9 = 9.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 2
up to (1 to 1000)> 100
20 happy numbers up to 100: 1 7 10 13 19 23 28 31 32 44 49 68 70 79 82 86 91 94 97 100
Every other number falls into the cycle 4, 16, 37, 58, 89, 145, 42, 20 and never reaches 1.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 3
up to (1 to 10000)> 10000
16 Armstrong numbers up to 10000: 1 2 3 4 5 6 7 8 9 153 370 371 407 1634 8208 9474
Each single digit is one; after them the next are 153, 370, 371 and 407, then 1634, 8208 and 9474.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 4
a number of 3 or 4 digits, zeros in front allowed (such as 0021)> 0021
Kaprekar's routine on 4 digits:
  2100 - 0012 = 2088
  8820 - 0288 = 8532
  8532 - 2358 = 6174
  7641 - 1467 = 6174
It reaches 6174 in 3 steps, and 6174 gives itself again.
Every number from 1000 to 9999 whose digits are not all the same reaches 6174 within 7 steps.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 4
a number of 3 or 4 digits, zeros in front allowed (such as 0021)> 495
Kaprekar's routine on 3 digits:
  954 - 459 = 495
It reaches 495 in 1 step, and 495 gives itself again.
Every number from 100 to 999 whose digits are not all the same reaches 495 within 6 steps.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 4
a number of 3 or 4 digits, zeros in front allowed (such as 0021)> 2111
Kaprekar's routine on 4 digits:
  2111 - 1112 = 0999
  9990 - 0999 = 8991
  9981 - 1899 = 8082
  8820 - 0288 = 8532
  8532 - 2358 = 6174
  7641 - 1467 = 6174
It reaches 6174 in 5 steps, and 6174 gives itself again.
Every number from 1000 to 9999 whose digits are not all the same reaches 6174 within 7 steps.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 4
a number of 3 or 4 digits, zeros in front allowed (such as 0021)> 5555
Kaprekar's routine needs at least two different digits; 5555 goes straight to 0000.
Every number from 1000 to 9999 whose digits are not all the same reaches 6174 within 7 steps.

1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit
choice> 5
Bye.
```

## Modules

### main.eml

```eml
# P113 number curiosities: one number's digits four ways, happy and
# Armstrong numbers up to a limit, and Kaprekar's routine step by step.
import curious

def plain(s):
    0 => i
    len(s) => j
    while i < j and s[i] == " ":
        i + 1 => i
    while j > i and s[j - 1] == " ":
        j - 1 => j
    return s[i:j]

def number(s, most):
    if len(s) == 0 or len(s) > most:
        return -1
    0 => n
    for c in s:
        if not (c >= "0" and c <= "9"):
            return -1
        n * 10 + int(c) => n
    return n

def ask(prompt, low, high):
    while True:
        plain(input(prompt + " (" + str(low) + " to " + str(high) + ")> ")) => a
        if a == "":
            return -1
        number(a, 10) => n
        if n >= low and n <= high:
            return n
        ("Type a whole number from " + str(low) + " to " + str(high) + ".") ^0

def arrows(xs):
    "" => out
    for x in xs:
        if out != "":
            out + " -> " => out
        out + str(x) => out
    return out

def padded(n, width):
    str(n) => s
    while len(s) < width:
        "0" + s => s
    return s

def one():
    ask("number", 1, 999999999) => n
    if n == -1:
        "Cancelled." ^0
        return
    curious.happy_chain(n) => h
    if h[0]:
        ("Happy: " + arrows(h[1]) + ".") ^0
    else:
        ("Not happy: " + arrows(h[1]) + ", round the cycle of 4, 16, 37, 58, 89, 145, 42 and 20.") ^0
    curious.digits(n) => ds
    curious.armstrong_sum(n) => a
    "" => terms
    for d in ds:
        if terms != "":
            terms + " + " => terms
        terms + str(d) + "^" + str(len(ds)) => terms
    if a == n:
        ("Armstrong: " + terms + " = " + str(a) + ", the number itself.") ^0
    else:
        ("Not Armstrong: " + terms + " = " + str(a) + ".") ^0
    curious.root_steps(n) => r
    ("Digital root " + str(r[len(r) - 1]) + ": " + arrows(r) + "; and 1 + (" + str(n) + " - 1) mod 9 = " + str(curious.root_formula(n)) + ".") ^0
    if len(ds) == 3 or len(ds) == 4:
        kap(n, len(ds))

def kap(n, width):
    if curious.same_digits(n, width):
        ("Kaprekar's routine needs at least two different digits; " + padded(n, width) + " goes straight to " + padded(0, width) + ".") ^0
        return
    curious.kaprekar(n, width) => st
    ("Kaprekar's routine on " + str(width) + " digits:") ^0
    0 => k
    -1 => reached
    for s in st:
        k + 1 => k
        ("  " + padded(s[0], width) + " - " + padded(s[1], width) + " = " + padded(s[2], width)) ^0
        if reached == -1 and (s[2] == 6174 or s[2] == 495):
            k => reached
    if reached >= 0:
        ("It reaches " + str(st[reached - 1][2]) + " in " + str(reached) + " step" + plural(reached) + ", and " + str(st[reached - 1][2]) + " gives itself again.") ^0

def plural(n):
    if n == 1:
        return ""
    return "s"

def list_happy():
    ask("up to", 1, 1000) => n
    if n == -1:
        "Cancelled." ^0
        return
    [] => hs
    for k in [1:n]:
        if curious.happy_chain(k)[0]:
            hs + [k] => hs
    "" => line
    for h in hs:
        if line != "":
            line + " " => line
        line + str(h) => line
    (str(len(hs)) + " happy numbers up to " + str(n) + ": " + line) ^0
    "Every other number falls into the cycle 4, 16, 37, 58, 89, 145, 42, 20 and never reaches 1." ^0

def list_armstrong():
    ask("up to", 1, 10000) => n
    if n == -1:
        "Cancelled." ^0
        return
    "" => line
    0 => c
    for k in [1:n]:
        if curious.armstrong_sum(k) == k:
            c + 1 => c
            if line != "":
                line + " " => line
            line + str(k) => line
    (str(c) + " Armstrong numbers up to " + str(n) + ": " + line) ^0
    "Each single digit is one; after them the next are 153, 370, 371 and 407, then 1634, 8208 and 9474." ^0

def kaprekar_menu():
    plain(input("a number of 3 or 4 digits, zeros in front allowed (such as 0021)> ")) => t
    if t == "":
        "Cancelled." ^0
        return
    number(t, 4) => n
    if n < 0 or len(t) < 3:
        "Type 3 or 4 digits." ^0
        return
    kap(n, len(t))
    if len(t) == 4:
        "Every number from 1000 to 9999 whose digits are not all the same reaches 6174 within 7 steps." ^0
    else:
        "Every number from 100 to 999 whose digits are not all the same reaches 495 within 6 steps." ^0

"== Number curiosities ==" ^0
"What a number's digits do: happy numbers, Armstrong numbers, the digital root and Kaprekar's routine." ^0
True => running
while running:
    "" ^0
    "1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit" ^0
    plain(input("choice> ")) => choice
    if choice == "1":
        one()
    elif choice == "2":
        list_happy()
    elif choice == "3":
        list_armstrong()
    elif choice == "4":
        kaprekar_menu()
    elif choice == "5":
        False => running
    else:
        "Pick a number from 1 to 5." ^0
"Bye." ^0
```

Python projection of main.eml:

```python
import curious

def plain(s):
    i = 0
    j = len(s)
    while i < j and s[i] == " ":
        i = i + 1
    while j > i and s[j - 1] == " ":
        j = j - 1
    return s[i:j]

def number(s, most):
    if len(s) == 0 or len(s) > most:
        return -1
    n = 0
    for c in s:
        if not (c >= "0" and c <= "9"):
            return -1
        n = n * 10 + int(c)
    return n

def ask(prompt, low, high):
    while True:
        a = plain(input(prompt + " (" + str(low) + " to " + str(high) + ")> "))
        if a == "":
            return -1
        n = number(a, 10)
        if n >= low and n <= high:
            return n
        print("Type a whole number from " + str(low) + " to " + str(high) + ".")

def arrows(xs):
    out = ""
    for x in xs:
        if out != "":
            out = out + " -> "
        out = out + str(x)
    return out

def padded(n, width):
    s = str(n)
    while len(s) < width:
        s = "0" + s
    return s

def one():
    n = ask("number", 1, 999999999)
    if n == -1:
        print("Cancelled.")
        return
    h = curious.happy_chain(n)
    if h[0]:
        print("Happy: " + arrows(h[1]) + ".")
    else:
        print("Not happy: " + arrows(h[1]) + ", round the cycle of 4, 16, 37, 58, 89, 145, 42 and 20.")
    ds = curious.digits(n)
    a = curious.armstrong_sum(n)
    terms = ""
    for d in ds:
        if terms != "":
            terms = terms + " + "
        terms = terms + str(d) + "^" + str(len(ds))
    if a == n:
        print("Armstrong: " + terms + " = " + str(a) + ", the number itself.")
    else:
        print("Not Armstrong: " + terms + " = " + str(a) + ".")
    r = curious.root_steps(n)
    print("Digital root " + str(r[len(r) - 1]) + ": " + arrows(r) + "; and 1 + (" + str(n) + " - 1) mod 9 = " + str(curious.root_formula(n)) + ".")
    if len(ds) == 3 or len(ds) == 4:
        kap(n, len(ds))

def kap(n, width):
    if curious.same_digits(n, width):
        print("Kaprekar's routine needs at least two different digits; " + padded(n, width) + " goes straight to " + padded(0, width) + ".")
        return
    st = curious.kaprekar(n, width)
    print("Kaprekar's routine on " + str(width) + " digits:")
    k = 0
    reached = -1
    for s in st:
        k = k + 1
        print("  " + padded(s[0], width) + " - " + padded(s[1], width) + " = " + padded(s[2], width))
        if reached == -1 and (s[2] == 6174 or s[2] == 495):
            reached = k
    if reached >= 0:
        print("It reaches " + str(st[reached - 1][2]) + " in " + str(reached) + " step" + plural(reached) + ", and " + str(st[reached - 1][2]) + " gives itself again.")

def plural(n):
    if n == 1:
        return ""
    return "s"

def list_happy():
    n = ask("up to", 1, 1000)
    if n == -1:
        print("Cancelled.")
        return
    hs = []
    for k in range(1, n+1):
        if curious.happy_chain(k)[0]:
            hs = hs + [k]
    line = ""
    for h in hs:
        if line != "":
            line = line + " "
        line = line + str(h)
    print(str(len(hs)) + " happy numbers up to " + str(n) + ": " + line)
    print("Every other number falls into the cycle 4, 16, 37, 58, 89, 145, 42, 20 and never reaches 1.")

def list_armstrong():
    n = ask("up to", 1, 10000)
    if n == -1:
        print("Cancelled.")
        return
    line = ""
    c = 0
    for k in range(1, n+1):
        if curious.armstrong_sum(k) == k:
            c = c + 1
            if line != "":
                line = line + " "
            line = line + str(k)
    print(str(c) + " Armstrong numbers up to " + str(n) + ": " + line)
    print("Each single digit is one; after them the next are 153, 370, 371 and 407, then 1634, 8208 and 9474.")

def kaprekar_menu():
    t = plain(input("a number of 3 or 4 digits, zeros in front allowed (such as 0021)> "))
    if t == "":
        print("Cancelled.")
        return
    n = number(t, 4)
    if n < 0 or len(t) < 3:
        print("Type 3 or 4 digits.")
        return
    kap(n, len(t))
    if len(t) == 4:
        print("Every number from 1000 to 9999 whose digits are not all the same reaches 6174 within 7 steps.")
    else:
        print("Every number from 100 to 999 whose digits are not all the same reaches 495 within 6 steps.")

print("== Number curiosities ==")
print("What a number's digits do: happy numbers, Armstrong numbers, the digital root and Kaprekar's routine.")
running = True
while running:
    print("")
    print("1) one number  2) happy numbers  3) Armstrong numbers  4) Kaprekar's routine  5) quit")
    choice = plain(input("choice> "))
    if choice == "1":
        one()
    elif choice == "2":
        list_happy()
    elif choice == "3":
        list_armstrong()
    elif choice == "4":
        kaprekar_menu()
    elif choice == "5":
        running = False
    else:
        print("Pick a number from 1 to 5.")
print("Bye.")
```

### curious.eml

```eml
# P113 number curiosities - four things a number's digits do:
#   happy numbers: replace a number by the sum of the squares of its digits;
#     it reaches 1 (happy) or falls into 4, 16, 37, 58, 89, 145, 42, 20
#     (the corpus case happy-number);
#   Armstrong numbers: the sum of the digits, each raised to the number of
#     digits, is the number itself (the corpus case armstrong-number-checker);
#   the digital root: add the digits until one is left; it is 1 + (n - 1)
#     mod 9 for n above 0 (the corpus case digital-root-recursive);
#   Kaprekar's routine: the digits sorted high to low, minus sorted low to
#     high, again and again; four digits reach 6174, three reach 495.

def digits(n):
    # most significant first
    [] => out
    n => x
    if x == 0:
        return [0]
    while x > 0:
        [x % 10] + out => out
        int((x - x % 10) / 10) => x
    return out

def square_sum(n):
    0 => s
    for d in digits(n):
        s + d * d => s
    return s

def happy_chain(n):
    # [happy, the numbers visited]: stops at 1, or at the first number seen
    # twice
    [n] => seen
    n => x
    while x != 1:
        square_sum(x) => x
        for y in seen:
            if y == x:
                return [False, seen + [x]]
        seen + [x] => seen
    return [True, seen]

def power(b, e):
    1 => p
    for i in [1:e]:
        p * b => p
    return p

def armstrong_sum(n):
    digits(n) => ds
    0 => s
    for d in ds:
        s + power(d, len(ds)) => s
    return s

def root_steps(n):
    # the digit sums down to one digit, n first
    [n] => out
    n => x
    while x > 9:
        0 => s
        for d in digits(x):
            s + d => s
        s => x
        out + [x] => out
    return out

def root_formula(n):
    if n == 0:
        return 0
    return 1 + (n - 1) % 9

def kaprekar_step(n, width):
    # [big, small, big - small], with leading zeros kept to `width` digits
    digits(n) => ds
    while len(ds) < width:
        [0] + ds => ds
    # sort low to high
    for i in [1:len(ds) - 1]:
        i => j
        while j > 0 and ds[j] < ds[j - 1]:
            ds[j] => t
            ds[j - 1] => ds[j]
            t => ds[j - 1]
            j - 1 => j
    0 => small
    0 => big
    for d in ds:
        small * 10 + d => small
    for k in [0:len(ds) - 1]:
        big * 10 + ds[len(ds) - 1 - k] => big
    return [big, small, big - small]

def kaprekar(n, width):
    # the steps until the number repeats: [[big, small, result], ...]
    [] => out
    [n] => seen
    n => x
    True => going
    while going:
        kaprekar_step(x, width) => st
        out + [st] => out
        st[2] => x
        for y in seen:
            if y == x:
                False => going
        seen + [x] => seen
    return out

def same_digits(n, width):
    digits(n) => ds
    while len(ds) < width:
        [0] + ds => ds
    for d in ds:
        if d != ds[0]:
            return False
    return True
```

Python projection of curious.eml:

```python
def digits(n):
    out = []
    x = n
    if x == 0:
        return [0]
    while x > 0:
        out = [x % 10] + out
        x = int((x - x % 10) / 10)
    return out

def square_sum(n):
    s = 0
    for d in digits(n):
        s = s + d * d
    return s

def happy_chain(n):
    seen = [n]
    x = n
    while x != 1:
        x = square_sum(x)
        for y in seen:
            if y == x:
                return [False, seen + [x]]
        seen = seen + [x]
    return [True, seen]

def power(b, e):
    p = 1
    for i in range(1, e+1):
        p = p * b
    return p

def armstrong_sum(n):
    ds = digits(n)
    s = 0
    for d in ds:
        s = s + power(d, len(ds))
    return s

def root_steps(n):
    out = [n]
    x = n
    while x > 9:
        s = 0
        for d in digits(x):
            s = s + d
        x = s
        out = out + [x]
    return out

def root_formula(n):
    if n == 0:
        return 0
    return 1 + (n - 1) % 9

def kaprekar_step(n, width):
    ds = digits(n)
    while len(ds) < width:
        ds = [0] + ds
    for i in range(1, len(ds)):
        j = i
        while j > 0 and ds[j] < ds[j - 1]:
            t = ds[j]
            ds[j] = ds[j - 1]
            ds[j - 1] = t
            j = j - 1
    small = 0
    big = 0
    for d in ds:
        small = small * 10 + d
    for k in range(0, len(ds)):
        big = big * 10 + ds[len(ds) - 1 - k]
    return [big, small, big - small]

def kaprekar(n, width):
    out = []
    seen = [n]
    x = n
    going = True
    while going:
        st = kaprekar_step(x, width)
        out = out + [st]
        x = st[2]
        for y in seen:
            if y == x:
                going = False
        seen = seen + [x]
    return out

def same_digits(n, width):
    ds = digits(n)
    while len(ds) < width:
        ds = [0] + ds
    for d in ds:
        if d != ds[0]:
            return False
    return True
```

## README

# P113 - Number curiosities

What a number's digits do, four ways: happy numbers, Armstrong numbers,
the digital root, and Kaprekar's routine.

- `main.eml` - the menu, one number four ways, the lists, and Kaprekar's
  routine step by step
- `curious.eml` - digits, the happy chain, Armstrong sums, digital roots
  and Kaprekar's steps

How each part works:

- Happy numbers, as in the corpus case `happy-number`: replace a number by
  the sum of the squares of its digits, again and again. A happy number
  reaches 1. Every other number falls into the cycle 4, 16, 37, 58, 89, 145,
  42, 20 and never reaches 1. The chain stops at the first number seen
  twice.
- Armstrong numbers, as in the corpus case `armstrong-number-checker`: the
  digits, each raised to the number of digits, add up to the number itself.
  Up to 10,000 there are 16: the nine single digits, 153, 370, 371, 407,
  1634, 8208 and 9474.
- The digital root, as in the corpus case `digital-root-recursive`: add
  the digits until one is left. It equals 1 + (n - 1) mod 9, and the
  program shows both.
- Kaprekar's routine: sort the digits high to low, subtract them sorted
  low to high, and repeat, keeping zeros in front. Every number from 1000
  to 9999 whose digits are not all the same reaches 6174 within 7 steps,
  and every one from 100 to 999 reaches 495 within 6. That was found by
  trying all 8,991 and all 891 of them, in the cross-check; the program
  states the result.

What is checked: menu choices 1 to 5; a number from 1 to 999,999,999; up
to 1,000 for the happy list and 10,000 for the Armstrong list; 3 or 4
digits for Kaprekar's routine, zeros in front allowed. An empty answer
cancels.

Sessions: `sessions/basic.in` gives:
- 7 (happy, Armstrong) and 4 (unhappy, inside the cycle);
- 153 (Armstrong, Kaprekar to 495 in 3 steps), 3087, 9474 (Armstrong,
  5 steps to 6174) and 999,999,999;
- the happy numbers to 100 and the Armstrong numbers to 10,000;
- Kaprekar's routine on 0021, 495, 2111 (through 0999) and 5555 (all
  digits the same).

`sessions/bad-input.in` gives:
- menu choices 0 and x;
- numbers 0, 1,000,000,000 and abc, then a cancel;
- list limits 0, 1,001 and 10,001, with cancels;
- Kaprekar inputs: a cancel, 12, 12345, abc, and 000.

Built on the verified corpus cases `happy-number` (the sum of squared
digits, followed to 1 or to a cycle), `armstrong-number-checker` (digits
to the power of their count) and `digital-root-recursive` (digit sums
down to one digit).
