Project P028

Spelling suggester

Checks a line of text against a list of 352 common English words and suggests, for each word it does not know, the closest words by edit distance - insertions, deletions, substitutions and swaps of two neighbouring letters - the more common word first on a tie; suggests for a single word, and adds new words for the session.

3 modules · 2 recorded sessionstext-menu UI in the terminalupdated 2026-10-06

Every screen below was recorded under CPython. When this page was built, the EML interpreter replayed each session from the same input and printed the same bytes.

About

Checks a line of text against a list of 352 common English words. For each word it does not know, it suggests the closest words in the list by edit distance. It also suggests for a single word, and new words can be added for the session.

  • main.eml - the menu, the questions and their checks, and what the screen shows
  • spelling.eml - the edit distance, the words of a text, and suggestions
  • words.eml - the word list, most common words first

How each part works:

  • The edit distance is the fewest one-letter insertions, deletions and substitutions, and swaps of two neighbouring letters, that turn one word into another. It is the Levenshtein table of the corpus case edit-distance with one more way into a cell, for a swap: teh is one edit from the, not two. (This "optimal string alignment" distance never edits a stretch twice, so ca is three edits from abc.)
  • Only distances that matter are worked out in full: a word whose length differs by more than the limit is skipped at once.
  • Suggestions are the words within 2 edits when checking a line (at most 3) and within 3 edits for a single word (at most 5), nearest first. Two words equally near go in the order of the list, which runs from the most common word down, so teh suggests the before be and to.
  • A word is a run of letters and apostrophes in any case; apostrophes at either end are dropped, so don't and it's are single words and 'quoted' is quoted. A word that appears several times is reported once, with how many times.
  • Added words go to the end of the list, so they rank after the built-in words they tie with; they last until the program ends.

What is checked: a line is at most 200 characters; a single word is letters with apostrophes only inside, at most 20 characters; a word already in the list is not added again. An empty answer cancels.

Sessions: sessions/basic.in checks a line with teh twice, quikc, jumpd and dogg, and a line with freind, langauge and becuase, suggests for wrld, finds The in the list, adds receive and Tomorrow, suggests for recieve (now receive first), checks a line that is all known words, and lists the added words; sessions/bad-input.in types menu choices that are not 1 to 5, an empty line, 201 characters, a line with no words, two words, x1 and a-b as one word, it's, a word with nothing near, the to add again, 'quote' and 21 letters, adds Don't, and checks a line with nothing near and a line with apostrophes.

Built on the verified corpus case edit-distance (the Levenshtein distance as a bottom-up table).

Recorded sessions

What the screen shows while someone uses the program. Each typed line appears after its prompt, the way a terminal shows it.

bad-input

interpreter: byte-equal

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 0
Pick a number from 1 to 5.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> abc
Pick a number from 1 to 5.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 6
Pick a number from 1 to 5.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 1
text> 
Cancelled.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 1
text> word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word x
That line has 201 characters; at most 200. Type it again.
text> 123 + 456 = 579 !!!
No words in that line.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 2
word> two words
Type one word of letters (an apostrophe inside is fine), at most 20.
word> x1
Type one word of letters (an apostrophe inside is fine), at most 20.
word> a-b
Type one word of letters (an apostrophe inside is fine), at most 20.
word> 
Cancelled.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 2
word> it's
Closest to 'it's':
  its - 1 edit
  it - 2 edits
  is - 2 edits
  the - 3 edits
  to - 3 edits

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 2
word> xyzzyq
Nothing in the word list is within 3 edits of 'xyzzyq'.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 4
No words added yet.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 3
word> the
'the' is already in the word list.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 3
word> 'quote'
Type one word of letters (an apostrophe inside is fine), at most 20.
word> abcdefghijklmnopqrstu
Type one word of letters (an apostrophe inside is fine), at most 20.
word> Don't
Added 'don't'; the word list now has 353 words.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 3
word> 
Cancelled.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 1
text> zzzz qqq
2 words, 2 not in the word list:
  zzzz -> nothing within 2 edits
  qqq -> nothing within 2 edits

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 1
text> 'Don't' panic, it's fine.
4 words, 3 not in the word list:
  panic -> nothing within 2 edits
  it's -> its, it, is
  fine -> line, find, fire

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 4
Added this session: don't.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 5
Bye.
What was typed (32 lines)
0
abc
6
1

1
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word x
123 + 456 = 579 !!!
2
two words
x1
a-b

2
it's
2
xyzzyq
4
3
the
3
'quote'
abcdefghijklmnopqrstu
Don't
3

1
zzzz qqq
1
'Don't' panic, it's fine.
4
5

basic

interpreter: byte-equal

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 1
text> Teh quikc brown fox jumpd over teh lazy dogg.
9 words, 4 not in the word list:
  teh (2 times) -> the, be, to
  quikc -> quick
  jumpd -> jump, jumped
  dogg -> dog, do, does

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 1
text> My freind found the langauge hard becuase of spelling.
9 words, 3 not in the word list:
  freind -> friend, find
  langauge -> language
  becuase -> because

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 2
word> wrld
Closest to 'wrld':
  world - 1 edit
  will - 2 edits
  would - 2 edits
  well - 2 edits
  told - 2 edits

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 2
word> The
'the' is in the word list.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 3
word> receive
Added 'receive'; the word list now has 353 words.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 3
word> Tomorrow
Added 'tomorrow'; the word list now has 354 words.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 2
word> recieve
Closest to 'recieve':
  receive - 1 edit
  believe - 2 edits

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 1
text> I will receive the book tomorrow.
All 6 words are in the word list.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 4
Added this session: receive and tomorrow.

== Spelling suggester ==
1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit
choice> 5
Bye.
What was typed (18 lines)
1
Teh quikc brown fox jumpd over teh lazy dogg.
1
My freind found the langauge hard becuase of spelling.
2
wrld
2
The
3
receive
3
Tomorrow
2
recieve
1
I will receive the book tomorrow.
4
5

Modules

The program as written, entry module first. Each module transpiles to its own Python file, which is what eml project run executes.

main.eml(entry)

eml
# P028 spelling suggester: check a line of text against a word list, suggest
# the closest words by edit distance, and add new words for this session.
import words
import spelling

200 => longest_line

def trim(s):
    0 => i
    len(s) => j
    while i < j and s[i] == " ":
        i + 1 => i
    while j > i and s[j - 1] == " ":
        j - 1 => j
    return s[i:j]

def listed(items):
    "" => out
    0 => i
    while i < len(items):
        if i > 0 and i == len(items) - 1:
            out + " and " => out
        elif i > 0:
            out + ", " => out
        out + items[i] => out
        i + 1 => i
    return out

def plural(n, word):
    if n == 1:
        return "1 " + word
    return str(n) + " " + word + "s"

def one_word(s):
    # The word in lower case if s is one word of letters (an apostrophe inside
    # is fine), at most 20 characters; "" otherwise.
    trim(s) => s
    if s == "" or len(s) > 20:
        return ""
    spelling.words_of(s) => ws
    if len(ws) != 1 or len(ws[0]) != len(s):
        return ""
    return ws[0]

def ask_word():
    # A word, or "" when the answer is empty, which cancels.
    while True:
        input("word> ") => answer
        if trim(answer) == "":
            return ""
        one_word(answer) => w
        if w != "":
            return w
        "Type one word of letters (an apostrophe inside is fine), at most 20." ^0

def check(text, known, vocabulary):
    spelling.words_of(text) => ws
    if len(ws) == 0:
        "No words in that line." ^0
        return
    [] => unknown
    {} => times
    for w in ws:
        if not (w in known):
            if w in times:
                times[w] + 1 => times[w]
            else:
                1 => times[w]
                unknown + [w] => unknown
    if len(unknown) == 0:
        ("All " + plural(len(ws), "word") + " are in the word list.") ^0
        return
    (plural(len(ws), "word") + ", " + str(len(unknown)) + " not in the word list:") ^0
    for w in unknown:
        "  " + w => line
        if times[w] > 1:
            line + " (" + str(times[w]) + " times)" => line
        spelling.suggestions(w, vocabulary, 2, 3) => found
        if len(found) == 0:
            (line + " -> nothing within 2 edits") ^0
        else:
            "" => names
            for f in found:
                if names != "":
                    names + ", " => names
                names + f[0] => names
            (line + " -> " + names) ^0

def suggest(w, known, vocabulary):
    if w in known:
        ("'" + w + "' is in the word list.") ^0
        return
    spelling.suggestions(w, vocabulary, 3, 5) => found
    if len(found) == 0:
        ("Nothing in the word list is within 3 edits of '" + w + "'.") ^0
        return
    ("Closest to '" + w + "':") ^0
    for f in found:
        ("  " + f[0] + " - " + plural(f[1], "edit")) ^0

{} => known
[] => vocabulary
for w in words.common:
    True => known[w]
    vocabulary + [w] => vocabulary
[] => added

True => running
while running:
    "" ^0
    "== Spelling suggester ==" ^0
    "1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit" ^0
    trim(input("choice> ")) => choice
    if choice == "1":
        "" => text
        True => asking
        while asking:
            input("text> ") => text
            if len(text) > longest_line:
                ("That line has " + str(len(text)) + " characters; at most " + str(longest_line) + ". Type it again.") ^0
            else:
                False => asking
        if trim(text) == "":
            "Cancelled." ^0
        else:
            check(text, known, vocabulary)
    elif choice == "2":
        ask_word() => w
        if w == "":
            "Cancelled." ^0
        else:
            suggest(w, known, vocabulary)
    elif choice == "3":
        ask_word() => w
        if w == "":
            "Cancelled." ^0
        elif w in known:
            ("'" + w + "' is already in the word list.") ^0
        else:
            True => known[w]
            vocabulary + [w] => vocabulary
            added + [w] => added
            ("Added '" + w + "'; the word list now has " + str(len(vocabulary)) + " words.") ^0
    elif choice == "4":
        if len(added) == 0:
            "No words added yet." ^0
        else:
            ("Added this session: " + listed(added) + ".") ^0
    elif choice == "5":
        False => running
    else:
        "Pick a number from 1 to 5." ^0
"Bye." ^0
Python projection (main.py)
import words
import spelling
longest_line = 200

def trim(s):
    i = 0
    j = len(s)
    while i < j and s[i] == " ":
        i = i + 1
    while j > i and s[j - 1] == " ":
        j = j - 1
    return s[i:j]

def listed(items):
    out = ""
    i = 0
    while i < len(items):
        if i > 0 and i == len(items) - 1:
            out = out + " and "
        elif i > 0:
            out = out + ", "
        out = out + items[i]
        i = i + 1
    return out

def plural(n, word):
    if n == 1:
        return "1 " + word
    return str(n) + " " + word + "s"

def one_word(s):
    s = trim(s)
    if s == "" or len(s) > 20:
        return ""
    ws = spelling.words_of(s)
    if len(ws) != 1 or len(ws[0]) != len(s):
        return ""
    return ws[0]

def ask_word():
    while True:
        answer = input("word> ")
        if trim(answer) == "":
            return ""
        w = one_word(answer)
        if w != "":
            return w
        print("Type one word of letters (an apostrophe inside is fine), at most 20.")

def check(text, known, vocabulary):
    ws = spelling.words_of(text)
    if len(ws) == 0:
        print("No words in that line.")
        return
    unknown = []
    times = {}
    for w in ws:
        if not w in known:
            if w in times:
                times[w] = times[w] + 1
            else:
                times[w] = 1
                unknown = unknown + [w]
    if len(unknown) == 0:
        print("All " + plural(len(ws), "word") + " are in the word list.")
        return
    print(plural(len(ws), "word") + ", " + str(len(unknown)) + " not in the word list:")
    for w in unknown:
        line = "  " + w
        if times[w] > 1:
            line = line + " (" + str(times[w]) + " times)"
        found = spelling.suggestions(w, vocabulary, 2, 3)
        if len(found) == 0:
            print(line + " -> nothing within 2 edits")
        else:
            names = ""
            for f in found:
                if names != "":
                    names = names + ", "
                names = names + f[0]
            print(line + " -> " + names)

def suggest(w, known, vocabulary):
    if w in known:
        print("'" + w + "' is in the word list.")
        return
    found = spelling.suggestions(w, vocabulary, 3, 5)
    if len(found) == 0:
        print("Nothing in the word list is within 3 edits of '" + w + "'.")
        return
    print("Closest to '" + w + "':")
    for f in found:
        print("  " + f[0] + " - " + plural(f[1], "edit"))

known = {}
vocabulary = []
for w in words.common:
    known[w] = True
    vocabulary = vocabulary + [w]
added = []
running = True
while running:
    print("")
    print("== Spelling suggester ==")
    print("1) check a line  2) suggest for a word  3) add a word  4) added words  5) quit")
    choice = trim(input("choice> "))
    if choice == "1":
        text = ""
        asking = True
        while asking:
            text = input("text> ")
            if len(text) > longest_line:
                print("That line has " + str(len(text)) + " characters; at most " + str(longest_line) + ". Type it again.")
            else:
                asking = False
        if trim(text) == "":
            print("Cancelled.")
        else:
            check(text, known, vocabulary)
    elif choice == "2":
        w = ask_word()
        if w == "":
            print("Cancelled.")
        else:
            suggest(w, known, vocabulary)
    elif choice == "3":
        w = ask_word()
        if w == "":
            print("Cancelled.")
        elif w in known:
            print("'" + w + "' is already in the word list.")
        else:
            known[w] = True
            vocabulary = vocabulary + [w]
            added = added + [w]
            print("Added '" + w + "'; the word list now has " + str(len(vocabulary)) + " words.")
    elif choice == "4":
        if len(added) == 0:
            print("No words added yet.")
        else:
            print("Added this session: " + listed(added) + ".")
    elif choice == "5":
        running = False
    else:
        print("Pick a number from 1 to 5.")
print("Bye.")

spelling.eml

eml
# P028 spelling suggester - edit distance, the words of a text, and
# suggestions.

"abcdefghijklmnopqrstuvwxyz" => small
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" => capital

def distance(a, b, limit):
    # The fewest one-letter insertions, deletions and substitutions, and swaps
    # of two neighbouring letters, that turn a into b - the Levenshtein table
    # of the corpus case edit-distance with one more way into a cell (the
    # "optimal string alignment" distance). Anything over limit comes back as
    # limit + 1, at once when the lengths alone differ by more.
    len(a) => n
    len(b) => m
    if n - m > limit or m - n > limit:
        return limit + 1
    [] => t
    for i in [0:n]:
        [0] * (m + 1) => row
        i => row[0]
        t + [row] => t
    for j in [0:m]:
        j => t[0][j]
    for i in [1:n]:
        for j in [1:m]:
            1 => cost
            if a[i - 1] == b[j - 1]:
                0 => cost
            t[i - 1][j] + 1 => best
            if t[i][j - 1] + 1 < best:
                t[i][j - 1] + 1 => best
            if t[i - 1][j - 1] + cost < best:
                t[i - 1][j - 1] + cost => best
            if i > 1 and j > 1 and a[i - 1] == b[j - 2] and a[i - 2] == b[j - 1]:
                if t[i - 2][j - 2] + 1 < best:
                    t[i - 2][j - 2] + 1 => best
            best => t[i][j]
    if t[n][m] > limit:
        return limit + 1
    return t[n][m]

def lower_letter(c):
    # c in lower case if it is a letter, "'" for an apostrophe, else "".
    if c == "'":
        return c
    0 => k
    while k < 26:
        if small[k] == c or capital[k] == c:
            return small[k]
        k + 1 => k
    return ""

def without_apostrophes_around(w):
    0 => i
    len(w) => j
    while i < j and w[i] == "'":
        i + 1 => i
    while j > i and w[j - 1] == "'":
        j - 1 => j
    return w[i:j]

def words_of(text):
    # The words of a text in lower case: runs of letters and apostrophes, with
    # apostrophes at either end dropped, so "don't" stays one word.
    [] => out
    "" => w
    for c in text + " ":
        lower_letter(c) => l
        if l != "":
            w + l => w
        else:
            without_apostrophes_around(w) => s
            if s != "":
                out + [s] => out
            "" => w
    return out

def suggestions(word, vocabulary, limit, most):
    # Up to `most` words of the vocabulary within `limit` edits of word, as
    # [word, edits] pairs, nearest first; between equally near words the one
    # earlier in the vocabulary (the more common one) comes first.
    [] => found
    for w in vocabulary:
        distance(word, w, limit) => d
        if d <= limit:
            len(found) => j
            while j > 0 and found[j - 1][1] > d:
                j - 1 => j
            found[0:j] + [[w, d]] + found[j:len(found)] => found
            if len(found) > most:
                found[0:most] => found
    return found
Python projection (spelling.py)
small = "abcdefghijklmnopqrstuvwxyz"
capital = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

def distance(a, b, limit):
    n = len(a)
    m = len(b)
    if n - m > limit or m - n > limit:
        return limit + 1
    t = []
    for i in range(0, n+1):
        row = [0] * (m + 1)
        row[0] = i
        t = t + [row]
    for j in range(0, m+1):
        t[0][j] = j
    for i in range(1, n+1):
        for j in range(1, m+1):
            cost = 1
            if a[i - 1] == b[j - 1]:
                cost = 0
            best = t[i - 1][j] + 1
            if t[i][j - 1] + 1 < best:
                best = t[i][j - 1] + 1
            if t[i - 1][j - 1] + cost < best:
                best = t[i - 1][j - 1] + cost
            if i > 1 and j > 1 and a[i - 1] == b[j - 2] and a[i - 2] == b[j - 1]:
                if t[i - 2][j - 2] + 1 < best:
                    best = t[i - 2][j - 2] + 1
            t[i][j] = best
    if t[n][m] > limit:
        return limit + 1
    return t[n][m]

def lower_letter(c):
    if c == "'":
        return c
    k = 0
    while k < 26:
        if small[k] == c or capital[k] == c:
            return small[k]
        k = k + 1
    return ""

def without_apostrophes_around(w):
    i = 0
    j = len(w)
    while i < j and w[i] == "'":
        i = i + 1
    while j > i and w[j - 1] == "'":
        j = j - 1
    return w[i:j]

def words_of(text):
    out = []
    w = ""
    for c in text + " ":
        l = lower_letter(c)
        if l != "":
            w = w + l
        else:
            s = without_apostrophes_around(w)
            if s != "":
                out = out + [s]
            w = ""
    return out

def suggestions(word, vocabulary, limit, most):
    found = []
    for w in vocabulary:
        d = distance(word, w, limit)
        if d <= limit:
            j = len(found)
            while j > 0 and found[j - 1][1] > d:
                j = j - 1
            found = found[0:j] + [[w, d]] + found[j:len(found)]
            if len(found) > most:
                found = found[0:most]
    return found

words.eml

eml
# P028 spelling suggester - the built-in word list: 352 common English words,
# most common first. When two suggestions are the same number of edits away,
# the one that comes first here comes first.

[
    "the", "be", "to", "of", "and", "a", "in", "that", "have", "i", "it",
    "for", "not", "on", "with", "he", "as", "you", "do", "at", "this", "but",
    "his", "by", "from", "they", "we", "say", "her", "she", "or", "an",
    "will", "my", "one", "all", "would", "there", "their", "what", "so",
    "up", "out", "if", "about", "who", "get", "which", "go", "me", "when",
    "make", "can", "like", "time", "no", "just", "him", "know", "take",
    "people", "into", "year", "your", "good", "some", "could", "them", "see",
    "other", "than", "then", "now", "look", "only", "come", "its", "over",
    "think", "also", "back", "after", "use", "two", "how", "our", "work",
    "first", "well", "way", "even", "new", "want", "because", "any", "these",
    "give", "day", "most", "us", "is", "was", "are", "been", "has", "had",
    "were", "said", "did", "made", "went", "came", "saw", "got", "gave",
    "took", "found", "told", "thought", "called", "asked", "going", "being",
    "does", "done", "man", "men", "woman", "child", "children", "world",
    "life", "hand", "part", "place", "case", "week", "point", "number",
    "home", "water", "room", "mother", "father", "night", "thing", "things",
    "name", "house", "book", "word", "words", "story", "school", "family",
    "friend", "city", "country", "money", "eye", "eyes", "head", "face",
    "door", "line", "end", "side", "kind", "group", "problem", "question",
    "idea", "fact", "light", "song", "game", "paper", "picture", "letter",
    "language", "sentence", "spelling", "great", "little", "old", "big",
    "high", "different", "small", "large", "next", "early", "young",
    "important", "few", "public", "bad", "same", "able", "last", "long",
    "best", "better", "right", "left", "full", "fast", "quick", "quickly",
    "brown", "lazy", "black", "white", "red", "green", "blue", "cold", "hot",
    "hard", "easy", "real", "sure", "free", "find", "tell", "ask", "seem",
    "feel", "try", "leave", "call", "keep", "let", "begin", "help", "talk",
    "turn", "start", "show", "hear", "play", "run", "move", "live",
    "believe", "hold", "bring", "happen", "write", "sit", "stand", "lose",
    "pay", "meet", "include", "continue", "set", "learn", "change", "lead",
    "understand", "watch", "follow", "stop", "create", "speak", "read",
    "spend", "grow", "open", "walk", "win", "offer", "remember", "love",
    "consider", "appear", "buy", "wait", "serve", "die", "send", "expect",
    "build", "stay", "fall", "cut", "reach", "kill", "remain", "jump",
    "jumped", "spell", "draw", "carry", "eat", "here", "where", "why",
    "each", "between", "under", "never", "again", "always", "often", "still",
    "once", "soon", "together", "without", "until", "while", "through",
    "around", "below", "above", "against", "away", "down", "off", "too",
    "very", "really", "almost", "enough", "every", "something", "sometimes",
    "another", "such", "both", "own", "later", "dog", "fox", "cat", "bird",
    "tree", "river", "sea", "earth", "fire", "food", "car", "street",
    "state", "mile", "animal", "plant", "page", "list"
] => common
Python projection (words.py)
common = ["the", "be", "to", "of", "and", "a", "in", "that", "have", "i", "it", "for", "not", "on", "with", "he", "as", "you", "do", "at", "this", "but", "his", "by", "from", "they", "we", "say", "her", "she", "or", "an", "will", "my", "one", "all", "would", "there", "their", "what", "so", "up", "out", "if", "about", "who", "get", "which", "go", "me", "when", "make", "can", "like", "time", "no", "just", "him", "know", "take", "people", "into", "year", "your", "good", "some", "could", "them", "see", "other", "than", "then", "now", "look", "only", "come", "its", "over", "think", "also", "back", "after", "use", "two", "how", "our", "work", "first", "well", "way", "even", "new", "want", "because", "any", "these", "give", "day", "most", "us", "is", "was", "are", "been", "has", "had", "were", "said", "did", "made", "went", "came", "saw", "got", "gave", "took", "found", "told", "thought", "called", "asked", "going", "being", "does", "done", "man", "men", "woman", "child", "children", "world", "life", "hand", "part", "place", "case", "week", "point", "number", "home", "water", "room", "mother", "father", "night", "thing", "things", "name", "house", "book", "word", "words", "story", "school", "family", "friend", "city", "country", "money", "eye", "eyes", "head", "face", "door", "line", "end", "side", "kind", "group", "problem", "question", "idea", "fact", "light", "song", "game", "paper", "picture", "letter", "language", "sentence", "spelling", "great", "little", "old", "big", "high", "different", "small", "large", "next", "early", "young", "important", "few", "public", "bad", "same", "able", "last", "long", "best", "better", "right", "left", "full", "fast", "quick", "quickly", "brown", "lazy", "black", "white", "red", "green", "blue", "cold", "hot", "hard", "easy", "real", "sure", "free", "find", "tell", "ask", "seem", "feel", "try", "leave", "call", "keep", "let", "begin", "help", "talk", "turn", "start", "show", "hear", "play", "run", "move", "live", "believe", "hold", "bring", "happen", "write", "sit", "stand", "lose", "pay", "meet", "include", "continue", "set", "learn", "change", "lead", "understand", "watch", "follow", "stop", "create", "speak", "read", "spend", "grow", "open", "walk", "win", "offer", "remember", "love", "consider", "appear", "buy", "wait", "serve", "die", "send", "expect", "build", "stay", "fall", "cut", "reach", "kill", "remain", "jump", "jumped", "spell", "draw", "carry", "eat", "here", "where", "why", "each", "between", "under", "never", "again", "always", "often", "still", "once", "soon", "together", "without", "until", "while", "through", "around", "below", "above", "against", "away", "down", "off", "too", "very", "really", "almost", "enough", "every", "something", "sometimes", "another", "such", "both", "own", "later", "dog", "fox", "cat", "bird", "tree", "river", "sea", "earth", "fire", "food", "car", "street", "state", "mile", "animal", "plant", "page", "list"]

Built on these corpus cases

ΣEML 2026

Efficient New Language — a high-density semantic overlay for humans and AI agents.

This site’s demos run on the real EML toolchain, in your browser.

© 2026 EveMissLab (一言諾科技有限公司) / Neo.K. All rights reserved.