http://www.perlmonks.org?node_id=1209857

Hi! I would like to introduce my module - my first contribution to www.cpan.org. It is generating a logical puzzle. Get it from https://metacpan.org/release/App-ForKids-LogicalPuzzleGenerator. You can use it as follows:

use App::ForKids::LogicalPuzzleGenerator; my $x = App::ForKids::LogicalPuzzleGenerator->new(range=>3, amount_of_facts_per_session => 4); print $$x{intro_story}; print $$x{story}; print $$x{solution_story};

It is heavily using AI::Prolog. An example of such puzzle is below:

John,Patrick and James live here. Each has a different favourite fruit (pinapples,apples,pears). Each has a different profession (fisherman,blacksmith,witcher).

- My name is John. The one who likes apples is not a blacksmith. Patrick is not a witcher. James does not like pinapples. James is not a fisherman.

- My name is James. John does not like pears. Patrick does not like apples. I don't like apples. The one who likes apples is not a fisherman.

John likes apples. John is a witcher. Patrick likes pinapples. Patrick is a fisherman. James likes pears. James is a blacksmith.

Pawel Biernacki

Replies are listed 'Best First'.
Re: My first cpan module - App::ForKids::LogicalPuzzleGenerator
by Your Mother (Archbishop) on Feb 23, 2018 at 19:35 UTC

    Super fun++. A few observations without having looked at the code yet or tried more than the example you gave–

    • It's very slow. I don't know if that's something that can be fixed.
    • It could use a simple spacing and article clean up; e.g., s/white,red,yellow/white, red, or yellow/ and s/a owl/an owl/.
    • The POD seems to have some boiler plate still.
    • The output should really be done with methods instead of direct access to the object with dereferencing.
    • I strongly encourage you to put the code on github to make collaboration easier.

    I am absolutely going to put some of the output from this in front of kids. I appreciate you getting this up there!

      > It's very slow

      Most probably because of AI::Prolog

      I have the impression - I might be wrong - that these clauses can be represented as entries in a 3x3x3 matrix = (name x profession x fruit) in the example given.

      Entries would be undef, 0 and 1 and each 3x3 sub-square must have exactly one 1 entry and all others 0 for a solution.

      A solver could be built by filling that matrix and constantly checking all 9 sub layers for deduced entries. (see example here)

      Giving a set of random clauses it should be possible to pick n til the solver proves it's solvable (rejecting contradictory clauses)

      This reminds me of a graphic technique we learned at uni for finding boolean rules and logical circuits from a given truth table, but I can't remember the name.

      (Update: this looks right http://en.wikipedia.org/wiki/Karnaugh_map )

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Wikisyntax for the Monastery

        You are probably right about the matrix. I have a website which contains the puzzles and there are some diagrams generated to fill them:

        http://www.pawelbiernacki.net/4kids/logicalpuzzle/4x4/puzzle_4x4_en_US_0.jsp.

        I think the diagram reflects the matrix you have mentioned.

        The version on my website is available in different languages but I was not sure how to apply gettext on a Perl project by ExtUtils::MakeMaker, so I simply removed the translations.

        Pawel Biernacki
Re: My first cpan module - App::ForKids::LogicalPuzzleGenerator
by choroba (Cardinal) on Feb 23, 2018 at 21:56 UTC
    I know it as Einstein's Puzzle and one of its charms is that you don't name the full sets, so the question sounds like a joke to an unprepared:

    Three friends live here. Each likes a different fruit and has a different profession.
    John doesn't like pears. The programmer likes cherries. Patrick is a blacksmith. Edward isn't a fisherman.
    Who likes apples?

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

      That was fun! Thanks.

      #!/usr/bin/perl -l # http://perlmonks.org/?node_id=1209857 use strict; use warnings; $_ = <<END; # starting conditions John apples,cherries,pears blacksmith,fisherman,programmer Patrick apples,cherries,pears blacksmith,fisherman,programmer Edward apples,cherries,pears blacksmith,fisherman,programmer END my $prev; do { print; $prev = $_; s/^John \S*\Kpears//m; # John doesn't like pears s/^Patrick \S+ \K\S+/blacksmith/m; # Patrick is a blacksmith s/^Edward \S+ \S*\Kfisherman//m; # Edward isn't a fisherman s/\S+(?= programmer$)/cherries/m; # The programmer likes cherries s/,+\K,|\B,+|,+\B//g; # cleanup extra commas for my $col (1 .. tr/ // / tr/\n// ) # for each column { for my $one ( /^(?:\S+ ){$col}(\w+)\s/gm ) # find each single one { s/^(?:\S+ ){$col}(?:\K$one,|\S+\K,$one\b)//gm; # delete in other + rows } } } until $_ eq $prev;

      Outputs:

      John apples,cherries,pears blacksmith,fisherman,programmer Patrick apples,cherries,pears blacksmith,fisherman,programmer Edward apples,cherries,pears blacksmith,fisherman,programmer John apples,cherries fisherman,programmer Patrick apples,cherries,pears blacksmith Edward apples,cherries,pears programmer John apples fisherman Patrick apples,pears blacksmith Edward cherries programmer John apples fisherman Patrick pears blacksmith Edward cherries programmer
        Choroba's Version of the Zebra puzzle was very easy.

        For real "fun" try to solve this one with regexes

        The following version of the puzzle appeared in Life International in 1962:
        • There are five houses.
        • The Englishman lives in the red house.
        • The Spaniard owns the dog.
        • Coffee is drunk in the green house.
        • The Ukrainian drinks tea.
        • The green house is immediately to the right of the ivory house.
        • The Old Gold smoker owns snails.
        • Kools are smoked in the yellow house.
        • Milk is drunk in the middle house.
        • The Norwegian lives in the first house.
        • The man who smokes Chesterfields lives in the house next to the man with the fox.
        • Kools are smoked in the house next to the house where the horse is kept.
        • The Lucky Strike smoker drinks orange juice.
        • The Japanese smokes Parliaments.
        • The Norwegian lives next to the blue house.
        update

        Now, who drinks water? Who owns the zebra?

        In the interest of clarity, it must be added that each of the five houses is painted a different color, and their inhabitants are of different national extractions, own different pets, drink different beverages and smoke different brands of American cigarets sic. One other thing: in statement 6, right means your right.

        — Life International, December 17, 1962

        update end

        At some point you will need a branch and bound algorithm here, maybe by exploiting the backtracking of the regex engine.

        Good fun! ;)

        Extra motivation: you can add your potential regex solution to Rosetta code then.

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Wikisyntax for the Monastery

      testing if my approach also works here ...

      The difference is that you have positive clauses like The programmer likes cherries , which result in 12 zeroes instead of only 3:

      • 6 for (programmer)x(apples,pears)
      • 6 for (blacksmith,fisherman) x (cherries)

      That's why you fewer clauses than the OP to be decisive.

      Applying all clauses:

      FRUITS PROFESSIONS NAMES P B F cherries . 0 0 apples 0 0 . John pears 0 0 0 cherries 0 0 0 apples 0 . 0 Patrick pears 0 . 0 cherries . 0 0 apples 0 0 0 Edward pears 0 0 0
      • => (Edward,programmer,cherries)
      • => (fisherman,John, apples)
      • excluding other possibilities
      FRUITS PROFESSIONS NAMES P B F cherries 0 0 0 apples 0 0 1 John pears 0 0 0 cherries 0 0 0 apples 0 0 0 Patrick pears 0 . 0 cherries 1 0 0 apples 0 0 0 Edward pears 0 0 0
      • => (Patrick, blacksmith, pears)

      I'd say a bit too easy. :)

      But I think it's obvious now how we could use this "hyper-cube" solver for creating riddles in low dimensions.

      update

      Though I'm not sure if a "solvable" riddle (i.e. only one solution possible) is always as obvious as the examples given so far.

      For instance what if every cut has at least 2 undefined points, such that the first step is not obvious.

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Wikisyntax for the Monastery

      update

      This riddle is even easier and already solved right away without eliminations. since there is only one possibility for pears after initially filling the matrix.

      I am pretty sure there is a solver for such puzzles in CPAN. But I do not remember its name.

      Pawel Biernacki
      > I know it as Einstein's Puzzle

      But the constraints in an Einstein or Zebra puzzle have an additional quality of order!

      like: "John lives in the house right of the blacksmith."

      or

      "The Blend smoker has a neighbour who keeps cats."

      update

      For instance, I can't encode this last one in a hyper-cube, if there are 2 neighbours!

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Wikisyntax for the Monastery

Re: My first cpan module - App::ForKids::LogicalPuzzleGenerator
by LanX (Saint) on Feb 23, 2018 at 20:55 UTC

      Ha! I almost wrote in my post: These are supposed to be easy for adults right? Asking for a friend.

        Try one with a parameter range=>4. They are more difficult ;).

        Pawel Biernacki