Perl Weekly Challenge 148: Eban Numbers

by Abigail

Challenge

Write a script to generate all Eban Numbers <= 100.

An Eban number is a number that has no letter ‘e’ in it when the number is spelled in English (American or British).

Example

2, 4, 6, 30, 32 are the first 5 Eban numbers.

Discussion

This is sequence A006933 in The On-Line Encyclopedia of Integer Sequences.

Given that we're asked to produce the first N numbers of a sequence, for a fixed N, an easy solution would be:

say "2 4 6 30 32 34 36 40 42 44 46 50 52 54 56 60 62 64 66";

Solution

A solution would be to translate the numbers into English, check whether the number contains an "e", and print the numbers which don't contain an "e".

But that is doing more work than needed.

Let's first look at the structure of English numbers. Single digit numbers consist of a single word. Double digit numbers (starting from 20) all have the form "footy-bar", where the "footy" is the same for all numbers starting with the same digit, and bar is the word for the last digit. Numbers 13 till 19 all end in teen. And we have special words for 10, 11, 12 and 100.

Look at the following table:

Number English Has "e"
0 ZERO Y
1 ONE Y
2 TWO N
3 THREE Y
4 FOUR N
5 FIVE Y
6 SIX N
7 SEVEN Y
8 EIGHT Y
9 NINE Y
10 TEN Y
11 ELEVEN Y
12 TWELVE Y
1? *-TEEN Y
2? TWENTY-* Y
3? THIRTY-* N
4? FORTY-* N
5? FIFTY-* N
6? SIXTY-* N
7? SEVENTY-* Y
8? EIGHTY-* Y
9? NINETY-* Y
100 HUNDRED Y

From this table, we can conclude a number (not exceeding 100) contains an "e" iff the number contains a 1, a 7, an 8, or a 9, or if the number ends with a 3 or a 5, or if the number starts with a 2 and is followed by another digit, or if the number is 0.

So, we can take this list of numbers up to 100 and use the conclusion reached above to filter out the numbers containing an "e". Either using a regular expression, or by inspecting the individual digits.

Perl

In Perl, this is just a one liner:

say join " " => grep {!/^0$ | [1789] | ^2. | [35]$/x} 0 .. 100;

Find the full program on GitHub.

C

C doesn't have native regular expressions. So, we will just get the tens and unit digits, and do the checks:

int main (void) {
    for (int i = 0; i <= 100; i ++) {
        int u = i % 10;
        int t = i / 10;
        if (!(i == 0 || t == 1 || u == 1 || t == 7 || u == 7
                     || t == 8 || u == 8 || t == 9 || u == 9
                     || t == 2 || u == 3 || u == 5 || i == 100)) {
            printf ("%d ", i);
        }
    }
    printf ("\n");
}

Find the full program on GitHub.

Other languages

We also have implementation in a bunch of other languages, which all either use a regular expression (as the Perl solution does), or inspect the digits (as the C solution does):

AWK, Bash, bc, Go, Java, Lua, Node.js, Pascal, Python, R, Ruby, Tcl, and Scheme.


Please leave any comments as a GitHub issue.