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.
Grafting-Trees/growing_a_tree_sketch.py

157 lines
4.3 KiB
Python

#!/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