1 #!/usr/bin/perl
  2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-210/#TASK2
  3 #
  4 # Task 2: Number Collision
  5 # ========================
  6 #
  7 # You are given an array of integers which can move in right direction if it is
  8 # positive and left direction when negative. If two numbers collide then the
  9 # smaller one will explode. And if both are same then they both explode. We
 10 # take the absolute value in consideration when comparing.
 11 #
 12 # All numbers move at the same speed, therefore any 2 numbers moving in the
 13 # same direction will never collide.
 14 #
 15 # Write a script to find out who survives the collision.
 16 #
 17 ## Example 1:
 18 ##
 19 ## Input: @list = (2, 3, -1)
 20 ## Output: (2, 3)
 21 ##
 22 ## The numbers 3 and -1 collide and -1 explodes in the end. So we are left with (2, 3).
 23 #
 24 ## Example 2:
 25 ##
 26 ## Input: @list = (3, 2, -4)
 27 ## Output: (-4)
 28 ##
 29 ## The numbers 2 and -4 collide and 2 explodes in the end. That gives us (3, -4).
 30 ## Now the numbers 3 and -4 collide and 3 explodes. Finally we are left with -4.
 31 #
 32 ## Example 3:
 33 ##
 34 ## Input: @list = (1, -1)
 35 ## Output: ()
 36 ##
 37 ## The numbers 1 and -1 both collide and explode. Nothing left in the end.
 38 #
 39 ############################################################
 40 ##
 41 ## discussion
 42 ############################################################
 43 #
 44 # Negative numbers at the left and positive numbers at the right of the array
 45 # are finished moving. Numbers can only move if a negative number is right of a
 46 # positive number.
 47 
 48 use strict;
 49 use warnings;
 50 
 51 number_collision(2, 3, -1);
 52 number_collision(3, 2, -4);
 53 number_collision(1, -1);
 54 
 55 sub number_collision {
 56    my @list = @_;
 57    print "Input: (" . join(", ", @list) . ")\n";
 58    my @result = explode(@list);
 59    print "Output: (" . join(", ", @result) . ")\n";
 60 }
 61 
 62 sub explode {
 63    my @list = @_;
 64    my @result = ();
 65    while(@list && $list[0] < 0) {
 66       push @result, shift @list;
 67    }
 68    my $exploded = 0;
 69    foreach my $i (0..$#list-1) {
 70       if($list[$i] >= 0 && $list[$i+1] < 0) {
 71          if($list[$i] == abs($list[$i+1])) {
 72             # both explode
 73             $i++;
 74             $exploded = 1;
 75             next;
 76          } elsif ($list[$i] > abs($list[$i+1])) {
 77             push @result, $list[$i];
 78             $i++;
 79             $exploded = 1;
 80             next;
 81          } else {
 82             push @result, $list[$i+1];
 83             $i++;
 84             $exploded = 1;
 85             next;
 86          }
 87       } elsif ($list[$i] == 0 && $list[$i+1] >= 0) {
 88          push @result, $list[$i];
 89          next;
 90       } elsif ($list[$i] > 0 && $list[$i+1] == 0) {
 91          push @result, $list[$i];
 92          $i++; # skip the following 0
 93          $exploded = 1;
 94          next;
 95       } elsif($list[$i] > 0 && $list[$i+1] > 0) {
 96          push @result, $list[$i];
 97          if($i == $#list - 1) {
 98             push @result, $list[$i+1];
 99          }
100          next;
101       } else { # $list[$i] < 0
102          push @result, $list[$i];
103          next;
104       }
105    }
106    if($exploded) {
107       return explode(@result);
108    } else {
109       return @result;
110    }
111 }
112