8
\$\begingroup\$

Write a program or function that given a string (or your language's equivalent), determine if the string is a word, or not, and output a truthy or falsy value.

(This is not a duplicate of Is this even a word? The incorrect words are generated in a very different way that I believe makes this a completely different challenge)

The words will all be lowercase, between 5 and 10 characters, and have no apostrophes.

The correct words are a randomly selected subset of the SCOWL English words list (size 50).

The incorrect words are generated via two methods: swapping and substitution.

The "swapping" words are generated using a modified Fisher-Yates shuffle on the letters of randomly selected (real) words. Instead of swapping the letters every time, a letter may or may not be swapped (the probability varies, so some words will be more realistic than others). If the new word matches an existing word, the result is discarded and it generates another word.

The "substitution" words are generated using a similar method, but instead of swapping the letter with another letter, each letter has a chance of being replaced with another random letter.

Each method is used to generate 50% of the fake words.

Scoring

Your function must be less than 150 bytes. The scoring is determined as follows:

percentage of answers correct + ((150 - length of program) / 10) 

Rules

Since this deals with a large number of test cases (each wordlist is 1000 words), an automated testing program is fine. The automated tester does not count towards the length of the program; however, it should be posted so that others are able to test it.

  • No loopholes.
  • No spelling/dictionary related built-ins.

Resources

List of words: http://pastebin.com/Leb6rUvt

List of not words (updated): http://pastebin.com/rEyWdV7S

Other resources (SCOWL wordlist and the code used to generate the random words): https://www.dropbox.com/sh/46k13ekm0zvm19z/AAAFL25Z8ogLvXWTDmRwVdiGa?dl=0

\$\endgroup\$
12
  • 2
    \$\begingroup\$ I know having a word list available would defeat the point of the challenge, but how is a program supposed to know that grits (404 in not-word list) isn't a word, considering it really really is one? \$\endgroup\$
    – Geobits
    Feb 17, 2016 at 0:44
  • 2
    \$\begingroup\$ Don't get me wrong; I don't like grits at all. Why anyone would eat them is beyond me. But even I wouldn't go so far as to reject the word itself :P \$\endgroup\$
    – Geobits
    Feb 17, 2016 at 0:46
  • \$\begingroup\$ Fair warning: I haven't gone any farther than that on the list, so it's possible there are others. \$\endgroup\$
    – Geobits
    Feb 17, 2016 at 0:49
  • \$\begingroup\$ Few more word non-words, some slightly obscure: quais, paves, colic, supermax. (Side note: I was delighted to find out that supermax is an actual word) \$\endgroup\$
    – Sp3000
    Feb 17, 2016 at 1:03
  • \$\begingroup\$ What's weird is even running the list through SCOWL's largest list didn't catch any of those, though they definitely are words. I generated another 1000 words (they are in the other resources link), and if a not-word is actually a word, it will be replaced by the word on the alternate list that's at the same line number. In the meantime, I updated the pastebin thing to use the alternate words for the word not-words. \$\endgroup\$
    – Daniel M.
    Feb 17, 2016 at 1:34

5 Answers 5

8
\$\begingroup\$

PHP, 64.9 (50%, 1 byte)

Well, I'm not really sure if this is an acceptable answer, but here goes:

1

Run like this:

echo '1' | php -- word

Obviously, for an equally large list of correct and incorrect words, this results in 50% false positives and 0% false negatives, so 50% correct. As the program is 1 byte though, you're getting the maximum possible length bonus (zero-length answers notwithstanding).

\$\endgroup\$
1
  • \$\begingroup\$ Interestingly, this is fairly competing due to scoring balance. +1 \$\endgroup\$ Feb 18, 2016 at 11:51
6
\$\begingroup\$

CJam, 78.6 (78.5%, 149 bytes)

l2b0"(1»\]ÁûKëá*ßð%äp`Ï_5ÚY÷:Ä$î ëQXV)­JKÆ¿-(ivHì?{'à\ßÐiCæz°P0ãª/îÏèÄ)WCÅH±Ø^2Ô¥?
î'jJ#OAõ~×cA$[8,ô#~¬#7>"255b2b+=

Matches 696 real words and doesn't match 874 non-words, giving 1570/2000 = 0.785. Tested on the online interpreter in Chrome - I'm not sure if the permalink will work in Firefox. In case it doesn't, the string, which contains unprintables, can be obtained by

[24 40 5 49 25 187 92 93 193 251 158 131 75 235 131 225 42 129 223 240 14 37 228 112 96 207 95 53 218 89 247 58 3 196 3 36 1 238 143 32 235 139 81 15 88 86 41 20 173 74 75 198 191 45 40 105 118 72 236 63 123 39 224 15 15 92 223 208 16 147 105 140 67 16 230 122 176 80 26 48 133 227 148 144 170 47 238 207 232 136 24 196 41 87 132 67 197 72 177 216 94 24 50 212 165 63 10 238 39 106 74 35 79 65 245 126 215 136 6 99 65 36 91 56 44 143 155 150 244 35 126 172 35 55 62]:c

The program merely hashes the input and performs a lookup based on 1077 possible buckets. I tried regex golfing this, but the non-words were too close to real words for it to be useful.

Try it online! | Test suite (paste full word list to count number of matches)

\$\endgroup\$
1
  • 1
    \$\begingroup\$ "I tried regex golfing this, but the non-words were too close to real words" -pretty much the goal \$\endgroup\$
    – Daniel M.
    Feb 18, 2016 at 11:43
3
\$\begingroup\$

Mathematica, 69.35 (69.35%, 150 bytes)

StringContainsQ[" "|##&@@"seaeiislaanreuaooesrtnlneimdiuuosnlrlggtwtwnsdjexexavsvnuvtxsgokcmairlzlzeyatgpnlfiyhtcdxrvmuqtqtmsfohnk"~StringPartition~2]

Explanation

The function will check whether the word contains certain letter pairs that rarely occur in real words. If so, the function will return True, indicating that the word is probably not a real word. For example, pair "ii" occurs 21 times in the list of not words, while does not occur in the list of words.

Correct rate

Words:      85.4%  
Not words:  53.3%
\$\endgroup\$
0
\$\begingroup\$

CSharp, 69.85 (57.45%, 26 bytes)

"hoeiaunrt".Contains(s[1])

I check if second letter of the word is on the list most popular second letters in english (from this site).

Automated test:

static void Main(string[] args)
{
string[] good = System.IO.File.ReadAllLines( @"PATH_GOOD.txt");
string[] bad = System.IO.File.ReadAllLines(@"PATH_BAD.txt");

int counter_good = 0;
int counter_bad = 0;

foreach (string s in good)
{
    if ("hoeiaunrt".Contains(s[1])) counter_good++;
}

foreach (string s in bad)
{
    if (!("hoeiaunrt".Contains(s[1]))) counter_bad++;
}

Console.WriteLine(counter_good);
Console.WriteLine(counter_bad);

Console.ReadLine();
}

Result:

828
321

Calculation:

(828+321)/20 + 124/10 = 57.45 + 12.4 = 69.85
\$\endgroup\$
0
\$\begingroup\$

ES6, 76 (67.4%, 64 bytes)

A more serious answer this time. This is a pretty simple algorithm. It returns a truthy value when the second character of a word is one of aeinoru. It does not yield a significantly better success ratio than just 1, but it is still very short.

w=>/^[^qxy][aehil-prux]/.test(w)>/[^aeiouy]{3}|[fiopq]$/.test(w)

Test here.

  • +2.7 by adding a regex to find words with 3 or more consecutive consonants and rule them "non-word"
  • +0.1 by replacing &! with >
  • +1.95 by excluding the most uncommon first characters qxy, adding more valid (common) second characters to compensate for false negatives, getting rid of the redundant comma in regex
  • +0.05 by excluding words ending with the unlikely ending characters fiopq
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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