Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

A few weeks after posting this node, I noticed that Korea's leading golfer, "leonid", had jumped from 118 strokes to 111 strokes, thus snatching the Ruby lead from flagitious and me.

To respond to this provocation, I began by staring at my 112 stroker:

r=*$<;'XXXXXXXXXXXX'.each_byte{|i|$><<"%#{327%i/9}c"% 'ohmx'[1>>(i-r.to_i)%12^2&2<<i%12-r[3,2].to_i/5]+$/*(i/85)}
The most obvious candidate for improvement here is the ungainly expression in 'ohmx'[expr], namely:
which can be clarified somewhat by writing as:
where h represents hours (0..23) and m minutes (0..11). How to shorten?

Though relying on inspiration in cases like these might work on a good day, a more dependable approach is to write a program to search for shorter solutions. Accordingly, I wrote the following Ruby brute force searcher:

# Search for Ruby solutions by building expressions from the sym # and numsymop arrays below, then evaluating them (via eval). # 0, 11, 1, 10, 2, 9, 3, 8, 4, 7, 5, 6 i_arr = [ 120, 47, 253, 22, 194, 21, 183, 44, 196, 55, 125, 246 ] sym = [ '*', '/', '%', '+', '-', '>>', '<<', '&', '^', '|' ] numsymop = (-12..12).to_a numsymop.unshift('i'); numsymop.unshift('-i'); numsymop.unshift('~i') numsymop.unshift('m'); numsymop.unshift('-m'); numsymop.unshift('~m') for op2 in numsymop for s2 in sym $stderr.print "#{op2} #{s2}\n" for op3 in numsymop for s3 in sym for op4 in numsymop for s4 in sym for op5 in numsymop expr = op2.to_s + s2 + op3.to_s + s3 + op4.to_s + s4 + o +p5.to_s i = 120; m = 0 # (d = 0) c_expr = "i=#{i};m=#{m};" + expr veq1 = -4242 begin veq1 = eval(c_expr) rescue end next if veq1 == -4242 i = 47; m = 11 # (d = 11) c_expr = "i=#{i};m=#{m};" + expr veq2 = -4242 begin veq2 = eval(c_expr) rescue end next if veq2 == -4242 next if veq1 != veq2 i = 120; m = 11 # (d = 0) c_expr = "i=#{i};m=#{m};" + expr vneq1 = -4242 begin vneq1 = eval(c_expr) rescue end next if vneq1 == -4242 next if vneq1 == veq1 i = 47; m = 10 # (d = 11) c_expr = "i=#{i};m=#{m};" + expr vneq2 = -4242 begin vneq2 = eval(c_expr) rescue end next if vneq2 == -4242 next if vneq1 != vneq2 good = 1 for i in i_arr d = i % 12 m = d c_expr = "i=#{i};m=#{m};" + expr veq2 = -4242 begin veq2 = eval(c_expr) rescue end if veq2 == -4242 good = 0 break end if veq1 != veq2 good = 0 break end end next if good == 0 for i in i_arr d = i % 12 for m in 0..11 next if m == d c_expr = "i=#{i};m=#{m};" + expr vneq2 = -4242 begin vneq2 = eval(c_expr) rescue end if vneq2 == -4242 good = 0 break end if vneq1 != vneq2 good = 0 break end end break if good == 0 end next if good == 0 print "woohoo: #{expr}: veq=#{veq1} vneq=#{vneq1}\n" $stdout.flush end end end end end end end
As an aside, writing "eval" search programs like these seems to be a good way to unearth bugs in dusty corners of a language; at least, I had to remove '**' from the sym array above to workaround various random crashes and hangs of the Ruby interpreter.

Anyway, after dutifully chugging away for several hours, the above program did find a lucky hit, namely:

woohoo: ~m%i%12/11: veq=1 vneq=0
Further simple variations of this search program found new solutions for the "hours" portion of the expression also, such as:
Combining these two new expressions enabled me to shorten the overall expression as shown below:
1>>(i-h)%12^2&2<<i%12-m # original (i-h)%12/~i^~m%i%12/11 # new and improved
and thus match leonid's 111 strokes via:
r=*$<;'XXXXXXXXXXXX'.each_byte{|i|$><<"%#{327%i/9}c"% 'hxmo'[(i-r.to_i)%12/~i^~r[3,2].to_i/5%i%12/11]+$/*(i/85)}
Of course, I have no idea if this is the same one stroke improvement that leonid found. If not, and he reads this post, I expect shortly to watch him move ahead to 110 strokes. :)

My main point is that relying on inspiration alone, I doubt I would ever have thought of this new shortened solution. That is, writing and running little search programs like these is part and parcel of being a serious golfer.

Update: Some time later, I discovered an easier way to get to 111 by changing the way hours and minutes are extracted from stdin, as shown below:

r=*$<; r r[3,2] # original gets;~/:/; $_ $' # new
By way of explanation, note that the Ruby gets function automatically sets $_. And, like Perl, ~/:/ automatically sets $'. Unlike Perl though, ~/:/ returns the (zero-based) index of the match. In this game therefore, ~/:/ always returns two (the index of : in, for example, 12:34).

At first glance, the new method looks like a step backwards because it consumes one more stroke than the original. As is often the case in golf though, a tactical trick is available to shorten it. By pure luck, you see, the original 2&2<<i%12-m expression contains two twos! So we can replace one of them with the return value of ~/:/ thus transforming the new approach from one stroke longer to one stroke shorter:

gets;'XXXXXXXXXXXX'.each_byte{|i|$><<"%#{327%i/9}c"%'ohmx'[1>>(i-$ +_i)%12^~/:/&2<<i%12-$'.to_i/5]+$/*(i/85)}

Alas, this new tactical trick cannot be similarly applied to my shortened ~m%i%12/11 expression because, unluckily, it does not contain a two.

Python Update

Inspired by this new Ruby magic formula, I was later able to shave a stroke from my 127-stroke Python solution by shortening the last part of the magic formula from:

This (cheating) 126-stroke Python "solution" is not correct for all possible inputs but has a good chance of passing the (poor) set of test data provided for this game. To clarify, I chose 42 in the original magic formula for artistic effect only; any number greater than eleven will do. Replacing 42 with i therefore works for eleven of the twelve string ord values, namely 48, 23, 85, 22, 86, 87, 20, 88, 31, 77, 78 ... but fails for the single ord value that is less than eleven, namely the 9 that forms the string's sixth character.

Hallvabo was kind enough to send me his two best solutions to this game. Here is his (second-placed) 128 stroke Python entry:

_=raw_input() for c in'XXXXXXXXXXXX':n=ord(c);print 3459%n/9*' '+'ohmx'[n%13==int(_[ +:2])%12::2][n%13==int(_[3:])/5]+n%3*'\n',
where XXXXXXXXXXXX above is a string with ord values 130, 180, 92, 75, 197, 48, 185, 138, 134, 228, 148, 188. And here is an alternate hallvabo 128-stroker:
_=raw_input() for c in'XXXXXXXXXXXX':n=ord(c);print 247%n/7*' '+'ohmx'[n%12==int(_[: +2])%12::2][n%12==int(_[3:])/5]+n/72*'\n',
where XXXXXXXXXXXX above is a string with ord values 72, 71, 205, 34, 158, 9, 147, 20, 160, 43, 101, 186. Note that both these solutions require a leading 3-character BOM (0xef, 0xbb, 0xbf). Note too that hallvabo employed his favourite "slice and dice" trick once again, just as he did in 99 Bottles of Beer.

It never occurred to me to use "slice and dice" in this game. As it turns out, the two different techniques produce similar lengths, as indicated below:

[(i%12==int(r[3:])/5)^(i-int(r[:2]))%-12/42] [-(i%12==int(r[3:])/5)^1>>(i-int(r[:2]))%12] [i%12==int(r[3:])/5::2][i%12==int(r[:2])%12] [i%12==int(r[3:])/5::2][1>>(i-int(r[:2]))%12]

In reply to Re: The golf course looks great, my swing feels good, I like my chances (Part VI) by eyepopslikeamosquito
in thread The golf course looks great, my swing feels good, I like my chances (Part VI) by eyepopslikeamosquito

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others drinking their drinks and smoking their pipes about the Monastery: (10)
    As of 2018-06-22 18:26 GMT
    Find Nodes?
      Voting Booth?
      Should cpanminus be part of the standard Perl release?

      Results (124 votes). Check out past polls.