A terrible science haiku generator

For the first time in my recent memory, I have a tiny bit of free time on my hands. How have I spent it? Writing a terrible Python program that generates haikus about exploring one’s place in the Universe with science. It’s truly awful. But one in every twenty or so haikus kind of makes sense. Here are some examples:

chasing after truth
beautiful contradictions
attracting questions

scientific thoughts
reactive information
simple Universe

pursuing great facts
confusing algorithms
deft experiments

I still have to manually add in the commas

scientific light
surprising, questioning thoughts
contrasting warm truth

graceful, simple facts
great secrets, hypotheses
uncovering light

misunderstood time
risky, beautiful secrets
colourful, cold truth

Sometimes I have to get real liberal with the commas:

chasing time, space, truth
deft matter, zeros and ones
cold data, warm thoughts

colourful chaos
changing theories, answers, thoughts
uncovering truth

It’s not a machine-learning algorithm, but rather a fancy word bank with random selection processes subject to a few rules. These words banks include verbs, nouns, and adjectives. There are no adverbs or prepositions, although I do include a conjunction or two after some verbs. No word repetitions are permitted. I enforce the 5-7-5 syllable count structure, impose a word count limit for the middle line, and restrict certain parts of speech to certain places in the line. Nevertheless, I still get lots of completely nonsensical stanzas, such as:

great molecules, thoughts
misunderstood graceful space
overwhelming code

overwhelming space
thoughts surprising everything
searching for light facts

Here are some of my favorite dramatic phrases produced by the algorithm:

  • “cold data, warm thoughts”
  • “haunting code chaos” (basically my life)
  • “contradicting space data”

Sometimes it spits out some mildly anti-scientific phrases:

  • “rejecting data”
  • “risky science facts”

Haikus that sound like they might make sense but don’t really:

chasing after light
matter questioning science
scavenging for time

complex reagents
fluid, reactive theories
contradicting facts

discovering space
beautiful science process
chasing everything

graceful, warm matter
charged chaos algorithms
surprising, dark truth

The Python program is shown below. The code is functional, though a bit hacky. If desired, you can paste it into a file called “science_haiku_generator.py” and run it to generate your own haikus:

"""
This script generates poems about exploring
one's place in the universe with science.
"""

import random

noun_list = []
noun_list.append(("",))
noun_list.append(("truth", "facts", "time", "space", "thoughts", "light", "code"))
noun_list.append(("science", "ideas", "questions", "secrets", "answers",
                "matter", "data", "process", "chaos", "theories", "meaning", "atoms", "distance"))
noun_list.append(("chemicals", "reagents", "galaxies", "molecules", "reactions",
                "everything", "Universe", "elements"))
noun_list.append(("hypotheses", "information", "experiments", "zeros and ones", "algorithms",
                    "contradictions"))

adj_list = []
adj_list.append(("",))
adj_list.append(("charged", "vast", "dark", "cold", "warm", "great", "deft"))
adj_list.append(("fluid", "graceful", "complex", "simple", "basic", "active", "risky"))
adj_list.append(("exciting", "surprising", "reactive", "contrasting", "questioning",
                    "amazing", "colourful", "beautiful", "curious", "delicate", "confusing"))
adj_list.append(("unbelievable", "irrevocable", "contradicting", "overwhelming",
                    "scientific", "mysterious", "misunderstood"))

verb_list = []
verb_list.append(("",))
verb_list.append(("",))
verb_list.append(("changing", "glowing", "searching", "chasing", "haunting"))
verb_list.append(("questioning", "exciting", "surprising", "revealing", "attracting",
                    "pursuing", "designing", "searching for", "rejecting"))
verb_list.append(("discovering", "uncovering", "scavenging for", "chasing after"))

# Initialize haiku:
lines = []
lines.append("")
used = ["initial",]

word_count = [0, 0, 0]
index = 0
syllabs = [5, 7, 5]
syllab_count = [index, ]
syllab_count.append(0)
i = 0

total_syllabs = index

while(total_syllabs < 17):
    
    # Compute number of remaining syllables and choose next syllable
    remaining = syllabs[i] - syllab_count[i]
    upper_bound = 0
    if remaining <= 4: 
        upper_bound = remaining 
    else: 
        upper_bound = 4 
    index = random.randint(1,upper_bound) 
    word = "initial" 
    
    while(word in used): 
        # Count how many syllables to determine if we're 
        # on the last word in the line 
        syllab_test = syllab_count[i] + index 
        # If first word in line, choose adjective or verb 
        if syllab_count[i] == 0: 
            if i == 1: 
                word = random.choice((random.choice(verb_list[index]), random.choice(adj_list[index]), random.choice(noun_list[index]))) 
            else: word = random.choice((random.choice(verb_list[index]), random.choice(adj_list[index]))) 
        # If last word in line, choose noun 
        elif syllab_test == syllabs[i]: 
            word = random.choice(noun_list[index]) 
        # If in middle of line, choose noun or adjective 
        else: 
            # If middle line, prevent a bunch of one-syllable words 
            if i == 1 and upper_bound-1 >= 2:
                index = random.randint(2,upper_bound-1) # -1 to make sure we don't end on adj
            word = random.choice((random.choice(noun_list[index]),
                                    random.choice(adj_list[index])))
            # Prevent excessive words counts
            if word_count[i] >= 2:
                index = upper_bound
                word = random.choice(noun_list[index])

    if(len(word) > 0):
        lines[i] = lines[i] + word + " "
        word_count[i] += 1
        total_syllabs += index
        used.append(word)
        syllab_count[i] += index
        if syllab_count[i] == syllabs[i]:
            if i == 2:
                break
            else:
                i += 1
                lines.append("")
                syllab_count.append(0)


for i, line in enumerate(lines):
    print(line)

Leave a Reply

Your email address will not be published. Required fields are marked *