Skip to content

Instantly share code, notes, and snippets.

@ptmcg
Last active November 5, 2020 06:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ptmcg/ee97e8f037937ce1c47c5b2d767381c3 to your computer and use it in GitHub Desktop.
Save ptmcg/ee97e8f037937ce1c47c5b2d767381c3 to your computer and use it in GitHub Desktop.
A python racter-like
#
# py_rac.py
#
# Copyright 2020, Paul McGuire
#
names = ("Voltaire|Samuel Johnson|Valery|Dante|"
"Nietzsche|Kant|Lao Tzu|Macchiavelli|Einstein|"
"Russell|Leonardo|Plato|Aristotle|Socrates|Diderot|"
"Descartes|Thomas Aquinas|Hawking|Emerson|Faulkner|"
"Chamberlain|Livy|Caesar|Holmes|Moriarty|Edison|Tesla".split('|'))
concepts = """Wit Vitality Vigor Ambiguity Sexuality Philosophy
Ambition Mercy Morality Truth Folly Emotion Art Politics
Commerce Industry Beauty Instinct Reason Fortune Fate Destiny
Guile Chance Purpose Luck Misfortune Triviality Fashion
Passion Awareness Consciousness""".split()
opposites1 = """Envy/Kindness
Vanity/Modesty Lust/Chastity
Conceit/Humility Famine/Plenty
Pleasure/Pain
Sin/Virtue Vice/Virtue Love/Hate
Man/Woman Risk/Certainty
Foolishness/Wisdom Harmony/Conflict
Success/Failure Weakness/Strength
Loyalty/Treachery Danger/Safety
Illusion/Reality""".split()
for opp in opposites1:
concepts.extend(opp.split('/'))
opposites2 = """Gluttony/Moderation
Pride/Humility Life/Death Wrath/Patience
Greed/Charity Sloth/Endeavor Lust/Chastity
Good/Evil Courage/Fear Abstinence/Indulgence
Change/Stagnation Knowledge/Ignorance Victory/Defeat
Prosperity/Want Wealth/Poverty Depression/Levity
Masculinity/Feminity Pride/Shame Freedom/Slavery
Conformity/Individuality Justice/Injustice""".split()
opposites = opposites1 + opposites2
a_nouns = """truth shield weapon talent skill character person flame blade
flower reward curse blessing mistress wife lover enemy light husband
friend idea thought concept obstacle chain shackle bird abyss
arrow threat promise garment debt surplus voice secret whim
abyss obsession agenda constraint restraint lion snake crime
ambition study remedy reason thought bullet regret mystery
viper cow dog cat bush lie father mother child cousin fantasy process horse
sheep tiger locust moth disguise veil dream basis picture word
device nuisance comrade itch dagger ash gesture moment shield spear
force ant illusion charade fellow doubt instrument purpose antidote
weapon tool sword word legend awareness vision consciousness""".split()
coll_nouns = """food stone lead steel gold silver bread money meat poison
debt wealth energy power beauty truth flesh fire rust math science
decay luck dust ash grass water essence health medicine chaos
people innocence blood""".split()
coll_nouns += concepts
nouns = a_nouns + coll_nouns
body = """arm leg head chest breast soul foot hand neck eye
ear tongue shoulder stomach heart brain mind loins
gut brow""".split()
#~ nouns += body
nums = """10,000 10,000 a_million a_thousand a_thousand a_hundred a_couple_of two three seven a_dozen a_score_of""".split()
nouns += map(lambda s:s.replace('_',' '),
"""nom_de_plume nom_de_guerre sine_qua_non raison_d'etre
coup_de_grace summa_cum_laude magnum_opus fait_accompli
quid_pro_quo""".split())
plurals = []
irreg_plurals = dict(foot='feet',sheep='sheep',man='men',
woman='women',child='children',basis='bases')
for n in a_nouns+concepts:
if n.lower() in irreg_plurals:
plurals.append(irreg_plurals[n.lower()])
elif n.endswith('y') and not any(n.endswith(v+'y') for v in "aeiou"):
plurals.append(n[:-1]+"ies")
elif n.endswith('ey'):
plurals.append(n[:-2]+"ies")
elif any(n.endswith(suf) for suf in ('s','tch','sh','ch')):
plurals.append(n+'es')
elif n.endswith('fe'):
plurals.append(n[:-2]+'ves')
else:
plurals.append(n+'s')
plurals.remove("Politicses")
plurals.append("Politics")
plurals.extend(coll_nouns)
#~ print plurals
time_periods = """year day season hour minute second age eon week moment
""".split()
adjs = """golden lovely deadly sinister pleasant sensuous austere harsh loyal
treacherous leaden dull bright shiny broken cracked iron whimsical
frail grim cheerful flimsy brief tender true false great trivial
strong weak firm soft hard healthy sickly youthful weary inscrutable
welcome reluctant resistant persistent intelligent wise unwise foolish gentle
fragile shallow imaginary undeniable unreasonable tender determined
hidden secret childish relentless merciless ruthless futile deliberate
prudent imprudent practical impractical pointless brash idle secret
precious opposing overwhelming true deceitful faithful hollow
imaginary lucky vain humble welcome unwelcome""".split()
advs = """never ever always just purely heartily reluctantly vehemently
vigorously unflinchingly really blindly foolishly
truly wisely hardly relentlessly mercilessly
compassionately ruthlessly tenderly gently
carefully cautiously wildly carelessly recklessly
artfully temporarily permanently partially totally
completely randomly""".split()
ob_pros = """everyone no_one someone anyone everybody everything nothing all""".split()
sub_pros = """everyone no_one yourself someone anyone everybody one everything nothing all""".split()
v_t = """question challenge need have dispute want distrust trust love hate embrace treasure
indulge welcome engage know betray spoil kill destroy enrage pursue fight play
consume defeat conquer cut control make break keep disappoint feed""".split()
prog_v_t = [v + 'ing' if not v.endswith('e') else v[:-1]+'ing' for v in v_t]
v_i = "run walk talk be eat drink laugh cry sing dance breathe worry relax debate confer sleep rise stay".split()
prog_v_i = [v + 'ing' if not v.endswith('e') else v[:-1]+'ing' for v in v_i]
prog_v_i.remove('runing')
prog_v_i.append('running')
prog_v_i.remove('bing')
prog_v_i.append('being')
preps = """about above across after against along among around beside between
before behind below beneath beyond by for from in inside
into near on onto outside over past under underneath unlike until upon
versus via with within without""".split()
v_passive = """trusted contained wanted disguised loved
hated idolized ignored embraced
beloved despised impressed respected
revered considered heeded denied
convinced avoided denied indulged known
welcomed admired recognized rewarded made
cherished forgotten overlooked
beaten imagined dreamt_of
""".split()
neg_v_passive = """unrewarded unimpressed unconvinced
unloved unknown unwanted unheeded undone
unrecognized undreamed_of unimagined unprepared
disappointed shunned ridiculed betrayed
""".split()
v_passive += neg_v_passive
adjs += v_passive
intros = """\
By the way,
That reminds me,
In other words,
One other thing,
In conclusion,
According to {nm1},
Even {nm1} would have to admit,
Now
On a good day,
On any given day,
It is often said,
As {pl} go,
In the end,
But in the end,
In time,
Over time,
Some day,
In the future,
It goes without saying,
I have no doubt,
More than {np},
As I've said {num} times,
Without {np},
In every {tp},
Every {num} {tp}s,
Every {num} {tp}s or so,
For a single {tp},""".splitlines()
templates = """\
What becomes of a man who {v_t}s {ob_pro} but is himself {v_passive}?
What becomes of a man who {v_t}s {ob_pro} but is not himself {v_passive}?
What becomes of a woman who {v_t}s {ob_pro} but is herself {v_passive}?
What becomes of a woman who {v_t}s {ob_pro} but is not herself {v_passive}?
Every {n} is a {a} {c}.
After {o1}, my favorite {n} is {c}.
A {a} {n} cannot be {v_passive}.
A {a} {n} should not be {v_passive}.
One's {b} must be {a}.
One's {b} must {adv} be {a}.
{o1} and {o2} are {a} {pl}.
From {pl} come {np}.
{nm1} and {nm2} will {v_t} each other.
You must {v_t} your {n}.
You must {v_t} your {pl}.
Behind every {n1} is a {n2}.
{c} {v_t}s {ob_pro}.
{c} will {v_t} {ob_pro}.
{v_t} your {n}.
Don't {v_t} {pl1} you can't {v_t2}.
{v_t} {pl1} even if you can't {v_t2} them.
Must all {pl} be {v_passive}?
Can any {n} be truly {v_passive}?
The {n} often goes {neg_v_passive}.
Some day, {ob_pro} will be {v_passive}.
Some day, {ob_pro} will be {a}.
Some day, {ob_pro} will be {a} for {num} {tp}s.
Some day, {ob_pro} will be {a} for just one {tp}.
Some day, {ob_pro} will be {a} for a single {tp}.
{ob_pro} can be {v_passive}.
{ob_pro} can be {a}.
{ob_pro} can be {a} for {num} {tp}s.
{ob_pro} can be {a} for just one {tp}.
{ob_pro} can be {a} for a single {tp}.
In the future, {ob_pro} will be {v_passive}.
In the future, {ob_pro} will be {a}.
In the future, {ob_pro} will be {a} for {num} {tp}s.
{nm1} would {v_t} {np}.
{pl1} are {pl2}.
{pl2} are really {pl1}.
Our {pl1} are really our {a} {pl2}.
{pl1} are {a} {pl2}.
{pl2} are really just {pl1}.
{pl2} are just {pl1}.
{pl} are {a}.
{pl} can be {a}.
{pl} can be {a1} if you are not {a2}.
{pl} can become {a1} if you do not {v_t} them.
{nm1} {v_t}s {c}.
{nm1} {v_t}s {pl}.
Your {n1} is your {n2}.
{pl} lead to {c}.
All {c1} is just {c2}.
All {c} is just {np}.
{o1} is really just {o2} having a bad day.
{o1} is really just {o2} in disguise.
{o1} is really just {o2} in a mirror.
Every {o1} hides a {a} {o2}.
Be as {np} to {ob_pro}.
Be {np} to {ob_pro}.
{c} is just {np}.
{prog_v_i} with {pl} is {np}.
{v_t} your {n} or your {n} will {v_t} you.
{v_t} your {n} before your {n} {v_t}s you.
{v_t}.
{v_t}, just {v_t}.
{v_t} or be {v_passive}.
{v_t} and be {v_passive}.
{v_t} {c}.
{v_t} {ob_pro}.
{v_t} {ob_pro}, as {ob_pro} {v_t}s you.
{v_t} {np}.
{v_t} {np}, just {v_t} it.
{v_t} {np}, as {np} {v_t}s you.
{v_t} {np}, or {np} will {v_t} you.
{v_t} {np}, and {np} will {v_t} you.
{v_t} {np1} or {np2}.
{np1} is {np2}.
{np1} is {np2} to be {v_passive}.
{np1} is a {a_n2} to {v_t}.
{num} {pl} are not equal to a single {n}.
{np} equals {num} {pl}.
{np} is equal to {num} {pl}.
{np} is greater than {num} {pl}.
One {n} will lead to {num} {pl}.
A {n1} in the {n2} is worth {num} in the {n3}.
One must {v_t} {np}.
One must {v_t} {np} or {v_i}.
You are {np}.
You are your own {c}.
My {c1} is exceeded only by my {c2}.
{v_t} your inner {n}.
{v_t} your inner {n}, just as your inner {n} {v_t}s you.
{v_t} your {pl}.
{v_t} {pl}.
We are all {np}.
{v_t} {pl}, as the {pl} {v_t} you.
{v_t} your {pl}, at all costs.
{v_i} with the {pl}.
{v_i} with your {pl}.
{o1} becomes {o2}.
{np} is {a}.
{np} is {a} to {v_t}.
{n} will not be {v_passive}.
Too much {coll_n} will {v_t} {np}.
Too many {a_n}s {v_t} {np}.
To {v_t} {c1}, one must first {v_t} {c2}.
It is {a} to {v_t} {np}.
It is {c} to {v_t} {np}.
{pl} are {a} to {v_t}.
{ob_pro} is {np}.
{ob_pro} can be {np}.
{ob_pro} has {np}.
All {c1} is {c2}.
{c1} is {c2}, {c2} {c1}.
{sub_pro} must have the courage to {v_t} their {coll_n}.
{sub_pro} must have the courage to {v_t} their {n}.
{v_i} {prep} {np}.""".splitlines()
emp_patt = """\
I {v_t} {c}
{nm1} must {v_t} {np}
{c} cannot be {v_passive}
{c} can only be {v_passive}
{pl} can only be {v_passive}
only {c} can be {v_passive}
{nm1} must be {v_passive}
{nm1} must not be {v_passive}
{adv}
even if just for a {tp}
{adv1} and {adv2}
without {c}
without exception""".splitlines()
from random import random, choice, shuffle
def mutate(fill=None):
if not fill:
fill = {}
fill['nm1'] = choice(names)
fill['nm2'] = fill['nm1']
while fill['nm2'] == fill['nm1']:
fill['nm2'] = choice(names)
for key in 'n n1 n2 n3'.split():
if key == 'n2':
fill[key] = fill['n1']
while fill[key] == fill['n1']:
fill[key] = choice(nouns+concepts)
else:
fill[key] = choice(nouns+concepts)
while random() < 0.1:
fill[key] = choice(adjs) + ' ' + fill[key]
if random() < 0.1:
fill[key] = fill[key] + ' of ' + choice(concepts)
elif random() < 0.1:
fill[key] = fill[key] + ' for ' + gen('{np}')
fill['c'] = choice(concepts)
fill['c1'] = choice(concepts)
fill['c2'] = fill['c1']
while fill['c2'] == fill['c1']:
fill['c2'] = choice(concepts)
fill['o1'],fill['o2'] = (choice(opposites).split('/'))[::choice((1,-1))]
fill['ob_pro'] = choice(ob_pros)
fill['sub_pro'] = choice(sub_pros)
fill['prog_v_i'] = choice(prog_v_i)
fill['a'] = choice(adjs)
if random() < 0.1:
fill['a'] = choice(advs) + ' ' + fill['a']
for key in 'a1 a2'.split():
fill[key] = choice(adjs)
fill['b'] = choice(body)
fill['v_passive'] = choice(v_passive)
fill['neg_v_passive'] = choice(neg_v_passive)
while random() < 0.1:
fill['v_passive'] = choice(advs) + ' ' + fill['v_passive']
for key in 'v_t v_t1 v_t2'.split():
fill[key] = choice(v_t)
while random() < 0.1:
fill[key] = choice(advs) + ' ' + fill[key]
fill['v_i'] = choice(v_i)
while random() < 0.1:
fill['v_i'] = choice(advs) + ' ' + fill['v_i']
for key in 'pl pl1 pl2'.split():
fill[key] = choice(plurals)
while random() < 0.1:
fill[key] = choice(adjs) + ' ' + fill[key]
for key in 'adv adv1 adv2'.split():
if key == 'adv2':
fill[key] = fill['adv1']
while fill[key] == fill['adv1']:
fill[key] = choice(a_nouns)
else:
fill[key] = choice(a_nouns)
articles = 'a_ a_ the_ the_ the_ your_ your_own_'.split()
for key in 'np np1 np2'.split():
if key == 'np2':
fill[key] = fill['np1']
while fill[key] == fill['np1']:
fill[key] = choice((choice(coll_nouns), choice(articles) + choice(a_nouns)))
else:
fill[key] = choice((choice(coll_nouns), choice(articles) + choice(a_nouns)))
fill['a_n'] = choice(a_nouns)
fill['coll_n'] = choice(coll_nouns)
for key in 'a_n a_n1 a_n2'.split():
if key == 'a_n2':
fill[key] = fill['a_n1']
while fill[key] == fill['a_n1']:
fill[key] = choice(a_nouns)
else:
fill[key] = choice(a_nouns)
fill['num'] = choice(nums)
fill['prep'] = choice(preps)
fill['tp'] = choice(time_periods)
if random() < 0.1:
fill['tp'] = choice(adjs) + ' ' + fill['tp']
else:
fill2 = mutate()
if random() < 0.8:
fill['v_t'] = fill2['v_t']
while random() < 0.7:
key = choice(list(fill2.keys()))
if key.endswith('1') or key.endswith('2'):
key,other = key[:-1]+'1', key[:-1]+'2'
fill[key] = fill2[key]
fill[other] = fill2[other]
else:
fill[key] = fill2[key]
return fill
def uncap(s):
if any(s.startswith(nm) for nm in names):
return s
if s.startswith("I "):
return s
return s[0].lower() + s[1:]
def gen(s=None, fill=None, lastpatt=['']):
if fill is None:
fill = mutate()
if s is None:
patt = choice(templates)
while patt==lastpatt[0]:
patt = choice(templates)
lastpatt[0] = patt
while random() < 0.1 and patt[-1] != '?':
patt = (gen(s=choice(intros)) +
' ' + (patt[0].lower()
if not patt.startswith("I ")
else patt[0]) + patt[1:])
while random() < 0.1:
patt = patt[:-1] + ', ' + uncap(gen(s=choice(emp_patt))) + patt[-1]
else:
patt = s
#~ ret = patt.format(**fill)
import re
patt = re.sub(r'{([^}]+)}',r'%(\1)s', patt)
ret = patt % fill
ret = ret.replace('_',' ')
for v in "aeiouAEIOU":
if ret.lower().startswith('a '+v):
ret = 'an ' + ret[2:]
ret = ret.replace(' a '+v, ' an '+v)
ret = ret.replace(' to I,', ' to my way of thinking,')
if s is None and random() < 0.05:
ret = ret[:-1]+'!'
return ret[0].upper() + ret[1:]
def pyrac():
sentences = []
for j in range(3):
fill = mutate()
for i in range(12):
sentences.append(gen(fill=fill))
fill = mutate(fill)
sentences.append('')
return sentences
if __name__ == "__main__":
for s in pyrac():
print(s)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment