Markov chain poetry generator
Posted by Affectionate-Town-67@reddit | Python | View on Reddit | 0 comments
Hi, I'm new here. I have been Python coding for 6 weeks pretty seriously on a daily basis and writing avant-garde poetry for years. I made a script today for using a Markov chain to generate a poem line by line, including a corpus text of about 2,600 sentences that I have on my GitHub. This isn't necessarily for production, but it is usable. It's excellent to generate ideas for phrases and lines.
This is the first thing I've developed that has some level of real value to me. None of it was written by AI. The script is here for your viewing pleasure. You can find the .py file and poetry lines CSV for the corpus at my GitHub if you want to try it out in an IDE:
https://github.com/QuothTheRaven42/Projects/blob/main/Markov%20Chain%20Poetry%20Generator.py
https://github.com/QuothTheRaven42/Projects/blob/main/poetry_lines.csv
import random, sys
from termcolor import colored
print(colored("---------------MARKOV CHAIN POETRY GENERATOR---------------", "blue", "on_grey", attrs=["bold"], force_color=True))
def main(poem=""):
count = 0
quadruplets = []
piece = []
piece2 = []
piece3 = []
piece4 = []
with open("poetry_lines.csv", encoding="utf-8") as f:
poetry_lines = f.readlines()
for line in poetry_lines:
# reset so the quads don't bleed over into other sentences awkwardly
piece = []
piece2 = []
piece3 = []
piece4 = []
count += 1
# staggering the start of quads
for word in line.split():
finalized_word = (word.lower()
.replace(".", "")
.replace("—", ""))
if count == 1:
piece.append(finalized_word)
elif count == 2:
piece.append(finalized_word)
piece2.append(finalized_word)
elif count == 3:
piece.append(finalized_word)
piece2.append(finalized_word)
piece3.append(finalized_word)
else:
piece.append(finalized_word)
piece2.append(finalized_word)
piece3.append(finalized_word)
piece4.append(finalized_word)
# append once a quad list has the required 4
if len(piece) == 4:
quadruplets.append(piece)
piece = []
elif len(piece2) == 4:
quadruplets.append(piece2)
piece2 = []
elif len(piece3) == 4:
quadruplets.append(piece3)
piece3 = []
elif len(piece4) == 4:
quadruplets.append(piece4)
piece4 = []
# always ask for the first word of each line
word = input("What should the first word of this line be? ").lower()
print()
# reset input if no quad starts with their word
while not any(quad[0] == word for quad in quadruplets):
word = input("Word not found in corpus. Try again: ").lower()
this_line = ""
for _ in range(5):
try:
# append next quad to the sentence
quads = [quad for quad in quadruplets if quad[0].lower() == word.lower()]
chosen_quad = random.choice(quads)
if _ == 0:
this_line += " ".join(chosen_quad)
else:
# don't add first word if it's not the first quad so the word doesn't repeat
this_line += " ".join(chosen_quad[1:])
word = chosen_quad[3]
this_line += " "
except IndexError:
break
finalized_line = this_line.capitalize().strip()
print(finalized_line + "\n")
finalized_poem = (poem.strip()
.replace(" i ", " I ")
.replace("i'", "I'")
.replace(" ", " ")
.replace(",", "")
+ ".")
choice = input("""Do you want to:
(1) Append to your poem?
(2) Retry this line?
(3) Print final poem and quit?
(4) Save to file and quit?
(5) Quit? """).strip()
enjoy = "***********ENJOY YOUR NEW POEM!***********"
match choice:
case "1":
poem += "\n" + finalized_line
print(poem + '\n')
main(poem)
case "2":
print(poem + "\n")
main(poem)
case "3":
poem += "\n" + finalized_line
print("\n" + finalized_poem + "\n")
print(enjoy)
case "4":
title = input("\nWhat do you want to name this poem? ")
filename = title + '.txt'
with open(filename, 'w') as file:
poem += "\n" + finalized_line
print(f'\n"{title.capitalize()}"')
print("\n" + finalized_poem)
file.write(finalized_poem)
print(f"\nfile saved as {filename}\n")
print(enjoy)
sys.exit()
case _:
poem += "\n" + finalized_line
print("\n" + finalized_poem + "\n")
print(enjoy)
sys.exit()
if __name__ == '__main__':
main()