Cow1337killr has asked for the wisdom of the Perl Monks concerning the following question:

If I could use a Perl version of the Rosetta Code zebra puzzle that complied with the concepts of Modern Perl, then potentially this question would be written regarding the Perl programming language; I expected at least a Moose version of a solution.

I found the Rosetta Code zebra puzzle written in Sidef, but I decided that the Sidef community was not large enough to answer any questions I might have; I admit I did not try asking.

So, I looked at the Raku solution (again) and determined that it had promise (i.e, I might learn something from it and I might use what I learned to write future programs for problems that I may enounter in the future, especially because Raku uses ideas from many modern languages and many modern languages look to Raku for an inspiration for new ideas.)

I knew I could use “use trace;” to get a trace from Google (Google search “raku debug”, then click on https://docs.raku.org/programs/01-debugging).

I installed version 2023.06 on Ubuntu Linux on Google Colaboratory.

I ran the Raku version of the Rosetta Code zebra puzzle.

As readers can see, my trace encountered an exception which one does not receive if they do NOT use the “use trace;” pragma.

%%writefile raku-zebra-puzzle-002.raku use trace; my Hash @houses = (1 .. 5).map: { %(:num($_)) }; # 1 there are five ho +uses my @facts = ( { :nat<English>, :color<red> }, # 2 The English man lives in +the red house. { :nat<Swede>, :pet<dog> }, # 3 The Swede has a dog. { :nat<Dane>, :drink<tea> }, # 4 The Dane drinks tea. { :color<green>, :Left-Of(:color<white>) }, # 5 the green house is + immediately to the left of the white house { :drink<coffee>, :color<green> }, # 6 They drink coffee in the +green house. { :smoke<Pall-Mall>, :pet<birds> }, # 7 The man who smokes Pall M +all has birds. { :color<yellow>, :smoke<Dunhill> }, # 8 In the yellow house they +smoke Dunhill. { :num(3), :drink<milk> }, # 9 In the middle house they +drink milk. { :num(1), :nat<Norwegian> }, # 10 The Norwegian lives in t +he first house. { :smoke<Blend>, :Next-To(:pet<cats>) }, # 11 The man who smokes B +lend lives in the house next to the house with cats. { :pet<horse>, :Next-To(:smoke<Dunhill>) }, # 12 In a house next t +o the house where they have a horse, they smoke Dunhill. { :smoke<Blue-Master>, :drink<beer> }, # 13 The man who smokes Blu +e Master drinks beer. { :nat<German>, :smoke<Prince> }, # 14 The German smokes Prin +ce. { :nat<Norwegian>, :Next-To(:color<blue>) }, # 15 The Norwegian li +ves next to the blue house. { :drink<water>, :Next-To(:smoke<Blend>) }, # 16 They drink water + in a house next to the house where they smoke Blend. { :pet<zebra> }, # who owns this? ); sub MAIN { for gather solve(@houses, @facts) { #-- output say .head.sort.map(*.key.uc.fmt("%-9s")).join(' | '); say .sort.map(*.value.fmt("%-9s")).join(' | ') for .list; last; # stop after first solution } } #| a solution has been found that fits all the facts multi sub solve(@solution, @facts [ ]) { say 'multi sub solve(@solution, @facts [ ]) {'; say @solution.elems; @solution.say; take @solution; } #| extend this scenario to fit the next fact multi sub solve(@scenario, [ $fact, *@facts ]) { for gather match(@scenario, |$fact) -> @houses { solve(@houses, @facts) } } #| find all possible solutions for pairs of houses with #| properties %b, left of a house with properties %a multi sub match(@houses, :Left-Of(%a)!, *%b) { for 1 ..^ @houses { my %left-house := @houses[$_-1]; my %right-house := @houses[$_]; if plausible(%left-house, %a) && plausible(%right-house, %b) { temp %left-house ,= %a; temp %right-house ,= %b; take @houses; } } } #| match these houses are next to each other (left or right) multi sub match(@houses, :Next-To(%b)!, *%a ) { match(@houses, |%a, :Left-Of(%b) ); match(@houses, |%b, :Left-Of(%a) ); } #| find all possible houses that match the given properties multi sub match(@houses, *%props) { for @houses.grep({plausible($_, %props)}) -> %house { temp %house ,= %props; take @houses; } } #| plausible if doesn't conflict with anything sub plausible(%house, %props) { ! %props.first: {%house{.key} && %house{.key} ne .value }; }
2 (/content/raku-zebra-puzzle-002.raku line 2) my Hash @houses = (1 .. 5).map: { %(:num($_)) } 3 (/content/raku-zebra-puzzle-002.raku line 2) 1 .. 5 5 (/content/raku-zebra-puzzle-002.raku line 2) %(:num($_)) 6 (/content/raku-zebra-puzzle-002.raku line 2) :num($_) 7 (/content/raku-zebra-puzzle-002.raku line 2) $_ 5 (/content/raku-zebra-puzzle-002.raku line 2) %(:num($_)) 6 (/content/raku-zebra-puzzle-002.raku line 2) :num($_) 7 (/content/raku-zebra-puzzle-002.raku line 2) $_ 5 (/content/raku-zebra-puzzle-002.raku line 2) %(:num($_)) 6 (/content/raku-zebra-puzzle-002.raku line 2) :num($_) 7 (/content/raku-zebra-puzzle-002.raku line 2) $_ 5 (/content/raku-zebra-puzzle-002.raku line 2) %(:num($_)) 6 (/content/raku-zebra-puzzle-002.raku line 2) :num($_) 7 (/content/raku-zebra-puzzle-002.raku line 2) $_ 5 (/content/raku-zebra-puzzle-002.raku line 2) %(:num($_)) 6 (/content/raku-zebra-puzzle-002.raku line 2) :num($_) 7 (/content/raku-zebra-puzzle-002.raku line 2) $_ 11 (/content/raku-zebra-puzzle-002.raku line 4) my @facts = ( { :nat<English>, :color<red> }, # 2 The English man lives in +the red house. { :nat<Swede>, :pet<dog> }, # 3 The Swede has a dog. { :nat<Dane>, :drink<tea> }, # 4 The Dane drinks tea. { :color<green>, :Left-Of(:color<white>) }, # 5 the green house is + immediately to the left of the white house { :drink<coffee>, :color<green> }, # 6 They drink coffee in the +green house. { :smoke<Pall-Mall>, :pet<birds> }, # 7 The man who smokes Pall M +all has birds. { :color<yellow>, :smoke<Dunhill> }, # 8 In the yellow house they +smoke Dunhill. { :num(3), :drink<milk> }, # 9 In the middle house they +drink milk. { :num(1), :nat<Norwegian> }, # 10 The Norwegian lives in t +he first house. { :smoke<Blend>, :Next-To(:pet<cats>) }, # 11 The man who smokes B +lend lives in the house next to the house with cats. { :pet<horse>, :Next-To(:smoke<Dunhill>) }, # 12 In a house next t +o the house where they have a horse, they smoke Dunhill. { :smoke<Blue-Master>, :drink<beer> }, # 13 The man who smokes Blu +e Master drinks beer. { :nat<German>, :smoke<Prince> }, # 14 The German smokes Prin +ce. { :nat<Norwegian>, :Next-To(:color<blue>) }, # 15 The Norwegian li +ves next to the blue house. { :drink<water>, :Next-To(:smoke<Blend>) }, # 16 They drink water + in a house next to the house where they smoke Blend. { :pet<zebra> }, # who owns this? ) 12 (/content/raku-zebra-puzzle-002.raku line 5) { :nat<English>, :color<red> }, # 2 The English man lives in the +red house. { :nat<Swede>, :pet<dog> }, # 3 The Swede has a dog. { :nat<Dane>, :drink<tea> }, # 4 The Dane drinks tea. { :color<green>, :Left-Of(:color<white>) }, # 5 the green house is + immediately to the left of the white house { :drink<coffee>, :color<green> }, # 6 They drink coffee in the +green house. { :smoke<Pall-Mall>, :pet<birds> }, # 7 The man who smokes Pall M +all has birds. { :color<yellow>, :smoke<Dunhill> }, # 8 In the yellow house they +smoke Dunhill. { :num(3), :drink<milk> }, # 9 In the middle house they +drink milk. { :num(1), :nat<Norwegian> }, # 10 The Norwegian lives in t +he first house. { :smoke<Blend>, :Next-To(:pet<cats>) }, # 11 The man who smokes B +lend lives in the house next to the house with cats. { :pet<horse>, :Next-To(:smoke<Dunhill>) }, # 12 In a house next t +o the house where they have a horse, they smoke Dunhill. { :smoke<Blue-Master>, :drink<beer> }, # 13 The man who smokes Blu +e Master drinks beer. { :nat<German>, :smoke<Prince> }, # 14 The German smokes Prin +ce. { :nat<Norwegian>, :Next-To(:color<blue>) }, # 15 The Norwegian li +ves next to the blue house. { :drink<water>, :Next-To(:smoke<Blend>) }, # 16 They drink water + in a house next to the house where they smoke Blend. { :pet<zebra> }, # who owns this? 60 (/content/raku-zebra-puzzle-002.raku line 23) sub MAIN { for gather solve(@houses, @facts) { #-- output say .head.sort.map(*.key.uc.fmt("%-9s")).join(' | '); say .sort.map(*.value.fmt("%-9s")).join(' | ') for .list; last; # stop after first solution } } #| a solution has been found that fits all the facts 68 (/content/raku-zebra-puzzle-002.raku line 34) multi sub solve(@solution, @facts [ ]) { say 'multi sub solve(@solution, @facts [ ]) {'; say @solution.elems; @solution.say; take @solution; } #| extend this scenario to fit the next fact 74 (/content/raku-zebra-puzzle-002.raku line 42) multi sub solve(@scenario, [ $fact, *@facts ]) { for gather match(@scenario, |$fact) -> @houses { solve(@houses, @facts) } } #| find all possible solutions for pairs of houses with #| properties %b, left of a house with properties %a 80 (/content/raku-zebra-puzzle-002.raku line 50) multi sub match(@houses, :Left-Of(%a)!, *%b) { for 1 ..^ @houses { my %left-house := @houses[$_-1]; my %right-house := @houses[$_]; if plausible(%left-house, %a) && plausible(%right-house, %b) { temp %left-house ,= %a; temp %right-house ,= %b; take @houses; } } } #| match these houses are next to each other (left or right) 95 (/content/raku-zebra-puzzle-002.raku line 64) multi sub match(@houses, :Next-To(%b)!, *%a ) { match(@houses, |%a, :Left-Of(%b) ); match(@houses, |%b, :Left-Of(%a) ); } #| find all possible houses that match the given properties 103 (/content/raku-zebra-puzzle-002.raku line 70) multi sub match(@houses, *%props) { for @houses.grep({plausible($_, %props)}) -> %house { temp %house ,= %props; take @houses; } } #| plausible if doesn't conflict with anything 111 (/content/raku-zebra-puzzle-002.raku line 78) sub plausible(%house, %props) { ! %props.first: {%house{.key} && %house{.key} ne .value }; } 61 (/content/raku-zebra-puzzle-002.raku line 24) for gather solve(@houses, @facts) { #-- output say .head.sort.map(*.key.uc.fmt("%-9s")).join(' | '); say .sort.map(*.value.fmt("%-9s")).join(' | ') for .list; last; # stop after first solution } 62 (/content/raku-zebra-puzzle-002.raku line 24) solve(@houses, @facts) 75 (/content/raku-zebra-puzzle-002.raku line 43) for gather match(@scenario, |$fact) -> @houses { solve(@houses, @facts) } 76 (/content/raku-zebra-puzzle-002.raku line 43) match(@scenario, |$fact) Cannot resolve caller match(Array[Hash]:D, Block:D); none of these sig +natures matches: (@houses, :Left-Of(%a)!, *%b) (@houses, :Next-To(%b)!, *%a) (@houses, *%props) in sub solve at raku-zebra-puzzle-002.raku line 43 in sub MAIN at raku-zebra-puzzle-002.raku line 24 in block <unit> at raku-zebra-puzzle-002.raku line 78

How do I proceed? Do I write a “match” subroutine that accepts “Any” for all parameters and does nothing?