You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
4.3 KiB
Python
157 lines
4.3 KiB
Python
4 years ago
|
#!/usr/bin/env python
|
||
|
# -*- coding: <utf-8> -*-
|
||
|
|
||
|
'''
|
||
|
It automatises the Oulipo constraint Litterature Definitionelle:
|
||
|
http://oulipo.net/fr/contraintes/litterature-definitionnelle
|
||
|
|
||
|
invented by Marcel Benabou in 1966
|
||
|
In a given phrase, one replaces every significant element (noun, adjective, verb, adverb)
|
||
|
by one of its definitions in a given dictionary ; one reiterates the operation on the newly received phrase,
|
||
|
and again.
|
||
|
|
||
|
|
||
|
Copyright (C) 2018 Constant, Algolit, An Mertens, Gijs de Heij
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details: <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
'''
|
||
|
|
||
|
import nltk
|
||
|
from nltk.corpus import wordnet as wn
|
||
|
from nltk import word_tokenize
|
||
|
import nltk.data
|
||
|
import random
|
||
|
import re
|
||
|
import time
|
||
|
import wikipedia
|
||
|
from trees import trees
|
||
|
import os
|
||
|
import os.path
|
||
|
|
||
|
from colored import fg, attr
|
||
|
|
||
|
## Text attributes
|
||
|
bold = attr(1)
|
||
|
underlined = (4)
|
||
|
reset = attr(0)
|
||
|
|
||
|
## Text colors
|
||
|
black = fg(0)
|
||
|
spring_green = fg(48)
|
||
|
light_gray = fg(7)
|
||
|
sky_blue = fg(109)
|
||
|
yellow = fg(3)
|
||
|
|
||
|
|
||
|
def choose_a_tree(dict):
|
||
|
collection = random.choice(list(trees.items()))
|
||
|
# Give name gardener
|
||
|
gardening = collection[0]
|
||
|
cut = " in "
|
||
|
if cut in gardening:
|
||
|
index = re.search(cut, gardening).start()
|
||
|
gardener = gardening[:index]
|
||
|
source = gardening[index+3:]
|
||
|
else:
|
||
|
gardener = gardening
|
||
|
source = 'Unknown'
|
||
|
# Trees (s)he planted
|
||
|
tree = collection[1]
|
||
|
# if (s)he planted more than 1 tree, pick 1
|
||
|
if type(tree) == list:
|
||
|
tree = random.choice(tree)
|
||
|
return gardener, source, tree
|
||
|
|
||
|
# find bio gardener on Wikipedia
|
||
|
def bio(gardener):
|
||
|
try:
|
||
|
bio = wikipedia.page(gardener)
|
||
|
short_bio = bio.summary
|
||
|
except:
|
||
|
short_bio = "{}There is no English Wikipedia page about this person.{}".format(sky_blue, reset)
|
||
|
return short_bio
|
||
|
|
||
|
def bio_offline(gardener):
|
||
|
filename = os.path.join('bios', re.sub(r'\W', '', gardener))
|
||
|
|
||
|
if os.path.exists(filename):
|
||
|
with open(filename, 'r') as h:
|
||
|
return h.read()
|
||
|
|
||
|
return "{}There is no English Wikipedia page about this person.{}".format(sky_blue, reset)
|
||
|
|
||
|
|
||
|
"""
|
||
|
Return blossoming version of the knot.
|
||
|
knot string
|
||
|
return string
|
||
|
"""
|
||
|
def grow_new_branch (bud):
|
||
|
branch = wn.synsets(bud)
|
||
|
|
||
|
if branch:
|
||
|
return branch[0].definition()
|
||
|
|
||
|
return bud
|
||
|
|
||
|
# Turn nltk tree back into a sentence
|
||
|
def trim_tree (branches):
|
||
|
tree = " ".join([branch[0] for branch in branches])
|
||
|
return re.sub(r'\s[\.,:;\(\)]', '', tree)
|
||
|
|
||
|
def show (state, length=1):
|
||
|
os.system('clear')
|
||
|
# Optionally vertically align here
|
||
|
print(state)
|
||
|
time.sleep(length)
|
||
|
|
||
|
def grow (tree, generation = 1):
|
||
|
branches = nltk.pos_tag(word_tokenize(tree))
|
||
|
# Filter out nouns, pick one
|
||
|
position, bud = random.choice([(position, bud[0]) for position, bud in enumerate(branches) if bud[1] == 'NN'])
|
||
|
|
||
|
# Make new tree placeholder for the bud show we can show it in two states and then grow out
|
||
|
next_tree = '{} {{}} {}'.format(trim_tree(branches[:max(0, position)]), trim_tree(branches[position+1:]))
|
||
|
new_branch = grow_new_branch(bud)
|
||
|
|
||
|
show(tree, 3 if generation == 1 else 1)
|
||
|
# Mark the bud, underlined and orange
|
||
|
show(next_tree.format("{}{}{}{}{}".format(bold, yellow, bud, reset, black)), 2)
|
||
|
# Mark the new branch green
|
||
|
show(next_tree.format("{}{}{}".format(spring_green, new_branch, black)), 2)
|
||
|
show(next_tree.format("{}{}{}".format(fg(82), new_branch, black)), 1)
|
||
|
show(next_tree.format("{}{}{}".format(fg(120), new_branch, black)), 1)
|
||
|
show(next_tree.format("{}{}{}".format(fg(157), new_branch, black)), 1)
|
||
|
show(next_tree.format("{}{}{}".format(fg(195), new_branch, black)), 1)
|
||
|
# Let it grow again
|
||
|
|
||
|
return next_tree.format(new_branch)
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
while True:
|
||
|
gardener, source, tree = choose_a_tree(trees)
|
||
|
short_bio = bio_offline(gardener)
|
||
|
|
||
|
show(
|
||
|
'Using a quote by {}{}{}\n\n'.format(bold, gardener, reset) \
|
||
|
+ short_bio, 3
|
||
|
)
|
||
|
|
||
|
generation = 1
|
||
|
|
||
|
while len(tree) < 1500:
|
||
|
next_tree = grow(tree, generation)
|
||
|
if next_tree == tree:
|
||
|
break
|
||
|
else:
|
||
|
tree = next_tree
|
||
|
generation += 1
|