Esthetic numbers: Difference between revisions

Content added Content deleted
(Added Algol 68)
No edit summary
Line 4,387: Line 4,387:
123434565 123434567 123454321 123454323 123454343 123454345 123454543 123454545 123454565
123434565 123434567 123454321 123454323 123454343 123454345 123454543 123454545 123454565
123454567 123456543 123456545 123456565 123456567 123456765 123456767 123456787 123456789
123454567 123456543 123456545 123456565 123456567 123456765 123456767 123456787 123456789
</pre>

=={{header|Python}}==

{{works with|Python|3.9.5}}
<lang python>from collections import deque
from itertools import dropwhile, islice, takewhile
from textwrap import wrap
from typing import Iterable, Iterator


Digits = str # Alias for the return type of to_digits()


def esthetic_nums(base: int) -> Iterator[int]:
"""Generate the esthetic number sequence for a given base

>>> list(islice(esthetic_nums(base=10), 20))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 21, 23, 32, 34, 43, 45, 54, 56, 65]
"""
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 # Shift num left one digit
queue.extendleft((num + d, d) for d in new_lsds)


def to_digits(num: int, base: int) -> Digits:
"""Return a representation of an integer as digits in a given base

>>> to_digits(0x3def84f0ce, base=16)
'3def84f0ce'
"""
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:
"""Pretty print an iterable which returns strings

>>> pprint_it(map(str, range(20)), indent=0, width=40)
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19
<BLANKLINE>
"""
joined = ", ".join(it)
lines = wrap(joined, width=width - indent)
for line in lines:
print(f"{indent*' '}{line}")
print()


def task_2():
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) # start and stop are 1-based indices
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):
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)

</lang>

{{out}}
<pre>
======
Task 2
======

Base-2 esthetic numbers from index 8 through index 12 inclusive:

10101010, 101010101, 1010101010, 10101010101, 101010101010

Base-3 esthetic numbers from index 12 through index 18 inclusive:

1210, 1212, 2101, 2121, 10101, 10121, 12101

Base-4 esthetic numbers from index 16 through index 24 inclusive:

323, 1010, 1012, 1210, 1212, 1232, 2101, 2121, 2123

Base-5 esthetic numbers from index 20 through index 30 inclusive:

323, 343, 432, 434, 1010, 1012, 1210, 1212, 1232, 1234, 2101

Base-6 esthetic numbers from index 24 through index 36 inclusive:

343, 345, 432, 434, 454, 543, 545, 1010, 1012, 1210, 1212, 1232, 1234

Base-7 esthetic numbers from index 28 through index 42 inclusive:

345, 432, 434, 454, 456, 543, 545, 565, 654, 656, 1010, 1012, 1210, 1212,
1232

Base-8 esthetic numbers from index 32 through index 48 inclusive:

432, 434, 454, 456, 543, 545, 565, 567, 654, 656, 676, 765, 767, 1010, 1012,
1210, 1212

Base-9 esthetic numbers from index 36 through index 54 inclusive:

434, 454, 456, 543, 545, 565, 567, 654, 656, 676, 678, 765, 767, 787, 876,
878, 1010, 1012, 1210

Base-10 esthetic numbers from index 40 through index 60 inclusive:

454, 456, 543, 545, 565, 567, 654, 656, 676, 678, 765, 767, 787, 789, 876,
878, 898, 987, 989, 1010, 1012

Base-11 esthetic numbers from index 44 through index 66 inclusive:

456, 543, 545, 565, 567, 654, 656, 676, 678, 765, 767, 787, 789, 876, 878,
898, 89a, 987, 989, 9a9, a98, a9a, 1010

Base-12 esthetic numbers from index 48 through index 72 inclusive:

543, 545, 565, 567, 654, 656, 676, 678, 765, 767, 787, 789, 876, 878, 898,
89a, 987, 989, 9a9, 9ab, a98, a9a, aba, ba9, bab

Base-13 esthetic numbers from index 52 through index 78 inclusive:

545, 565, 567, 654, 656, 676, 678, 765, 767, 787, 789, 876, 878, 898, 89a,
987, 989, 9a9, 9ab, a98, a9a, aba, abc, ba9, bab, bcb, cba

Base-14 esthetic numbers from index 56 through index 84 inclusive:

565, 567, 654, 656, 676, 678, 765, 767, 787, 789, 876, 878, 898, 89a, 987,
989, 9a9, 9ab, a98, a9a, aba, abc, ba9, bab, bcb, bcd, cba, cbc, cdc

Base-15 esthetic numbers from index 60 through index 90 inclusive:

567, 654, 656, 676, 678, 765, 767, 787, 789, 876, 878, 898, 89a, 987, 989,
9a9, 9ab, a98, a9a, aba, abc, ba9, bab, bcb, bcd, cba, cbc, cdc, cde, dcb,
dcd

Base-16 esthetic numbers from index 64 through index 96 inclusive:

654, 656, 676, 678, 765, 767, 787, 789, 876, 878, 898, 89a, 987, 989, 9a9,
9ab, a98, a9a, aba, abc, ba9, bab, bcb, bcd, cba, cbc, cdc, cde, dcb, dcd,
ded, def, edc

======
Task 3
======

Base-10 esthetic numbers with magnitude between 1,000 and 9,999:

1010, 1012, 1210, 1212, 1232, 1234, 2101, 2121, 2123, 2321, 2323, 2343,
2345, 3210, 3212, 3232, 3234, 3432, 3434, 3454, 3456, 4321, 4323, 4343,
4345, 4543, 4545, 4565, 4567, 5432, 5434, 5454, 5456, 5654, 5656, 5676,
5678, 6543, 6545, 6565, 6567, 6765, 6767, 6787, 6789, 7654, 7656, 7676,
7678, 7876, 7878, 7898, 8765, 8767, 8787, 8789, 8987, 8989, 9876, 9878, 9898

======
Task 4
======

Base-10 esthetic numbers with magnitude between 100,000,000 and 130,000,000:

101010101, 101010121, 101010123, 101012101, 101012121, 101012123, 101012321,
101012323, 101012343, 101012345, 101210101, 101210121, 101210123, 101212101,
101212121, 101212123, 101212321, 101212323, 101212343, 101212345, 101232101,
101232121, 101232123, 101232321, 101232323, 101232343, 101232345, 101234321,
101234323, 101234343, 101234345, 101234543, 101234545, 101234565, 101234567,
121010101, 121010121, 121010123, 121012101, 121012121, 121012123, 121012321,
121012323, 121012343, 121012345, 121210101, 121210121, 121210123, 121212101,
121212121, 121212123, 121212321, 121212323, 121212343, 121212345, 121232101,
121232121, 121232123, 121232321, 121232323, 121232343, 121232345, 121234321,
121234323, 121234343, 121234345, 121234543, 121234545, 121234565, 121234567,
123210101, 123210121, 123210123, 123212101, 123212121, 123212123, 123212321,
123212323, 123212343, 123212345, 123232101, 123232121, 123232123, 123232321,
123232323, 123232343, 123232345, 123234321, 123234323, 123234343, 123234345,
123234543, 123234545, 123234565, 123234567, 123432101, 123432121, 123432123,
123432321, 123432323, 123432343, 123432345, 123434321, 123434323, 123434343,
123434345, 123434543, 123434545, 123434565, 123434567, 123454321, 123454323,
123454343, 123454345, 123454543, 123454545, 123454565, 123454567, 123456543,
123456545, 123456565, 123456567, 123456765, 123456767, 123456787, 123456789
</pre>
</pre>