# Sunday Times Teaser 3109 – Hole Numbers

*by Colin Vout*

#### Published Sunday April 24 2022 (link)

In theoretical golf, you have a set of “clubs” each of which hits a ball an exact number of yards forwards or backwards. You own the following set: 3, 8, 17, 19 and 35. For example, if a hole is 31 yards long, you can reach it in three strokes, with two forward hits of the 17 and a backward hit of the 3. In the next competition, you are only allowed to use three clubs, and the course consists of three holes whose lengths are 101, 151 and 197 yards. In order to get round the course in the fewest possible strokes, you must make a wise choice of clubs.

Which three clubs (in ascending order) should you choose, and what will the individual hole scores be (in order)?

12 Comments
Leave one →

In my original version, my approach to producing the stroke sequences was much slower than Jim Randell’s equivalent version so I have adopted his approach here.

Without my usual code compression ad incomprehension

My choice of range of strokes was arbitrary and happened to be right on! And the ‘product’ function is not necessarily the most time-efficient stroke sequence generator but is very code-efficient.

Saving and printing stroke sequences as you did Brian, would have required a few more lines of code but was not required for the Teaser’s solution so I left it out.

HI John,

I really like your version as it shows a nice combination of Python features in a sensible and understandable way.

I checked out your -10 and +10 limits and it turns out that a lower limit of -4 is sufficient and does improve the speed.

You could also save yourself a few lines using the dictionary get() function to avoid the need for prior initialisation of the dictionary entry:

Thanks Brian and thanks for the tip on the ‘get ‘ method which I’ve incorporated into a new version of my code below. I avoid anything in my code that is influenced by foreknowledge of the result. My ‘range(-10, 11)’ does in fact cover the case of ten strokes in the (3, 8, 19) bag. I guessed that that -10 to 10 would be more than adequate. I didn’t realise it would be just adequate.

I’ve also compressed lines 35-40 above into 2 lines below. It is possible to compress it into one line but at the expense of multiple recalculations of ‘min(s3t.values())’

An interesting alternative to the dictionary ‘get’ method for dealing with uninitialized entries would be to replace line 8 with:

with the requisite import of ‘defaultdict’ and modification of line 24. However, this would probably be slower than the ‘get’ method.

As the maximum total strokes for the 3 clubs with range(-10, 11) is 30, 10000 can be replaced by 31.

Unless I really need defaultdict, I prefer to avoid it since it involves another import and is probably slower as you suggest.

I stole the itertools.product-method John’s code above and got rid of three nested loops to produce the a, b, c …

HI Erling,

For your amusement, here is a shorter version of your code:

Thanks Brian

The construction of h in line 12-13 did not look good to me either.. (‘syntax-errors pushed me into it’). I shall study your code. As it uses my symbols (and logic?) I should be able to learn from it.

..Not quite the same logic. Mapping club-sets to scores rather than the other way around, as I did, allows for simply look up the minimum among the dictionary’s unique keys. (Expense is that only one (the last?) club-set is recorded.)

I have not managed to rewrite your compacted version to ‘my level of syntax’ yet, but shall give it another try.

To quote Mick Jagger again: “Tables turn … it’s all over now.”