#!/usr/bin/env python # coding: utf-8 # # Implementations of early and well-known poetry generators # # By [Allison Parrish](http://www.decontextualize.com/) # # This notebook has some Python implementations of a number of early and well-known poetry generators, including Knowles and Tenney's *A House of Dust*, Strachey's love letter generator and Nick Montfort's *Taroko Gorge*. # ## To Make a Dadaist Poem # # Original written by [Tristan Tzara](http://www.391.org/manifestos/1920-dada-manifesto-feeble-love-bitter-love-tristan-tzara.html#.WnPkJYJOndd) in 1920. # In[1]: import random import textwrap newspaper = """ Dada was an informal international movement, with participants in Europe and North America. The beginnings of Dada correspond to the outbreak of World War I. For many participants, the movement was a protest against the bourgeois nationalist and colonialist interests, which many Dadaists believed were the root cause of the war, and against the cultural and intellectual conformity — in art and more broadly in society — that corresponded to the war.""" words = newspaper.split() random.shuffle(words) print(textwrap.fill(" ".join(words), 60)) # ## A House of Dust # # Original written in Fortran in 1967 by Alison Knowles and James Tenney. [ELMCIP entry](https://elmcip.net/creative-work/house-dust). [More information](http://blog.calarts.edu/2009/09/10/alison-knowles-james-tenney-and-the-house-of-dust-at-calarts/). [Watch Alison Knowles read from this piece](https://www.youtube.com/watch?v=-68Z708lFsY). # In[2]: import random # In[3]: materials = [ 'brick', 'broken dishes', 'discarded clothing', 'dust', 'glass', 'leaves', 'mud', 'paper', 'plastic', 'roots', 'sand', 'steel', 'stone', 'straw', 'tin', 'weeds', 'wood' ] # In[4]: locations = [ 'among high mountains', 'among other houses', 'among small hills', 'by a river', 'by an abandoned lake', 'by the sea', 'in a cold, windy climate', 'in a deserted airport', 'in a deserted church', 'in a deserted factory', 'in a green, mossy terrain', 'in a hot climate', 'in a metropolis', 'in a place with both heavy rain and bright sun', 'in an overpopulated area', 'in dense woods', 'in heavy jungle undergrowth', 'in japan', 'in michigan', 'in southern france', 'inside a mountain', 'on an island', 'on the sea', 'underwater' ] # In[5]: lights = [ 'all available lighting', 'candles', 'electricity', 'natural light' ] # In[6]: inhabitants = [ 'all races of men represented wearing predominantly red clothing', 'children and old people', 'collectors of all types', 'fishermen and families', 'french and german speaking people', 'friends', 'friends and enemies', 'horses and birds', 'little boys', 'lovers', 'people from many walks of life', 'people speaking many languages wearing little or no clothing', 'people who eat a great deal', 'people who enjoy eating together', 'people who love to read', 'people who sleep almost all the time', 'people who sleep very little', 'various birds and fish', 'vegetarians', 'very tall people' ] # In[7]: stanza_count = 7 for i in range(stanza_count): print() print("A house of " + random.choice(materials)) print(" " + random.choice(locations)) print(" using " + random.choice(lights)) print(" inhabited by " + random.choice(inhabitants)) # ## Love Letter Generator # # Original by Christopher Strachey, written for the Manchester Mark I in 1952. [Read more here](https://grandtextauto.soe.ucsc.edu/2005/08/01/christopher-strachey-first-digital-artist/). # # Vocabulary based on [this implementation](https://github.com/gingerbeardman/loveletter/blob/master/index.php). # In[8]: sal_adjs = [ "Beloved", "Darling", "Dear", "Dearest", "Fanciful", "Honey"] # In[9]: sal_nouns = [ "Chickpea", "Dear", "Duck", "Jewel", "Love", "Moppet", "Sweetheart" ] # In[10]: adjs = [ 'affectionate', 'amorous', 'anxious', 'avid', 'beautiful', 'breathless', 'burning', 'covetous', 'craving', 'curious', 'eager', 'fervent', 'fondest', 'loveable', 'lovesick', 'loving', 'passionate', 'precious', 'seductive', 'sweet', 'sympathetic', 'tender', 'unsatisfied', 'winning', 'wistful' ] # In[11]: nouns = [ 'adoration', 'affection', 'ambition', 'appetite', 'ardour', 'being', 'burning', 'charm', 'craving', 'desire', 'devotion', 'eagerness', 'enchantment', 'enthusiasm', 'fancy', 'fellow feeling', 'fervour', 'fondness', 'heart', 'hunger', 'infatuation', 'little liking', 'longing', 'love', 'lust', 'passion', 'rapture', 'sympathy', 'thirst', 'wish', 'yearning' ] # In[12]: advs = [ 'affectionately', 'ardently', 'anxiously', 'beautifully', 'burningly', 'covetously', 'curiously', 'eagerly', 'fervently', 'fondly', 'impatiently', 'keenly', 'lovingly', 'passionately', 'seductively', 'tenderly', 'wistfully' ] # In[13]: verbs = [ 'adores', 'attracts', 'clings to', 'holds dear', 'hopes for', 'hungers for', 'likes', 'longs for', 'loves', 'lusts after', 'pants for', 'pines for', 'sighs for', 'tempts', 'thirsts for', 'treasures', 'yearns for', 'woos' ] # In[14]: # textwrap library used to "wrap" the text at a particular length import textwrap # output begins with salutation output = random.choice(sal_adjs) + " " + random.choice(sal_nouns) + ",\n" output += "\n" # inside this loop, build the phrases. strachey implemented "short" phrases # and "long" phrases; two or more "short" phrases in a row have special # formatting rules, so we need to know what the last phrase kind was in # order to generate the output. history = [] body = "" for i in range(5): kind = random.choice(["short", "long"]) if kind == "long": # adjectives and adverbs will be present only 50% of the time line = " ".join([ "My", random.choice([random.choice(adjs), ""]), random.choice(nouns), random.choice([random.choice(advs), ""]), random.choice(verbs), "your", random.choice([random.choice(adjs), ""]), random.choice(nouns)]) body += line else: adj_noun = random.choice(adjs) + " " + random.choice(nouns) # if the last phrase was "short," use truncated form if len(history) > 0 and history[-1] == "short": body += ": my " + adj_noun else: body += "You are my " + adj_noun body += ". " history.append(kind) # clean up output body = body.replace(" ", " ") body = body.replace(". :", ":") # put everything together output += textwrap.fill(body, 60) output += "\n\nYours " + random.choice(advs) + ",\n" output += "M.U.C." print(output) # ## Taroko Gorge # # [Original](http://nickm.com/taroko_gorge/) by [Nick Montfort](http://nickm.com/). [ELMCIP entry here](https://elmcip.net/creative-work/taroko-gorge). # In[15]: above = ['brow', 'mist', 'shape', 'layer', 'the crag', 'stone', 'forest', 'height'] below = ['flow', 'basin', 'shape', 'vein', 'rippling', 'stone', 'cove', 'rock'] transitive = ['command', 'pace', 'roam', 'trail', 'frame', 'sweep', 'exercise', 'range'] imperative = ['track', 'shade', 'translate', 'stamp', 'progress through', 'direct', 'run', 'enter'] intransitive = ['linger', 'dwell', 'rest', 'relax', 'hold', 'dream', 'hum'] texture = ['rough', 'fine'] adjectives = ['encompassing', 'sinuous', 'straight', 'objective', 'arched', 'cool', 'clear', 'dim', 'driven'] # In[16]: def path(): plural = random.sample(["s", ""], k=2) words = random.choice(above) if words == "forest" and random.randrange(4) == 0: words = "monkeys" + " " + random.choice(transitive) else: words += plural[0] + " " + random.choice(transitive) + plural[1] words += " the " + random.choice(below) + random.choice(["s", ""]) + "." return words.capitalize() # In[17]: def cave(): adjs = adjectives[:] + random.sample(texture, 1) return " " + random.choice(imperative) + " " + \ " ".join(random.sample(adjs, random.randrange(1, 4))) + " —" # In[18]: def site(): if random.randrange(2) == 0: words = random.choice(above) else: words = random.choice(below) words += "s " + random.choice(intransitive) + "." return words.capitalize() # In[19]: stanza_count = 10 for repeat in range(stanza_count): line_count = random.randrange(3, 6) for i in range(line_count): if i == 0: print(path()) elif i == line_count - 2: print(path()) elif i == line_count - 1: print() print(cave()) print() else: print(site())