# Make a bottom up poem

Based on the "Pretty Ugly" poem.

Input consists of a number of stanzas (positive integer), and four arrays/lists of strings, called the "negatives", "negations", "positives", and "filler" sentences.

You must output a "pretty ugly" poem with the specified number of stanzas. A stanza consists of a negative, negation, positive and filler sentence, in that order. Finally, the poem must end with the string (Now read bottom up).

In other words, the output must be a list of strings of the form [negative, negation, positive, filler, negative, negation, positive, filler, negative, ..., "(Now read bottom up)"], with the negative, negation, positive , filler part repeated once per stanza.

Rules:

• The lines should be chosen at random from the lists
• Output can be in any format, as long as it's a comprehensible poem. Printing to STDOUT, returning a list of strings, returning a string with lines separated by commas, and so on are all allowed
• You may assume that the 4 lists are all non-empty, but not that they have the same length
• The number of stanzas can be zero. If so, the output is (Now read bottom up)
• Shortest program (in bytes) wins

Sample input:

n = 4

negatives = [
"I am a terrible person",
"Everything I do is useless",
"I don't deserve to be loved",
"I will never succeed at anything"
]

negations = [
"It's foolish to believe that",
"I don't think it's reasonable to say that",
"I will never believe that",
"No one can convince me into thinking that"
]

positives = [
"I am beautiful inside and out",
"The people around me love me",
"I will succeed at my career",
"I can be successful"
]

fillers = [
"I just have to accept that",
"After all, it's pretty clear",
"So I think it's pretty obvious",
"It will be clear if you think about it"
]


Sample output:

I don't deserve to be loved
I don't think it's reasonable to say that
I will succeed at my career
After all, it's pretty clear
I don't deserve to be loved
I don't think it's reasonable to say that
I can be successful
I just have to accept that
Everything I do is useless
No one can convince me into thinking that
I can be successful
So I think it's pretty obvious
I don't deserve to be loved
It's foolish to believe that
I am beautiful inside and out
I just have to accept that

• I think some test cases would help make this more clear. – Jonah Feb 2 at 3:43
• I'm not sure what's unclear, but I added a sample input and output. – David Lui Feb 2 at 4:01
• Welcome to Code Golf! I'd recommend using the sandbox for future challenges, although I think this is a pretty good first challenge. (To close voter(s): I don't see anything particularly unclear). – Redwolf Programs Feb 2 at 4:49
• @RedwolfPrograms This challenge was sandboxed. – xnor Feb 2 at 6:40

# Perl 5, 62 61 bytes

@randomdude999 pointed out a space I could remove to save a byte.

sub f{(map{map_[rand@$_],@_}1..pop),"(Now read bottom up)"}  Try it online! A function which takes in the sets of statements as a reference to an array for each type of statement and the number of stanzas. Returns an array of strings, one element for each line of the poem. • you can drop the space in rand @$_ to save 1 byte – randomdude999 Feb 3 at 13:43

# Python 2, 135118 115 bytes

from random import*
def f(a,b):
for _ in range(b):
for x in a:shuffle(x);print x[0]


Try it online!

13 for @Danis and 3 for @Arnauld cheers!

• @Arnauld edited please see, now second parameter will take it – Wasif Feb 2 at 5:46
• @Danis so nice of you – Wasif Feb 2 at 5:48
• You should probably use x[0] instead of x.pop(). I think the number of stanzas can be higher than the number of available options, and re-using the same line several times is fine according to the spec. – Arnauld Feb 2 at 5:49
• @Arnauld thanks – Wasif Feb 2 at 6:06
• Does print choice(x) work? Know your Python built-ins... – user202729 Feb 2 at 6:10

# Raku, 56 bytes

{flat @_[^4].map(*.pick)xx^@_[4],"(Now read bottom up)"}


Takes the list arguments in a list.

Try it online!

# Ruby, 57 bytes

Returns a list containing the items.

->a,r{(1..r).map{a.map &:sample}<<"(Now read bottom up)"}


Try it online!

# Ruby, 68 62 bytes

->a,r{r.times{puts a.map &:sample};puts"(Now read bottom up)"}


Try it online!

# Wolfram Language (Mathematica), 55 bytes

Tuples@#2~RandomChoice~#~Append~"(Now read bottom up)"&


Try it online!

Returns a list of stanzas, each of which is a list of strings, followed by the single string "(Now read bottom up)".

# PowerShell, 5966 59 bytes

+7 bytes to fix the zero-stanza case AND -2 bytes after fixing it, thanks to @mazzy; additional 5 bytes cut by iterating on that 2 byte save

param($a,$b),1*$a|%{$b|%{$_|random}} "(Now read bottom up)"  Try it online! • nice. there is the rule 3 The number of stanzas can be zero. If so, the output is (Now read bottom up) – mazzy Feb 2 at 21:37 • @mazzy Thanks, missed that one! Fixed. – Zaelin Goodman Feb 2 at 21:46 • – mazzy Feb 3 at 8:57 • @mazzy thanks! Got it back down to 59 with that idea – Zaelin Goodman Feb 3 at 14:58 # Vyxal, W, 24 bytes ?(4(?℅)?_)(λṠ ƛ□ ¢¼ up)  Try it Online! ## Explained ?(  Start a for loop, repeating number of stanzas times. 4(?℅)  From each list of possible lines, choose a random line. ?_)  Skip over the next input (which would be the number of stanzas again - input is cyclical in Vyxal, meaning that it loops around if EOI is reached [not applicable when using STDIN, only when passing input through command line]) (λ≗ ƛΐ æ∺ up)  Push the string "(Now read bottom up) -W flag  Wrap the entire stack into a list and implicitly output to STDOUT # R, 63 bytes function(n,l)c(l[sample(4,4*n,T)+0:3*4],"(Now read bottom up)")  Try it online! # JavaScript (ES6), 92 bytes Expects ([a0,a1,a2,a3])(n). a=>g=n=>n?a.map(a=>a.sort(_=>Math.random()-.5)[0]).join + +g(n-1):"(Now read bottom up)"  Try it online! # Jelly, 18 bytes ẋX€“ÐƇḶc⁻F¢nḲỵƝḣ»ṭ  Try it online! Takes a list of the four lists as the first argument and the number of stanzas as the second argument. Returns a list of strings. ## Explanation ẋX€“ÐƇḶc⁻F¢nḲỵƝḣ»ṭ Main dyadic link ẋ Cycle the list n times X Choose a random item € from each sublist ṭ Tack (append) “ÐƇḶc⁻F¢nḲỵƝḣ» "(Now read bottom up)"  # 05AB1E, 19 bytes и€Ω“ow‚Ø—è€¾)“„(Nìª  First input is the amount of stanzas, second a list of lists of sentences. Output is a list of strings. Try it online (the » in the footer joins by newlines; feel free to remove it to see the actual list-output). Explanation: и # Repeat the second (implicit) list of lists of strings input the # first (implicit) integer-input amount of times as list € # Map over each inner list: Ω # And take a random string from the list “ow‚Ø—è€¾)“ # Push dictionary string "ow read bottom up)" „(N # Push string "(N" ì # Prepend it at the front "(Now read bottom up)" ª # And append it to the list of sentences # (after which the list is output implicitly as result)  See this 05AB1E tip of mine (section How to use the dictionary?) to understand why “ow‚Ø—è€¾)“ is "ow read bottom up)". # Charcoal, 25 bytes Ｅ⊗⊗θ‽§ηι(N” &？t]₂➙υ/εT§¬+  Try it online! Link is to verbose version of code. Explantion:  θ Number of stanzas ⊗ Doubled ⊗ Redoubled Ｅ Map over implicit range η Array of array of phrases § Cyclically indexed by ι Current index ‽ Choose random phrase Implicitly output on separate lines (N Output literal string (N ” &？t]₂➙υ/εT§¬+ Output compressed string ow read bottom up)  # Retina, 50 bytes L$^\d+
*$' "¶¶"%G@. ¶¶ ¶$


Try it online! Each array of strings must end with a blank marker line. Explanation:

L$^\d+ *$'


Repeat the arrays according to the number of stanzas.

"¶¶"%G@.


Keep a random line from each array.

¶¶
¶


Join the arrays together.

$¶(Now read bottom up)  Append the specified string. # Python 3, 72 bytes lambda a,b:[*map(choice,a*b),'(Now read bottom up)'] from random import*  Try it online! Inspired by @Danis's comment on @Wasif Hasan's Python 2 answer. Input is the same format as both of those (first argument: list of 4 lists of strings, 2nd argument: number of stanzas) # PHP, 124 123 bytes function($a,$n){for(;$n--;)$r=array_merge(array_map(fn($b)=>$b[array_rand($b)],$a),$r??['(Now read bottom up)']);return\$r;}


Try it online!

One time again PHP is suboptimal here, because of the way you can't really use loops or recursion in arrow functions. For reference, my attempt with recursion is 4 bytes longer.

Takes an array of arrays of lines and an integer as input, returns an array of lines

EDIT: saved byte by removing the space after return

# VBScript, 122 bytes

Randomize:n=n-1
For i=0 to n
For Each x in Array(a,b,c,d)
WSH.Echo x(Int(4*Rnd))
Next
Next


a = Array("I am a terrible person","Everything I do is useless","I don't deserve to be loved","I will never succeed at anything")
b = Array("It's foolish to believe that","I don't think it's reasonable to say that","I will never believe that","No one can convince me into thinking that")
c = Array("I am beautiful inside and out","The people around me love me","I will succeed at my career","I can be successful")
d = Array("I just have to accept that","After all, it's pretty clear","So I think it's pretty obvious","It will be clear if you think about it")
n=4


# Husk, 35 20 bytes

:z!İπ*⁰²¨(ηøṘΔż₀Tüp)


Try it online!

Husk is completely deterministic, and has no random number generator. So, on the face of it, "anything involving randomness ... can't be answered in Husk without considerable extra effort or rule-bending"(1).

However, the constraint that 'lines should be chosen at random' seems (to me) to be sufficiently relaxed that we can elect to choose the lines of each stanza using a random (stanza-to-stanza) distribution, even if this is not re-randomized between runs of our program (so sequential runs will output the same 'random' poem (2)).

Some googling indicates that the digits of Pi have been shown to be 'random' (in a certain statistical sense), if a set of constraints about the distribution of chaotic sequences holds true (3). Although this conjecture is still unproven, it suggests that we can use the digits of Pi as a random sequence, until proven otherwise.

So:

:z!İπ*⁰²¨(ηøṘΔż₀Tüp)    # Program with arg1=number of stanzas,
# arg2=list of lists of lines:

*⁰²                # repeat the list of lists of lines arg1 times,
z!İπ                   # and, for each list, select the line at the index
# given by the next digit of pi
# (wrapping around the end of the list if there are
# <10 elements, and ignoring any lines beyond the
# tenth),
:       ¨(ηøṘΔż₀Tüp)    # and finally append the compressed string:


(1) Credit: Zgarb's description of Husk caveats in its nomination for 'language of the month'.
(2) If you don't like successive runs outputting the same random poem, we can offset the digit of Pi at which to start, using a user-provided 'random seed' in arg 3, for 2 more bytes.
(3) https://www.nersc.gov/news-publications/nersc-news/science-news/2001/are-the-digits-of-pi-random/

# Julia, 57 bytes

f(n,l)=n<1 ? "(Now read bottom up)" : [rand.(l);f(n-1,l)]


Try it online!

output is a list of strings