Enigmatic Code

Programming Enigma Puzzles

Enigma 1433: A cribbed deal

From New Scientist #2594, 10th March 2007

I have been introducing my niece and nephew to a simple form of the game of cribbage. I have discarded the “picture” cards from a standard pack of cards, leaving 40 cards. The aces count as ones. I give each of us four of the cards and explain how to work out the score of each hand. Each pair of identical numbers scores two points. Each group of cards adding up to 15 scores another two points. If the four cards have consecutive numbers on them they score a further four points, but if not then any three of the cards which have consecutive numbers on them score another three points. So, for example, a hand comprising 3, 4, 5 and 5 would score eight points and a hand comprising 7, 8, 8, 8 would score 12 points.

In one interesting deal the three of us each had four cards whose score equalled the total of their faces. I then shuffled just those 12 cards and gave us four each again. This time we all had different score from each other, but for each hand the sum of the face values was a multiple (larger than 1) of the score.

What (in increasing order of scores) were the three hands on that last occasion?

[enigma1433]

Advertisements

One response to “Enigma 1433: A cribbed deal

  1. Jim Randell 7 May 2013 at 7:05 am

    The following Python program runs in 60ms. In Python 3 the last line of the recursive solve() function could be replaced with a yield from construct. I left it as a loop so that it works with Python 2 or Python 3.

    from itertools import combinations, combinations_with_replacement
    from collections import Counter
    from enigma import powerset, irange, flatten, uniq, printf
    
    # determine the score of a hand
    def score(cs):
      s = 0
      # two points for each pair
      for (c1, c2) in combinations(cs, 2):
        if c1 == c2: s += 2
      # two points for each group that sums 15
      for c in powerset(cs):
        if sum(c) == 15: s += 2
      # four points for 4 consecutive values
      c = sorted(cs)
      if c[0] + 3 == c[1] + 2 == c[2] + 1 == c[3]: s += 4
      else:
        # otherwise, three points for each 3 consecutive values
        for (c1, c2, c3) in combinations(c, 3):
          if c1 + 2 == c2 + 1 == c3: s += 3
      return s
    
    # check the scores we're given
    assert score((3, 4, 5, 5)) == 8
    assert score((7, 8, 8, 8)) == 12
    
    # find solution hands with increasing scores
    # c - Counter object with the set of remaining cards
    # s - solution hands (with increasing scores)
    # scs - the scores for the hands
    def solve(c, s, scs):
      # are we done
      if len(s) == 3:
        yield (s, scs)
      else:
        # chose a hand
        for h in uniq(combinations(c.elements(), 4)):
          (sm, sc) = (sum(h), score(h))
          # sum should be a multiple of the score
          (d, r) = divmod(sm, sc)
          if not(d > 1 and r == 0): continue
          # score should be different and increasing
          if scs and not(scs[-1] < sc): continue
          # try to solve for remaining cards
          c1 = c.copy()
          c1.subtract(h)
          for x in solve(c1, s + [h], scs + [sc]): yield x
    
    # find 4 card hands where the score is the sum of card values
    hands = list(c for c in combinations_with_replacement(irange(1, 10), 4) if sum(c) == score(c))
    
    # and choose 3 of these hands
    for s in combinations_with_replacement(hands, 3):
      # what cards are involved?
      cs = flatten(s)
      # we can't have more than 4 cards of the same value
      c = Counter(cs)
      if not all(x < 5 for x in c.values()): continue
      # solve this set of cards
      for (s, scs) in solve(c, [], []):
        printf("hands: {s}, sums: {sms}, scores: {scs}", sms=list(sum(x) for x in s))
    

    Solution: The hands were as follows: score = 2, cards = 1, 2, 2, 5; score = 4, cards = 1, 1, 3, 3; score = 8, cards = 1, 5, 5, 5.

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: