in reply to Passing a complex array to a function

While this isn't a response to your question, it is an enlightenment. This task is ("is" => "can be") a case for a regex, which has been updated as per the responses below:
# solving math puzzles with regexes is FUN! ("." x 10_000) =~ m{ ^ # camille (.{0,3960}) (?(?{ length($1) >= 3960 })(?!)) # june (.{100} \1) (?(?{ length($1.$2) >= 3960 })(?!)) # martha (.{100} \2) (?(?{ length($1.$2.$3) != 3960 })(?!)) (?{ print join(" ", map length, $1, $2, $3), "\n" }) (?: \1 (?: \2 \2 (??{ ".{" . 1.5*length($3) . "}" }) $ (?{ print join(" ", map .5 * length, $1 x 2, $3 x 4, $2 x 3), +"\n" }) | \3 \3 (??{ ".{" . 1.5*length($2) . "}" }) $ (?{ print join(" ", map .5 * length, $1 x 2, $2 x 4, $3 x 3), +"\n" }) ) | \2 (?: \1 \1 (??{ ".{" . 1.5*length($3) . "}" }) $ (?{ print join(" ", map .5 * length, $2 x 2, $3 x 4, $1 x 3), +"\n" }) | \3 \3 (??{ ".{" . 1.5*length($1) . "}" }) $ (?{ print join(" ", map .5 * length, $2 x 2, $1 x 4, $3 x 3), +"\n" }) ) | \3 (?: \1 \1 (??{ ".{" . 1.5*length($2) . "}" }) $ (?{ print join(" ", map .5 * length, $3 x 2, $2 x 4, $1 x 3), +"\n" }) | \2 \2 (??{ ".{" . 1.5*length($1) . "}" }) $ (?{ print join(" ", map .5 * length, $3 x 2, $1 x 4, $2 x 3), +"\n" }) ) ) }x;
This code prints two rows of three columns. The first row is Camille, Jane, and Martha; the second row is the money of their respective husbands, whose names can then be determined by the allotment clues.

_____________________________________________________
Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Replies are listed 'Best First'.
Re: Re: Passing a complex array to a function
by particle (Vicar) on Jan 26, 2002 at 11:58 UTC
    i believe the order of the second row of your output is incorrect.

    in order to output the husbands money respectively, the affected part of your regex should read:

    (?: \1 (?: \2 \2 (??{ ".{" . 1.5*length($3) . "}" }) $ (?{ print join(" ", map .5 * length, $1 x 2, $3 x 3, $2 x 4), +"\n" }) | \3 \3 (??{ ".{" . 1.5*length($2) . "}" }) $ (?{ print join(" ", map .5 * length, $1 x 2, $2 x 3, $3 x 4), +"\n" }) ) | \2 (?: \1 \1 (??{ ".{" . 1.5*length($3) . "}" }) $ (?{ print join(" ", map .5 * length, $2 x 2, $3 x 3, $1 x 4), +"\n" }) | \3 \3 (??{ ".{" . 1.5*length($1) . "}" }) $ (?{ print join(" ", map .5 * length, $2 x 2, $1 x 3, $3 x 4), +"\n" }) ) | \3 (?: \1 \1 (??{ ".{" . 1.5*length($2) . "}" }) $ (?{ print join(" ", map .5 * length, $3 x 2, $2 x 3, $1 x 4), +"\n" }) | \2 \2 (??{ ".{" . 1.5*length($1) . "}" }) $ (?{ print join(" ", map .5 * length, $3 x 2, $1 x 3, $2 x 4), +"\n" }) ) )
    the affected areas are in the print statements. the order of the multipliers (2, 4, 3) in your original code should be (2, 3, 4,) which will make the output:
    1220 1320 1420 1220 1980 2840
    which is, left to right, in format: names (multipliers)
    first row: Camille, June, Martha
    second row: Jack Smith (x100%), Horace Sanders (x150%), Terry Conners (x200%)

    i must say, i'm still trying to wrap my brain around this code. it's quite a lot for me to process. in fact, i'm amazed to learn that these type of problems can be attacked by regular expressions. brilliant! now, if i can only understand how to do it, then i can use it.

    as far as my mechanical engineering background allows me to understand your algorithm, this is what i've been able to figure out. you've created a vector of 10_000 '.' characters. your first regexes work within the first 3_960 elements to determine the answer to the equation:

    Camille + June + Martha = Total wives = 3_960
    or, after a bit of algebra:
    C + ( C + 100 ) + ( C + 200 ) = 3 * C + 300 = 3_960

    although i don't understand your advanced regex magic, the algorithm is quite clear. the length of the matches is printed, and the elements are discarded, leaving the remainder of the vector as the husbands' total.

    enter the second stage of regex magic. i think you are basically using vector products in this bit of code. i can explain the print statement pretty well (the tricky bit is the map .5 * length, ... which translates the multipliers (2, 3, 4) into the problem multipliers of (100%, 150%, 200%).

    what i don't understand is what seems to me to be superfulous code. i hope you can explain this to me. if i modify your second section of your regex to read:

    (?: \1 (?: \2 \2 (??{ ".{" . 1.5*length($3) . "}" }) $ (?{ print join(" ", map .5 * length, $1 x 2, $3 x 3, $2 x 4), +"\n" }) | \3 \3 (??{ ".{" . 1.5*length($2) . "}" }) $ (?{ print join(" ", map .5 * length, $1 x 2, $2 x 3, $3 x 4), +"\n" }) ) )
    (i've removed everything after the \1 block) the answer remains the same. what are the consequences of the removal of this code?

    again, i've never seen this type of problem approached in this manner, and i'm awed by the power, beauty, and simplicity of a well-crafted solution using perl's regular expression engine. i know understanding your method (and madness) will make me a better coder, and an even bigger fan of Perl.

    ~Particle

      The first part partitions the first 3960 characters to the wives. The second chunk uses those values and attempts to figure out how they mesh again (at ratios of 1:1, 3:2, and 2:1).

      It could be considered cheating that I hard-wired the permutations of the \1, \2, and \3 part. I'll have another stab at it that has the regex engine do the permutations on its own.

      _____________________________________________________
      Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
      s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

Re: Re: Passing a complex array to a function
by trs80 (Priest) on Jan 26, 2002 at 11:43 UTC
    I ran this and the columns didn't line up. I got:

    1220 1320 1420
    1220 2840 1980

    it should be:

    1220 1320 1420
    1220 1980 2840
    I am still amazed by the process however.