aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-058/jo-37/README1
-rw-r--r--challenge-058/jo-37/perl/ch-2.pl94
2 files changed, 95 insertions, 0 deletions
diff --git a/challenge-058/jo-37/README b/challenge-058/jo-37/README
new file mode 100644
index 0000000000..b124ddbd7c
--- /dev/null
+++ b/challenge-058/jo-37/README
@@ -0,0 +1 @@
+Solution by Jo S.
diff --git a/challenge-058/jo-37/perl/ch-2.pl b/challenge-058/jo-37/perl/ch-2.pl
new file mode 100644
index 0000000000..13ca638146
--- /dev/null
+++ b/challenge-058/jo-37/perl/ch-2.pl
@@ -0,0 +1,94 @@
+#!/usr/bin/perl
+
+use Test2::V0;
+
+# exchange item at position $pos and next taller item.
+# return position of found next item.
+sub exchange {
+ my ($items, $pos) = @_;
+ my $next;
+ for ($next = $pos; $next < @$items; $next++) {
+ last if $items->[$next]{height} > $items->[$pos]{height};
+ }
+ my $tmp = $items->[$pos];
+ $items->[$pos] = $items->[$next];
+ $items->[$next] = $tmp;
+ return $next;
+}
+
+sub lineup {
+ my ($heights, $talls) = @_;
+ die "hights and talls have different sizes" if @$heights != @$talls;
+
+ # collect hights and talls into single array.
+ my @items;
+ while (defined (my $height = shift @$heights)) {
+ my $taller = shift @$talls;
+ push @items, {height => $height, taller => $taller};
+ }
+
+ # sort array by height
+ @items = sort {$a->{height} <=> $b->{height}} @items;
+
+ # check solvability: the required number of taller predecessors must
+ # not exceed the number of taller items.
+ for (my $i = 0; $i < @items; $i++) {
+ my $item = $items[$i];
+ die "height: $item->{height}, " .
+ "requested: $item->{taller}, available: " . ($#items - $i)
+ if $item->{taller} > $#items - $i;
+ }
+
+ # create an index to locate items in the array.
+ my @index = (0 .. $#items);
+
+ # process items by size.
+ for (my $i = 0; $i < @index; $i++) {
+ my $pos = $index[$i];
+ my $item = $items[$pos];
+
+
+ # move item to the right for the desired number of taller
+ # predecessors.
+ foreach my $offs (1 .. $item->{taller}) {
+ my $taller = exchange \@items, $pos;
+
+ # store new position of moved item
+ $index[$i + $offs] = $pos;
+ $pos = $taller;
+ }
+ }
+ return [map $_->{height}, @items];
+}
+
+# main
+
+my @H = (2, 6, 4, 5, 1, 3);
+my @T = (1, 0, 2, 0, 1, 2);
+my @A = (5, 1, 2, 6, 3, 4);
+
+my $result = lineup \@H, \@T;
+is $result, \@A, 'first example';
+
+# Heights
+@H = (27, 21, 37, 4, 19, 52, 23, 64, 1, 7, 51, 17, 24, 50, 3, 2,
+ 34, 40, 47, 20, 8, 56, 14, 16, 42, 38, 62, 53, 31, 41, 55, 59,
+ 48, 12, 32, 61, 9, 60, 46, 26, 58, 25, 15, 36, 11, 44, 63, 28,
+ 5, 54, 10, 49, 57, 30, 29, 22, 35, 39, 45, 43, 18, 6, 13, 33);
+
+# Number taller people in front
+@T = ( 6, 41, 1, 49, 38, 12, 1, 0, 58, 47, 4, 17, 26, 1, 61, 12,
+ 29, 3, 4, 11, 45, 1, 32, 5, 9, 19, 1, 4, 28, 12, 2, 2,
+ 13, 18, 19, 3, 4, 1, 10, 16, 4, 3, 29, 5, 49, 1, 1, 24,
+ 2, 1, 38, 7, 7, 14, 35, 25, 0, 5, 4, 19, 10, 13, 4, 12);
+
+# Expected answer
+@A = (35, 23, 5, 64, 37, 9, 13, 25, 16, 44, 50, 40, 2, 27, 36, 6,
+ 18, 54, 20, 39, 56, 45, 12, 47, 17, 33, 55, 30, 26, 51, 42, 53,
+ 49, 41, 32, 15, 22, 60, 14, 46, 24, 59, 10, 28, 62, 38, 58, 63,
+ 8, 48, 4, 7, 31, 19, 61, 43, 57, 11, 1, 34, 21, 52, 29, 3);
+
+$result = lineup \@H, \@T;
+is $result, \@A, 'second example';
+
+done_testing;