Code crimes: mama and beer
python by Vagrant GautamWhy replace substrings in a string in a normal way, when you could instead do it with jiggery-pokery?
It all started with Simon saying, in classic sarcastic fashion:
Now, of course there are plenty of boring ways to do this in Python, but we wanted what we always want: trickery, fuckery, jiggery-pokery.
Disappointingly Kevin couldn't think of any way to hack the str.replace implementation enough such that 'foo'.replace('o', x)
returned a different value of x for each char. Obviously I took this as a challenge.
Solution 1
Here's a solution to that problem.
The secret here is wildly cursed monkeypatching with the Forbidden Fruit Python package.
Here's the code. The trick is to "curse" the in-built Python string replace function with my redefined replace function that picks a random letter every time. Yes, it's evil. But it's also easy.
from forbiddenfruit import curse
import string
import random
def replace(self, a, b):
new_str = ''
for i in self:
if i == a:
new_str += random.choice(string.ascii_letters)
else:
new_str += i
return new_str
curse(str, 'replace', replace)
'mama'.replace('m', 'x')
Solution 2
This is a solution to the original problem. It's less internally devious but it ends up looking kludgier as a result.
As you might guess from the syntax there, yes, it does use classes!
class S1:
def __init__(self):
self.x = ['a', 'mama']
def __get__(self, i, o):
return self.x.pop(0)
class S2:
def __init__(self):
self.x = ['b', 'beer']
def __get__(self, i, o):
return self.x.pop(0)
class Box1:
s = S1()
class Box2:
s = S2()
my = Box1()
myother = Box2()
print(my.s, myother.s)
'mama'.replace(my.s, myother.s)
It's not very neat or concise code, and it's even brittle because it relies on elements being popped from an array and therefore you have to call the get methods exactly once before doing the replacement for everything to work perfectly. But it's certainly less crimey than the other solutions.
Solution 3
Of course I couldn't stop there. I wanted to write code that would do the original cursed thing, i.e., replace 'mama' with 'beer' by hacking string replace. So I did that!
"In fact," I said, "I'll do ya one better, I'll prove I'm not monkeypatching with forbidden fruit anymore."
People were perplexed. Some replies:
I told them that what I had actually done was sneaky as hell (a sneaky combination of a few things, in fact) and that they were all going to hate me when I told them.
Some more replies:
The secret is two things. I'll let you have a look at the code first before I explain (bash first, then Python):
alias python3='python3 -i -c "_b_='\''\b\b\b\bbeer\b'\''"'
python3
print("mama".replace('a', _b_))
What I'm doing here is that I'm secretly aliasing python3 to first execute a variable assignment before opening up the interpreter. I have a variable _b_
and I assign it a string with the word beer in it surrounded by some sneaky backspace control characters.
The second piece of the trick is that I installed FontForge on my computer and created a new custom font that would display underscore characters as single quotes. Then I made iTerm use this custom font.
That's why the second version of the code is the TRUE version, and the first version is almost photoshop, but not quite. Personally I think it's cleverer than that!
Kevin and I discussed it for an inordinate amount of time before I arrived at this solution. He gets partial credit for reminding me that control characters exist. I had initially wanted to defeat the lexer and make it allow me to assign to a variable called 'b'
but I couldn't do it. I forget why (this is from December 2020, i.e., Too Long Ago).
That's all! Happy hacking!
- Next post: Dr. Ian Malcolm was right
- Previous post: In perilous pursuit of pelicans
- Back to the archive