aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad S Anwar <Mohammad.Anwar@yahoo.com>2023-01-23 00:57:32 +0000
committerGitHub <noreply@github.com>2023-01-23 00:57:32 +0000
commitd50d9efdd37150564b73569be31535bbbce9ce69 (patch)
treeb1c0df268014492cbfb5d8d13b594424cdc2c12c
parente5670fdc4ea9def34b31d09aae2b70d82a0a922c (diff)
parent8b231ed01b1d11f340478f6f17675bda1e3ba29b (diff)
downloadperlweeklychallenge-club-d50d9efdd37150564b73569be31535bbbce9ce69.tar.gz
perlweeklychallenge-club-d50d9efdd37150564b73569be31535bbbce9ce69.tar.bz2
perlweeklychallenge-club-d50d9efdd37150564b73569be31535bbbce9ce69.zip
Merge pull request #7447 from Util/branch-for-challenge-200
Add TWC 200 solutions by Bruce Gray (Raku only).
-rw-r--r--challenge-200/bruce-gray/raku/ch-1.raku67
-rw-r--r--challenge-200/bruce-gray/raku/ch-2.raku29
2 files changed, 96 insertions, 0 deletions
diff --git a/challenge-200/bruce-gray/raku/ch-1.raku b/challenge-200/bruce-gray/raku/ch-1.raku
new file mode 100644
index 0000000000..d12080aa92
--- /dev/null
+++ b/challenge-200/bruce-gray/raku/ch-1.raku
@@ -0,0 +1,67 @@
+# I tried to decompose the task into discrete ideas:
+# * Make the longest possible groups of contiguous elements,
+# based on some property of 2 neighboring elements: f(x,y).
+# * The "property" we group on will be the difference (subtraction).
+# * Contiguous subsets of every group.
+# * Only subsets of size >= 3.
+#
+# Resulting details:
+# * The endpoints of those groups will be shared between groups, since `f()` takes two inputs.
+# * The algorithm would be the same as Run Length Encoding, except that some elements are in two groups.
+# * So, imagining the posts needed to change the "angle/direction" property of real-life fences,
+# and how those all but the first and last posts are each part of two fence segments,
+# `fencepost_grouping` was the best name I came up with for this concept.
+# * Anonymous code `sub ($x,$y) { return $x - $y }` is easily abbreviated as `* - *` for the "property".
+# * Sub `fencepost_grouping` also returns groups of size 2, which is an advantage to its genericity,
+# and efficiently resolved for this task by `contiguous_subsets_3_minimum` ignoring size<3.
+# * I could have generated *all* subsets, even sized 0|1|2, then filtered with `grep`, but this felt inefficient.
+# * In the real world, I would have passed 3 as a parameter to a more generic `contiguous_subsets()`;
+# hard-coding fit this particular task better.
+# * Using LAST allowed me to combine the `gather` and `for`;
+# without LAST, the `gather` would have needed its own block.
+# * I considered building a list of sizes, then returning `@ns.rotor( size1 => -1, size2 => -1 ...)`,
+# but did not pursue this design.
+
+
+sub task1 ( @ns ) {
+ return map &contiguous_subsets_3_minimum, fencepost_grouping(@ns, * - *);
+
+ # Combining the component code in this way results in a second layer of grouping.
+ # For example: task1([1,2,3,4,6,8,10,12,13,15,17]) returns 3 high-level groupings of the groups:
+ # ( (1 2 3) (2 3 4) (1 2 3 4) )
+ # ( (4 6 8) (6 8 10) (8 10 12) (4 6 8 10) (6 8 10 12) (4 6 8 10 12) )
+ # ( (13 15 17) )
+ # I found that I preferred this result, since it provides detail
+ # that would be effortful to recreate if I had flattened to single-level.
+}
+
+# @a is any list to be grouped.
+# $f is the code defining the "property" to be grouped on, between two neighboring elements.
+sub fencepost_grouping ( @a, Code $f where $f.arity == 2 ) {
+ my ( $last_fxy, @temp );
+
+ return gather for @a.rotor(2 => -1) -> ($x, $y) {
+ my $fxy = $f.($x, $y);
+
+ if !$last_fxy.defined or $fxy !eq $last_fxy {
+ take @temp if @temp;
+ @temp = Empty;
+ push @temp, $x;
+ }
+ push @temp, $y;
+
+ $last_fxy = $fxy;
+ LAST { take @temp if @temp }
+ }
+}
+
+# <a b c d e> will return <a b c>,<b c d>,<c d e>,<a b c d>,<b c d e>,<a b c d e>
+sub contiguous_subsets_3_minimum ( @a ) {
+ return @a < 3 ?? Empty !!
+ (3 .. +@a).map: -> $size { |@a.rotor( $size => (1 - $size) ) }
+}
+
+say task1([1,2,3,4]);
+
+say task1([]);
+# ENOTENOUGHTIME: Commentary is awkwardly worded; more time needed to enhance comprehendability.
diff --git a/challenge-200/bruce-gray/raku/ch-2.raku b/challenge-200/bruce-gray/raku/ch-2.raku
new file mode 100644
index 0000000000..0c54fc166d
--- /dev/null
+++ b/challenge-200/bruce-gray/raku/ch-2.raku
@@ -0,0 +1,29 @@
+# Generic; works for all 128 shapes of a..g .
+# Returns a 7 element list of 7-character strings.
+sub shape-to-segments ( $shape ) {
+ sub h ($x) { $shape.contains($x) ?? '-' !! ' ' }
+ sub v ($x) { $shape.contains($x) ?? '|' !! ' ' }
+
+ sub horizontal ( $x ) { h($x) x 7 }
+ sub vertical ( $x, $y ) { (v($x) ~ (" " x 5) ~ v($y)) xx 2 }
+
+ return (
+ horizontal('a'), |vertical('f','b'),
+ horizontal('g'), |vertical('e','c'),
+ horizontal('d'),
+ );
+}
+sub int_to_ascii ( UInt $n ) {
+ # Prebuild all 10 numerals at compile-time:
+ constant @ascii_numerals = map &shape-to-segments,
+ <abcdef bc abdeg abcdg bcfg acdfg acdefg abc abcdefg abcfg>;
+
+ my @ans = @ascii_numerals[ $n.comb ];
+
+ return (^7).map: -> $row_num {
+ @ansĀ».[$row_num].join(" ");
+ }
+}
+
+.say for int_to_ascii(200);
+.say for int_to_ascii(1234567890);