aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2025-08-31 13:13:15 +0100
committerGitHub <noreply@github.com>2025-08-31 13:13:15 +0100
commitf2a523b4b34995415e06e52fa247af852ad011cf (patch)
tree4f2465ff7d321458015023e8c07708cf4c1ef201
parent1cda67fc152a1c71cf521ffe30c5f503959c81a1 (diff)
parent551a847730016426f7f0c7c3f5772770cfb214f7 (diff)
downloadperlweeklychallenge-club-f2a523b4b34995415e06e52fa247af852ad011cf.tar.gz
perlweeklychallenge-club-f2a523b4b34995415e06e52fa247af852ad011cf.tar.bz2
perlweeklychallenge-club-f2a523b4b34995415e06e52fa247af852ad011cf.zip
Merge pull request #12596 from 0rir/work
336 nand more on 334
-rw-r--r--challenge-335/0rir/raku/ch-2.raku153
-rw-r--r--challenge-336/0rir/raku/ch-1.raku72
-rw-r--r--challenge-336/0rir/raku/ch-2.raku89
3 files changed, 304 insertions, 10 deletions
diff --git a/challenge-335/0rir/raku/ch-2.raku b/challenge-335/0rir/raku/ch-2.raku
index 86066bfa38..daa90d93d4 100644
--- a/challenge-335/0rir/raku/ch-2.raku
+++ b/challenge-335/0rir/raku/ch-2.raku
@@ -1,6 +1,6 @@
#!/usr/bin/env raku
# :vim ft=raku sw=4 expandtab # 🦋 ∅∪∩∋∈∉⊆ ≡ ≢ «␤ » ∴ 🐧
-use v6.d;
+use v6.e.PREVIEW;
use Test;
=begin comment
@@ -57,11 +57,11 @@ Game Board:
[ _ _ A ]
=end comment
-constant \EARLY = 4;
-constant \DONE = 9;
-constant \PENDING = 'Pending';
-constant \DRAW = 'Draw';
-
+constant \EARLY = 4; # too early to have a winner
+constant \DONE = 9; # only 9 elems can be used
+constant \PENDING = 'Pending'; # meaning of !DONE and no winner
+constant \DRAW = 'Draw'; # no victor in DONE data
+constant \_ = '_'; # empty tic
my @Test =
([0,0],[2,0],[1,1],[2,1],[2,2]), 'A', # -> SE
@@ -73,15 +73,16 @@ my @Test =
([0,0],[2,1],[1,0],[1,1],[2,0]), 'A', # -> S
([1,1],[1,2],[2,2],[0,0],[2,1],[2,0],[0,1]), 'A',
;
-plan +@Test ÷ 2;
+plan 3 × +@Test ÷ 2;
+
+# Version the first ===============================================
-constant \_ = '_'; # empty tic
my @player = <A B>;
my @board[3;3];
# Could not get binding twixt array elems to work.
-# Return True if $player has 3 in a row.
+# Return True if $player has 3 in a row, column, or slant.
sub win-q( @b, $player, $r, $c -->Bool) {
return True if (@b[$r;0],@b[$r;1],@b[$r;2]).all eq $player; # row
@@ -118,8 +119,140 @@ sub task( @move -->Str) {
}
}
+# Version the second, requires v6.e.PREVIEW ===========================
+
+=begin comment
+This is PWC 335 Task 2 as I initially planned to write it with a larger
+array with all elems bound to the tic-tac-toe board array. I wanted to
+play with binding array positions.
+
+This is not as clean as I had hoped.
+
+My idea of mapping of the @b (board) to the @r (review) missed the literal
+corner cases, which added four more diagonals of three.
+
+Also my use of side effects and embedded subs implicitly accessing outer
+vars seems odd.
+=end comment
+
+sub task-bind-ary( @move -->Str) {
+
+ return PENDING if @move ≤ EARLY;
+
+ # set up
+ my @b[3;3];
+ my @g[5;5];
+
+ for 0..2 -> \i { for 0..2 -> \j { @b[i;j] = _ ; }}
+
+ # Bind elems of @g, the ground, to the @b, the board.
+
+ # @b idx @g indices
+ my @bind =
+ [0,0], [1,1, 1,4, 4,1, 4,4],
+ [0,1], [1,2, 4,2,],
+ [0,2], [1,3, 1,0, 4,0, 4,3],
+ [1,0], [2,1, 2,4,],
+ [1,1], [2,2,],
+ [1,2], [2,3, 2,0,],
+ [2,0], [3,1, 0,1, 0,4, 3,4],
+ [2,1], [3,2, 0,2,],
+ [2,2], [3,3, 0,0, 0,3, 3,0];
+
+ for @bind -> @sq, @alias {
+ my (\ro, \co) = @sq;
+ for @alias -> \r, \c {
+ @g[r;c] := @b[ro;co];
+ }
+ }
+
+ my $i = 0;
+ # The current player
+ sub player( -->Str) { $i %% 2 ?? 'A' !! 'B' }
+
+ ### Enter early moves
+ while $i < EARLY {
+ my (\r, \c) = enter-move;
+ ++$i;
+ }
+ # Return indices for checking against @g
+ sub enter-move(-->List) {
+ my ($r,$c) = @move[$i];
+ @b[$r;$c] = player;
+ return ( ++$r, ++$c);
+ }
+
+ ### Enter and check moves
+ while $i < min DONE, @move {
+ my (\r, \c) = enter-move;
+ if win-q( r, c) {
+ return player;
+ }
+ ++$i;
+ } # Did current tic or big X win?
+ sub win-q( \r, \c -->Bool) {
+ return ? any( N(r,c),E(r,c), Ne, Nw);
+ }
+ sub E( \r,\c) { @g[r;c] eq @g[r ;c-1] eq @g[r ;c+1]} # |
+ sub N( \r,\c) { @g[r;c] eq @g[r-1;c ] eq @g[r+1;c ]} # _
+ sub Nw() { @g[2;2] eq @g[1 ;1 ] eq @g[3 ;3 ]} # \
+ sub Ne() { @g[2;2] eq @g[1 ;3 ] eq @g[3 ;1 ]} # /
+
+ return DRAW if $i == DONE;
+ return PENDING;
+}
+
+# Version the third ===================================================
+
+=begin comment
+This is another approach to PWC 335 Task 2.
+
+Return pending if arg list is too short.
+View the tic-tac-toe grid as locations 'a'... 'i'.
+Convert the matrix indices to locations.
+Iter over input list (while toggling A and B) inserting loca to a player's set.
+Compare A's set, then B's, to list of winning sets.
+If no winner, check move counter to choose pending or draw.
+=end comment
+
+my @win = do for <a b c>, <d e f>, <g h i>, <a d g>,
+ <b e h>, <c f i>, <a e i>, <c e g> -> $s {
+ $s.Set;
+ };
+
+sub coords2id( @a -->Str) { <a b c d e f g h i>[ @a[0] × 3 + @a[1]]; }
+
+multi task-set( @coord where * ≤ EARLY -->Str) { PENDING }
+
+multi task-set( @coord where * < 10 -->Str) {
+
+ my SetHash $a;
+ my SetHash $b;
+ my @tic = $a, $b;
+
+ my $player = 1; # set Player B
+
+ my $i = 0;
+ for @coord -> @c {
+ last if $i == DONE;
+ $player = (!$player);
+ @tic[$player]{coords2id( @c)} = True; # take location
+ ++$i;
+ }
+
+ return 'A' if @tic[0] ⊇ any @win;
+ return 'B' if @tic[1] ⊇ any @win;
+
+ return PENDING if $i < DONE;
+ return DRAW;
+}
+
+# Testing ===========================================================
+
for @Test -> @in, $exp {
- is task( @in), $exp, "{$exp // $exp.^name()} <- @in.raku()";
+ is task( @in), $exp, "{$exp // $exp.^name()} <- @in.raku()";
+ is task-bind-ary( @in), $exp, "{$exp // $exp.^name()} <- @in.raku()";
+ is task-set( @in), $exp, "{$exp // $exp.^name()} <- @in.raku()";
}
done-testing;
diff --git a/challenge-336/0rir/raku/ch-1.raku b/challenge-336/0rir/raku/ch-1.raku
new file mode 100644
index 0000000000..c500589b2d
--- /dev/null
+++ b/challenge-336/0rir/raku/ch-1.raku
@@ -0,0 +1,72 @@
+#!/usr/bin/env raku
+# :vim ft=raku sw=4 expandtab # 🦋 ∅∪∩∋∈∉⊆ ≡ ≢ «␤ » ∴ 🐧
+use v6.e.PREVIEW;
+use lib $?FILE.IO.cleanup.parent(2).add("lib");
+use Test;
+
+=begin comment
+336-1: Equal Group Submitted by: Mohammad Sajid Anwar
+You are given an array of integers.
+
+Write a script to return true if the given array can be divided into one or more groups: each group must be of the same size as the others, with at least two members, and with all members having the same value.
+
+
+Example 1
+Input: @ints = (1,1,2,2,2,2)
+Output: true
+
+Groups: (1,1), (2,2), (2,2)
+
+Example 2
+Input: @ints = (1,1,1,2,2,2,3,3)
+Output: false
+
+Groups: (1,1,1), (2,2,2), (3,3)
+
+Example 3
+Input: @ints = (5,5,5,5,5,5,7,7,7,7,7,7)
+Output: true
+
+Groups: (5,5,5,5,5,5), (7,7,7,7,7,7)
+
+Example 4
+Input: @ints = (1,2,3,4)
+Output: false
+
+Example 5
+Input: @ints = (8,8,9,9,10,10,11,11)
+Output: true
+
+Groups: (8,8), (9,9), (10,10), (11,11)
+
+=end comment
+
+my @Test =
+ (1,1,2,2,2,2), True,
+ (1,1,1,2,2,2,3,3), False,
+ (5,5,5,5,5,5,7,7,7,7,7,7), True,
+ (1,2,3,4), False,
+ (8,8,9,9,10,10,11,11), True,
+
+ (1,1,2,2), True,
+ (1,1,1), True,
+ (1,1), True,
+ (1,), False,
+ (), False,
+;
+plan +@Test ÷ 2;
+
+multi task( @a where (@a ~~ Empty or @a == 1) ) { False }
+multi task( @a -->Bool:D) {
+ my BagHash[Int] $bh;
+ ++$bh{$_} for @a;
+ (my $m = $bh.values.min) > 1 and so $bh.values.all %% $m;
+}
+
+for @Test -> @in, $exp {
+ is task( @in), $exp, "{$exp // $exp.^name()} <- @in.raku()";
+}
+done-testing;
+my @int = 8,8,9,9,10,10,11,11 ;
+say "\nInput: @int = ({@int.join( ', ')})\nOutput: &task( @int)"
+
diff --git a/challenge-336/0rir/raku/ch-2.raku b/challenge-336/0rir/raku/ch-2.raku
new file mode 100644
index 0000000000..28c2b49423
--- /dev/null
+++ b/challenge-336/0rir/raku/ch-2.raku
@@ -0,0 +1,89 @@
+#!/usr/bin/env raku
+# :vim ft=raku sw=4 expandtab # 🦋 ∅∪∩∋∈∉⊆ ≡ ≢ «␤ » ∴ 🐧
+use v6.e.PREVIEW;
+use Test;
+
+=begin comment
+336-2: Final Score Submitted by: Mohammad Sajid Anwar
+
+You are given an array of scores by a team.
+
+Write a script to find the total score of the given team. The score can be any integer, +, C or D. The + adds the sum of previous two scores. The score C invalidates the previous score. The score D will double the previous score.
+
+
+Example 1
+Input: @scores = ("5","2","C","D","+")
+Output: 30
+
+Example 2
+Input: @scores = ("5","-2","4","C","D","9","+","+")
+Output: 27
+
+Round 1: 5
+Round 2: 5 + (-2)
+Round 3: 5 + (-2) + 4
+Round 4: 5 + (-2) (invalidate the previous score 4)
+Round 5: 5 + (-2) + (-4) (double the previous score -2)
+Round 6: 5 + (-2) + (-4) + 9
+Round 7: 5 + (-2) + (-4) + 9 + 5 (sum of previous two scores)
+Round 8: 5 + (-2) + (-4) + 9 + 5 + 14 (sum of previous two scores)
+
+Total Scores: 27
+
+Example 3
+Input: @scores = ("7","D","D","C","+","3")
+Output: 45
+
+Example 4
+Input: @scores = ("-5","-10","+","D","C","+")
+Output: -55
+
+Example 5
+Input: @scores = ("3","6","+","D","C","8","+","D","-2","C","+")
+Output: 128
+
+=end comment
+
+my @Test =
+# # @in $exp
+ ("5","2","C","D","+"), 30,
+ ("5","-2","4","C","D","9","+","+"), 27,
+ ("7","D","D","C","+","3"), 45,
+ ("-5","-10","+","D","C","+"), -55,
+ ("3","6","+","D","C","8","+","D","-2","C","+"), 128,
+
+ ('1', '1'), 2,
+;
+plan +@Test;
+
+grammar Final-score {
+ rule TOP { ^ <number> [[ <plus> |<double>|<cancel>] | <number> ]+ $ }
+ token number { [ '+' | '-'] ? \d+ }
+ token plus { '+' }
+ token double { 'D' }
+ token cancel { 'C' }
+}
+
+class Fs {
+ has @.score = [0,];
+ method TOP( $/) { $/.make: @.score.sum; }
+ method number( $/) { @.score.push: $/.Int; }
+ method plus( $/) { @.score.push: (@.score[*-2,*-1]).sum; }
+ method double( $/) { @.score.push: (@.score[*-1].Int × 2).Int; }
+ method cancel( $/) { @.score.pop; }
+}
+
+sub task( $a --> Int) {
+ my $m = Final-score.parse: $a.join( ' '), :actions(Fs.new);
+ $m.made.Str.Int;
+}
+
+for @Test -> $code, $exp {
+ my $m = Final-score.parse: $code.join( ' ');
+ is $m.Str, $code.join(' '), 'parses';
+ is task($code), $exp, "$exp <- $code.raku()";
+}
+done-testing;
+my @score = "-5","-10","+","D","C","+";
+
+say qq{\nInput: @score = ["{@score.join: '","' }"]\nOutput: }, task @score;