Re: Need a Challenge?
- Posted by David Cuny <dcuny at LANSET.COM> Aug 16, 2001
- 445 views
Irv Mullins wrote: > I found this puzzle in an example program > for a language I downloaded. Can you write > a program (100 lines or less, plz) to solve it? I've included two versions. The first uses some pruning, so it doesn't take forever. It's about 125 lines of code. The second works in theory - I haven't had the patience to run it all the way through. But it's 100 lines long. Basically, it's a brute force approach. 'calc_permutes' pre-calculates all the combinations of {1..5}. 'main' loops through the entire search space, looking for a match. 'test' checks to see if a particular combination matches the criteria. If it does, the program halts. There are some pruning tests to reduce the search space, so the redundant tests in test() are commented out. Otherwise, it would be a *long* time to arrive at the answer. as it is, it takes my P200 about 18 seconds to find the solution. The code could be a lot more efficient, but it would take more lines, and I think it's *sort* of explanatory, even without comments. The answer is: english red snail sculptor milk third spanish white dog violinist juice fifth japanese green zebra painter coffee fourth italian blue horse doctor tea second norwegian yellow fox diplomat water first If you *really* want to speed it up, just change the constants to match the solution. -- David Cuny -- Version 1 sequence color, job, pet, drink, house, permutes, list constant colors = { "red", "green", "yellow", "white", "blue" }, nations = { "english", "spanish", "japanese", "italian", "norwegian" }, jobs = { "painter", "sculptor", "diplomat", "violinist", "doctor" }, pets = { "dog", "snail", "fox", "horse", "zebra" }, drinks = { "tea", "coffee", "milk", "juice", "water" }, houses = { "first", "second", "third", "fourth", "fifth" }, country = { 1, 2, 3, 4, 5 }, Red = 1, Green = 2, Yellow = 3, White = 4, Blue = 5, English = 1, Spaniard = 2, Japanese = 3, Italian = 4, Norwegian = 5, Painter = 1, Sculptor = 2, Diplomat = 3, Violinist = 4, Doctor = 5, Dog = 1, Snail = 2, Fox = 3, Horse = 4, Zebra = 5, Tea = 1, Coffee = 2, Milk = 3, Juice = 4, Water = 5 procedure calc_permutes( integer i, integer j ) if j = 0 then -- initialize permutes = {} list = repeat( 0, i ) calc_permutes( i, j+1 ) elsif j > i then permutes = append( permutes, list ) return else for k = 1 to i do if list[k] = 0 then list[k] = j calc_permutes( i, j+1 ) list[k] = 0 end if end for end if end procedure function both( sequence s1, integer i1, sequence s2, integer i2 ) integer at at = find( i1, s1 ) if at then return s2[at] = i2 else return 0 end if end function function nextTo( sequence s1, integer i1, sequence s2, integer i2 ) integer at1, at2 at1 = find( i1, s1 ) at2 = find( i2, s2 ) if at1 and at2 then return ( house[at1] = house[at2]-1 or house[at1] = house[at2]+1 ) else return 0 end if end function function onRight( sequence s1, integer i1, sequence s2, integer i2 ) integer at1, at2 at1 = find( i1, s1 ) at2 = find( i2, s2 ) return ( house[at1] = house[at2]-1 ) end function procedure test() if 1 -- and both( country, English, color, Red ) -- and both( country, Spaniard, pet, Dog ) -- and both( country, Japanese, job, Painter ) -- and both( country, Italian, drink, Tea ) -- and both( country, Norwegian, house, 1 ) and both( color, Green, drink, Coffee ) and onRight( color, Green, color, White ) and both( job, Sculptor, pet, Snail ) and both( job, Diplomat, color, Yellow ) and both( drink, Milk, house, 3 ) and nextTo( country, Norwegian, color, Blue ) and both( job, Violinist, drink, Juice ) and nextTo( pet, Fox, job, Doctor ) and nextTo( pet, Horse, job, Diplomat ) then for i = 1 to 5 do puts( 1, nations[i] & " " & colors[color[i]] & " " & pets[pet[i]] & " " & jobs[job[i]] & " " & drinks[drink[i]] & " " & houses[house[i]] & "\n" ) end for abort(0) end if end procedure procedure main() calc_permutes( 5, 0 ) for colors = 1 to length( permutes ) do color = permutes[colors] if color[English] = Red then for pets = 1 to length( permutes ) do pet = permutes[pets] if pet[Spaniard] = Dog then for jobs = 1 to length( permutes ) do job = permutes[jobs] if job[Japanese] = Painter then for drinks = 1 to length( permutes ) do drink = permutes[drinks] if drink[Italian] = Tea then for houses = 1 to length( permutes ) do house = permutes[houses] if house[Norwegian] = 1 then test() end if end for end if end for end if end for end if end for end if end for end procedure main() -- Version 2: *very* slow sequence color, job, pet, drink, house, permutes, list, matrix constant colors = { "red", "green", "yellow", "white", "blue" }, nations = { "english", "spanish", "japanese", "italian", "norwegian" }, jobs = { "painter", "sculptor", "diplomat", "violinist", "doctor" }, pets = { "dog", "snail", "fox", "horse", "zebra" }, drinks = { "tea", "coffee", "milk", "juice", "water" }, houses = { "first", "second", "third", "fourth", "fifth" }, country = { 1, 2, 3, 4, 5 }, Color = 1, Job = 2, Pet = 3, Drink = 4, House = 5, Red = 1, Green = 2, Yellow = 3, White = 4, Blue = 5, English = 1, Spaniard = 2, Japanese = 3, Italian = 4, Norwegian = 5, Painter = 1, Sculptor = 2, Diplomat = 3, Violinist = 4, Doctor = 5, Dog = 1, Snail = 2, Fox = 3, Horse = 4, Zebra = 5, Tea = 1, Coffee = 2, Milk = 3, Juice = 4, Water = 5 procedure calc_permutes( integer i, integer j ) if j > i then permutes = append( permutes, list ) return else for k = 1 to i do if list[k] = 0 then list[k] = j calc_permutes( i, j+1 ) list[k] = 0 end if end for end if end procedure function both( sequence s1, integer i1, sequence s2, integer i2 ) integer at at = find( i1, s1 ) if at then return s2[at] = i2 end if return 0 end function function nextTo( sequence s1, integer i1, sequence s2, integer i2 ) integer at1, at2 at1 = find( i1, s1 ) at2 = find( i2, s2 ) if at1 and at2 then return ( house[at1] = house[at2]-1 or house[at1] = house[at2]+1 ) end if return 0 end function function onRight( sequence s1, integer i1, sequence s2, integer i2 ) integer at1, at2 at1 = find( i1, s1 ) at2 = find( i2, s2 ) return ( house[at1] = house[at2]-1 ) end function procedure test() if both( country, English, matrix[Color], Red ) and both( country, Spaniard, matrix[Pet], Dog ) and both( country, Japanese, matrix[Job], Painter ) and both( country, Italian, matrix[Drink], Tea ) and both( country, Norwegian, matrix[House], 1 ) and both( matrix[Color], Green, matrix[Drink], Coffee ) and onRight( matrix[Color], Green, matrix[Color], White ) and both( matrix[Job], Sculptor, matrix[Pet], Snail ) and both( matrix[Job], Diplomat, matrix[Color], Yellow ) and both( matrix[Drink], Milk, matrix[House], 3 ) and nextTo( country, Norwegian, matrix[Color], Blue ) and both( matrix[Job], Violinist, matrix[Drink], Juice ) and nextTo( matrix[Pet], Fox, matrix[Job], Doctor ) and nextTo( matrix[Pet], Horse, matrix[Job], Diplomat ) then for i = 1 to 5 do puts( 1, nations[i] & " " & colors[matrix[Color][i]] & " " & pets[matrix[Pet][i]] & " " & jobs[matrix[Job][i]] & " " & drinks[matrix[Drink][i]] & " " & houses[matrix[House][i]] & "\n" ) end for abort(0) end if end procedure procedure search( integer index, integer max ) for i = 1 to length( permutes ) do matrix[index] = permutes[i] if index = max then test() else search( index+1, max ) end if end for end procedure permutes = {} list = repeat( 0, 5 ) calc_permutes( 5, 1 ) matrix = repeat( {}, House ) search( 1, House )