Jonathan. Frech’s WebBlog

Arithmetic Golfing (#179)

Jonathan Frech,

A recent PCG golfing ques­tion When do I get my sandwich? asked to find a mapping be­tween seven input strings (sandwich names) and the seven days of the week (indexed by num­ber).

The first an­swer was made by a user named i cri everytim and utilized a string of characters which uniquely ap­pear at the same position in all seven input strings, enklact, to per­form the mapping in Python 2 requiring 29 bytes. After their an­swer, a lot of answers appeared using the same magic string in dif­fer­ent languages to reduce the num­ber of bytes needed. Yet nobody reduced the byte count in Python.

Trying to solve the prob­lem on my own, my first at­tempt was using on­ly the input strings’ last dec­i­mal dig­it to per­form the mapping, though this ap­proach did not save on bytes (read my PCG an­swer for more on this 30 byte solution).

After a few more hours of working on this prob­lem, how­ev­er, I achieved to bring down the byte count by one en­tire byte.

I did so by using a simple brute-force algorithm to check for Python expressions which can be used to per­form the sought after mapping. To do so, I use Python’s apostrophes (`...`) to turn the found expression into a string — str(...) is three whole bytes longer — and index that string with the input strings’ lengths. It sure is not very readable, but on­ly takes 28 bytes — and that is all that matters.

lambda S:`6793**164`[len(S)]

After finding the 28 byte func­tion which uses a 9 byte expression (6793**164), I attempted to find an even shorter expression. And even though I did not yet find one, I did write a more gen­er­al brute-force Python pro­gram (source code shown below; can also be downloaded) than the one I linked to in my PCG an­swer.

Brute-forcing takes exponentially more time the more digits you have to check, so my brute-forcer still re­quires the user to decide for them­selves which expressions should be tried.
There are three pa­ram­e­ters that define the search; a regex pattern that should be contained in the expression’s string, an offset that pattern should ideally have and a target length. If an expression is found that takes as many bytes as or less bytes than the target length, an exclamation point is printed
Though this pro­gram did not prove useful in this case, there may come another challenge where an arithmetic expression golfer could come in handy.

My pro­gram may not have found shorter expressions, but definitely some impressive ones (the +... at the end refers to an additional offset from the string index which — unsurprisingly — take additional bytes):

I also considered using division to gen­er­ate long strings of digits which may match; the on­ly prob­lem is that Python float­ing-point numbers on­ly have a certain precision which does not produce long enough strings. Again, using ex­po­nen­ti­a­tion (**) and bitshifting (<<) I could not come up with a working expression that takes less bytes.

Source code: arithmetic-golfing_brute.py