Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

dpuu (6090)

  (email not shown publicly)
Yahoo! ID: dave_whipp (Add User, Send Message)

Journal of dpuu (6090)

Tuesday December 23, 2008
11:13 PM

The Bowling challenge

[ #38145 ]

Having played with the "pairs" challenge, I looked through the other beginners events. Most dealt with files and databases: I didn't want to tackle that right now. So I skipped to challenge-10: interpret a bowling game that is input as an array.

For this one, my thought was to exploit "multi" subs: there're only so many patterns to each frame: I can just code them explicitly. Lets start with my solution:

my @scores = 2,5,7,"/",8,1,"X",9,"/",5,3,7,0,4,5,"X",2,0;

my $total = 0;

multi frame_score ( Str $a, Str $b, Str $c ;; *@next ) { 30 }
multi frame_score ( Str $a, Str $b, Int $c ;; *@next ) { 20 + $c }
multi frame_score ( Str $a, Int $b, Str $c ;; *@next ) { 20 }
multi frame_score ( Str $a, Int $b, Int $c ;; *@next ) { [+] 10, $b, $c }
multi frame_score ( Int $a, Str $b, Str $c ;; *@next ) { 20 }
multi frame_score ( Int $a, Str $b, Int $c ;; *@next ) { 10 + $c }
multi frame_score ( Int $a, Int $b ;; *@next ) { $a + $b };

while @scores {
        $total += frame_score |@scores;
        say "score now $total";

        @scores.shift unless @scores[0] eq "X";

So what went wrong? Actually, this one went pretty smoothly. I probably should use specific string values, instead of relying on just the fact that "/" and "X" are generic strings (and it doesn't matter which). That's something I need to investigate. The one thing that feels a bit clunky is that logic at the bottom that decides how many bowls were bowled in each frame (and therefore how many to shift off the array. I'd really like to be able to use a "for" loop to iterate the array.

The're two features missing that don't permit that: one is that it's not possible to do multi pointy-blocks. That would need a syntax something like:

for @x:
    Int $x -> { ... },
    Str $x -> { ... }

That specific syntax possibly wouldn't work, but you get the idea...

the other thing missing is the ability to pass non-consumed args to the pointy-block. Something like:

for @a -> $x, $y ;; $z { ... }

where "$x" would not be consumed: only two items would be consumed from the list. ";;" wouldn't be the right syntax for the separate though, because there's not necessary relation between the usage of args for selecting between multi-pointies, and the args that are to be consumed.

Overall, this challenge was felt good in perl6!

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.
  • The code is really hard to follow. It takes a lot of careful scanning and thinking to understand which cases will invoke which variant of the sub. At first I thought you hadn’t handled the case where a strike is followed by a spare.

    Also, the logic for how much to advance is confusingly written. A little extra work would make this 10× easier to read:

    subset Strike of Any where { $_ eq 'X' };
    subset Spare  of Any where { $_ eq '/' };
    subset  Some  of Any where { $_ ne 'X' & '/' };

    • Thanks for the subset suggestion. I'd tried putting "where" clauses inline, but that was very clunky. Subsets definitely solve that.

      I'm not sure, however, I like your version of the consumption logic any better than mine: using a modifier-op ("shift" in both the conditional and consequent confuses me (I like conditionals to be pure). I would tend to agree, though, that my form was equally confusing. It might be best to be explicit:

              my $bowls_this_frame = @scores[0] eq "X" ?? 1 !!