It’s Friday, and time again for a new Fragment: my weekly programming-related puzzle. For some background on Friday Fragments, see the earlier post.
This Week’s Fragment
I “borrowed” this week’s fragment from a recent Car Talk puzzler. I prefer original ones, but since this one follows last week’s well, I thought I’d re-use it.
You have 13 bottles of wine, and have been tipped off that one of them is tainted with a deadly poison: so deadly that one drop can kill a person or large animal within 24 hours. With the help of four lab rats, how can you determine which one contains the fatal potion within one day?
If you want to “play along”, post a solution as a comment or send it via email. To avoid “spoilers”, simply don’t expand comments for this post.
Last Week’s Fragment – Solution
“If God had intended man to have computers, he would have given him 16 fingers.”
Last week’s puzzle reminds us that there are three kinds of people in the world: those who understand binary, and those who don’t. Your job was to write code to dictate which pile each of 52 playing cards should land in when sorting in multiple passes with only four piles. It was a spin on an old fine sort with base conversion and compression algorithm used for sorting checks and other things.
I received some excellent responses from base conversion pros like Joe Richardson and Stephen Ake. I’ll publish Stephen’s code, since I like his better than mine:
pileNumber := ((card / (pileCount raisedTo: (eaPass – 1))) ceiling) \\ pileCount.
(pileNumber = 0) ifTrue: [pileNumber := pileCount].
If you’re in that second (third?) group who doesn’t keep their checkbooks in hex and is happy with the 10 fingers God gave us, think of it the following way…
If I let you use 13 piles on the first pass, then you could easily do it in two passes. In the first pass, sort by rank (13 piles), and then stack those up and sort by suit (4 piles). You could treat the suit and rank of each card as a two-digit number, with the rank as the low-order “digit” and the suit as the high-order “digit.”
But Johnny didn’t have room on his Toy Story 2 lunchbox for 13 piles on the second pass, only 4. So he had to convert the suit and rank of each card to a base 4 number. That’s the base conversion part, which is important when the number of available piles (or pockets on a sorter) doesn’t match the original base of the number. That’s because you want to make the best use of all piles/pockets on all passes.
When sorting by things like account numbers on checks, there can also be gaps in the numbers, which wastes pockets and passes. To avoid this problem, you assign “aliases” to each number. For example, if the first two account numbers are 13500001 and 13511115, renumber the first account as “1”, and the second as “2”, and sort on the aliases. That’s the compression part.
This is easier for ten-fingered humans to follow if we use 10 piles to sort cards with the numbers 000 through 999. The pile number for the first pass would be the digit in the ones position, then the tens position, and then the hundredths position. That’s the 10^1, then 10^2, then 10^3 position, or the pocket count raised to the pass number. In code, a modulus (remainder) division “strips off” this digit for use.
Kudos to Joe and Stephen for also noticing that it can be done in only three passes, not four. That’s because 52 base 4 is a three-digit number. I wasn’t trying to be tricky; I just forgot to edit after deciding to give Johnny 4 piles instead of 3. And kudos to Stephen for solving it in Smalltalk (plugging into the scaffolding code I provided), since Smalltalk throws some extra twists: 1-based (not 0-based) arrays to adjust for, and a less-common exponentiation operator (raisedTo:, not ^). You can find Stephen’s post in last week’s comments; Joe sent me a funny response via email back on March 22; here’s an excerpt:
Little Johnny is always one step ahead. He can sort the deck of cards using only 3 passes. Since Johnny is a smart kid, he assigns the numbers 1 through 13 to the cards of the first suit, 14-26 to the second suit, 27-39 the third, and 40-52 to the cards for the fourth suit. He does this in his head with no need of a sort pass. He then converts this decimal number to base 4 (since 4 piles are used). Knowing that 52 base 10 = 310 base 4, a three digit number, Johnny knows that it will take at most 3 passes to sort the cards. He might get lucky and sort the cards in only one or two passes. The first sort pass uses the right most digit of this assigned base 4 number. The second pass uses the middle digit and the third pass uses the left most digit.
Little Johnny has time left over to once again ask “Are we there yet?”
Finally, I neglected to mention that Luke (my middle son) solved last week’s cryptogram. I often have to decode his (teen-speak) sentences, too.
Number the mice as mouse 1, 2, 4, and 8. Number the bottles from 1 to 13. Feed the odd numbered bottles to mouse 1, bottles 2, 3, 6, 7, 10, 11 to mouse 2, bottles 4-7, 12, and 13 to mouse 4, and bottles 8-13 to mouse 8. Then depending on which mice die you know which bottle contained poison (add up the mouse numbers). Could have done this with 16 bottles.
Thanks for the sorting tutorial – I shall use that toward my yearly required continuing education!
Binary search. For simplicity, add three untainted bottles to the collection so that we have sixteen bottles, one of which is poisoned. Divide into two groups of eight, create two samples by mixing from each of the bottles of the two groups. Administer one of the two samples to the rat. Whether he lives or dies determines which group contains the poisoned bottle. From the poisoned group, make two groups of four and repeat (second tasting). From the poisoned group, divide into two groups of two and repeat (third tasting). Repeat to determine which particular bottle is the candidate. Since it requires a maximum of four tastings, you need at most for rats.