aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-247/bruce-gray/raku/ch-1.raku90
-rw-r--r--challenge-247/bruce-gray/raku/ch-2.raku16
2 files changed, 106 insertions, 0 deletions
diff --git a/challenge-247/bruce-gray/raku/ch-1.raku b/challenge-247/bruce-gray/raku/ch-1.raku
new file mode 100644
index 0000000000..c043e2d732
--- /dev/null
+++ b/challenge-247/bruce-gray/raku/ch-1.raku
@@ -0,0 +1,90 @@
+# This code is a hot mess, and lots of corner cases are not covered.
+# Also, the task examples showed mutual (paired) exchange,
+# but that is not how Secret Santa is usually played,
+# so I have a boolean PAIR flag for that.
+
+use Adverb::Eject;
+# constant $PAIR = True;
+constant $PAIR = False;
+
+proto task1 ( | ) { * }
+multi sub task1 ( @n where 0 ) { Empty }
+multi sub task1 ( @n where 1 ) { @n[0] => @n[0] }
+multi sub task1 ( @n where 2 ) { @n[0] => @n[1],
+ @n[1] => @n[0] }
+multi sub task1 ( @n where 3 ) { @n[0] => @n[1],
+ @n[1] => @n[2],
+ @n[2] => @n[0] }
+
+multi sub task1 (@names) {
+ my @c = @names.classify(*.words[1]).map({ .value.pick(*).Array }).pick(*).flat;
+
+ my @ret;
+ if @c.elems !%% 2 {
+ my $first = @c.shift;
+ my $last = @c.pop;
+ my $half = @c.end div 2;
+ my $mid = @c[$half]; @c[$half]:eject;
+
+ @ret.append: |samewith([$first, $mid, $last]);
+ }
+
+ # @n.elems is now even.
+ @ret.append: |pair_or_chain(@c);
+
+ return @ret;
+}
+sub pair_or_chain ( @names ) {
+ die unless @names %% 2;
+
+ # @a is passed in grouped order.
+ # By creating with pairings half-the-size-of-the-list distance away,
+ # we minimize the number of inter-group pairings
+ my $half = @names.elems div 2;
+ my @a = @names.head($half);
+ my @b = @names.tail($half);
+
+ return |(@a Z=> @b), |(@b Z=> @a) if $PAIR;
+
+ my @cycle = (@a Z @b).flat;
+ push @cycle, @a.head;
+
+ return @cycle.rotor(2 => -1).map({ .[0] => .[1] });
+}
+my @examples =
+ (
+ 'Mr. Wall',
+ 'Mrs. Wall',
+ 'Mr. Anwar',
+ 'Mrs. Anwar',
+ 'Mr. Conway',
+ 'Mr. Cross',
+ ),
+ (
+ 'Mr. Wall',
+ 'Mrs. Wall',
+ 'Mr. Anwar',
+ ),
+ # Example from Peter Campbell Smith
+ (
+ 'Rudolph Reindeer',
+ 'Dasher Reindeer',
+ 'Dancer Reindeer',
+ 'Prancer Reindeer',
+ 'Vixen Reindeer',
+ 'Comet Reindeer',
+ 'Cupid Reindeer',
+ 'Donner Reindeer',
+ 'Blitzen Reindeer',
+ 'Santa Claus',
+ 'Mrs. Claus',
+ 'Subordinate Claus',
+ ),
+;
+
+# XXX Not really testing this time, just exercising the examples.
+# use Test; plan @tests;
+for @examples -> @names {
+ say '';
+ .say for task1(@names);
+}
diff --git a/challenge-247/bruce-gray/raku/ch-2.raku b/challenge-247/bruce-gray/raku/ch-2.raku
new file mode 100644
index 0000000000..d7c99ebf1c
--- /dev/null
+++ b/challenge-247/bruce-gray/raku/ch-2.raku
@@ -0,0 +1,16 @@
+sub task2 ( Str $s --> Str ) {
+ return $s.comb.rotor(2 => -1)».join.Bag.maxpairs».key.min;
+
+ # Or, use the min-of-negative trick to remove `.maxpairs».key` :
+ # return $s.comb.rotor(2 => -1)».join.Bag.min({ -.value, .key }).key;
+}
+
+
+my @tests =
+ <bc abcdbca>,
+ <ab cdeabeabfcdfabgcd>,
+;
+use Test; plan @tests;
+for @tests -> ($expected, $in) {
+ is task2($in), $expected, $in;
+}