Task: Esthetic numbers




Go: package main

import (
    "fmt"
    "strconv"
)

func uabs(a, b uint64) uint64 {
    if a > b {
        return a - b
    }
    return b - a
}

func isEsthetic(n, b uint64) bool {
    if n == 0 {
        return false
    }
    i := n % b
    n /= b
    for n > 0 {
        j := n % b
        if uabs(i, j) != 1 {
            return false
        }
        n /= b
        i = j
    }
    return true
}

var esths []uint64

func dfs(n, m, i uint64) {
    if i >= n && i <= m {
        esths = append(esths, i)
    }
    if i == 0 || i > m {
        return
    }
    d := i % 10
    i1 := i*10 + d - 1
    i2 := i1 + 2
    if d == 0 {
        dfs(n, m, i2)
    } else if d == 9 {
        dfs(n, m, i1)
    } else {
        dfs(n, m, i1)
        dfs(n, m, i2)
    }
}

func listEsths(n, n2, m, m2 uint64, perLine int, all bool) {
    esths = esths[:0]
    for i := uint64(0); i < 10; i++ {
        dfs(n2, m2, i)
    }
    le := len(esths)
    fmt.Printf("Base 10: %s esthetic numbers between %s and %s:\n",
        commatize(uint64(le)), commatize(n), commatize(m))
    if all {
        for c, esth := range esths {
            fmt.Printf("%d ", esth)
            if (c+1)%perLine == 0 {
                fmt.Println()
            }
        }
    } else {
        for i := 0; i < perLine; i++ {
            fmt.Printf("%d ", esths[i])
        }
        fmt.Println("\n............\n")
        for i := le - perLine; i < le; i++ {
            fmt.Printf("%d ", esths[i])
        }
    }
    fmt.Println("\n")
}

func commatize(n uint64) string {
    s := fmt.Sprintf("%d", n)
    le := len(s)
    for i := le - 3; i >= 1; i -= 3 {
        s = s[0:i] + "," + s[i:]
    }
    return s
}

func main() {
    for b := uint64(2); b <= 16; b++ {
        fmt.Printf("Base %d: %dth to %dth esthetic numbers:\n", b, 4*b, 6*b)
        for n, c := uint64(1), uint64(0); c < 6*b; n++ {
            if isEsthetic(n, b) {
                c++
                if c >= 4*b {
                    fmt.Printf("%s ", strconv.FormatUint(n, int(b)))
                }
            }
        }
        fmt.Println("\n")
    }

    
    listEsths(1000, 1010, 9999, 9898, 16, true)
    listEsths(1e8, 101_010_101, 13*1e7, 123_456_789, 9, true)
    listEsths(1e11, 101_010_101_010, 13*1e10, 123_456_789_898, 7, false)
    listEsths(1e14, 101_010_101_010_101, 13*1e13, 123_456_789_898_989, 5, false)
    listEsths(1e17, 101_010_101_010_101_010, 13*1e16, 123_456_789_898_989_898, 4, false)
}




Python: from collections import deque
from itertools import dropwhile, islice, takewhile
from textwrap import wrap
from typing import Iterable, Iterator


Digits = str  


def esthetic_nums(base: int) -> Iterator[int]:
    
    queue: deque[tuple[int, int]] = deque()
    queue.extendleft((d, d) for d in range(1, base))
    while True:
        num, lsd = queue.pop()
        yield num
        new_lsds = (d for d in (lsd - 1, lsd + 1) if 0 <= d < base)
        num *= base  
        queue.extendleft((num + d, d) for d in new_lsds)


def to_digits(num: int, base: int) -> Digits:
    
    digits: list[str] = []
    while num:
        num, d = divmod(num, base)
        digits.append("0123456789abcdef"[d])
    return "".join(reversed(digits)) if digits else "0"


def pprint_it(it: Iterable[str], indent: int = 4, width: int = 80) -> None:
    
    joined = ", ".join(it)
    lines = wrap(joined, width=width - indent)
    for line in lines:
        print(f"{indent*' '}{line}")
    print()


def task_2() -> None:
    nums: Iterator[int]
    for base in range(2, 16 + 1):
        start, stop = 4 * base, 6 * base
        nums = esthetic_nums(base)
        nums = islice(nums, start - 1, stop)  
        print(
            f"Base-{base} esthetic numbers from "
            f"index {start} through index {stop} inclusive:\n"
        )
        pprint_it(to_digits(num, base) for num in nums)


def task_3(lower: int, upper: int, base: int = 10) -> None:
    nums: Iterator[int] = esthetic_nums(base)
    nums = dropwhile(lambda num: num < lower, nums)
    nums = takewhile(lambda num: num <= upper, nums)
    print(
        f"Base-{base} esthetic numbers with "
        f"magnitude between {lower:,} and {upper:,}:\n"
    )
    pprint_it(to_digits(num, base) for num in nums)


if __name__ == "__main__":
    print("======\nTask 2\n======\n")
    task_2()

    print("======\nTask 3\n======\n")
    task_3(1_000, 9_999)

    print("======\nTask 4\n======\n")
    task_3(100_000_000, 130_000_000)