#!perl -w # Code for Puzzle Pres - Ottawa.Pm 13 Mar 2003 @housecolour =qw(blue green red white yellow); @nationality =qw(Brit Dane German Norwegian Swede); @beverage =qw(beer coffee milk tea water); @smoke =qw(BlueM Dunhill PaulMaul Prince Blend); @pet =qw(cat bird fish horse dog); my @pers= ({hp=>1}, {hp=>2}, {hp=>3}, {hp=>4}, {hp=>5}); for (@nationality) { $pers[0]->{nat}= $_; unless (verify(@pers)) { $pers[0]->{nat}= undef; next } for (@nationality) { $pers[1]->{nat}= $_; unless (verify(@pers)) { $pers[1]->{nat}= undef; next } for (@nationality) { $pers[2]->{nat}= $_; unless (verify(@pers)) { $pers[2]->{nat}= undef; next } for (@nationality) { $pers[3]->{nat}= $_; unless (verify(@pers)) { $pers[3]->{nat}= undef; next } for (@nationality) { $pers[4]->{nat}= $_; unless (verify(@pers)) { $pers[4]->{nat}= undef; next } for (@housecolour) { $pers[0]->{hc}= $_; unless (verify(@pers)) { $pers[0]->{hc}= undef; next } for (@housecolour) { $pers[1]->{hc}= $_; unless (verify(@pers)) { $pers[1]->{hc}= undef; next } for (@housecolour) { $pers[2]->{hc}= $_; unless (verify(@pers)) { $pers[2]->{hc}= undef; next } for (@housecolour) { $pers[3]->{hc}= $_; unless (verify(@pers)) { $pers[3]->{hc}= undef; next } for (@housecolour) { $pers[4]->{hc}= $_; unless (verify(@pers)) { $pers[4]->{hc}= undef; next } for (@beverage) { $pers[0]->{bev}= $_; unless (verify(@pers)) { $pers[0]->{bev}= undef; next } for (@beverage) { $pers[1]->{bev}= $_; unless (verify(@pers)) { $pers[1]->{bev}= undef; next } for (@beverage) { $pers[2]->{bev}= $_; unless (verify(@pers)) { $pers[2]->{bev}= undef; next } for (@beverage) { $pers[3]->{bev}= $_; unless (verify(@pers)) { $pers[3]->{bev}= undef; next } for (@beverage) { $pers[4]->{bev}= $_; unless (verify(@pers)) { $pers[4]->{bev}= undef; next } for (@smoke) { $pers[0]->{smo}= $_; unless (verify(@pers)) { $pers[0]->{smo}= undef; next } for (@smoke) { $pers[1]->{smo}= $_; unless (verify(@pers)) { $pers[1]->{smo}= undef; next } for (@smoke) { $pers[2]->{smo}= $_; unless (verify(@pers)) { $pers[2]->{smo}= undef; next } for (@smoke) { $pers[3]->{smo}= $_; unless (verify(@pers)) { $pers[3]->{smo}= undef; next } for (@smoke) { $pers[4]->{smo}= $_; unless (verify(@pers)) { $pers[4]->{smo}= undef; next } for (@pet) { $pers[0]->{pet}= $_; unless (verify(@pers)) { $pers[0]->{pet}= undef; next } for (@pet) { $pers[1]->{pet}= $_; unless (verify(@pers)) { $pers[1]->{pet}= undef; next } for (@pet) { $pers[2]->{pet}= $_; unless (verify(@pers)) { $pers[2]->{pet}= undef; next } for (@pet) { $pers[3]->{pet}= $_; unless (verify(@pers)) { $pers[3]->{pet}= undef; next } for (@pet) { $pers[4]->{pet}= $_; unless (verify(@pers)) { $pers[4]->{pet}= undef; next } my $p2 = getpers(\@pers, "pet", "fish"); print $p2->{"nat"}," has fish\n"; exit 0; $pers[4]->{pet}= undef; } $pers[3]->{pet}= undef; } $pers[2]->{pet}= undef; } $pers[1]->{pet}= undef; } $pers[0]->{pet}= undef; } $pers[4]->{smo}= undef; } $pers[3]->{smo}= undef; } $pers[2]->{smo}= undef; } $pers[1]->{smo}= undef; } $pers[0]->{smo}= undef; } $pers[4]->{bev}= undef; } $pers[3]->{bev}= undef; } $pers[2]->{bev}= undef; } $pers[1]->{bev}= undef; } $pers[0]->{bev}= undef; } $pers[4]->{hc} = undef; } $pers[3]->{hc} = undef; } $pers[2]->{hc} = undef; } $pers[1]->{hc} = undef; } $pers[0]->{hc} = undef; } $pers[4]->{nat}= undef; } $pers[3]->{nat}= undef; } $pers[2]->{nat}= undef; } $pers[1]->{nat}= undef; } $pers[0]->{nat}= undef; } { use Data::Dumper ; print Dumper(@pers); die}; sub verify { my @pers= @_; for my $cat qw(hp hc nat bev smo pet) { my %verif; for my $pers (@pers) { next unless $pers->{$cat}; return 0 if $verif{$pers->{$cat}}; $verif{$pers->{$cat}}=1; } } # 1. The Brit lives in a red house. { my $p = getpers(\@pers, "nat", "Brit"); if ($p && $p->{hc} ) { return 0 unless $p->{hc} eq "red"; } } # 2. The Swede keeps dogs as pets. { my $p = getpers(\@pers, "nat", "Swede"); if ($p && $p->{pet} ) { return 0 unless $p->{pet} eq "dog"; } } # 3. The Dane drinks tea. { my $p = getpers(\@pers, "nat", "Dane"); if ($p && $p->{bev} ) { return 0 unless $p->{bev} eq "tea"; } } # 4. The green house is on the left of the white house (next to it). { my $p1 = getpers(\@pers, "hc", "green"); my $p2 = getpers(\@pers, "hc", "white"); if ($p1 && $p2 && $p1->{hp} && $p2->{hp} ) { return 0 unless ($p2->{hp} - $p1->{hp} ==-1); # return 0 unless abs($p2->{hp} - $p1->{hp}) ==1; } } # 5. The green house owner drinks coffee. { my $p = getpers(\@pers, "hc", "green"); if ($p && $p->{bev} ) { return 0 unless $p->{bev} eq "coffee"; } } # 6. The person who smokes Pall Mall rears birds. { my $p = getpers(\@pers, "smo", "PaulMaul"); if ($p && $p->{pet} ) { return 0 unless $p->{pet} eq "bird"; } } # 7. The owner of the yellow house smokes Dunhill. { my $p = getpers(\@pers, "hc", "yellow"); if ($p && $p->{smo} ) { return 0 unless $p->{smo} eq "Dunhill"; } } # 8. The man living in the house right in the center drinks milk. { my $p = getpers(\@pers, "hp", "3"); if ($p && $p->{bev} ) { return 0 unless $p->{bev} eq "milk"; } } # 9. The Norwegian lives in the first house. { my $p = getpers(\@pers, "nat", "Norwegian"); if ($p && $p->{hp} ) { return 0 unless $p->{hp} eq "1"; } } # 10. The man who smokes blend lives next to the one who keeps cats. { my $p1 = getpers(\@pers, "smo", "Blend"); my $p2 = getpers(\@pers, "pet", "cat"); if ($p1 && $p2 && $p1->{hp} && $p2->{hp} ) { return 0 unless ( abs($p2->{hp} - $p1->{hp}) ==1); } } # 11. The man who keeps horses lives next to the man who smokes Dunhill. { my $p1 = getpers(\@pers, "smo", "Dunhill"); my $p2 = getpers(\@pers, "pet", "horse"); if ($p1 && $p2 && $p1->{hp} && $p2->{hp} ) { return 0 unless ( abs($p2->{hp} - $p1->{hp}) ==1); } } # 12. The owner who smokes Blue Master drinks beer. { my $p = getpers(\@pers, "smo", "BlueM"); if ($p && $p->{bev} ) { return 0 unless $p->{bev} eq "beer"; } } # 13. The German smokes Prince. { my $p = getpers(\@pers, "nat", "German"); if ($p && $p->{smo} ) { return 0 unless $p->{smo} eq "Prince"; } } # 14. The Norwegian lives next to the blue house. { my $p1 = getpers(\@pers, "nat", "Norwegian"); my $p2 = getpers(\@pers, "hc", "blue"); if ($p1 && $p2 && $p1->{hp} && $p2->{hp} ) { return 0 unless ( abs($p2->{hp} - $p1->{hp}) ==1); } } # 15. The man who smokes blend has a neighbor who drinks water. { my $p1 = getpers(\@pers, "smo", "Blend"); my $p2 = getpers(\@pers, "bev", "water"); if ($p1 && $p2 && $p1->{hp} && $p2->{hp} ) { return 0 unless ( abs($p2->{hp} - $p1->{hp}) ==1); } } return 1; } sub getpers { my @pers = @{shift()}; my $cat = shift; my $val = shift; for my $pers (@pers) { next unless $pers->{$cat}; return $pers if $pers->{$cat} eq $val; } return undef; }