An esthetic number is a positive integer where every adjacent digit differs from its neighbour by 1.



E.G.
 12 is an esthetic number. One and two differ by 1.
 5654 is an esthetic number. Each digit is exactly 1 away from its neighbour.
 890 is not an esthetic number. Nine and zero differ by 9.


These examples are nominally in base 10 but the concept extends easily to numbers in other bases. Traditionally, single digit numbers are included in esthetic numbers; zero may or may not be. For our purposes, for this task, do not include zero (0) as an esthetic number. Do not include numbers with leading zeros.

Esthetic numbers are also sometimes referred to as stepping numbers.



Task
 Write a routine (function, procedure, whatever) to find esthetic numbers in a given base.
 Use that routine to find esthetic numbers in bases 2 through 16 and display, here on this page, the esthectic numbers from index (base × 4) through index (base × 6), inclusive. (E.G. for base 2: 8th through 12th, for base 6: 24th through 36th, etc.)
 Find and display, here on this page, the base 10 esthetic numbers with a magnitude between 1000 and 9999.
 Stretch: Find and display, here on this page, the base 10 esthetic numbers with a magnitude between 1.0e8 and 1.3e8.


Related task

   numbers with equal rises and falls


See also

OEIS A033075 - Positive numbers n such that all pairs of consecutive decimal digits differ by 1
Numbers Aplenty - Esthetic numbers
Geeks for Geeks - Stepping numbers


BEGIN # find some esthetic numbers: numbers whose successive digits differ by 1 #
    # returns TRUE if n is esthetic in the specified base, FALSE otherwise #
    PRIO ISESTHETIC = 1;
    OP   ISESTHETIC = ( INT n, base )BOOL:
         BEGIN
            INT  v             := ABS n;
            BOOL is esthetic   := TRUE;
            INT  prev digit    := v MOD base;
            v OVERAB base;
            WHILE v > 0 AND is esthetic
            DO
                INT next digit := v MOD base;
                is esthetic    := ABS ( next digit - prev digit ) = 1;
                prev digit     := next digit;
                v OVERAB base
            OD;
            is esthetic
         END # ISESTHETIC # ;
    # returns an array of the first n esthetic numbers in the specified base #
    PRIO ESTHETIC = 1;
    OP   ESTHETIC = ( INT n, base )[]INT:
         BEGIN
            [ 1 : n ]INT result;
            INT          e count := 0;
            FOR i WHILE  e count < n DO
                IF i ISESTHETIC base THEN result[ e count +:= 1 ] := i FI
            OD;
            result
         END # ESTHETIC # ;
    # returns a string erpresentation of n in the specified base, 2 <= base <= 16 must be TRUE #
    PRIO TOBASESTRING = 1;
    OP   TOBASESTRING = ( INT n, base )STRING:
         IF base < 2 OR base > 16
         THEN # invalid vbase #
             "?" + whole( n, 0 ) + ":" + whole( base, 0 ) + "?"
         ELSE
            INT    v      := ABS n;
            STRING digits  = "0123456789abcdef";
            STRING result := digits[ ( v MOD base ) + 1 ];
            WHILE ( v OVERAB base ) > 0 DO
                digits[ ( v MOD base ) + 1 ] +=: result
            OD;
            IF n < 0 THEN "-" +=: result FI;
            result
        FI # TOBASESTRING # ;
    # sets count to the number of esthetic numbers with length digits in base b less than max #
    # also displays the esthetic numbers #
    PROC show esthetic = ( INT number, base, length, max, REF INT count )VOID:
         IF length = 1
         THEN # number is esthetic #
             IF number <= max THEN
                 # number is in the required range #
                 print( ( " ", whole( number, 0 ) ) );
                 IF ( count +:= 1 ) MOD 9 = 0 THEN print( ( newline ) ) FI
             FI
         ELSE
             # find the esthetic numbers that start with number #
             INT digit  = number MOD base;
             INT prefix = number * base;
             IF digit > 0 THEN # can have a lower digit #
                 show esthetic( prefix + ( digit - 1 ), base, length - 1, max, count )
             FI;
             IF digit < base - 1 THEN # can have a higher digit #
                 show esthetic( prefix + ( digit + 1 ), base, length - 1, max, count )
             FI
         FI # show esthetic # ;
    # task #
    # esthetic numbers from base * 4 to base * 6 for bases 2 to 16 #
    FOR base FROM 2 TO 16 DO
        INT e from = base * 4;
        INT e to   = base * 6;
        print( ( "Esthetic numbers ", whole( e from, 0 ), " to ", whole( e to, 0 ), " in base ", whole( base, 0 ), newline ) );
        []INT e numbers = e to ESTHETIC base;
        print( ( "  " ) );
        FOR n FROM e from TO e to DO
            print( ( " ", e numbers[ n ] TOBASESTRING base ) )
        OD;
        print( ( newline ) )
    OD;
    # esthetic base 10 numbers between 1000 and 9999 #
    print( ( "Base 10 eshetic numbers between 1000 and 9999", newline ) );
    INT e count := 0;
    FOR i FROM 1000 TO 9999 DO
        IF i ISESTHETIC 10 THEN
            print( ( " ", whole( i, 0 ) ) );
            IF ( e count +:= 1 ) MOD 16 = 0 THEN print( ( newline ) ) FI
        FI
    OD;
    print( ( newline, newline ) );
    print( ( "Esthetic numbers between 100 000 000 and 130 000 000:", newline ) );
    e count := 0;
    show esthetic( 1, 10, 9, 130 000 000, e count );
    print( ( newline ) );
    print( ( "Found ", whole( e count, 0 ), " esthetic numbers", newline ) )
END