Updated 2014-04-07 18:50:14 by LarrySmith

Summary  edit

A simple program that produces random culinary recipes

See Also  edit

A simple memory game
inspired by this page

Description  edit

Richard Suchenwirth 2003-06-26: Re-reading an old book on DR Logo, I found this funny little program that produces random recipes (please correct my re-translations to English where needed). Small as it is, it can produce 900 different recipes, though they might not be to everybody's taste... but may be helpful when we teach programming to children?

The basic idea is to pick an arbitrary element from a list, which is easily done in Tcl with the following:
proc ? L {
    lindex $L [expr {int(rand()*[llength $L])}]
}

This is used several times in:
proc recipe {} {
    set a {
        {3 eggs} {an apple} {a pound of garlic}
        {a pumpkin} {20 marshmallows}
    }
    set b {
        {Cut in small pieces} {Dissolve in lemonade} {Bury in the ground for 3 months}
        {Bake at 300 degrees} {Cook until tender}
    }
    set c {parsley snow nutmeg curry raisins cinnamon}
    set d {
         {ice cream} {chocolate cake} spinach {fried potatoes} rice {soy sprouts}
    }
    return "   Take [? $a].
    [? $b].
    Top with [? $c].
    Serve with [? $d]."
}

Larry Smith: In the gaming world, we call these generators. There are lots of good examples and explanations of the theory at http://www.seventhsanctum.com/. As it happens, I have been working on such a program in Tcl for my own use. You can do some amazing things with them.

One problem with using Tcl, though, is recursion. I started hitting the recursion limit with very simple expressions, and really didn't manage to dodge it until I added my own code to process the statements non-recursively. Thus

You see a [color] mushroom.

Becomes

You see a <color> mushroom.

Kind of sad, really, especially since having the entire Tcl language available at the substitution point is a huge advantage. You can do things like save certain choices and refer back to them in other areas to keep things consistent. For example, I have one table for spell ingredients where the first table selects an animal - a carp, a bat, whatever - but saves "fish" or "bat" or "reptile" - which are used later to select subtables of the appropriate bits - so that the system never demands a "foot of a fish" or the "wing of a cow". The recursion limit is forcing me to implement other escapes to get these effects and making it quite a bit more complicated. If anyone is interested they can consult Gaming Generators in Tcl.

And as modern programs always need a GUI, here is a minimal one that appears when you source this file at top level, and shows a new recipe every time you click on it:
if {[file tail [info script]]==[file tail $argv0]} {
    package require Tk
    pack [text .t -width 40 -height 5]
    bind .t <1> {showRecipe %W; break}
    proc showRecipe w {
        $w delete 1.0 end
        $w insert end [recipe]
    }
    showRecipe .t
}

TV: Good, me like. Looks like the beginning of a little expert system. Maybe one would want ot value the various combinations and suggest a taste base.

AM: What about adding a few questions for those young programmers:

  • Show why the program can come up with 900 different receipes
  • Adjust the program so that it will show two or three receipes at the same time
  • Adjust the program so that no receipe will contain both apples and spinach together
  • Adjust the program so that it will show 1050 receipes
  • Adjust the program so that it will show 901 receipes

Actually the last question is not that easy to answer: it requires restructuring a part of the program rather than small, almost negligeable changes. It is what one might call an example of the discontinuous nature of programs. Sometimes (often) small changes in the requirements lead to big changes in the program code. They might as well get used to this at an early age :(