Numbers k such that the last letter of k is the same as the first letter of k+1
You are encouraged to solve this task according to the task description, using any language you may know.
- Definition
For the purposes of this task, a qualifying number is a non-negative integer, k, whose last letter is the same as the first letter of k+1 when written in English.
For example, 18 (i.e 'eighteen' in English) is a qualifying number because its last letter 'n' is the same as the first letter of 'nineteen'.
Take the English equivalent of 0 to be 'zero' and not 'nought' or similar words.
For numbers such as 100 or 1000, the equivalent English should be taken as 'one hundred' or 'one thousand' and not 'a hundred' or 'a thousand'.
- Task
1. Find and show here the first 50 qualifying numbers.
2. What are the 1,000th and 10,000th qualifying numbers?
3. For the first 1,000 and 10,000 qualifying numbers, show their breakdown by final digit. This can be shown numerically, graphically or both.
If it is difficult for your language to meet all of these requirements, then just do what you reasonably can.
- Stretch
4. What are the 100,000th and millionth qualifying numbers?
5. For the first 100,000 and million qualifying numbers, show their breakdown by final digit.
- References
- OEIS sequence A363659:Numbers k such that the last letter of k is the same as the first letter of k+1 when written in English.
- GCHQ, The GCHQ Puzzle Book, Penguin, 2016. See Puzzle 31, page 37 (referred to in OEIS link).
ALGOL 68
Brute force but only calculating the first and last characters of the name, not the whole name.
BEGIN # find numbers k where the name of k ends with the start of k + 1 #
[]CHAR unit start = ( "o", "t", "t", "f", "f", "s", "s", "e", "n" );
[]CHAR tens start = ( "t", "t", "t", "f", "f", "s", "s", "e", "n" );
[]CHAR unit end = []CHAR( "y", "e", "o", "e", "r", "e", "x", "n", "t", "e" )[ AT 0 ];
[ 0 : 99 ]CHAR s99; # starting characters for 0..99 #
FOR i TO 99 DO
s99[ i ] := IF i < 10 THEN unit start[ i ]
ELIF i = 10 THEN "t"
ELIF i = 11 THEN "e"
ELIF i < 20 THEN unit start[ i - 10 ]
ELSE tens start[ i OVER 10 ]
FI
OD;
s99[ 0 ] := "z";
[ 0 : 99 ]CHAR e99; # ending characters for 0..99 #
FOR i FROM 1 TO 99 DO e99[ i ] := unit end[ i MOD 10 ] OD;
FOR i FROM 10 TO 19 DO e99[ i ] := "n" OD;
e99[ 0 ] := "o"; e99[ 10 ] := "n"; e99[ 12 ] := "e";
# prints a histogram of data scaled to fit in width #
PROC show histogram = ( []INT data, INT width )VOID:
IF LWB data <= UPB data THEN
INT max value := data[ LWB data ];
FOR i FROM LWB data + 1 TO UPB data DO
IF data[ i ] > max value THEN max value := data[ i ] FI
OD;
FOR i FROM LWB data TO UPB data DO
INT v = ROUND ( ( data[ i ] * width ) / max value );
print( ( whole( i, -2 ), ": ", v * "=", ( ( width - v ) + 1 ) * " " ) );
print( ( " (", whole( data[ i ], 0 ), ")", newline ) )
OD
FI # show histogram # ;
[ 0 : 9 ]INT d count; FOR i FROM LWB d count TO UPB d count DO d count[ i ] := 0 OD;
CHAR prev end := "o"; # zero #
INT next to show := 1 000;
INT count := 0;
print( ( "The first 50 numbers:", newline ) );
FOR n WHILE count < 1 000 000 DO
INT k = n - 1;
INT ddd := n; WHILE ddd >= 1 000 DO ddd OVERAB 1 000 OD;
CHAR curr start = IF ddd < 100
THEN s99[ ddd ]
ELSE unit start[ ddd OVER 100 ]
FI;
IF curr start = prev end THEN
count +:= 1;
d count[ k MOD 10 ] +:= 1;
IF count <= 50 THEN
print( ( " ", whole( k, -4 ) ) );
IF count MOD 10 = 0 THEN print( ( newline ) ) FI
ELIF count = next to show THEN
print( ( newline ) );
print( ( "The ", whole( count, 0 ), "th number is: ", whole( k, 0 ), newline ) );
print( ( "Breakdown by final digit of the numbers:", newline ) );
show histogram( d count, 60 );
next to show *:= 10
FI
FI;
INT n99 = n MOD 100;
prev end := IF n99 > 0
THEN e99[ n99 ]
ELIF n MOD 1 000 000 = 0
THEN "n"
ELSE "d"
FI
OD
END
- Output:
The first 50 numbers: 0 18 28 38 79 81 83 85 97 102 122 132 142 152 162 172 182 192 208 228 238 248 258 268 278 288 298 308 328 338 348 358 368 378 388 398 799 801 803 805 809 812 821 823 825 829 831 833 835 839 The 1000th number is: 10988 Breakdown by final digit of the numbers: 0: == (12) 1: ====================== (111) 2: ====================== (110) 3: ====================== (111) 4: == (11) 5: ====================== (111) 6: == (11) 7: ====================== (111) 8: ============================================================ (301) 9: ====================== (111) The 10000th number is: 106652 Breakdown by final digit of the numbers: 0: === (122) 1: ================================= (1301) 2: ===================== (829) 3: ================================= (1301) 4: === (121) 5: ================================= (1301) 6: === (121) 7: ============================== (1211) 8: ============================================================ (2392) 9: ================================= (1301) The 100000th number is: 1095542 Breakdown by final digit of the numbers: 0: === (1122) 1: ================================ (11301) 2: ===================================================== (18829) 3: ================================ (11301) 4: === (1121) 5: ================================ (11301) 6: === (1121) 7: =============================== (11211) 8: ============================================================ (21392) 9: ================================ (11301) The 1000000th number is: 10984428 Breakdown by final digit of the numbers: 0: == (11123) 1: ====================== (111301) 2: ====================== (110230) 3: ====================== (111301) 4: == (11121) 5: ====================== (111301) 6: == (11121) 7: ====================== (111211) 8: ============================================================ (299990) 9: ====================== (111301)
C++
#include <algorithm>
#include <cassert>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <string>
std::string cardinal(int n) {
static const char* small[] = {
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine",
"ten", "eleven", "twelve", "thirteen", "fourteen",
"fifteen", "sixteen", "seventeen", "eighteen", "nineteen",
};
static const char* tens[] = {
"twenty", "thirty", "forty", "fifty",
"sixty", "seventy", "eighty", "ninety",
};
assert(n >= 0 && n < 1000);
std::string str;
if (n < 20)
str = small[n];
else if (n < 100) {
str = tens[n / 10 - 2];
if (n % 10 != 0) {
str += "-";
str += small[n % 10];
}
} else {
str = cardinal(n / 100);
str += " hundred";
if (n % 100 != 0) {
str += " ";
str += cardinal(n % 100);
}
}
return str;
}
class a363659_generator {
public:
explicit a363659_generator() : num(0) {
for (int i = 0; i < 1000; ++i) {
std::string name = cardinal(i);
first[i] = name.front();
last[i] = name.back();
}
}
int next() {
while (first_char(num + 1) != last_char(num))
++num;
return num++;
}
private:
char first_char(int n) const {
int i = 0;
for (; n > 0; n /= 1000)
i = n % 1000;
return first[i];
}
char last_char(int n) const {
int i = n % 1000;
if (i > 0)
return last[i];
else if (n == 0)
return last[0];
else if (n % 1000000 == 0)
return 'n';
return 'd';
}
int num;
char first[1000];
char last[1000];
};
template <typename Iterator>
void histogram(Iterator begin, Iterator end) {
if (begin == end)
return;
double max_value = *std::max_element(begin, end);
const int width = 60;
int i = 0;
for (Iterator it = begin; it != end; ++it) {
std::cout << i++ << ": ";
double value = *it;
int n = max_value != 0 ? std::lround((value * width) / max_value) : 0;
int j = 0;
for (; j < n; ++j)
std::cout << u8"\u2586";
for (; j < width; ++j)
std::cout << ' ';
std::cout << ' ' << *it << '\n';
}
}
int main() {
std::cout << "First 50 numbers:\n";
a363659_generator gen;
int count[10] = {};
int i = 1, n;
for (; i <= 50; ++i) {
n = gen.next();
++count[n % 10];
std::cout << std::setw(3) << n << (i % 10 == 0 ? '\n' : ' ');
}
for (int limit = 1000; limit <= 1000000; limit *= 10) {
for (; i <= limit; ++i) {
n = gen.next();
++count[n % 10];
}
std::cout << "\nThe " << limit << "th number is " << n << ".\n";
std::cout << "Breakdown by last digit of first " << limit
<< " numbers:\n";
histogram(count, count + 10);
}
}
- Output:
First 50 numbers: 0 18 28 38 79 81 83 85 97 102 122 132 142 152 162 172 182 192 208 228 238 248 258 268 278 288 298 308 328 338 348 358 368 378 388 398 799 801 803 805 809 812 821 823 825 829 831 833 835 839 The 1000th number is 10988. Breakdown by last digit of first 1000 numbers: 0: ▆▆ 12 1: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 111 2: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 110 3: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 111 4: ▆▆ 11 5: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 111 6: ▆▆ 11 7: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 111 8: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 301 9: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 111 The 10000th number is 106652. Breakdown by last digit of first 10000 numbers: 0: ▆▆▆ 122 1: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 1301 2: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 829 3: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 1301 4: ▆▆▆ 121 5: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 1301 6: ▆▆▆ 121 7: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 1211 8: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 2392 9: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 1301 The 100000th number is 1095542. Breakdown by last digit of first 100000 numbers: 0: ▆▆▆ 1122 1: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 11301 2: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 18829 3: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 11301 4: ▆▆▆ 1121 5: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 11301 6: ▆▆▆ 1121 7: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 11211 8: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 21392 9: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 11301 The 1000000th number is 10984428. Breakdown by last digit of first 1000000 numbers: 0: ▆▆ 11123 1: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 111301 2: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 110230 3: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 111301 4: ▆▆ 11121 5: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 111301 6: ▆▆ 11121 7: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 111211 8: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 299990 9: ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 111301
FreeBASIC
Using https://rosettacode.org/wiki/Number_names#FreeBASIC
Dim As Uinteger i = 0, c = 0, j = 0
Dim As Integer l
Dim As Uinteger nums(50)
Dim As Integer lastDigs(9)
Dim As String prev = "zero", sgte = ""
Dim As Uinteger limit = 1000
While limit <= 1000000
sgte = numname(i+1)
If Right(prev,1) = Left(sgte,1) Then
If c < 50 Then nums(c) = i
Dim As Integer ld = i Mod 10
lastDigs(ld) += 1
c += 1
If c = 50 Then
Print "First 50 numbers:"
For j = 0 To c-1
Print Using "### "; nums(j);
If (j+1) Mod 10 = 0 Then Print
Next j
Elseif c = limit Then
Print Using !"\nThe & number is ##,###,###."; numname(c); i
Print !"Breakdown by last digit of the qualifiers up to this:\nFrequencies"
Print String (80, "-")
For j = 0 To 9
l = Cint(lastDigs(j) * 28 / lastDigs(9))
Print j; " "; String(l, Chr(254)); " "; lastDigs(j)
Next j
Print String (80, "-")
limit *= 10
End If
End If
prev = sgte
i += 1
Wend
Sleep
- Output:
First 50 numbers: 0 18 28 38 79 81 83 85 97 102 122 132 142 152 162 172 182 192 208 228 238 248 258 268 278 288 298 308 328 338 348 358 368 378 388 398 799 801 803 805 809 812 821 823 825 829 831 833 835 839 The one thousand number is 10,988. Breakdown by last digit of the qualifiers up to this: Frequencies -------------------------------------------------------------------------------- 0 ■■■■ 12 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 2 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 110 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 4 ■■■ 11 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 6 ■■■ 11 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 301 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 -------------------------------------------------------------------------------- The ten thousand number is 106,652. Breakdown by last digit of the qualifiers up to this: Frequencies -------------------------------------------------------------------------------- 0 ■■■ 122 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 2 ■■■■■■■■■■■■■■■■■■■■■■■■ 829 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 4 ■■■ 121 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 6 ■■■ 121 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1211 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 2392 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 -------------------------------------------------------------------------------- The one hundred thousand number is 1,095,542. Breakdown by last digit of the qualifiers up to this: Frequencies -------------------------------------------------------------------------------- 0 ■■■ 1122 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 2 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 18829 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 4 ■■■ 1121 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 6 ■■■ 1121 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11211 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 21392 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 -------------------------------------------------------------------------------- The one million number is 10,984,428. Breakdown by last digit of the qualifiers up to this: Frequencies -------------------------------------------------------------------------------- 0 ■■■ 11123 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 2 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 110230 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 4 ■■■ 11121 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 6 ■■■ 11121 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111211 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 299990 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 --------------------------------------------------------------------------------
J
Using Number names, we can generate a sample of the desired numbers which (in this example) are smaller than a million:
#sample=: I.({:=1|.!.' '{.)|:({.,{:)@us"0 i.1e6
91401
5 10$sample NB. first fifty
0 18 28 38 79 81 83 85 97 102
122 132 142 152 162 172 182 192 208 228
238 248 258 268 278 288 298 308 328 338
348 358 368 378 388 398 799 801 803 805
809 812 821 823 825 829 831 833 835 839
(],. sample {~ <:) 1e3 1e4 NB. 1000th and 10000th
1000 10988
10000 106652
(~.,.#/.~) /:~10|1e3{.sample NB. counts by final digit (first 1e3 k)
0 12
1 111
2 110
3 111
4 11
5 111
6 11
7 111
8 301
9 111
(~.,.#/.~) /:~10|1e4{.sample NB. counts by final digit (first 1e4 k)
0 122
1 1301
2 829
3 1301
4 121
5 1301
6 121
7 1211
8 2392
9 1301
Java
import java.util.Arrays;
public final class NumbersKSuchThatTheLastLetterOfKIsTheSameAsTheFirstLetterOfKPlusOne {
public static void main(String[] args) {
System.out.println("The first 50 numbers:");
A363659Generator generator = new A363659Generator();
int[] digitCount = new int[10];
int index = 1;
int number = 0;
while ( index <= 50 ) {
number = generator.next();
digitCount[number % 10] += 1;
System.out.print(String.format("%3d%s", number, ( index % 10 == 0 ) ? "\n" : " " ));
index += 1;
}
System.out.println();
for ( int limit = 1_000; limit <= 1_000_000; limit *= 10 ) {
while ( index <= limit ) {
number = generator.next();
digitCount[number % 10] += 1;
index += 1;
}
System.out.println("The " + limit + "th number is " + number + ".");
System.out.println("Breakdown by last digit of first " + limit + " numbers:");
drawHistogram(digitCount);
}
}
private static void drawHistogram(int[] digitCount) {
final int MAX_VALUE = Arrays.stream(digitCount).boxed().max(Integer::compare).get();
final int WIDTH = 60;
for ( int i = 0; i < digitCount.length; i++ ) {
System.out.print(i + ": ");
final int rowLength = ( MAX_VALUE != 0 ) ? ( digitCount[i] * WIDTH ) / MAX_VALUE : 0;
for ( int index = 0; index < WIDTH; index++ ) {
String toPrint = ( index < rowLength ) ? "■" : " ";
System.out.print(toPrint);
}
System.out.println(" " + digitCount[i]);
}
System.out.println();
}
}
final class A363659Generator {
public A363659Generator() {
for ( int i = 0; i < 1_000; i++ ) {
String name = NumberToWordsConverter.convert(i);
firstChar[i] = name.toLowerCase().charAt(0);
lastChar[i] = name.charAt(name.length() - 1);
}
}
public int next() {
while ( firstChar(number + 1) != lastChar(number) ) {
number += 1;
}
return number++;
}
private char firstChar(int n) {
int i = 0;
while ( n > 0 ) {
i = n % 1_000;
n /= 1_000;
}
return firstChar[i];
}
private char lastChar(int n) {
final int i = n % 1_000;
if ( i > 0 ) {
return lastChar[i];
}
if ( n == 0 ) {
return lastChar[0];
}
if ( n % 1_000_000 == 0 ) {
return 'n';
}
return 'd';
}
private int number = 0;
private char[] firstChar = new char[1_000];
private char[] lastChar = new char[1_000];
}
final class NumberToWordsConverter { // Valid for positive integers ≤ 999_999_999
public static String convert(int n) {
if ( n < 20 ) {
return units[n];
}
if ( n < 100 ) {
return tens[n / 10] + ( ( n % 10 > 0 ) ? " " + convert(n % 10) : "" );
}
if ( n < 1_000 ) {
return units[n / 100] + " Hundred" + ( ( n % 100 > 0 ) ? " and " + convert(n % 100) : "" );
}
if ( n < 1_000_000 ) {
return convert(n / 1_000) + " Thousand" + ( ( n % 1_000 > 0 ) ? " " + convert(n % 1_000) : "" );
}
return convert(n / 1_000_000) + " Million"
+ ( ( n % 1_000_000 > 0 ) ? " " + convert(n % 1_000_000) : "" );
}
private static final String[] units = { "Zero", "One", "Two", "Three", "Four", "Five", "Six",
"Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
"Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen" };
private static final String[] tens =
{ "","", "Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety" };
}
- Output:
The first 50 numbers: 0 18 28 38 79 81 83 85 97 102 122 132 142 152 162 172 182 192 208 228 238 248 258 268 278 288 298 308 328 338 348 358 368 378 388 398 799 801 803 805 809 812 821 823 825 829 831 833 835 839 The 1000th number is 10988. Breakdown by last digit of first 1000 numbers: 0: ■■ 12 1: ■■■■■■■■■■■■■■■■■■■■■■ 111 2: ■■■■■■■■■■■■■■■■■■■■■ 110 3: ■■■■■■■■■■■■■■■■■■■■■■ 111 4: ■■ 11 5: ■■■■■■■■■■■■■■■■■■■■■■ 111 6: ■■ 11 7: ■■■■■■■■■■■■■■■■■■■■■■ 111 8: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 301 9: ■■■■■■■■■■■■■■■■■■■■■■ 111 The 10000th number is 106652. Breakdown by last digit of first 10000 numbers: 0: ■■■ 122 1: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 2: ■■■■■■■■■■■■■■■■■■■■ 829 3: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 4: ■■■ 121 5: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 6: ■■■ 121 7: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1211 8: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 2392 9: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 The 100000th number is 1095542. Breakdown by last digit of first 100000 numbers: 0: ■■■ 1122 1: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 2: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 18829 3: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 4: ■■■ 1121 5: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 6: ■■■ 1121 7: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11211 8: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 21392 9: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 The 1000000th number is 10984428. Breakdown by last digit of first 1000000 numbers: 0: ■■ 11123 1: ■■■■■■■■■■■■■■■■■■■■■■ 111301 2: ■■■■■■■■■■■■■■■■■■■■■■ 110230 3: ■■■■■■■■■■■■■■■■■■■■■■ 111301 4: ■■ 11121 5: ■■■■■■■■■■■■■■■■■■■■■■ 111301 6: ■■ 11121 7: ■■■■■■■■■■■■■■■■■■■■■■ 111211 8: ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 299990 9: ■■■■■■■■■■■■■■■■■■■■■■ 111301
jq
Adapted from Wren
Also works with gojq, the Go implementation of jq.
The following is probably mainly of interest because of the utility functions:
- lpad # left pad
- rpad # right pad
- tprint # tabular print
- whilst # control structure
- number2name # English name of a number
- barChart # horizontal barchart
Preliminaries
# The following may be omitted if using the C implementation of jq
def _nwise($n):
def n: if length <= $n then . else .[0:$n] , (.[$n:] | n) end;
n;
def lpad($len): tostring | ($len - length) as $l | (" " * $l) + .;
def rpad($len): tostring | ($len - length) as $l | . + (" " * $l);
# tabular print
def tprint(columns; wide):
reduce _nwise(columns) as $row ("";
. + ($row|map(lpad(wide)) | join(" ")) + "\n" );
# If cond then emit f and use that value to recurse
def whilst(cond; f): def r: select(cond) | f | (., r); r;
# Input: a positive or negative number for which tostring prints with only characters from [-.0-9]
# Output: the name of the number, e.g. "zero" for 0
# An error is raised if the above-mentioned requirement is not met.
def number2name:
def __small: [
"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven",
"twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" ];
def __tens: ["", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"];
def __illions: [
"", " thousand", " million", " billion"," trillion", " quadrillion", " quintillion",
" sextillion", " septillion", " octillion", " nonillion", "decillion" ];
. as $n
| if tostring | test("[eE]") then "number2name cannot handle \(.)" | error else . end
| false as $_uk # United Kingdom mode
| "minus" as $_neg
| "point" as $_point
| {f: "",
and: (if $_uk then "and " else "" end) }
| if $n < 0
then .t = $_neg + " "
| .n = - $n
else .n = $n
end
| if (.n | (. != floor))
then .f = (.n | tostring | sub("^[0-9]*[.]";""))
| .n |= trunc
else .
end
| if .n < 20
then .t += __small[.n]
elif .n < 100
then .t += __tens[(.n/10)|floor]
| (.n % 10) as $s
| if $s > 0 then .t += "-" + __small[$s] else . end
elif .n < 1000
then .t += __small[(.n/100)|floor] + " hundred"
| (.n % 100) as $s
| if $s > 0 then .t += " " + .and + ($s|number2name) else . end
else .sx = ""
| .i = 0
| until (.n <= 0;
(.n % 1000) as $p
| .n |= ((./1000)|floor)
| if $p > 0
then .ix = ($p|number2name) + __illions[.i]
| if .sx != "" then .ix += " " + .sx else . end
| .sx = .ix
else .
end
| .i += 1)
| .t += .sx
end
| if .f != ""
then .t += " " + $_point
| reduce (.f | explode[] | [.] | implode | tonumber) as $d
(.; .t += " \(__small[$d])" )
else .
end
| .t ;
# Draws a horizontal bar chart on the terminal representing an array
# of numerical 'data', which must be non-negative, for example:
# Title
# --------------------------------------------------
# a □ 0
# bb ■■■■■■■■■■■■■■■■■■■■■■ 1
# ccc ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 2
# --------------------------------------------------
# 'labels' is a list of the corresponding text for each bar.
# If 'rjust' is true then the labels are right-justified within their maximum length,
# otherwise they are left-justified.
# 'width' is the desired total width of the chart in characters.
# 'symbol' is the character to be used to draw each bar,
# 'symbol2' is used to represent scaled non-zero data and 'symbol3' zero data which
# would otherwise be blank. The actual data is printed at the end of each bar.
#
def barChart ($title; $width; $labels; $data; $rjust; $symbol; $symbol2; $symbol3):
def times($n): if $n > 0 then . * $n else "" end;
def n: if isinfinite then "∞" else tostring end;
($labels|length) as $barCount
| if ($data|length) != $barCount then "Mismatch between labels and data." | error else . end
| ($labels | map(length) | max) as $maxLabelLen
| ($labels
| if $rjust
then map( lpad( $maxLabelLen ) )
else map( rpad( $maxLabelLen ) )
end ) as $labels
| ($data|max) as $maxData
| ($data|map(if isinfinite then 1 else tostring|length end)|max) as $maxDataLength
| ($width - $maxLabelLen - $maxDataLength - 2) as $maxLen # maximum length of a bar
| ($data | map( if isinfinite then $maxLen else ((. * $maxLen / $maxData)|floor) end)) as $scaledData
| ( "-" * ([$width, ($title|length)] | max)) as $dashes
| $title,
$dashes,
(range(0; $barCount) as $i
| ($symbol | times($scaledData[$i]))
| if . == "" then (if $data[$i] > 0 then $symbol2 else $symbol3 end) else . end
| "\($labels[$i]) \(.) \($data[$i]|n)" ),
$dashes ;
# Convenience version of the above function using default symbols:
def barChart($title; $width; $labels; $data; $rjust):
barChart($title; $width; $labels; $data; $rjust; "■"; "◧"; "□");
# Convenience version using right justification for labels.
def barChart($title; $width; $labels; $data):
barChart($title; $width; $labels; $data; true; "■"; "◧"; "□");
The task
def task($limit):
[range(0;10) | tostring] as $labels
| {i: 0,
c: 0,
nums: [],
lastDigs: [range(0;10)|0],
prev: "zero",
limit: 1000 }
| whilst (.limit <= $limit;
.emit = null
| (.i+1 | number2name) as $next
| if .prev[-1:] == $next[:1]
then if (.c < 50) then .nums += [.i] else . end
| .lastDigs[.i % 10] += 1
| .c += 1
| if .c == 50
then .emit = ["First 50 numbers:", (.nums|tprint(10;3))]
elif .c == .limit
then .emit = ["\nThe \(.c)th number is \(.i)\n"]
| "Breakdown by last digit of first \(.c) numbers" as $title
| .emit += [barChart($title; 80; $labels; .lastDigs)]
| .limit *= 10
else .
end
else .
end
| .prev = $next
| .i += 1 )
| select(.emit).emit[] ;
task(1e6)
- Output:
First 50 numbers: 0 18 28 38 79 81 83 85 97 102 122 132 142 152 162 172 182 192 208 228 238 248 258 268 278 288 298 308 328 338 348 358 368 378 388 398 799 801 803 805 809 812 821 823 825 829 831 833 835 839 The 1000th number is 10988 Breakdown by last digit of first 1000 numbers -------------------------------------------------------------------------------- 0 ■■ 12 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 2 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 110 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 4 ■■ 11 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 6 ■■ 11 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 301 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 -------------------------------------------------------------------------------- The 10000th number is 106652 Breakdown by last digit of first 10000 numbers -------------------------------------------------------------------------------- 0 ■■■ 122 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 2 ■■■■■■■■■■■■■■■■■■■■■■■■■ 829 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 4 ■■■ 121 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 6 ■■■ 121 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1211 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 2392 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 -------------------------------------------------------------------------------- The 100000th number is 1095542 Breakdown by last digit of first 100000 numbers -------------------------------------------------------------------------------- 0 ■■■ 1122 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 2 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 18829 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 4 ■■■ 1121 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 6 ■■■ 1121 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11211 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 21392 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 -------------------------------------------------------------------------------- The 1000000th number is 10984428 Breakdown by last digit of first 1000000 numbers -------------------------------------------------------------------------------- 0 ■■ 11123 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 2 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 110230 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 4 ■■ 11121 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 6 ■■ 11121 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 111211 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 299990 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 --------------------------------------------------------------------------------
Julia
using Formatting, SpelledOut, UnicodePlots
const spelledcache = [spelled_out(n, lang = :en) for n in 1:999]
const firstcache, lastcache = map(first, spelledcache), map(last, spelledcache)
function inOEIS363659(n)
lastchar = n % 1000 > 0 ? lastcache[n % 1000] : n == 0 ? 'o' : n % 1_000_000 == 0 ? 'n' : 'd'
n += 1
j = 0
while n > 0
n, j = divrem(n, 1000)
end
return firstcache[j] == lastchar
end
""" test the sequence """
function testOEIS363659()
ncount = 0
lastdigits = UInt8[]
println("First 50 qualifying numbers:")
for n in 0:typemax(Int32)
if inOEIS363659(n)
ncount += 1
push!(lastdigits, n % 10)
if ncount < 51
print(rpad(n, 5), ncount % 10 == 0 ? "\n" : "")
elseif ncount in [10^3, 10^4, 10^5, 10^6, 10^7, 10^8]
println("\nThe $(spelled_out(ncount))th number is $(format(n, commas = true)).")
println("Breakdown by last digit of the qualifiers up to this:")
display(histogram(lastdigits, nbins = 10))
println()
ncount == 100_000_000 && break
end
end
end
end
testOEIS363659()
- Output:
First 50 qualifying numbers: 0 18 28 38 79 81 83 85 97 102 122 132 142 152 162 172 182 192 208 228 238 248 258 268 278 288 298 308 328 338 348 358 368 378 388 398 799 801 803 805 809 812 821 823 825 829 831 833 835 839 The one thousandth number is 10,988. Breakdown by last digit of the qualifiers up to this: ┌ ┐ [ 0.0, 1.0) ┤█▍ 12 [ 1.0, 2.0) ┤████████████▊ 111 [ 2.0, 3.0) ┤████████████▊ 110 [ 3.0, 4.0) ┤████████████▊ 111 [ 4.0, 5.0) ┤█▍ 11 [ 5.0, 6.0) ┤████████████▊ 111 [ 6.0, 7.0) ┤█▍ 11 [ 7.0, 8.0) ┤████████████▊ 111 [ 8.0, 9.0) ┤███████████████████████████████████ 301 [ 9.0, 10.0) ┤████████████▊ 111 └ ┘ Frequency The ten thousandth number is 106,652. Breakdown by last digit of the qualifiers up to this: ┌ ┐ [ 0.0, 1.0) ┤█▋ 122 [ 1.0, 2.0) ┤█████████████████▉ 1 301 [ 2.0, 3.0) ┤███████████▌ 829 [ 3.0, 4.0) ┤█████████████████▉ 1 301 [ 4.0, 5.0) ┤█▋ 121 [ 5.0, 6.0) ┤█████████████████▉ 1 301 [ 6.0, 7.0) ┤█▋ 121 [ 7.0, 8.0) ┤████████████████▋ 1 211 [ 8.0, 9.0) ┤█████████████████████████████████ 2 392 [ 9.0, 10.0) ┤█████████████████▉ 1 301 └ ┘ Frequency The one hundred thousandth number is 1,095,542. Breakdown by last digit of the qualifiers up to this: ┌ ┐ [ 0.0, 1.0) ┤█▋ 1 122 [ 1.0, 2.0) ┤████████████████▊ 11 301 [ 2.0, 3.0) ┤████████████████████████████▎ 18 829 [ 3.0, 4.0) ┤████████████████▊ 11 301 [ 4.0, 5.0) ┤█▋ 1 121 [ 5.0, 6.0) ┤████████████████▊ 11 301 [ 6.0, 7.0) ┤█▋ 1 121 [ 7.0, 8.0) ┤████████████████▊ 11 211 [ 8.0, 9.0) ┤████████████████████████████████ 21 392 [ 9.0, 10.0) ┤████████████████▊ 11 301 └ ┘ Frequency The one millionth number is 10,984,428. Breakdown by last digit of the qualifiers up to this: ┌ ┐ [ 0.0, 1.0) ┤█▎ 11 123 [ 1.0, 2.0) ┤███████████▌ 111 301 [ 2.0, 3.0) ┤███████████▍ 110 230 [ 3.0, 4.0) ┤███████████▌ 111 301 [ 4.0, 5.0) ┤█▎ 11 121 [ 5.0, 6.0) ┤███████████▌ 111 301 [ 6.0, 7.0) ┤█▎ 11 121 [ 7.0, 8.0) ┤███████████▌ 111 211 [ 8.0, 9.0) ┤███████████████████████████████ 299 990 [ 9.0, 10.0) ┤███████████▌ 111 301 └ ┘ Frequency The ten millionth number is 106,650,962. Breakdown by last digit of the qualifiers up to this: ┌ ┐ [ 0.0, 1.0) ┤█▌ 121 134 [ 1.0, 2.0) ┤███████████████▊ 1 301 301 [ 2.0, 3.0) ┤██████████▏ 828 817 [ 3.0, 4.0) ┤███████████████▊ 1 301 301 [ 4.0, 5.0) ┤█▌ 121 121 [ 5.0, 6.0) ┤███████████████▊ 1 301 301 [ 6.0, 7.0) ┤█▌ 121 121 [ 7.0, 8.0) ┤██████████████▋ 1 211 211 [ 8.0, 9.0) ┤█████████████████████████████ 2 391 392 [ 9.0, 10.0) ┤███████████████▊ 1 301 301 └ ┘ Frequency The one hundred millionth number is 1,095,538,742. Breakdown by last digit of the qualifiers up to this: ┌ ┐ [ 0.0, 1.0) ┤█▌ 1 121 234 [ 1.0, 2.0) ┤██████████████▊ 11 301 301 [ 2.0, 3.0) ┤████████████████████████▋ 18 828 717 [ 3.0, 4.0) ┤██████████████▊ 11 301 301 [ 4.0, 5.0) ┤█▌ 1 121 121 [ 5.0, 6.0) ┤██████████████▊ 11 301 301 [ 6.0, 7.0) ┤█▌ 1 121 121 [ 7.0, 8.0) ┤██████████████▋ 11 211 211 [ 8.0, 9.0) ┤████████████████████████████ 21 391 392 [ 9.0, 10.0) ┤██████████████▊ 11 301 301 └ ┘ Frequency
Perl
# 20240927 Perl programming solution
use strict;
use warnings;
use constant I
=> [ qw( zero one two three four five six seven eight nine ten eleven twelve
thirteen fourteen fifteen sixteen seventeen eighteen nineteen ) ];
use constant X
=> [ qw( 0 X twenty thirty forty fifty sixty seventy eighty ninety ) ];
use constant C => [map { I->[$_] . ' hundred' } 0..19];
use constant M => [
map { $_ . ' thousand' } (0),
map { $_ . 'illion' } ('m', 'b', 'tr', 'quadr', 'quint', 'sext', 'sept', 'oct', 'non',
map { ('', 'un', 'duo', 'tre', 'quattuor', 'quin', 'sex', 'septen', 'octo', 'novem') }
qw(dec vigint trigint quadragint quinquagint sexagint septuagint octogint nonagint))
];
sub int_name {
my ($num) = @_;
return "negative " . int_name(-$num) if $num < 0;
return I->[0] if $num == 0;
my ($m, @parts) = 0;
while ($num > 0) {
my $chunk = $num % 1000;
my $hundreds = int($chunk / 100);
my $tens = int(($chunk % 100) / 10);
my $ones = $chunk % 10;
if ($hundreds || $tens || $ones) {
my @chunk_parts;
push @chunk_parts, C->[$hundreds] if $hundreds;
if ($tens == 1) {
push @chunk_parts, I->[$ones + 10];
} else {
push @chunk_parts, X->[$tens] if $tens;
push @chunk_parts, I->[$ones] if $ones;
}
push @chunk_parts, M->[$m] if $m;
unshift @parts, join " ", @chunk_parts;
}
$num = int($num / 1000);
$m++;
}
return join ", ", @parts;
}
my ($i, $c, $limit, $prev, @nums, @lastDigs) = (0, 0, 1000, int_name(0));
while ($limit <= 1e4) {
my $next = int_name($i + 1);
if (substr($prev, -1) eq substr($next, 0, 1)) {
if ($c < 50) { push @nums, $i }
$lastDigs[$i % 10]++;
$c++;
if ($c == 50) {
print "First 50 numbers:\n";
for (my $j = 0; $j < @nums; $j += 10) {
printf "%4s", $_ for @nums[$j .. $j + 9];
print "\n";
}
print "\n";
} elsif ($c == $limit) {
print "The $c-th number is $i.\n";
print "Breakdown by last digit of first $c-th numbers\n";
print "N Freq\n";
my $max = (sort { $b <=> $a } @lastDigs)[0];
for my $d (0..9) {
printf "%d %4s %s\n", $d, $lastDigs[$d], '█' x int($lastDigs[$d] / $max * 72);
}
print "\n";
$limit *= 10;
}
}
$prev = $next;
$i++;
}
You may Attempt This Online!
Phix
with javascript_semantics string s99 = repeat('?',100), // starting char of 0..99 e99 = repeat('?',100) // ending char of 0..99 for n=0 to 99 do string s = ordinal(n,true) s99[n+1] = s[1] e99[n+1] = s[$] end for sequence d_count = repeat(0,10) -- nb 0s in [1] .. 9s in [10] integer this_end = 'o', // zero next_to_show = 1e3, count = 0, n = 0; printf(1,"The first 50 numbers:\n") while count<1e6 do integer next = n+1 while next>=1000 do next = floor(next/1000) end while if next>=100 then next = floor(next/100) end if integer next_start = s99[next+1] // (wrong for 0, but no e*illion anyway) if next_start=this_end then d_count[remainder(n,10)+1] += 1 count += 1 if count <= 50 then printf(1," %4d%n",{n,remainder(count,10)=0}) end if if count = next_to_show then printf(1,"\nThe %,dth number is: %,d\n",{count,n}) printf(1,"Breakdown by final digit of the numbers:\n") integer mv = max(d_count) for i,d in d_count do printf(1,"%2d: %s (%d)\n",{i-1,repeat('*',round(d*60/mv)),d}) end for next_to_show *= 10 end if end if n += 1 integer n99 = remainder(n,100) // from table or hundred,thousand -> 'd', million (etc) -> 'n': this_end = iff(n99>0?e99[n99+1]:iff(remainder(n,1e6)=0?'n':'d')) end while
- Output:
The first 50 numbers: 0 18 28 38 79 81 83 85 97 102 122 132 142 152 162 172 182 192 208 228 238 248 258 268 278 288 298 308 328 338 348 358 368 378 388 398 799 801 803 805 809 812 821 823 825 829 831 833 835 839 The 1,000th number is: 10,988 Breakdown by final digit of the numbers: 0: ** (12) 1: ********************** (111) 2: ********************** (110) 3: ********************** (111) 4: ** (11) 5: ********************** (111) 6: ** (11) 7: ********************** (111) 8: ************************************************************ (301) 9: ********************** (111) The 10,000th number is: 106,652 Breakdown by final digit of the numbers: 0: *** (122) 1: ********************************* (1301) 2: ********************* (829) 3: ********************************* (1301) 4: *** (121) 5: ********************************* (1301) 6: *** (121) 7: ****************************** (1211) 8: ************************************************************ (2392) 9: ********************************* (1301) The 100,000th number is: 1,095,542 Breakdown by final digit of the numbers: 0: *** (1122) 1: ******************************** (11301) 2: ***************************************************** (18829) 3: ******************************** (11301) 4: *** (1121) 5: ******************************** (11301) 6: *** (1121) 7: ******************************* (11211) 8: ************************************************************ (21392) 9: ******************************** (11301) The 1,000,000th number is: 10,984,428 Breakdown by final digit of the numbers: 0: ** (11123) 1: ********************** (111301) 2: ********************** (110230) 3: ********************** (111301) 4: ** (11121) 5: ********************** (111301) 6: ** (11121) 7: ********************** (111211) 8: ************************************************************ (299990) 9: ********************** (111301)
You can trivially extend the limit to 1e8, on 64-bit or change next_to_show (etc) to atom, and in about 75s, a tad slow, also get:
The 10,000,000th number is: 106,650,962 Breakdown by final digit of the numbers: 0: *** (121134) 1: ********************************* (1301301) 2: ********************* (828817) 3: ********************************* (1301301) 4: *** (121121) 5: ********************************* (1301301) 6: *** (121121) 7: ****************************** (1211211) 8: ************************************************************ (2391392) 9: ********************************* (1301301) The 100,000,000th number is: 1,095,538,742 Breakdown by final digit of the numbers: 0: *** (1121234) 1: ******************************** (11301301) 2: ***************************************************** (18828717) 3: ******************************** (11301301) 4: *** (1121121) 5: ******************************** (11301301) 6: *** (1121121) 7: ******************************* (11211211) 8: ************************************************************ (21391392) 9: ******************************** (11301301)
Python
""" rosettacode.org, wiki task regarding OEIS sequence A363659 """
from collections import Counter
from ascii_graph import Pyasciigraph
from num2words import num2words
sspelledcache = [num2words(n) for n in range(1000)]
firstcache, lastcache = [s[0] for s in spelledcache], [s[-1] for s in spelledcache]
def qualifies(n):
lastchar = lastcache[n % 1000] if n % 1000 > 0 else 'o' if n == 0 else \
'n' if n % 1_000_000 == 0 else 'd'
n += 1
j = 0
while n > 0:
n, j = divmod(n, 1000)
return firstcache[j] == lastchar
def testqualifies():
""" Test the generation of OEIS sequence A363659 """
ncount = 0
lastdigits = Counter()
print("First 50 qualifying numbers:")
for num in range(1_000_000_000):
if qualifies(num):
ncount += 1
lastdigits.update([num % 10])
if ncount < 51:
print(f'{num:5}', end='\n' if ncount % 10 == 0 else '')
elif ncount in [10**3, 10**4, 10**5, 10**6]:
print(f'\nThe {num2words(ncount)}th number is {num:,}.')
print('Breakdown by last digit of the qualifiers up to this:')
graph = Pyasciigraph()
for line in graph.graph('Frequencies', sorted(lastdigits.items())):
print(line)
print()
if ncount == 1_000_000:
break
if __name__ == '__main__':
testqualifies()
- Output:
First 50 qualifying numbers: 0 18 28 38 79 81 83 85 97 102 122 132 142 152 162 172 182 192 208 228 238 248 258 268 278 288 298 308 328 338 348 358 368 378 388 398 799 801 803 805 809 812 821 823 825 829 831 833 835 839 The one thousandth number is 10,988. Breakdown by last digit of the qualifiers up to this: Frequencies ############################################################################### ██ 12 0 ██████████████████████████ 111 1 █████████████████████████ 110 2 ██████████████████████████ 111 3 ██ 11 4 ██████████████████████████ 111 5 ██ 11 6 ██████████████████████████ 111 7 ███████████████████████████████████████████████████████████████████████ 301 8 ██████████████████████████ 111 9 The ten thousandth number is 106,652. Breakdown by last digit of the qualifiers up to this: Frequencies ############################################################################### ███ 122 0 ██████████████████████████████████████ 1301 1 ████████████████████████ 829 2 ██████████████████████████████████████ 1301 3 ███ 121 4 ██████████████████████████████████████ 1301 5 ███ 121 6 ███████████████████████████████████ 1211 7 ██████████████████████████████████████████████████████████████████████ 2392 8 ██████████████████████████████████████ 1301 9 The one hundred thousandth number is 1,095,542. Breakdown by last digit of the qualifiers up to this: Frequencies ############################################################################### ███ 1122 0 ████████████████████████████████████ 11301 1 ████████████████████████████████████████████████████████████ 18829 2 ████████████████████████████████████ 11301 3 ███ 1121 4 ████████████████████████████████████ 11301 5 ███ 1121 6 ████████████████████████████████████ 11211 7 █████████████████████████████████████████████████████████████████████ 21392 8 ████████████████████████████████████ 11301 9 The one millionth number is 10,984,428. Breakdown by last digit of the qualifiers up to this: Frequencies ############################################################################### ██ 11123 0 █████████████████████████ 111301 1 ████████████████████████ 110230 2 █████████████████████████ 111301 3 ██ 11121 4 █████████████████████████ 111301 5 ██ 11121 6 █████████████████████████ 111211 7 ████████████████████████████████████████████████████████████████████ 299990 8 █████████████████████████ 111301 9
Raku
# 20230713 Raku programming solution
###### https://rosettacode.org/wiki/Number_names#Raku
constant @I = <zero one two three four five six seven eight nine
ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen>;
constant @X = <0 X twenty thirty forty fifty sixty seventy eighty ninety>;
constant @C = @I X~ ' hundred';
constant @M = (<0 thousand>,
((<m b tr quadr quint sext sept oct non>,
(map { ('', <un duo tre quattuor quin sex septen octo novem>).flat X~ $_ },
<dec vigint trigint quadragint quinquagint sexagint septuagint octogint nonagint>),
'cent').flat X~ 'illion')).flat;
sub int-name ($num) {
if $num.substr(0,1) eq '-' { return "negative {int-name($num.substr(1))}" }
if $num eq '0' { return @I[0] }
my $m = 0;
return join ', ', reverse gather for $num.flip.comb(/\d ** 1..3/) {
my ($i,$x,$c) = .comb».Int;
if $i or $x or $c {
take join ' ', gather {
if $c { take @C[$c] }
if $x and $x == 1 { take @I[$i+10] }
else {
if $x { take @X[$x] }
if $i { take @I[$i] }
}
take @M[$m] // die "WOW! ZILLIONS!\n" if $m;
}
}
$m++;
}
}
######
my ($i, $c, $limit, $prev, @nums, @lastDigs) = 0, 0, 1000, int-name(0);
while $limit <= 1e4 {
my $next = int-name $i+1;
if $prev.substr(*-1) eq $next.substr(0,1) {
if ($c < 50) { @nums.append: $i };
@lastDigs[$i % 10] += 1;
$c++;
if $c == 50 {
say "First 50 numbers:";
say [~] $_>>.fmt('%4s') for @nums.rotor(10);
say();
} elsif $c == $limit {
print "The {$c}th number is $i.\n";
say "Breakdown by last digit of first {$c}th numbers";
say 'N Freq';
for 0..9 -> $d {
say "$d {@lastDigs[$d].fmt('%4s')} ",
'█' x (@lastDigs[$d]/@lastDigs.max*72).Int;
}
say();
$limit *= 10
}
}
$prev = $next;
$i++;
}
You may Attempt This Online!
Wren
Simple brute force approach.
import "./fmt" for Name, Fmt
import "./math" for Nums
var i = 0
var c = 0
var nums = []
var lastDigs = List.filled(10, 0)
var labels = (0..9).map { |d| d.toString }.toList
var prev = Name.fromNum(0) // "zero"
var limit = 1000
while (limit <= 1e6) {
var next = Name.fromNum(i+1)
if (prev[-1] == next[0]) {
if (c < 50) nums.add(i)
var ld = i % 10
lastDigs[ld] = lastDigs[ld] + 1
c = c + 1
if (c == 50) {
System.print("First 50 numbers:")
Fmt.tprint("$3d ", nums, 10)
System.print()
} else if (c == limit) {
Fmt.print("The $,r number is $,d.\n", c, i)
var title = Fmt.swrite("Breakdown by last digit of first $,d numbers", c)
Nums.barChart(title, 80, labels, lastDigs)
System.print()
limit = limit * 10
}
}
prev = next
i = i + 1
}
- Output:
First 50 numbers: 0 18 28 38 79 81 83 85 97 102 122 132 142 152 162 172 182 192 208 228 238 248 258 268 278 288 298 308 328 338 348 358 368 378 388 398 799 801 803 805 809 812 821 823 825 829 831 833 835 839 The 1,000th number is 10,988. Breakdown by last digit of first 1,000 numbers -------------------------------------------------------------------------------- 0 ■■ 12 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 2 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 110 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 4 ■■ 11 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 6 ■■ 11 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 301 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■■ 111 -------------------------------------------------------------------------------- The 10,000th number is 106,652. Breakdown by last digit of first 10,000 numbers -------------------------------------------------------------------------------- 0 ■■■ 122 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 2 ■■■■■■■■■■■■■■■■■■■■■■■■■ 829 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 4 ■■■ 121 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 6 ■■■ 121 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1211 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 2392 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 1301 -------------------------------------------------------------------------------- The 100,000th number is 1,095,542. Breakdown by last digit of first 100,000 numbers -------------------------------------------------------------------------------- 0 ■■■ 1122 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 2 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 18829 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 4 ■■■ 1121 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 6 ■■■ 1121 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11211 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 21392 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 11301 -------------------------------------------------------------------------------- The 1,000,000th number is 10,984,428. Breakdown by last digit of first 1,000,000 numbers -------------------------------------------------------------------------------- 0 ■■ 11123 1 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 2 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 110230 3 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 4 ■■ 11121 5 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 6 ■■ 11121 7 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 111211 8 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 299990 9 ■■■■■■■■■■■■■■■■■■■■■■■■■■ 111301 --------------------------------------------------------------------------------