Enigmatic Code

Programming Enigma Puzzles

Enigma 243C: Christmas Fare

From New Scientist #1389, 22nd December 1983 [link]

Last Christmas I tried out my new toy — a home computer — by running a program of recipes which came with it. After typing in “Christmas” there was a choice of four suitable outline menus, numbered 1, 2, 3 and 4. Each menu consisted of a starter, a main meal item, a sauce and a dessert. So to print out, for example, the dessert of the third menu one had to type in 3.4 — which made the recipe for the Yule Log appear on the screen. Another dessert was Brandy Snaps, and two of the main meal items were Goose, and Ham à la Champagne. One of the sauces was Chestnut, which went with one of the poultry dishes. Each of the four menus included fruit somewhere (a Melon and Red Wine starter, a Lemon Snowball dessert, a Grapefruit Sorbet starter, and Cranberry Sauce). Each of the four menus involved a geographical region (Pâté Provençal, Cumberland Sauce for the Roast Duck of course, Madeira Sauce, and Turkey!) And each menu included a festive or seasonal dish (as well as the Yule Log and Lemon Snowballs there was Christmas Pudding and Pumpkin Soup). Unfortunately, in my alcoholic haze last Christmas, to print out a menu I typed in error, 1.1, 2.2, 3.3 and 4.4. This meant that at least three of the items contained an alcoholic drink in their name — and the whole family ended up inebriated. So this year I’m going to stick to the first menu. Which four items will I have to prepare?

This completes the archive of puzzles from 1983, and brings the total number of Enigmas on the site to 756. This leaves 20 years of puzzles from 1984 to 2003 to solve.

[enigma243c] [enigma243]

Advertisements

2 responses to “Enigma 243C: Christmas Fare

  1. Jim Randell 15 December 2014 at 9:16 am

    This Python program looks at all the possibilities. It runs in 62ms.

    from itertools import permutations
    from enigma import printf
    
    # the courses
    starters = ('grapefruit sorbet', 'melon', 'pate', 'pumpkin soup')
    mains = ('duck', 'goose', 'ham', 'turkey')
    sauces = ('chestnut', 'cranberry', 'cumberland', 'madeira')
    desserts = ('brandy snaps', 'christmas pudding', 'lemon snowballs', 'yule log')
    
    # choose the desserts
    for c4 in permutations(desserts):
      if c4[2] != 'yule log': continue
    
      # choose the mains
      for c2 in permutations(mains):
    
        # choose the sauces
        for c3 in permutations(sauces):
          # cumberland sauce goes with the duck
          if c2[c3.index('cumberland')] != 'duck': continue
          # chestnut sauce goes with one of the (other) poultry dishes
          if c2[c3.index('chestnut')] not in ('goose', 'turkey'): continue
    
          # choose the starters
          for c1 in permutations(starters):
            # each menu has fruit in it
            if len(set((c1.index('melon'), c4.index('lemon snowballs'), c1.index('grapefruit sorbet'), c3.index('cranberry')))) != 4: continue
            # each menu has a geographical dish
            if len(set((c1.index('pate'), c3.index('cumberland'), c3.index('madeira'), c2.index('turkey')))) != 4: continue
            # each menu has a seasonal dish
            if len(set((c4.index('yule log'), c4.index('lemon snowballs'), c4.index('christmas pudding'), c1.index('pumpkin soup')))) != 4: continue
    
            # count the alcoholic drink names in 1.1, 2.2, 3.3, 4.4
            a = int(c1[0] == 'melon') + int(c2[1] == 'ham') + int(c3[2] == 'madeira') + int(c4[3] == 'brandy snaps')
            if a < 3: continue
    
            # assemble the four menus
            for m in zip(c1, c2, c3, c4):
              print(m)
            print()
    

    Solution: The first menu consists of a Melon and Red Wine starter, Roast Duck with Cumberland Sauce and Christmas Pudding.

    The recipes are:

    1.1 = Melon and Red Wine
    1.2 = Roast Duck
    1.3 = Cumberland Sauce
    1.4 = Christmas Pudding

    2.1 = Pâté Provençal
    2.2 = Goose
    2.3 = Chestnut Sauce
    2.4 = Lemon Snowballs

    3.1 = Grapefruit Sorbet
    3.2 = Ham à la Champagne
    3.3 = Madeira Sauce
    3.4 = Yule Log

    4.1 = Pumpkin Soup
    4.2 = Turkey
    4.3 = Cranberry Sauce
    4.4 = Brandy Snaps

    You could argue that a snowball is an alcoholic drink, and that menus 2 and 4 can therefore be interchanged. The first menu remains unchanged however.

    And there may well be the names of other cocktails hidden in there.

  2. Jim Randell 17 December 2014 at 12:59 pm

    Here’s a variation of my program. It’s a bit faster because it assigns the dishes to the menus, so is comparing integers instead of strings, and the variable names make it more readable. But then we need to assemble the menu at the end in a more complicated fashion. It runs in 47ms.

    from itertools import permutations
    from collections import defaultdict
    from enigma import printf
    
    # the menus
    menus = (1, 2, 3, 4)
    
    # choose menus to go with the desserts
    for (snaps, pudding, snowballs, log) in permutations(menus):
    
      # the yule log is on menu 3
      if log != 3: continue
    
      # choose menus to go with the mains
      for (duck, goose, ham, turkey) in permutations(menus):
    
        # choose menus to go with the sauces
        for (chestnut, cranberry, cumberland, madeira) in permutations(menus):
    
          # cumberland sauce goes with the duck
          if cumberland != duck: continue
    
          # chestnut sauce goes with one of the (other) poultry dishes
          if chestnut != goose and chestnut != turkey: continue
    
          # choose menus to go with the starters
          for (sorbet, melon, pate, soup) in permutations(menus):
    
            # each menu has fruit in it
            if len(set((melon, snowballs, sorbet, cranberry))) != 4: continue
    
            # each menu has a geographical dish
            if len(set((pate, cumberland, madeira, turkey))) != 4: continue
    
            # each menu has a seasonal dish
            if len(set((log, snowballs, pudding, soup))) != 4: continue
    
            # count the alcoholic drink names in 1.1, 2.2, 3.3, 4.4
            a = sum(1 for (x, y) in zip(menus, (melon, ham, madeira, snaps)) if x == y)
            if a < 3: continue
    
            # assemble the menu
            courses = (
              ((sorbet, melon, pate, soup), ('Grapefruit Sorbet', 'Melon and Red Wine', 'Pate Provencal', 'Pumpkin Soup')),
              ((duck, goose, ham, turkey), ('Roast Duck', 'Goose', 'Ham a la Champagne', 'Turkey')),
              ((chestnut, cranberry, cumberland, madeira), ('Chestnut Sauce', 'Cranberry Sauce', 'Cumberland Sauce', 'Madeira Sauce')),
              ((snaps, pudding, snowballs, log), ('Brandy Snaps', 'Christmas Pudding', 'Lemon Snowballs', 'Yule Log')),
            )
            menu = defaultdict(list)
            for course in courses:
              for (m, n) in zip(*course):
                menu[m].append(n)
    
            # output the menu
            for m in menus:
              printf("menu {m}: {s}", s=', '.join(menu[m]))
            printf()
    

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: