-
Notifications
You must be signed in to change notification settings - Fork 0
/
words.py
136 lines (104 loc) · 3.84 KB
/
words.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import re
from random import choice, randint
from maybe import flip, maybe, choice_without
CONSONANTS = list('bcdfghjklmnprstvwy')
VOWELS = list('aeiou')
COMBINATIONS = ['sh', 'ch', 'th', 'gh', 'st']
INITIAL_COMBINATIONS = ['br', 'dr', 'pr', 'tr', 'bl', 'pl']
TERMINAL_COMBINATIONS = ['nt', 'pt', 'll', 'ss', 'ck', 'sk']
INITIAL = CONSONANTS + COMBINATIONS + INITIAL_COMBINATIONS
TERMINAL = CONSONANTS + COMBINATIONS + TERMINAL_COMBINATIONS
LOWER_TITLE = [
'a', 'an', 'the', 'and', 'as', 'at', 'atop', 'but', 'by', 'for', 'from',
'in', 'into', 'of', 'off', 'on', 'onto', 'out', 'over', 'per', 'to', 'up',
'via', 'with'
]
def word(syllables=None):
syllables = syllables or randint(1, 3)
return ''.join(
syllable(s == 0, s == syllables - 1) for s in range(syllables)
)
def syllable(first=True, last=True):
"""
Usually start with a consonant (or consonant combination), add vowel,
optionally add another vowel, and optionally end with a consonant.
"""
initial = (
choice(INITIAL if first else INITIAL + TERMINAL)
if not first or maybe(0.75) else ''
)
vowel = choice(VOWELS)
extension = (
choice_without(VOWELS, vowel if vowel not in 'eo' else None)
if maybe(0.25) else ''
)
terminal = choice(TERMINAL) if last and maybe(0.75) else ''
return initial + vowel + extension + terminal
def name():
first = word().capitalize()
if flip():
return first
return f'{first} {"of " if maybe(0.25) else ""}{word().capitalize()}'
def capitalize(str):
"""
Capitalizes the first letter without changing the case of any other
letters.
"""
return str[0].upper() + str[1:] if str else str
def uncapitalize(str):
"""
Lowercases the first letter without changing the case of any other
letters.
"""
return str[0].lower() + str[1:] if str else str
def oxford(strings):
"""Joins strings using the serial comma standard."""
if len(strings) < 2:
return ''.join(strings)
if len(strings) == 2:
return ' and '.join(strings)
return ', '.join(strings[:-1]) + f', and {strings[-1]}'
def titlecase(str):
"""
Capitalizes each word, except those in a proscribed list (e.g., articles,
short prepositions, etc.). Note: all whitespace is replaced by single space
characters.
"""
return ' '.join(
w.capitalize() if i == 0 or w not in LOWER_TITLE else w
for i, w in enumerate(str.split())
)
def wordcount(*args):
# Ensure that hyphenated words aren't counted as two by replacing hyphens
args = [str.replace('-', '_') for str in args]
return sum((len(re.findall(r'\b\w', str)) for str in args))
def indefinite(noun):
"""Returns the given noun prefaced with 'a' or 'an', as appropriate."""
return f'an {noun}' if noun[0] in VOWELS else f'a {noun}'
def plural(noun):
"""Returns the plural of a given noun (a hopeless task in English)."""
if noun == 'ox':
return f'{noun}en'
if noun.endswith('foot'):
return f'{noun[:-4]}feet'
if noun.endswith('child'):
return f'{noun}ren'
if noun.endswith('man'):
return f'{noun[:-3]}men'
if noun.endswith(('moose', 'caribou', 'sheep', 'fish')):
return noun
if noun.endswith('ium'):
return f'{noun[:-3]}ia'
if noun.endswith(('pus', 'pod')):
return f'{noun[:-3]}podes'
if noun.endswith('scis'):
return f'{noun[:-4]}scides'
if noun.endswith('us') and not noun.endswith('lotus'):
return f'{noun[:-2]}i'
if noun.endswith('i'):
return noun
if noun.endswith('y'):
return f'{noun[:-1]}ies'
if noun.endswith(('s', 'x', 'ch', 'sh')):
return f'{noun}es'
return f'{noun}s'