30
\$\begingroup\$

Write a program or function that takes two inputs:

  1. A text message
  2. The dictionary of English language, as it appears in this Github file (containing about 60000 words)

and outputs the number of spelling errors in the message (see below for definition and test cases).

You can receive the dictionary as a parameter to your function, as a pre-defined file that your program expects to find, as hard-coded data in your code, or in any other sensible manner.


Your code should itself look like a text message, with a minimal number of spelling errors. So, you will calculate the score of your code by feeding it to itself as input.

The winner is code that has the lowest score (minimal possible score is 0). If there are several answers with the same score, the winner is decided by code size (in characters). If two answers are still tied, the winner is the earlier one.


If required, you can assume the input message to be ASCII (bytes 32...126) with newlines encoded in a conventional manner (1 byte "10" or 2 bytes "13 10"), and non-empty. However, if your code has non-ASCII characters, it should also support non-ASCII input (so it can calculate its own score).

Characters are subdivided into the following classes:

  • Letters a...z and A...Z
  • Whitespace (defined here as either the space character or the newline character)
  • Punctuation . , ; : ! ?
    • Sentence-ending . ! ?
  • Garbage (all the rest)

A word is defined as a sequence of letters, which is maximal (i.e. neither preceded nor followed by a letter).

A sentence is defined as a maximal sequence of characters that are not sentence-ending.

A character is a spelling error if it violates any of the spelling rules:

  1. A letter must belong to a dictionary word (or, in other words: each word of length N that doesn't appear in the dictionary counts as N spelling errors)
  2. The first character in a sentence, ignoring any initial whitespace characters, must be an uppercase letter
  3. All letters must be lowercase, except those specified by the previous rule
  4. A punctuation character is only allowed after a letter or garbage
  5. A newline character is only allowed after a sentence-ending character
  6. Whitespace characters are not allowed in the beginning of the message and after whitespace characters
  7. There should be no garbage (or, in other words: each garbage character counts is a spelling error)

In addition, the last sentence must be either empty or consist of exactly one newline character (i.e. the message should end with a sentence-ending character and an optional newline - let's call it rule 8).

Test cases (below each character is a rule that it violates; after => is the required answer):

Here is my 1st test case!!
           711           4                => 4

main(){puts("Hello World!");}
2   777    883     3     77 78            => 12

  This message starts with two spaces
66                                   8    => 3

What ? No apostrophe's??
     4              71 4                  => 4

  Extra   whitespace   is   BAD!
66      661111111111 66   66333           => 21

Several
lines?
Must be used only to separate sentences.
                                          => 1 (first linebreak is en error: rule 5)

"Come here," he said.
73         7                              => 3 (sentence starts with '"', not 'C')
\$\endgroup\$
15
  • 2
    \$\begingroup\$ I was expecting a bunch of loopholes, but you've seemed to cover them all. +1 from me. \$\endgroup\$ Commented Jan 22, 2017 at 16:06
  • 4
    \$\begingroup\$ I think SPL is the winner here. \$\endgroup\$ Commented Jan 22, 2017 at 16:46
  • 2
    \$\begingroup\$ .Gertrude is even better. Commands are arbitrary sentences, only word count and average word length matter. \$\endgroup\$
    – Rainer P.
    Commented Jan 22, 2017 at 18:03
  • \$\begingroup\$ I thought "Applescript" when I saw this. Don't have a Mac, though. \$\endgroup\$ Commented Jan 22, 2017 at 20:26
  • 1
    \$\begingroup\$ @PeterTaylor I don't want the rules to become too complicated. Your test case is fine; I added it to my post. \$\endgroup\$
    – anatolyg
    Commented Jan 23, 2017 at 9:14

3 Answers 3

6
\$\begingroup\$

Perl 6, 134 spelling errors

my token punctuation {<[.,;:!?]>}
my \text = slurp; my \mistakes=[]; for split /\.|\!|\?/, text { for .trim.match: :g, /<:letter>+/ -> \word { (append mistakes, .comb when none words slurp pi given lc word) or (push mistakes, $_ if ((.from or word.from) xor m/<[a..z]>/) for word.match: :g, /./) }}
append mistakes, comb / <after \s | <punctuation>> <punctuation> | <!before <punctuation> | <:letter> | \s> . | <!after \.|\!|\?> \n | [<before ^> | <after \s>] \s /, text; say mistakes.Numeric

With extra whitespace for readability:

my token punctuation {<[.,;:!?]>}
my \text = slurp;
my \mistakes=[];
for split /\.|\!|\?/, text {
    for .trim.match: :g, /<:letter>+/ -> \word {
        (append mistakes, .comb when none words slurp pi given lc word)
        or
        (push mistakes, $_ if ((.from or word.from) xor m/<[a..z]>/) for word.match: :g, /./)
    }
}
append mistakes, comb /
  <after \s | <punctuation>> <punctuation>
  | <!before <punctuation> | <:letter> | \s> .
  | <!after \.|\!|\?> \n
  | [<before ^> | <after \s>] \s
/, text;
say mistakes.Numeric

Notes:

  • Expects the dictionary in a file called 3.14159265358979 in the current working directory.
  • The only inspired part is the line
    append mistakes, .comb when none words slurp pi given lc word,
    the rest is pretty bad. But maybe it can at least serve as a baseline for better solutions... :)
\$\endgroup\$
1
  • 4
    \$\begingroup\$ The most readable perl code ever \$\endgroup\$
    – user41805
    Commented Jan 23, 2017 at 9:22
2
\$\begingroup\$

Python 3, 287 spelling errors

    import re
    def function(message):file = open("dictionary", "r");dictionary = file.read().split();words = re.findall("[a-zA-Z]+", message);sentences = re.findall("[^.!?]+", message);return sum(len(word) if word.lower() not in dictionary else 0 for word in words)+sum(1 if sentence.strip()[0].isalpha() and not sentence.strip()[0].isupper() else 0 for sentence in sentences)+sum(sum(1 if character.isupper() else 0 for character in sentence.strip()[1:]) for sentence in sentences)+len(re.findall("[\s.,;:!?][.,;:!?]", message))+len(re.findall("[^.!?]\n", message))+len(re.findall("^\s", message))+len(re.findall("\s\s", message))+len(re.findall("[^a-zA-Z\s.,;:!?]", message))+int(not sentences[-1] and count(sentences[-1], '\n') != 1)

Try it online!

Definitely not the best, but I gave it a solid shot, I think! Here it is in an actually readable format. Assumes there is a file called "dictionary" (no extension) in the cwd.


import re
def function(message):
    file = open("dictionary", "r")
    dictionary = file.read().split()
    words = re.findall("[a-zA-Z]+", message)
    sentences = re.findall("[^.!?]+", message)
    errors = 0
    errors += sum(len(word) if word.lower() not in dictionary else 0 for word in words)
    errors += sum(1 if sentence.strip()[0].isalpha() and not sentence.strip()[0].isupper() else 0 for sentence in sentences)
    errors += sum(sum(1 if character.isupper() else 0 for character in sentence.strip()[1:]) for sentence in sentences)
    errors += len(re.findall("[\s.,;:!?][.,;:!?]", message))
    errors += len(re.findall("[^.!?]\n", message))
    errors += len(re.findall("^\s", message))
    errors += len(re.findall("\s\s", message))
    errors += len(re.findall("[^a-zA-Z\s.,;:!?]", message))
    errors += int(not sentences[-1] and count(sentences[-1], '\n') != 1)
    return errors
\$\endgroup\$
1
  • \$\begingroup\$ I don't think this works all of the time; it seemed to output the wrong value for the second test case? \$\endgroup\$ Commented Oct 9, 2022 at 5:30
1
\$\begingroup\$

Python, 32 spelling errors

import re;be = open('be').read().split();exec(''.join(chr(be.index(it)) for it in 'aboriginal abominable aborting aborting abolishing abominate abominable abbreviated abetting abbreviated abominates aboriginals aborigines abortionist abortion abdicating abdication abets abortions aborigine aborted abolitionists aborting abbreviated abetting abbreviated aborted abominable abduct abominably abominates aboriginals abolitionists abolishing abominations abominations abdicating abbreviating aboard abolishing abdominal abound abhorrent abdominal abnormally abodes abdomen abbreviating abdomens abbreviated aboriginal abominable aborting aborting abolishing abominate abominable abdication abets aborting abominable aboriginals abortion abominable aboriginals abolitionist abominable aborting abbreviated abetting abbreviated aborted abominable abduct abominably abominates aboriginals abolitionists abolishing abominations abominations abdicating abbreviating aboard abolish abduct abbreviates abhorred abodes abdomen abbreviating abdomens abbreviated aboriginal abominable aborting aborting abolishing abominate abominable abdication abets aborigines aborted abominates aboriginals abortion abdicating aborting abortionist aboriginal abdicating abominations abominable aboriginals abdicating abortions aborigine aborted abolitionists abdication abbreviated abominates abominably abbreviated abortions aborigine aborted abolitionists abduct abominations aborigine abortions abominable aborted abdicating abdication abbreviated aboriginals aborigine abortion abbreviated abominates aboriginals abbreviated abolition abominable abbreviated abominable abominations aborting abominable abbreviated abducting abbreviated abominably aborigine aborted abbreviated abortions aborigine aborted abolitionists abbreviated abominates aboriginals abbreviated abortions aborigine aborted abolitionists aborting abdication abdomen aborting abortionist aboriginal abdicating abduction abbreviated abominates abominably abbreviated aborting abominable aboriginals abortion abominable aboriginals abolitionist abominable abduct aborting abortion aborted abominates aborigines abdicating abdication aboard abducting abodes abduct abominates aborting abolishing abominations aborigines abominated abolishing abdicating abdication abbreviated abolishing aboriginals abolitionists abbreviated aboriginals aborigine abortion abbreviated aborting abominable aboriginals abortion abominable aboriginals abolitionist abominable abduct aborting abortion aborted abominates aborigines abdicating abdication aboard abducting abodes abduct abominates aborting abortionist aborigines aborigines abominable aborted abdicating abdication abbreviated abominable abominations aborting abominable abbreviated abducting abbreviated abominably aborigine aborted abbreviated aborting abominable aboriginals abortion abominable aboriginals abolitionist abominable abbreviated abominates aboriginals abbreviated aborting abominable aboriginals abortion abominable aboriginals abolitionist abominable aborting abdication abdomen aborting abortionist aboriginal abdicating aborting abortionist aboriginal abdicating abduction abbreviated abominates abominably abbreviated abolitionist abominated abolishing aborted abolishing abolitionist abortion abominable aborted abduct abominates aborting abortionist aborigines aborigines abominable aborted abdicating abdication abbreviated abominable abominations aborting abominable abbreviated abducting abbreviated abominably aborigine aborted abbreviated abolitionist abominated abolishing aborted abolishing abolitionist abortion abominable aborted abbreviated abominates aboriginals abbreviated aborting abominable aboriginals abortion abominable aboriginals abolitionist abominable abduct aborting abortion aborted abominates aborigines abdicating abdication aboard abduction abet abodes abdication abbreviated abominably aborigine aborted abbreviated aborting abominable aboriginals abortion abominable aboriginals abolitionist abominable abbreviated abominates aboriginals abbreviated aborting abominable aboriginals abortion abominable aboriginals abolitionist abominable aborting abdication abdomen abominations abominable aboriginals abdicating aborted abominable abduct abominably abominates aboriginals abolitionists abolishing abominations abominations abdicating abbreviating aboard abode aborting abduct abdomens abets abet abbreviates abhorred abodes aboard abduct abdomens abets abet abbreviates abhorred abodes abbreviating abdomens abbreviated aboriginal abominable aborting aborting abolishing abominate abominable abdication abdication abdomen abominations abominable aboriginals abdicating aborted abominable abduct abominably abominates aboriginals abolitionists abolishing abominations abominations abdicating abbreviating aboard abolish abduct abbreviates abhorred abodes abode aboriginals abbreviating abdomens abbreviated aboriginal abominable aborting aborting abolishing abominate abominable abdication abdication abdomen abominations abominable aboriginals abdicating aborted abominable abduct abominably abominates aboriginals abolitionists abolishing abominations abominations abdicating abbreviating abolish abode aborting abbreviating abdomens abbreviated aboriginal abominable aborting aborting abolishing abominate abominable abdication abdication abdomen abominations abominable aboriginals abdicating aborted abominable abduct abominably abominates aboriginals abolitionists abolishing abominations abominations abdicating abbreviating abode aborting abode aborting abbreviating abdomens abbreviated aboriginal abominable aborting aborting abolishing abominate abominable abdication abdication abdomen abominations abominable aboriginals abdicating aborted abominable abduct abominably abominates aboriginals abolitionists abolishing abominations abominations abdicating abbreviating aboard abolish abolishing abdominal abound abhorrent abdominal abnormally abode aborting abduct abdomens abets abet abbreviates abhorred abodes abbreviating abdomens abbreviated aboriginal abominable aborting aborting abolishing abominate abominable abdication abdication abdomen abominates aboriginals abortion abdicating aboriginals aborigine abortion abbreviated aborting abominable aboriginals abortion abominable aboriginals abolitionist abominable aborting aboard abdominal abduction abodes abbreviated abolishing aboriginals abolitionists abbreviated abolitionist aborigine abortionist aboriginals abortion abdicating aborting abominable aboriginals abortion abominable aboriginals abolitionist abominable aborting aboard abdominal abduction abodes abdomens abbreviated abdicates abode aboriginals abdicates abdication abbreviated abbreviates abetting abbreviated abduction abdication abdication'.split()))

Takes in input from standard in and outputs to standard out. This requires a dictionary in a file called be the same directory as the code.

I took the Python answer from GotCubes and encoded each character as an index into the dictionary, interpreted as an ASCII code point.

Here's the code that I used to generate my code:

be=open("be").read().split()
code="""message = input();words = re.findall("[a-zA-Z]+", message);sentences = re.findall("[^.!?]+", message);print(sum(len(word) if word.lower() not in be else 0 for word in words)+sum(1 if sentence.strip()[0].isalpha() and not sentence.strip()[0].isupper() else 0 for sentence in sentences)+sum(sum(1 if character.isupper() else 0 for character in sentence.strip()[1:]) for sentence in sentences)+len(re.findall("[\s.,;:!?][.,;:!?]", message))+len(re.findall("[^.!?]\\n", message))+len(re.findall("^\s", message))+len(re.findall("\s\s", message))+len(re.findall("[^a-zA-Z\s.,;:!?]", message))+int(not sentences[-1] and count(sentences[-1], '\\n') != 1))"""
words=" ".join(be[ord(c)] for c in code)
print(f"""import re;be=open('be').read().split();exec(''.join(chr(be.index(it))for it in '{words}'.split()))""")

You can definitely lower the score even more, but I will try that when it's not past midnight in my time zone.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.