diff options
| author | Mohammad Sajid Anwar <Mohammad.Anwar@yahoo.com> | 2023-07-31 01:13:29 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-31 01:13:29 +0100 |
| commit | c1c08cce0d2bd79fe3e5dd06fa5ff7007359b02b (patch) | |
| tree | 28e77fbf0865fa26558a2dc0f42fb3f5f07797fe | |
| parent | 091aab3405809252ef062e18eaf27dc3fc9202dc (diff) | |
| parent | 18752bc85eaa5efb37c1a9b1d80eefc2b8653d67 (diff) | |
| download | perlweeklychallenge-club-c1c08cce0d2bd79fe3e5dd06fa5ff7007359b02b.tar.gz perlweeklychallenge-club-c1c08cce0d2bd79fe3e5dd06fa5ff7007359b02b.tar.bz2 perlweeklychallenge-club-c1c08cce0d2bd79fe3e5dd06fa5ff7007359b02b.zip | |
Merge pull request #8469 from Util/c227
Add TWC 227 solutions by Bruce Gray (Raku only).
| -rw-r--r-- | challenge-227/bruce-gray/raku/ch-1.raku | 30 | ||||
| -rw-r--r-- | challenge-227/bruce-gray/raku/ch-2.raku | 66 |
2 files changed, 96 insertions, 0 deletions
diff --git a/challenge-227/bruce-gray/raku/ch-1.raku b/challenge-227/bruce-gray/raku/ch-1.raku new file mode 100644 index 0000000000..6c16d3097d --- /dev/null +++ b/challenge-227/bruce-gray/raku/ch-1.raku @@ -0,0 +1,30 @@ +enum DayNames «:Monday(1) Tuesday Wednesday Thursday Friday Saturday Sunday»; + +sub task1 ( UInt $year where 1753..9999 --> UInt ) { + return +grep { Date.new($year, $_, 13).day-of-week == Friday }, 1..12; +} + + +constant @tests = + ( 1753, 2 ), + ( 2023, 2 ), + ( 9999, 1 ), +; +use Test; +plan @tests + 1; +for @tests -> ( UInt $in, UInt $expected ) { + is task1($in), $expected; +} +ok all map { .&task1_alternate == .&task1 }, 1753..9999; + + +# By observing that the final answer completely depends on the +# day-of-week of the first day of the year, and whether it is a leap year, +# we could precompute then replace 12 .day-of-week calls +# with 1 .day-of-week and 1 .is-leap-year . +# However, I feel this takes the resulting code +# too far from the task description. +sub task1_alternate ( UInt $year --> UInt ) { + constant @t = Nil, (2, 2), (2, 1), (1, 2), (3, 2), (1, 1), (1, 1), (2, 3); + return @t[ .day-of-week ][ .is-leap-year ] given Date.new(:$year); +} diff --git a/challenge-227/bruce-gray/raku/ch-2.raku b/challenge-227/bruce-gray/raku/ch-2.raku new file mode 100644 index 0000000000..db170711ae --- /dev/null +++ b/challenge-227/bruce-gray/raku/ch-2.raku @@ -0,0 +1,66 @@ +# I spliced together https://rosettacode.org/wiki/Roman_numerals/ and +# https://andrewshitov.com/2018/10/31/creating-a-calculator-with-perl-6-grammars/ +# , added `**`, trimmed out the calc code that supported PEDMAS precedence and +# expressions of more than 2 terms, used Int::polydiv to implify because it is +# perfect for this task, then refactored everything. +use Int::polydiv; +constant @r_pairs = + M => 1000, CM => 900, D => 500, CD => 400, + C => 100, XC => 90, L => 50, XL => 40, + X => 10, IX => 9, V => 5, IV => 4, + I => 1, +; +constant @roman_letters = @r_pairs».key; +constant @roman_values = @r_pairs».value; +constant %r = @r_pairs; + +constant %operator_sub = < + - * / ** > + Z=> &[+], &[-], &[*], &[/], &[**] ; +constant @operators = %operator_sub.keys; + +# The Romans had no symbol for zero, +# and no numerics for fractions, negatives, or 4000+ . +multi sub to_roman ( 0 ) { 'nulla' } +multi sub to_roman ( Rat ) { 'non potest' } +multi sub to_roman ( Int $n where -∞ ..^ 0 ) { 'non potest' } +multi sub to_roman ( UInt $n where 4000 ..^ ∞ ) { 'non potest' } +multi sub to_roman ( UInt $n --> Str ) { + return [~] flat @roman_letters Zxx $n.polydiv(@roman_values); +} + +grammar Calc { + rule TOP { ^ <expression> $ } + rule expression { <term> ** 2 %% <op> } + token op { @operators } + token term { (@roman_letters)+ } +} +class CalcActions { + method TOP ($/) { $/.make: $<expression>.ast.narrow } + method expression ($/) { $/.make: $<op>[0].ast.( |$<term>.map(*.ast) ) } + method op ($/) { $/.make: %operator_sub{ ~$/ } } + method term ($/) { $/.make: %r{ $/[0] }.sum } +} + +sub task2 ( Str $to_calculate --> Str ) { + my $calc = Calc.parse( $to_calculate, :actions(CalcActions) ); + + return $calc.ast.&to_roman; +} + + +my @tests = + ( 'IV + V' , 'IX' ), + ( 'M - I' , 'CMXCIX' ), + ( 'X / II' , 'V' ), + ( 'XI * VI' , 'LXVI' ), + ( 'VII ** III' , 'CCCXLIII' ), + ( 'V - V' , 'nulla' ), + ( 'V / II' , 'non potest' ), + ( 'MMM + M' , 'non potest' ), + ( 'V - X' , 'non potest' ), +; +use Test; +plan +@tests; +for @tests -> ( $in, $expected ) { + is task2($in), $expected; +} |
