diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2023-01-23 00:57:32 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-23 00:57:32 +0000 |
| commit | d50d9efdd37150564b73569be31535bbbce9ce69 (patch) | |
| tree | b1c0df268014492cbfb5d8d13b594424cdc2c12c | |
| parent | e5670fdc4ea9def34b31d09aae2b70d82a0a922c (diff) | |
| parent | 8b231ed01b1d11f340478f6f17675bda1e3ba29b (diff) | |
| download | perlweeklychallenge-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.raku | 67 | ||||
| -rw-r--r-- | challenge-200/bruce-gray/raku/ch-2.raku | 29 |
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); |
