perl logo Perl logo (Thanks to Olaf Alders)

The weekly challenge 306 - Task 2: Last Element

  1 #!/usr/bin/env perl
  2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-306/#TASK2
  3 #
  4 # Task 2: Last Element
  5 # ====================
  6 #
  7 # You are given a array of integers, @ints.
  8 #
  9 # Write a script to play a game where you pick two biggest integers in the
 10 # given array, say x and y. Then do the following:
 11 #
 12 #   a) if x == y then remove both from the given array
 13 #   b) if x != y then remove x and replace y with (y - x)
 14 #
 15 # At the end of the game, there is at most one element left.
 16 #
 17 # Return the last element if found otherwise return 0.
 18 #
 19 ## Example 1
 20 ##
 21 ## Input: @ints = (3, 8, 5, 2, 9, 2)
 22 ## Output: 1
 23 ##
 24 ## Step 1: pick 8 and 9 => (3, 5, 2, 1, 2)
 25 ## Step 2: pick 3 and 5 => (2, 2, 1, 2)
 26 ## Step 3: pick 2 and 1 => (1, 2, 2)
 27 ## Step 4: pick 2 and 1 => (1, 2)
 28 ## Step 5: pick 1 and 2 => (1)
 29 #
 30 ## Example 2
 31 ##
 32 ## Input: @ints = (3, 2, 5)
 33 ## Output: 0
 34 ##
 35 ## Step 1: pick 3 and 5 => (2, 2)
 36 ## Step 2: pick 2 and 2 => ()
 37 #
 38 ############################################################
 39 ##
 40 ## discussion
 41 ##
 42 ############################################################
 43 #
 44 # There is a bit of ambiguity in the description that is clarified
 45 # by the examples: if there are multiple elements of different value,
 46 # but also multiple elements that are as big as the maximum element,
 47 # then pick one of the biggest values and one of the second biggest,
 48 # NOT two of the biggest. So from (2, 2, 1, 2) pick 2 and 1, not
 49 # 2 and 2.
 50 # With that clarified, we can now implement the whole thing: Search
 51 # the two biggest values in the array, then handle them as layed out
 52 # in the rules.
 53 #
 54 
 55 use v5.36;
 56 
 57 last_element(3, 8, 5, 2, 9, 2);
 58 last_element(3, 2, 5);
 59 
 60 sub last_element(@ints) {
 61    say "Input: (" . join(",", @ints) . ")";
 62    while(@ints) {
 63       if(1 == scalar(@ints)) {
 64          say "Output: " . $ints[0];
 65          return;
 66       }
 67       my ($max1, $max2) = @ints[0..1];
 68       if($max1 < $max2) {
 69          ($max1, $max2) = ($max2, $max1);
 70       }
 71       foreach my $i (2..$#ints) {
 72          if($ints[$i] > $max1) {
 73             ($max1, $max2) = ($ints[$i], $max1);
 74          } elsif ($max1 == $max2) {
 75             $max2 = $ints[$i];
 76          } else {
 77             if($ints[$i] > $max2 && $ints[$i] < $max1) {
 78                $max2 = $ints[$i];
 79             }
 80          }
 81       }
 82       if($max1 == $max2) {
 83          # remove two occurences of $max1
 84          my @tmp = ();
 85          my $removed = 0;
 86          foreach my $elem (@ints) {
 87             if($elem == $max1 && $removed < 2) {
 88                $removed++;
 89                next;
 90             }
 91             push @tmp, $elem;
 92          }
 93          @ints = @tmp;
 94       } else {
 95          # remove max2, replace max1 with max1-max2
 96          my @tmp = ();
 97          my $new = $max1 - $max2;
 98          my $removed = 0;
 99          my $replaced = 0;
100          foreach my $elem (@ints) {
101             if($elem == $max1 && ! $removed) {
102                $removed = 1;
103                next;
104             }
105             if($elem == $max2 && ! $replaced) {
106                push @tmp, $new;
107                $replaced = 1;
108                next;
109             }
110             push @tmp, $elem;
111          }
112          @ints = @tmp;
113       }
114    }
115    say "Output: 0";
116 }