aboutsummaryrefslogtreecommitdiff
path: root/challenge-152/athanasius/raku
diff options
context:
space:
mode:
authorPerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com>2022-02-20 22:27:10 +1000
committerPerlMonk-Athanasius <PerlMonk.Athanasius@gmail.com>2022-02-20 22:27:10 +1000
commite7baaf61556465b0769869b03422066438dee388 (patch)
tree2be7fc352e8d6253efd213ea76ad18f0845ec7f1 /challenge-152/athanasius/raku
parent9c7e8b8c714868fd4e9fe7ed7eff9f141f038069 (diff)
downloadperlweeklychallenge-club-e7baaf61556465b0769869b03422066438dee388.tar.gz
perlweeklychallenge-club-e7baaf61556465b0769869b03422066438dee388.tar.bz2
perlweeklychallenge-club-e7baaf61556465b0769869b03422066438dee388.zip
Perl & Raku solutions to Tasks 1 & 2 of the Weekly Challenge 152
Diffstat (limited to 'challenge-152/athanasius/raku')
-rw-r--r--challenge-152/athanasius/raku/ch-1.raku187
-rw-r--r--challenge-152/athanasius/raku/ch-2.raku152
2 files changed, 339 insertions, 0 deletions
diff --git a/challenge-152/athanasius/raku/ch-1.raku b/challenge-152/athanasius/raku/ch-1.raku
new file mode 100644
index 0000000000..ed892d456f
--- /dev/null
+++ b/challenge-152/athanasius/raku/ch-1.raku
@@ -0,0 +1,187 @@
+use v6d;
+
+###############################################################################
+=begin comment
+
+Perl Weekly Challenge 152
+=========================
+
+TASK #1
+-------
+*Triangle Sum Path*
+
+Submitted by: Mohammad S Anwar
+
+You are given a triangle array.
+
+Write a script to find the minimum sum path from top to bottom.
+
+Example 1:
+
+ Input: $triangle = [ [1], [5,3], [2,3,4], [7,1,0,2], [6,4,5,2,8] ]
+
+ 1
+ 5 3
+ 2 3 4
+ 7 1 0 2
+ 6 4 5 2 8
+
+ Output: 8
+
+ Minimum Sum Path = 1 + 3 + 2 + 0 + 2 => 8
+
+Example 2:
+
+ Input: $triangle = [ [5], [2,3], [4,1,5], [0,1,2,3], [7,2,4,1,9] ]
+
+ 5
+ 2 3
+ 4 1 5
+ 0 1 2 3
+ 7 2 4 1 9
+
+ Output: 9
+
+ Minimum Sum Path = 5 + 2 + 1 + 0 + 1 => 9
+
+=end comment
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2022 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=begin comment
+
+Interface
+---------
+1. Following the Examples, I have assumed that array elements are integers.
+2. The array elements are entered on the command line as a linear sequence
+ beginning with the top-most element and continuing down and to the right
+ until the final (bottom- and right-most) element. For example, the triangu-
+ lar array: 1
+ 2 3
+ 4 5 6 is entered as: raku ch-1.raku 1 2 3 4 5 6
+3. If the constant $VERBOSE is set to True (the default), the individual elem-
+ ents comprising the minimum sum path are shown in addition to the minimum
+ sum.
+
+Algorithm
+---------
+From the Examples, it appears that a "path" is simply a selection of elements
+drawn from the triangular array, with exactly one element drawn from each array
+level. Hence, the solution is found by taking the smallest element from each
+level, and summing these elements.
+
+The following test is used to determine whether the number of elements entered
+on the command line is a triangular number:
+
+ "... an integer _x_ is triangular if and only if 8_x_ + 1 is a square." [1]
+
+Reference
+---------
+[1] https://en.wikipedia.org/wiki/Triangular_number#Triangular_roots_and_tests_
+ for_triangular_numbers
+
+=end comment
+#==============================================================================
+
+my Bool constant $VERBOSE = True;
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ "\nChallenge 152, Task #1: Triangle Sum Path (Raku)\n".put;
+}
+
+#==============================================================================
+sub MAIN
+(
+ #| A triangular array of integers, in linear order
+
+ *@items where { is-triangular( .elems ) && .all ~~ Int:D }
+)
+#==============================================================================
+{
+ my Array[Int] @triangle = build-triangle( @items );
+
+ "Input: \$triangle = %s\n".printf: sprint-triangle( @triangle );
+
+ my Int @min-sum-path;
+ @min-sum-path.push: @triangle[ $_ ].min for 0 .. @triangle.end;
+
+ my Int $min-sum = [+] @min-sum-path;
+
+ "Output: $min-sum".put;
+
+ if $VERBOSE
+ {
+ "\n Minimum Sum Path: %s = %d\n".printf:
+ @min-sum-path.join( ' + ' ), $min-sum;
+ }
+}
+
+#------------------------------------------------------------------------------
+sub build-triangle( Array:D[Int:D] $items --> Array:D[Array:D[Int:D]] )
+#------------------------------------------------------------------------------
+{
+ my Array[Int] @triangle = Array[Array[Int]].new;
+ my UInt $row-idx = 0;
+ my UInt $index = 0;
+
+ while $index <= $items.end
+ {
+ my Int @row = Array[Int].new;
+
+ for 1 .. $row-idx + 1
+ {
+ @row.push: $items[ $index++ ];
+ }
+
+ @triangle.push: @row;
+
+ ++$row-idx;
+ }
+
+ return @triangle;
+}
+
+#------------------------------------------------------------------------------
+sub sprint-triangle( Array:D[Array:D[Int:D]] $triangle --> Str:D )
+#------------------------------------------------------------------------------
+{
+ my Str @rows;
+
+ for @$triangle -> Array[Int] $row
+ {
+ @rows.push: '[' ~ @$row.join( ',' ) ~ ']';
+ }
+
+ return '[ ' ~ @rows.join( ', ' ) ~ ' ]';
+}
+
+#------------------------------------------------------------------------------
+sub is-triangular( UInt:D $num --> Bool:D )
+#------------------------------------------------------------------------------
+{
+ my UInt $x = 8 * $num + 1;
+
+ my UInt $root = $x.sqrt.floor;
+
+ return $root * $root == $x;
+}
+
+#------------------------------------------------------------------------------
+sub USAGE()
+#------------------------------------------------------------------------------
+{
+ my Str $usage = $*USAGE;
+
+ $usage ~~ s/ ($*PROGRAM-NAME) /raku $0/;
+
+ $usage.put;
+}
+
+##############################################################################
diff --git a/challenge-152/athanasius/raku/ch-2.raku b/challenge-152/athanasius/raku/ch-2.raku
new file mode 100644
index 0000000000..31b1d95c17
--- /dev/null
+++ b/challenge-152/athanasius/raku/ch-2.raku
@@ -0,0 +1,152 @@
+use v6d;
+
+###############################################################################
+=begin comment
+
+Perl Weekly Challenge 152
+=========================
+
+TASK #2
+-------
+*Rectangle Area*
+
+Submitted by: Mohammad S Anwar
+
+You are given coordinates bottom-left and top-right corner of two rectangles in
+a 2D plane.
+
+Write a script to find the total area covered by the two rectangles.
+
+Example 1:
+
+ Input: Rectangle 1 => (-1,0), (2,2)
+ Rectangle 2 => (0,-1), (4,4)
+
+ Output: 22
+
+Example 2:
+
+ Input: Rectangle 1 => (-3,-1), (1,3)
+ Rectangle 2 => (-1,-3), (2,2)
+
+ Output: 25
+
+=end comment
+###############################################################################
+
+#--------------------------------------#
+# Copyright © 2022 PerlMonk Athanasius #
+#--------------------------------------#
+
+#==============================================================================
+=begin comment
+
+Interface
+---------
+Command-line input is 8 real numbers: the coordinates of the bottom-left and
+top-right corners, in (x, y) order, of 2 rectangles. Rectangles must have non-
+zero areas. Output is the total area covered by the 2 rectangles. If the
+constant $VERBOSE is set to True (the default), the output is followed by an
+explanation.
+
+Note re: the Windows command prompt:
+
+If the first number on the command line is negative, the minus sign will be
+interpreted as a command-line flag, resulting in a "Usage" error. To enter a
+negative number as the first argument, precede the arguments with a double
+hyphen:
+
+ raku ch-2.raku -- -1 0 2 2 0 -1 4 4
+
+Algorithm
+---------
+Consider 2 rectangles:
+
+ +------------a1
+ | |
+ | c-----K--------b1
+ | | | |
+ a0------J-----d |
+ | |
+ | |
+ b0--------------+
+
+The overlapping area, rectangle cJdK, has corners (J, K) where:
+ the x-coordinate of J is the larger of a0x and b0x;
+ the y-coordinate of J is the larger of a0y and b0y;
+ the x-coordinate of K is the smaller of a1x and b1x; and
+ the y-coordinate of K is the smaller of a1y and b1y.
+
+This holds true for all configurations of the 2 rectangles, provided that K is
+above and to the right of J; otherwise, the rectangles do not overlap.
+
+The combined area is the sum of the areas of the 2 rectangles less the area of
+their overlap (if any).
+
+=end comment
+#==============================================================================
+
+my Bool constant $VERBOSE = True;
+
+subset Coord of Real;
+
+#------------------------------------------------------------------------------
+BEGIN
+#------------------------------------------------------------------------------
+{
+ "\nChallenge 152, Task #2: Rectangle Area (Raku)\n".put;
+}
+
+#==============================================================================
+sub MAIN
+(
+ #| 8 coordinates (real numbers) describing 2 rectangles
+
+ *@c where { .elems == 8 && .all ~~ Coord:D &&
+ @c[ 2 ] > @c[ 0 ] && @c[ 3 ] > @c[ 1 ] &&
+ @c[ 6 ] > @c[ 4 ] && @c[ 7 ] > @c[ 5 ] }
+)
+#==============================================================================
+{
+ my Coord ($a0x, $a0y, $a1x, $a1y, $b0x, $b0y, $b1x, $b1y) = @c;
+
+ "Input: Rectangle 1 => ($a0x, $a0y), ($a1x, $a1y)".put;
+ " Rectangle 2 => ($b0x, $b0y), ($b1x, $b1y)".put;
+
+ my Coord $area1 = ($a1x - $a0x) * ($a1y - $a0y);
+ my Coord $area2 = ($b1x - $b0x) * ($b1y - $b0y);
+
+ # Common/shared rectangle
+
+ my Coord $c0x = ($a0x, $b0x).max;
+ my Coord $c0y = ($a0y, $b0y).max;
+ my Coord $c1x = ($a1x, $b1x).min;
+ my Coord $c1y = ($a1y, $b1y).min;
+ my Coord $area3 = ($c1x > $c0x && $c1y > $c0y) ??
+ ($c1x - $c0x) * ($c1y - $c0y) !! 0;
+
+ my Coord $total = $area1 + $area2 - $area3;
+
+ "\nOutput: $total".put;
+
+ if $VERBOSE
+ {
+ "\nExplanation\n-----------".put;
+ "The rectangles have areas of $area1 and $area2, respectively,".put;
+ "and a shared (i.e., overlapping) area of $area3".put;
+ "Total area is $area1 + $area2 - $area3 = $total".put;
+ }
+}
+
+#------------------------------------------------------------------------------
+sub USAGE()
+#------------------------------------------------------------------------------
+{
+ my Str $usage = $*USAGE;
+
+ $usage ~~ s/ ($*PROGRAM-NAME) /raku $0/;
+
+ $usage.put;
+}
+
+##############################################################################