Home More Samples
```///////////////////////////////////////////////////////////////////////////////
//
// Title: Bob's Shish Kebabs
// Author: Jo Mason
// Publication: Dell Logic Puzzles
// Issue: June, 1998
// Page: 24
// Stars: 3 (a 5 for the computer!)
//
// Bob and Patty invited their friends Javier and Marie over for a cookout. On
// the menu were grilled marinated beef cubes and four kinds of vegetables --
// mushrooms, onions, peppers, and tomatoes -- which were put onto skewers.
// The first skewer that each person made had three beef cubes and one piece
// of three kinds of vegetables -- each person disliked a different vegetable
// and omitted it from his or her skewer. The six pieces can be numbered 1 to
// 6 from the handle to the point of the skewer. Can you tell what item each
// person had in each position?
//
// 1.  No kebab had two beef cubes right next to each other.
// 2.  No one's beef cubes were in the same three positions as anyone else's.
// 3.  One shish kebab's first three items (numbers 1, 2, and 3 respectively)
//     were beef, pepper, and mushroom; this wasn't Javier's.
// 4.  One skewer had beef cubes in positions 1, 3, and 5, and a tomato wedge
//     in position 6.
// 5.  Bob, who loves onions and included a chunk on his skewer, had vegetables
//     in both positions 4 and 5.
// 6.  On the four kebabs, the items in position 5 were beef, mushroom, onion,
//     and tomato.
// 7.  Each onion chunk was immediately between two beef cubes.
// 8.  No pepper was immediately between two beef cubes.
// 9.  Marie can't stand mushrooms and left them off her skewer.
// 10. At least two kebabs had the same vegetable in the same position at
//     least once.
//
///////////////////////////////////////////////////////////////////////////////
//
// Query:
//
//          ShishKebabsSolutions()
//
///////////////////////////////////////////////////////////////////////////////
//
// Result:
//
// Number of solutions:1
// Bob:    [Beef,Onion,Beef,Pepper,Mushroom,Beef]
// Patty:  [Beef,Pepper,Mushroom,Beef,Tomato,Beef]
// Javier: [Beef,Onion,Beef,Mushroom,Beef,Tomato]
// Marie:  [Pepper,Beef,Tomato,Beef,Onion,Beef]
//
///////////////////////////////////////////////////////////////////////////////

local Person = Bob | Patty | Javier | Marie
local SkewerBit = Beef | Mushroom | Onion | Pepper | Tomato
local OneSkewer = [0..5]->SkewerBit
local Skewer = Person->>OneSkewer

proc ShishKebabsSolutions() iff
all skewer in l
ShishKebabs(skewer)
end & Print('\nNumber of solutions:',Len(l)) &
PrintShishKebabSolutions(l)

local proc PrintShishKebabSolutions(l :< list Skewer) iff
if l = h,t then
Print('\nBob:    ') & Print(h(Bob)) &
Print('\nPatty:  ') & Print(h(Patty)) &
Print('\nJavier: ') & Print(h(Javier)) &
Print('\nMarie:  ') & Print(h(Marie)) &
PrintShishKebabSolutions(t)
end

local pred ShishKebabs(skewer::Skewer) iff
// 1.  No kebab had two beef cubes right next to each other.
// 2.  No one's beef cubes were in the same three positions as anyone else's.

beefs::[0..3]->>[0..2]->I[0..5] & //beef positions for each skewer, all different
beefs = [beefmarie,beefpatty,beefjavier,beefbob] &

//  The first skewer that each person made had three beef cubes and one piece
//  of three kinds of vegetables -- each person disliked a different vegetable
//  and omitted it from his or her skewer.

ThreeBeefPieces(skewer(Bob),beefbob) &
ThreeBeefPieces(skewer(Patty),beefpatty) &
ThreeBeefPieces(skewer(Javier),beefjavier) &
ThreeBeefPieces(skewer(Marie),beefmarie) &

PlaceVeggies(skewer(_),Mushroom,Tomato,Onion) &
PlaceVeggies(skewer(_),Mushroom,Tomato,Pepper) &
PlaceVeggies(skewer(_),Mushroom,Onion,Pepper) &
PlaceVeggies(skewer(_),Onion,Pepper,Tomato) &

// 3.  One shish kebab's first three items (numbers 1, 2, and 3 respectively)
//     were beef, pepper, and mushroom; this wasn't Javier's.
skewer(x3) = [Beef,Pepper,Mushroom,_,_,_] & (x3 = Bob | x3 = Marie | x3 = Patty) &

// 4.  One skewer had beef cubes in positions 1, 3, and 5, and a tomato wedge
//     in position 6.
skewer(_) = [Beef,_,Beef,_,Beef,Tomato] &

// 5.  Bob, who loves onions and included a chunk on his skewer, had vegetables
//     in both positions 4 and 5.
skewer(Bob,_) = Onion &
skewer(Bob,3) <> Beef & skewer(Bob,4) <> Beef &

// 6.  On the four kebabs, the items in position 5 were beef, mushroom, onion,
//     and tomato.
skewer(_) = [_,_,_,_,Beef,_] &
skewer(_) = [_,_,_,_,Mushroom,_] &
skewer(_) = [_,_,_,_,Onion,_] &
skewer(_) = [_,_,_,_,Tomato,_] &

// 7.  Each onion chunk was immediately between two beef cubes.
OnionBetweenBeef(skewer(Bob)) &
OnionBetweenBeef(skewer(Patty)) &
OnionBetweenBeef(skewer(Javier)) &
OnionBetweenBeef(skewer(Marie)) &

// 8.  No pepper was immediately between two beef cubes.
NoPepperBetweenBeef(skewer(Bob)) &
NoPepperBetweenBeef(skewer(Patty)) &
NoPepperBetweenBeef(skewer(Javier)) &
NoPepperBetweenBeef(skewer(Marie))  &

// 9.  Marie can't stand mushrooms and left them off her skewer.
~Mushroom in skewer(Marie) &

// 10. At least two kebabs had the same vegetable in the same position at
//     least once.
IsVeggie(skewer(x10a,y)) & IsVeggie(skewer(x10b,y)) &
x10a <> x10b &
skewer(x10a,y) = skewer(x10b,y)

// Place three beef pieces on a skewer. (In three different positions)
// No two beef pieces can be next to each other
local pred ThreeBeefPieces(skewer::OneSkewer,beefpos::[0..2]->I[0..5]) iff
skewer(x1) = Beef & skewer(x2) = Beef & skewer(x3) = Beef &
x1 + 1 < x2 & x1 + 3 < x3 &
x2 + 1 < x3 &
beefpos = [x1,x2,x3]

// Ensure the requested skewer bit qualifies as a veggie piece
local pred IsVeggie(x::SkewerBit) iff
x = Mushroom | x = Onion | x = Tomato | x = Pepper

// Given a skewer, ensure it contains given veggies
local pred PlaceVeggies(skewer::OneSkewer,v1:<SkewerBit,v2:<SkewerBit,v3:<SkewerBit) iff
skewer(x) = v1 &
skewer(y) = v2 &
skewer(z) = v3

///////////////////////////////////////////////////////////////////////////////
// True iff:
// Either there is no pepper, or the pepper is not immediately between two
// beef cubes.
local pred NoPepperBetweenBeef(skewer::OneSkewer) iff
~Pepper in skewer |
(
skewer(x) = Pepper &
(
skewer(x+1) <> Beef |
skewer(x-1) <> Beef |
x = 0 |     // leftmost place
x = 5       // rightmost place
)
)

///////////////////////////////////////////////////////////////////////////////
// True iff:
// Either there is no onion, or the onion is immediately between two beef cubes
local pred OnionBetweenBeef(skewer::OneSkewer) iff
~Onion in skewer |
(skewer(x) = Onion & skewer(x-1) = Beef & skewer(x+1) = Beef)

```