Constrained programming, part 2
The second letter in “etaoin shrdlu” is t. Some Ruby method names and keywords that contain the letter t include return, #match, true, #split, #to_i, next, #empty?, #length, and #select. I write this here so I don’t have to figure out how to talk around those explicitly forbidden words.
Of the above, I couldn’t figure out how to get around #to_i without implementing it myself.
Day 2 | Ruby | Avoiding glyph before ‘u’
def as_number(word)
if word == "100"
100
elsif word.size == 1
word.ord - 48
else
(word.ord - 48) * 10 + word.chars[1].ord - 48
end
end
# Problem 1
games = IO.readlines('02').map(&:chop)
ids = games.map do |game|
draws = game.scan /(\d+) ([bgr])/
invalid = draws.keep_if do |draw|
num = as_number(draw[0])
color = draw[1]
(num > 12 && color == 'r') || (num > 13 && color == 'g') || (num > 14 && color == 'b')
end
invalid.size == 0 ? as_number(game.scan(/Game (\d+)/)[0][0]) : 0
end
p ids.sum
# Problem 2
powers = games.map do |game|
cubes = {"r" => 0, "b" => 0, "g" => 0}
game.scan(/(\d+) ([bgr])/) do |draw|
num = as_number(draw[0])
color = draw[1]
cubes[color] = num if cubes[color] < num
end
cubes.values.reduce(&:*)
end
p powers.sum
Constrained programming
I’ve enjoyed constrained writing (e.g. Oulipo) for a long time and am going to be trying to practice constrained programming in Advent of Code for as long as I can maintain interest this year. In particular, my plan is to go through each day as a lipogram of the nth-most-frequent letter in English. For the first twelve, even though English letter frequency is slightly different than ETAOIN SHRDLU, I’ll use that iconic order.
So my day 1 solution will not include the letter ‘e’, day 2 will not include the letter ‘t’, and so on. I’m excited to try this out. Here’s day 1:
Day 1 | Ruby | Avoiding fifth glyph
# part 1
digits = inputs.map { |input| input.gsub(/\D/, '')}
calibrations = digits.map { |digit| digit.chars.first.to_i * 10 + digit.chars.last.to_i }
p calibrations.sum
# part 2
glyph_to_avoid = "d".succ
@trigrams = {"two" => 2, "six" => 6}
@trigrams["onz".gsub(/z/, glyph_to_avoid)] = 1
@quadragrams = {"four" => 4}
@quadragrams["fivz".gsub(/z/, glyph_to_avoid)] = 5
@quadragrams["ninz".gsub(/z/, glyph_to_avoid)] = 9
@quintagrams = {}
@quintagrams["thrzz".gsub(/z/, glyph_to_avoid)] = 3
@quintagrams["szvzn".gsub(/z/, glyph_to_avoid)] = 7
@quintagrams["zight".gsub(/z/, glyph_to_avoid)] = 8
calibrations = inputs.map { |input|
first_digit = nil
(0..input.chars.count - 1).map { |idx|
first_digit = input[idx].to_i if !first_digit && /\d/ =~ input[idx]
tri = input[idx-2, 3] if idx >= 2
first_digit = @trigrams[tri] if !first_digit && tri && @trigrams[tri]
quad = input[idx-3, 4] if idx >= 3
first_digit = @quadragrams[quad] if !first_digit && quad && @quadragrams[quad]
quint = input[idx-4, 5] if idx >= 4
first_digit = @quintagrams[quint] if !first_digit && quint && @quintagrams[quint]
}
last_digit = nil
(1..input.chars.count).map { |idx|
last_digit = input[-idx].to_i if !last_digit && /\d/ =~ input[-idx]
tri = input[-idx, 3] if idx >= 2
last_digit = @trigrams[tri] if !last_digit && tri && @trigrams[tri]
quad = input[-idx, 4] if idx >= 3
last_digit = @quadragrams[quad] if !last_digit && quad && @quadragrams[quad]
quint = input[-idx, 5] if idx >= 4
last_digit = @quintagrams[quint] if !last_digit && quint && @quintagrams[quint]
}
first_digit * 10 + last_digit
}
p calibrations.sum
Not using control flow words was tough to work around. I initially had ‘x’ for a proxy glyph until I got to ‘six’.
rizz
The quality rizz was popularized by streamer Kai Cenat on Twitch and later YouTube in the summer of 2021. To us olds, Kai is probably most well-known for accidentally starting a riot in Union Square, NYC earlier this August. It’s thought to be a phonetic clipping of charisma. The word’s usage took off on TikTok in mid-2022, giving rise to incredible explainers like this one from Defector: https://defector.com/livvy-rizzing-up-baby-gronk-explained
The KnowYourMeme history of the term has more detail for the curious: https://knowyourmeme.com/memes/rizz-unspoken-rizz
spam
The canned meat spam was introduced by Minnesota-based Hormel Foods Corporation in 1937. Officially, the origin of the name is a corporate secret, but it’s likely named after a contraction of an earlier Hormel canned meat product sold as “spiced ham”.
Spam turned out to have the right combination of qualities to be effective food aid, so large quantities were produced and distributed as part of the WW2 Lend-Lease Act. In particular, the UK was sent vast quantities of the food, exemplified by Margaret Thatcher pejoratively describing it as a “wartime delicacy”. Spam became a key ingredient in Hawaiian and Filipino cuisine during this time.
A generation later, in 1970 UK comedy troupe Monty Python referenced the phenomenon in an absurdist sketch set in a restaurant where all the menu items contained spam, often more than once. Here’s a menu photo from a 2014 theatrical production.
Monty Python was then a touchstone of nerd culture, so the spam sketch and its associated song lyrics sometimes showed up as trolly chat macros on Usenet and IRC in the 1980s. Two different related slang meanings eventually became codified on the internet: email spam, which is first named as such in 1993, and the verb spamming for repeatedly sending messages to fill up the chat buffer. Both meanings first appear in a print dictionary in 1998.
winter
The season winter predates English, which means it was first used some time before the year 400. I’ve been focusing on new or interesting words in these posts, but that’s not really representative of the set of words we use in practice. The plurality of words used in both English speech and writing are still old Germanic in origin, i.e. from before the year 400. Courtesy of this youtube video, here’s a Dutch sentence that you could render into English using only Germanic words:
De koude winter is nabij, een sneeuwstorm zal komen. Kom in mijn warme huis, mijn vriend. Welkom! Kom hier, zing en dans, eet en drink. Dat is mijn plan. We hebben water, bier, en melk vers van de koe. Oh, en warme soep!
For completeness, about 1000 years ago the four seasons in English would be called lengthen, summer, harvest, and winter. The holiday Lent is named after the season it took place in. In this particular case, winter is probably more than 2,000 years old and less than 3,000 years old, but that’s about as accurate as you can get that far before writing.