Rockstar is an esoteric programming language that creates code that looks like song lyrics.
I tried to use it to solve this code puzzle: https://adventofcode.com/2022/day/1.
This wasn't that hard, and after puzzling a bit, I ended up with this code that works.
my ship is everythingwaves are everythinglet my life be waveslet my dreams be wavesListen to the sea
A pirate wants gold and freedomIf gold is greater than freedomsend gold
give freedom back
While the sea isn't mysterious or the mind isn't mysteriousIf the sea is silentlet my life be a pirate taking my ship, and my lifelet my ship be wavesPut the sea into the mindListen to the sea
If the sea isn't silentlet my love be the sea without waves let my ship be with my lovePut the sea into the mindListen to the sea
let the sea be my lifeshout her
(Full explanation of all the lines follows further below in this blogpost)
You can try it online, and it returns the correct answer if you append two newlines to the bottom of the input. But this could be nicer.
According to the specifications, the expression:
the sea is mysterious
In addition, the expression:
If the sea is silent
But in practice, due to a bug in the interpreter, both mysterious and silent act exactly the same and match both an empty string and a null value. This means we cannot distinguish between the two and need two newlines at the end to ensure the program can detect it.
If we write a program according to spec, we get these lines.
my ship is everything
waves are everything
let my life be waves
let my dreams be waves
Listen to the sea
A pirate wants gold and freedom
If gold is greater than freedom
send gold
give freedom back
While the sea isn't mysterious
If the sea is silent
let my life be a pirate taking my ship, and my life
let my ship be waves
Listen to the sea
If the sea isn't silent
let my love be the sea without waves
let my ship be with my love
Listen to the sea
let the sea be my life
shout herI also realigned the verses, so each verse has 4 lines. I also broke down long lines into two, and combined some shorter lines.
Both these changes completely break the program as a valid rockstar program, but make it possible to actually sing it.
So then I end up with verses that are close to the working program but not quite.
my ship is everything
waves are everything
let my life be waves; let my dreams be waves
Listen to the sea
A pirate wants gold and freedom
If gold is greater than freedom
send gold, give freedom back
While the sea isn't mysterious
If the sea is silent
let my life be a pirate
taking my ship, and my life
Listen to the sea
If the sea isn't silent
let my love be the sea without waves
let my ship be with my love
Listen to the sea
let the sea be my life
shout herThe full song (before I applied a bunch of artistic licences) is equivalent to the following python code.
There are only two caveats.
myShip = 0
waves = 0
myLife = waves
myDreams = waves
theSea = input()
def aPirate(gold, freedom):
if gold > freedom:
return gold
return freedom
while theSea is not None:
if theSea == '':
myLife = aPirate(
myShip, myLife
)
myShip = 0
theSea = input()
if theSea != '':
myLove = theSea - waves
myShip += myLove
theSea = input()
theSea = myLife
print(theSea)
- the input function in python blocks when there are no more lines to read, I modified it to return None instead. This matches the behaviour in rockstar
- Rockstar uses javascript internally, so a string minus an integer is an integer. In python, this gives an error.
You can add these lines above your script to mitigate both problems.
Here follows a line-by-line explanation of all the code:
with open("input1.txt") as file:
lines = list(reversed(file.read().split("\n")))
def input():
if lines:
l = lines.pop()
try:
return int(l)
except ValueError:
return l
myShip = 0 | my ship is everything
waves = 0 | waves are everything
myLife = waves | let my life be waves
myDreams = waves | let my dreams be waves
We initialise a bunch of variables. "everything" has ten letters, so the value of the poetic literal is 0.
The variable "myDreams" is never used, but it was left over after a refactor, and the song flows better using the variable, so I decided to leave it.
theSea = input() | Listen to the sea
Store the current line from the input into the sea. Rockstar does not have "foreach" nor "do while" loops, so the only way to read the input line by line is to initialize "theSea" to the first line before the while loop. More about that later.
def aPirate(gold, freedom): | A pirate wants gold and freedom
if gold > freedom: | If gold is greater than freedom
return gold | Send gold
return freedom | Give freedom back
Define a function "aPirate" that takes in two arguments ("gold" and "freedom") and returns the larger one. Needs a newline after "Send gold" to close the if block and after "return freedom" to close the function call.
while theSea is not None: | While the sea isn't mysterious
A while loop. while the input file has unread lines.
if theSea == '': | If the sea is silent
Checks if we have read an empty line. In the context of the riddle, we start to count the calories of a new elf.
myLife = aPirate(myShip, myLife) | let my life be a pirate taking my ship, and my life
"myLife" is a variable that stores the elf with the highest amount of calories. "myShip" stores the calories of the current elf. This line of code stores the maximum of the calories of the current elf and the already found maximum into the maximum. In python terms, this would be equivalent to myLife = max(myShip, myLife). This changes the variable "myLife" from "the highest number of calories excluding the current elf" to "the highest number of calories including the current elf."
myShip = 0 | let my ship be waves
Resets the "myShip", meaning the "current calory counter" back to zero. This line is missing in the sung version.
theSea = input() | Listen to the sea
Reads the next line of the input
if theSea != '': | If the sea isn't silent
Checks if we have read a non-empty line. This is the alternative (else) branch of the previous if. Although in practice, it can be shortcutted cause the variable "theSea" might have changed since the previous if. This makes no difference to the actual execution of the code.
myLove = theSea - waves | let my love be the sea without waves
Converts "theSea" to an integer. This is a hack. In javascript -and rockstar by extension- subtracting zero from a string converts it into an integer. So "myLove" ends up with a number of calories as an integer.
myShip += myLove | let my ship be with my love
Adds the number of calories on the current line to the number of calories of the current elf.
theSea = input() | Listen to the sea
Reads the next line of the input
theSea = myLife | let the sea be my life
print(theSea) | shout her
Just a poetic version of printing the current maximum stored in "myLife."