Untilted
hero
December 29, 2022

Playing Code Golf & Pair Programming with ChatGPT

Removing all E's from a webpage (Code Golf)

Inspired by a tweet at 1:00am, I thought it'd be fun to read a webpage with all the E's removed:

So, I looked for a simple answer on StackOverflow to start:

And, the solution made sense to me, and worked. I liked the approach.

function removeText(top, txt) {
var node = top.firstChild, index;
while(node && node != top) {
// if text node, check for our text
if (node.nodeType == 3) {
// without using regular expressions (to avoid escaping regex chars),
// replace all copies of this text in this text node
while ((index = node.nodeValue.indexOf(txt)) != -1) {
node.nodeValue = node.nodeValue.substr(0, index) + node.nodeValue.substr(index + txt.length);
}
}
if (node.firstChild) {
// if it has a child node, traverse down into children
node = node.firstChild;
} else if (node.nextSibling) {
// if it has a sibling, go to the next sibling
node = node.nextSibling;
} else {
// go up the parent chain until we find a parent that has a nextSibling
// so we can keep going
while ((node = node.parentNode) != top) {
if (node.nextSibling) {
node = node.nextSibling;
break;
}
}
}
}
}​

And, for fun, I thought I'd try code golfing it (the goal of code golf is to use some refactoring tricks to reduce the size of the function as much as possible). I got things down to a measly 338 characters.

function rt(t,tp=document.body,i,a=['firstChild','nodeValue','nextSibling']){for(var n=tp[a[0]];n&&n!=tp;){if(3==n.nodeType)for(;-1!=(i=n[a[1]].indexOf(t));)n[a[1]]=n[a[1]].substr(0,i)+n[a[1]].substr(i+t.length);if(n[a[0]])n=n[a[0]];else if(n[a[2]])n=n[a[2]];else for(;(n=n.parentNode)!=tp;)if(n[a[2]]){n=n[a[2]];break}}};rt('e');rt('E');

But, then I had an idea. Maybe I could ask ChatGPT to golf with me?

It didn't quite understand what code golf was. But, it did suggest something interesting:

Which, I refactored and golfed a few times, to trim things down even further (214 characters):

r=(e,i=['firstChild','nodeValue','nextSibling'])=>{q=l=>{if(l.nodeType==3){while(l[i[1]].includes(e)){l[i[1]]=l[i[1]].replace(e,'')}}else if(l[i[0]])q(l[i[0]]);if(l[i[2]])q(l[i[2]])};q(document.body)};r('e');r('E')

Which, you can paste into your browser console, to humorously read anything you want, minus the E's:

Which, was kind of fun.

Then, when I thought I was done, dammit, ChatGPT did it again!

Which, trimmed things down again to 196 characters:

r=(e,i=['firstChild','nodeValue','nextSibling'])=>{q=l=>{l.nodeType==3?l[i[1]].includes(e)&&(l[i[1]]=l[i[1]].replace(e,'')):l[i[0]]&&q(l[i[0]]),l[i[2]]&&q(l[i[2]])};q(document.body)};r('e');r('E')

One problem: It no longer worked.

I looked for a couple of minutes, but the answer wasn't obvious as to what mistake ChatGPT had made. I'd obfuscated things too much at this point, and didn't want to backtrack. I suspect it used a ternary operator incorrectly for the else-if, or needed a pair of parenthesis somewhere, but I haven't verified it.

Instead, after a minute or so, I decided to ask ChatGPT to find the mistake.

It confidently told me there was no mistake. And, I yelled the same thing at my laptop I'd yell at any other developer in this situation (and had yelled to me when I was a less experienced developer):

Did you test the fucking code you wrote before you handed it to me? Because it doesn't do what you think it does.

😅

I think ChatGPT passed some sort of Turing test just now.

Then, it gave me an even better approach to solve the problem, that also doesn't work:

And it occurred to me. Dammit. This is going to be an even more concise approach, if you make it work:

for (const node of document.querySelectorAll('body *')) {
if (node.firstChild && node.firstChild.nodeType == 3) {
node.firstChild.nodeValue = node.firstChild.nodeValue.replace(/[eE]/g, '');
}
}

I also realized a few other things that'd simplify it along the way, like the regex replace once we'd reduced the node traversal problem.

That reduces to this 132 character beauty:

for(n of document.querySelectorAll('*')){f='firstChild',v='nodeValue';if(n[f]&&n[f].nodeType==3)n[f][v]=n[f][v].replace(/[eE]/g,'')}

Which, I'm pretty happy with.

But if you would have hooked ChatGPT up to a Slack channel and fed me those same responses, I would have thought I was pair programming with a somewhat inexperienced, but competent developer. I would have thanked them for helping me come up with a halfway decent couple of ideas for refactoring that code, as trivial as it is.

For fun, I asked if it could make it even shorter:

Again, it doesn't work. Also, it's 4 characters longer.

So, That was fun.

🧐

I'm going to reflect on what us meat sacks are good at, and how AI can help with tools available today. Maybe it's less about replacing things with AI, vs. changing our workflow in creative ways to take advantage of what AI can actually do.