di / divspl

Dustin Ingram's Very Special Programming Language
https://pypi.python.org/pypi/divspl
56 stars 10 forks source link

Very Clever!! (I was inspired to port it to Perl 6) #3

Closed DabeDotCom closed 8 years ago

DabeDotCom commented 8 years ago

This isn't an "issue" per se... I just wanted to leave a comment.

As an old-school Perl [5] guy interested in learning new capabilities, whenever I see a clever trick like this, I immediately see it as an opportunity/exercise to help me better understand, "How would I do that in Perl 6?"

(And no, I don't mean this to be the start of some kind of Holy War! I'd rather see how Rubyists would do it in Ruby, and how Javascripters would port it to Javascript, or how Haskell/Erlang/Scala/Closure/Go supporters would tackle similar problems in their respective domains...)

Anyway, for posterity, here's what I came up with:

#!/usr/bin/env perl6
# Re: https://www.promptworks.com/blog/the-fastest-fizzbuzz-in-the-west

grammar FizzBuzz {
    token TOP {
        <range>
        [ <assignment> ]*
    }

    rule range { $<start>=[\d+] '...' $<end>=[\d+] }
    rule assignment { $<word>=[ <[a..z]>+ ] '=' $<num>=[\d+] }
}

class FizzBuzzActions {
    my ($start, $end, %words);

    method TOP($/) {
        make map -> $i {
              ( for %words.keys.sort -> $num { $i % $num ?? '' !! %words{$num} } ).join || $i
        }, $start..$end
    }
    method range($/) { ($start, $end) = $<start>, $<end> }
    method assignment($/) { %words{$<num>} = $<word> }
}

.say for FizzBuzz.parse(q:to/END_OF_FIZZBUZZ/, actions => FizzBuzzActions).made;
1...15
fizz=3
buzz=5
END_OF_FIZZBUZZ

Enjoy! :-D

di commented 8 years ago

@DabeDotCom Thanks for the message! One of my colleagues, @bduggan did an implementation in Perl 6 as well, you can see his implementation here: https://www.reddit.com/r/perl6/comments/50btmo/fun_with_fizzbuzz/

DabeDotCom commented 8 years ago

Wow! That's certainly more clever than mine! :-D

(Though I'm going to, uhm, say I was, ahh, trying to "Keep It Simple, Stupid!" Yeah, that's it... «wink»)

Anyway, it at least helped me figure out how to remove the temporary variables (e.g., %words), as well as pointing out the '%%' operator:

grammar FizzBuzz {
    token TOP { <range> [ <assignment> ]* }
    rule range { $<start>=[\d+] '...' $<end>=[\d+] }
    rule assignment { $<word>=[\w+] '=' $<num>=[\d+] }
}

class FizzBuzzActions {
    method TOP($/) {
        make $<range>.made.map: -> $i {
            [~] $<assignment>».made.sort.map: { $i %% .key ?? .value !! '' } or $i
        }
    }
    method range($/)      { make $<start> .. $<end>  }
    method assignment($/) { make $<num>   => $<word> }
}

.say for FizzBuzz.parse(q:to/END_OF_FIZZBUZZ/, :actions(FizzBuzzActions)).made;
1...15
fizz=3
buzz=5
END_OF_FIZZBUZZ

Thanks!