aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorE. Choroba <choroba@matfyz.cz>2021-12-14 00:01:29 +0100
committerE. Choroba <choroba@matfyz.cz>2021-12-14 00:01:29 +0100
commit38321bcb275b6e3bb9e55c55e4ff7122438d16b6 (patch)
treecb7da06e3b9d6dff3d2b17fbc57208c276564faa
parentecafe0e840b90c1462ec4ac924f3255dd3beb2c0 (diff)
downloadperlweeklychallenge-club-38321bcb275b6e3bb9e55c55e4ff7122438d16b6.tar.gz
perlweeklychallenge-club-38321bcb275b6e3bb9e55c55e4ff7122438d16b6.tar.bz2
perlweeklychallenge-club-38321bcb275b6e3bb9e55c55e4ff7122438d16b6.zip
Add solutions to 143: Calculator & Stealthy Number by E. Choroba
-rwxr-xr-xchallenge-143/e-choroba/perl/ch-1.pl62
-rwxr-xr-xchallenge-143/e-choroba/perl/ch-2.pl24
2 files changed, 86 insertions, 0 deletions
diff --git a/challenge-143/e-choroba/perl/ch-1.pl b/challenge-143/e-choroba/perl/ch-1.pl
new file mode 100755
index 0000000000..b1e25bec50
--- /dev/null
+++ b/challenge-143/e-choroba/perl/ch-1.pl
@@ -0,0 +1,62 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+
+sub calculator {
+ my ($expression) = @_;
+ while ($expression =~ m{[ ()]}) {
+ $expression =~ s/(-?\d+) (\*) (-?\d+)/$1 * $3/e;
+ $expression =~ s/(-?\d+) ([-+]) (-?\d+)/"$1 $2 $3"/ee;
+ $expression =~ s/\((-?\d+)\)/$1/g;
+ }
+ return $expression
+}
+
+use Marpa::R2;
+my $dsl = << '__DSL__';
+
+ lexeme default = latm => 1
+ :default ::= action => ::first
+
+ Expression ::= Number
+ | ('(') Expression (')') assoc => group
+ || Expression (ws asterisk ws) Expression action => multiply
+ || Expression (ws plus ws) Expression action => add
+ | Expression (ws minus ws) Expression action => subtract
+ Number ::= Negative | positive
+ Negative ::= minus positive action => neg
+
+ ws ~ [\s]+
+ asterisk ~ '*'
+ plus ~ '+'
+ positive ~ [\d]+
+ minus ~ '-'
+
+__DSL__
+
+sub add { $_[1] + $_[2] }
+sub subtract { $_[1] - $_[2] }
+sub multiply { $_[1] * $_[2] }
+sub neg { -$_[2] }
+sub second { $_[2] }
+
+my $grammar = 'Marpa::R2::Scanless::G'->new({source => \$dsl});
+
+sub calculate {
+ my ($input) = @_;
+ return ${ $grammar->parse(\$input, 'main') }
+}
+
+use Test2::V0;
+plan 8;
+
+my %tests = (
+ 'Example 1' => ['10 + 20 - 5', 25],
+ 'Example 2' => ['(10 + 20 - 5) * 2', 50],
+ Negative => ['(1 + 2) - (1 * 12)', -9],
+ Precedence => ['((-1 - -2 - -3 * -4 + -5))', -16]);
+
+for my $t (sort keys %tests) {
+ is calculator($tests{$t}[0]), $tests{$t}[1], "regex $t";
+ is calculate($tests{$t}[0]), $tests{$t}[1], "marpa $t";
+}
diff --git a/challenge-143/e-choroba/perl/ch-2.pl b/challenge-143/e-choroba/perl/ch-2.pl
new file mode 100755
index 0000000000..3feae62c6a
--- /dev/null
+++ b/challenge-143/e-choroba/perl/ch-2.pl
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use feature qw{ say };
+
+sub stealthy_number {
+ my ($n) = @_;
+ my @divisors = (map $n / $_, grep 0 == $n % $_, 1 .. sqrt $n);
+ for my $A (@divisors) {
+ for my $C (@divisors) {
+ my $B = $n / $A;
+ my $D = $n / $C;
+ return 1 if $A + $B == $C + $D + 1;
+ }
+ }
+ return 0
+}
+
+use Test2::V0;
+plan 3;
+
+is stealthy_number(36), 1, 'Example 1';
+is stealthy_number(12), 1, 'Example 2';
+is stealthy_number(6), 0, 'Example 3';