user
Definition

An **autogram** is a sentence that describes itself in the sense of providing an inventory of its own characters. An essential feature is the use of full cardinal number names such as "one", "two", etc., in recording character counts.

Autograms are also called 'self-enumerating' or 'self-documenting' sentences. Whilst they usually just count letters of the alphabet, they can also count punctuation symbols as well.

Example

If punctuation is ignored, the following sentence is an autogram:

```
This sentence employs two a's, two c's, two d's, twenty-eight e's, five f's, three g's, eight h's, eleven i's, three l's, two m's, thirteen n's, nine o's, two p's, five r's, twenty-five s's, twenty-three t's, six v's, ten w's, two x's, five y's, and one z.

```

Task

Write a routine in your language to check whether or not a given sentence is an autogram and use it to test the above example (Sentence 1.) and also the following sentences:

2. This sentence employs two a's, two c's, two d's, twenty eight e's, five f's, three g's, eight h's, eleven i's, three l's, two m's, thirteen n's, nine o's, two p's, five r's, twenty five s's, twenty three t's, six v's, ten w's, two x's, five y's, and one z.

3. Only the fool would take trouble to verify that his sentence was composed of ten a's, three b's, four c's, four d's, forty-six e's, sixteen f's, four g's, thirteen h's, fifteen i's, two k's, nine l's, four m's, twenty-five n's, twenty-four o's, five p's, sixteen r's, forty-one s's, thirty-seven t's, ten u's, eight v's, eight w's, four x's, eleven y's, twenty-seven commas, twenty-three apostrophes, seven hyphens and, last but not least, a single !

4. This pangram contains four as, one b, two cs, one d, thirty es, six fs, five gs, seven hs, eleven is, one j, one k, two ls, two ms, eighteen ns, fifteen os, two ps, one q, five rs, twenty-seven ss, eighteen ts, two us, seven vs, eight ws, two xs, three ys, & one z.

5. This sentence contains one hundred and ninety-seven letters: four a's, one b, three c's, five d's, thirty-four e's, seven f's, one g, six h's, twelve i's, three l's, twenty-six n's, ten o's, ten r's, twenty-nine s's, nineteen t's, six u's, seven v's, four w's, four x's, five y's, and one z.

6. Thirteen e's, five f's, two g's, five h's, eight i's, two l's, three n's, six o's, six r's, twenty s's, twelve t's, three u's, four v's, six w's, four x's, two y's.

7. Fifteen e's, seven f's, four g's, six h's, eight i's, four n's, five o's, six r's, eighteen s's, eight t's, four u's, three v's, two w's, three x's.

8. Sixteen e's, five f's, three g's, six h's, nine i's, five n's, four o's, six r's, eighteen s's, eight t's, three u's, three v's, two w's, four z's.

Punctuation should be ignored in all cases except for sentences number 3. and 7. For task 3 and 7, punctuation counts must be checked, and some ('comma', 'apostrophe', 'hyphen') punctuation may be represented in the autogram using the spelled out english names for the punctuation and the checker must respect the inconsistent use of apostrophes in the spellings of the counts (while still counting apostrophes accurately) and must accept 'single' as a synonym for 'one'.

Note that the only difference between sentences 1. and 2. is that there are no hyphens in the latter.

Assumptions

* Ignore capitalization.

* Never count spaces or full stops.

If it helps you may also make the following simplifying assumptions:

* No sentence will be such that there are more than 99 instances of any countable character.

* If punctuation is to be allowed for, only commas, hyphens, apostrophes and exclamation marks need be counted.

Reference

* Wikipedia: Autogram

Other tasks related to string operations:

Metrics

* Array length
* String length
* Copy a string
* Empty string  (assignment)

Counting

* Word frequency
* Letter frequency
* Jewels and stones
* I before E except after C
* Bioinformatics/base count
* Count occurrences of a substring
* Count how many vowels and consonants occur in a string

Remove/replace

* XXXX redacted
* Conjugate a Latin verb
* Remove vowels from a string
* String interpolation (included)
* Strip block comments
* Strip comments from a string
* Strip a set of characters from a string
* Strip whitespace from a string -- top and tail
* Strip control codes and extended characters from a string

Anagrams/Derangements/shuffling

* Word wheel
* ABC problem
* Sattolo cycle
* Knuth shuffle
* Ordered words
* Superpermutation minimisation
* Textonyms (using a phone text pad)
* Anagrams
* Anagrams/Deranged anagrams
* Permutations/Derangements

Find/Search/Determine

* ABC words
* Odd words
* Word ladder
* Semordnilap
* Word search
* Wordiff  (game)
* String matching
* Tea cup rim text
* Alternade words
* Changeable words
* State name puzzle
* String comparison
* Unique characters
* Unique characters in each string
* Extract file extension
* Levenshtein distance
* Palindrome detection
* Common list elements
* Longest common suffix
* Longest common prefix
* Compare a list of strings
* Longest common substring
* Find common directory path
* Words from neighbour ones
* Change e letters to i in words
* Non-continuous subsequences
* Longest common subsequence
* Longest palindromic substrings
* Longest increasing subsequence
* Words containing "the" substring
* Sum of the digits of n is substring of n
* Determine if a string is numeric
* Determine if a string is collapsible
* Determine if a string is squeezable
* Determine if a string has all unique characters
* Determine if a string has all the same characters
* Longest substrings without repeating characters
* Find words which contains all the vowels
* Find words which contain the most consonants
* Find words which contains more than 3 vowels
* Find words whose first and last three letters are equal
* Find words with alternating vowels and consonants

Formatting

* Substring
* Rep-string
* Word wrap
* String case
* Align columns
* Literals/String
* Repeat a string
* Brace expansion
* Brace expansion using ranges
* Reverse a string
* Phrase reversals
* Comma quibbling
* Special characters
* String concatenation
* Substring/Top and tail
* Commatizing numbers
* Reverse words in a string
* Suffixation of decimal numbers
* Long literals, with continuations
* Numerical and alphabetical suffixes
* Abbreviations, easy
* Abbreviations, simple
* Abbreviations, automatic

Song lyrics/poems/Mad Libs/phrases

* Mad Libs
* Magic 8-ball
* 99 bottles of beer
* The Name Game (a song)
* The Old lady swallowed a fly
* The Twelve Days of Christmas

Tokenize

* Text between
* Tokenize a string
* Word break problem
* Tokenize a string with escaping
* Split a character string based on change of character

Sequences

* Show ASCII table
* De Bruijn sequences
* Summarize and say sequence
* Generate lower case ASCII alphabet
assistant
Slightly fragile, especially for non-letter character counts, but good enough for here.

Using Text::Wrap from the ecosystem. Install command: `zef install -v git://github.com/jkramer/p6-Text-Wrap.git`.

```
my %nums = :0zero, :1one, :2two, :3three, :4four, :5five, :6six, :7seven, :8eight, :9nine, :10ten, :11eleven,
    :12twelve, :13thirteen, :14fourteen, :15fifteen, :16sixteen, :17seventeen, :18eighteen, :19nineteen,
    :20twenty, :30thirty, :40forty, :50fifty, :60sixty, :70seventy, :80eighty, :90ninety, :100hundred, :1single;

sub whitespace  { $^a.subst(:g, /\s|'.'/, '') }
sub non-letters { $^a.subst(:g, /\W/, '') }

my @tests =
    (&non-letters, "This sentence employs two a's, two c's, two d's, twenty-eight e's, five f's, three g's, eight h's, eleven i's, three l's, two m's, thirteen n's, nine o's, two p's, five r's, twenty-five s's, twenty-three t's, six v's, ten w's, two x's, five y's, and one z."),
    (&non-letters, "This sentence employs two a's, two c's, two d's, twenty eight e's, five f's, three g's, eight h's, eleven i's, three l's, two m's, thirteen n's, nine o's, two p's, five r's, twenty five s's, twenty three t's, six v's, ten w's, two x's, five y's, and one z."),
    (&whitespace,  "Only the fool would take trouble to verify that his sentence was composed of ten a's, three b's, four c's, four d's, forty-six e's, sixteen f's, four g's, thirteen h's, fifteen i's, two k's, nine l's, four m's, twenty-five n's, twenty-four o's, five p's, sixteen r's, forty-one s's, thirty-seven t's, ten u's, eight v's, eight w's, four x's, eleven y's, twenty-seven commas, twenty-three apostrophes, seven hyphens and, last but not least, a single !"),
    (&non-letters, "This pangram contains four as, one b, two cs, one d, thirty es, six fs, five gs, seven hs, eleven is, one j, one k, two ls, two ms, eighteen ns, fifteen os, two ps, one q, five rs, twenty-seven ss, eighteen ts, two us, seven vs, eight ws, two xs, three ys, & one z."),
    (&non-letters, "This sentence contains one hundred and ninety-seven letters: four a's, one b, three c's, five d's, thirty-four e's, seven f's, one g, six h's, twelve i's, three l's, twenty-six n's, ten o's, ten r's, twenty-nine s's, nineteen t's, six u's, seven v's, four w's, four x's, five y's, and one z."),
    (&non-letters, "Thirteen e's, five f's, two g's, five h's, eight i's, two l's, three n's, six o's, six r's, twenty s's, twelve t's, three u's, four v's, six w's, four x's, two y's."),
    (&whitespace,  "Fifteen e's, seven f's, four g's, six h's, eight i's, four n's, five o's, six r's, eighteen s's, eight t's, four u's, three v's, two w's, three x's."),
    (&non-letters, "Sixteen e's, five f's, three g's, six h's, nine i's, five n's, four o's, six r's, eighteen s's, eight t's, three u's, three v's, two w's, four z's.")
;

use Text::Wrap;

say '=' x 100;

for @tests ->  (&filter, $text) {

    # Original
    say wrap-text :100width, $text;

    say "\nFiltering out " ~ &filter.name ~ ':';

    # Semi-bogus and somewhat fragile names to numbers conversion.
    my $str = $text.lc;
    for %nums.kv -> $word, $number { $str ~~ s:g/ <|w> $word <|w> /$number/ }
    $str ~~ s:g/ (\d)<ws>['and'|'-']<ws>(\d)  /$0 $1/;
    $str ~~ s:g/ <|w>(\d ** 2)<ws>(\d ** 2) <|w> /{ $0 × 100 + $1}/;
    $str ~~ s:g/ ( [\d+<ws>]* \d+ ) /{[+] $0.split: ' '}/;

    # Build a hash of claimed characters.
    my %claim = flat $str.lc.match(:g, /\d+ <:ws> ['comma'|'apostrophe'|'hyphen'|.]/)».split(' ')»[1,0]».pairup;
    for <comma , hyphen - apostrophe '> #`['] -> $word, $symbol { %claim{$symbol} = %claim{$word}:delete if %claim{$word} }
    say "\nClaimed character counts:\n" ~ wrap-text :100width, %claim.sort( ~*.key ).map( { sprintf "%s\(%d)", .key, .value } ).join: ' ';

    # And of the actual character counts.
    my %count = &filter($text).lc.comb.Bag.hash;
    say "\nActual:\n" ~ wrap-text :100width, %count.sort( ~*.key ).map( { sprintf "%s\(%d)", .key, .value } ).join: ' ';

    # And compare them
    say "\nAutogram? " ~
    quietly (so all %count.map: { .value == %claim{.key} }) && (so all %claim.map: { .value == %count{.key} });

    say '=' x 100;
}

```

Output:

```
====================================================================================================
This sentence employs two a's, two c's, two d's, twenty-eight e's, five f's, three g's, eight h's,
eleven i's, three l's, two m's, thirteen n's, nine o's, two p's, five r's, twenty-five s's,
twenty-three t's, six v's, ten w's, two x's, five y's, and one z.

Filtering out non-letters:

Claimed character counts:
a(2) c(2) d(2) e(28) f(5) g(3) h(8) i(11) l(3) m(2) n(13) o(9) p(2) r(5) s(25) t(23) v(6) w(10) x(2)
y(5) z(1)

Actual:
a(2) c(2) d(2) e(28) f(5) g(3) h(8) i(11) l(3) m(2) n(13) o(9) p(2) r(5) s(25) t(23) v(6) w(10) x(2)
y(5) z(1)

Autogram? True
====================================================================================================
This sentence employs two a's, two c's, two d's, twenty eight e's, five f's, three g's, eight h's,
eleven i's, three l's, two m's, thirteen n's, nine o's, two p's, five r's, twenty five s's, twenty
three t's, six v's, ten w's, two x's, five y's, and one z.

Filtering out non-letters:

Claimed character counts:
a(2) c(2) d(2) e(28) f(5) g(3) h(8) i(11) l(3) m(2) n(13) o(9) p(2) r(5) s(25) t(23) v(6) w(10) x(2)
y(5) z(1)

Actual:
a(2) c(2) d(2) e(28) f(5) g(3) h(8) i(11) l(3) m(2) n(13) o(9) p(2) r(5) s(25) t(23) v(6) w(10) x(2)
y(5) z(1)

Autogram? True
====================================================================================================
Only the fool would take trouble to verify that his sentence was composed of ten a's, three b's,
four c's, four d's, forty-six e's, sixteen f's, four g's, thirteen h's, fifteen i's, two k's, nine
l's, four m's, twenty-five n's, twenty-four o's, five p's, sixteen r's, forty-one s's, thirty-seven
t's, ten u's, eight v's, eight w's, four x's, eleven y's, twenty-seven commas, twenty-three
apostrophes, seven hyphens and, last but not least, a single !

Filtering out whitespace:

Claimed character counts:
!(1) '(23) ,(27) -(7) a(10) b(3) c(4) d(4) e(46) f(16) g(4) h(13) i(15) k(2) l(9) m(4) n(25) o(24)
p(5) r(16) s(41) t(37) u(10) v(8) w(8) x(4) y(11)

Actual:
!(1) '(23) ,(27) -(7) a(10) b(3) c(4) d(4) e(46) f(16) g(4) h(13) i(15) k(2) l(9) m(4) n(25) o(24)
p(5) r(16) s(41) t(37) u(10) v(8) w(8) x(4) y(11)

Autogram? True
====================================================================================================
This pangram contains four as, one b, two cs, one d, thirty es, six fs, five gs, seven hs, eleven
is, one j, one k, two ls, two ms, eighteen ns, fifteen os, two ps, one q, five rs, twenty-seven ss,
eighteen ts, two us, seven vs, eight ws, two xs, three ys, & one z.

Filtering out non-letters:

Claimed character counts:
a(4) b(1) c(2) d(1) e(30) f(6) g(5) h(7) i(11) j(1) k(1) l(2) m(2) n(18) o(15) p(2) q(1) r(5) s(27)
t(18) u(2) v(7) w(8) x(2) y(3) z(1)

Actual:
a(4) b(1) c(2) d(1) e(30) f(6) g(5) h(7) i(11) j(1) k(1) l(2) m(2) n(18) o(15) p(2) q(1) r(5) s(27)
t(18) u(2) v(7) w(8) x(2) y(3) z(1)

Autogram? True
====================================================================================================
This sentence contains one hundred and ninety-seven letters: four a's, one b, three c's, five d's,
thirty-four e's, seven f's, one g, six h's, twelve i's, three l's, twenty-six n's, ten o's, ten r's,
twenty-nine s's, nineteen t's, six u's, seven v's, four w's, four x's, five y's, and one z.

Filtering out non-letters:

Claimed character counts:
a(4) b(1) c(3) d(5) e(34) f(7) g(1) h(6) i(12) l(3) n(26) o(10) r(10) s(29) t(19) u(6) v(7) w(4)
x(4) y(5) z(1)

Actual:
a(4) b(1) c(3) d(5) e(34) f(7) g(1) h(6) i(12) l(3) n(26) o(10) r(10) s(29) t(19) u(6) v(7) w(4)
x(4) y(5) z(1)

Autogram? True
====================================================================================================
Thirteen e's, five f's, two g's, five h's, eight i's, two l's, three n's, six o's, six r's, twenty
s's, twelve t's, three u's, four v's, six w's, four x's, two y's.

Filtering out non-letters:

Claimed character counts:
e(13) f(5) g(2) h(5) i(8) l(2) n(3) o(6) r(6) s(20) t(12) u(3) v(4) w(6) x(4) y(2)

Actual:
e(13) f(5) g(2) h(5) i(8) l(2) n(3) o(6) r(6) s(20) t(12) u(3) v(4) w(6) x(4) y(2)

Autogram? True
====================================================================================================
Fifteen e's, seven f's, four g's, six h's, eight i's, four n's, five o's, six r's, eighteen s's,
eight t's, four u's, three v's, two w's, three x's.

Filtering out whitespace:

Claimed character counts:
e(15) f(7) g(4) h(6) i(8) n(4) o(5) r(6) s(18) t(8) u(4) v(3) w(2) x(3)

Actual:
'(14) ,(13) e(15) f(7) g(4) h(6) i(8) n(4) o(5) r(6) s(18) t(8) u(4) v(3) w(2) x(3)

Autogram? False
====================================================================================================
Sixteen e's, five f's, three g's, six h's, nine i's, five n's, four o's, six r's, eighteen s's,
eight t's, three u's, three v's, two w's, four z's.

Filtering out non-letters:

Claimed character counts:
e(16) f(5) g(3) h(6) i(9) n(5) o(4) r(6) s(18) t(8) u(3) v(3) w(2) z(4)

Actual:
e(16) f(5) g(3) h(6) i(9) n(5) o(4) r(6) s(18) t(8) u(3) v(3) w(2) x(3) z(1)

Autogram? False
====================================================================================================
```