The weekly challenge 333 - Task 1: Straight Line
1 #!/usr/bin/env perl 2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-333/#TASK1 3 # 4 # Task 1: Straight Line 5 # ===================== 6 # 7 # You are given a list of co-ordinates. 8 # 9 # Write a script to find out if the given points make a straight line. 10 # 11 ## Example 1 12 ## 13 ## Input: @list = ([2, 1], [2, 3], [2, 5]) 14 ## Output: true 15 # 16 # 17 ## Example 2 18 ## 19 ## Input: @list = ([1, 4], [3, 4], [10, 4]) 20 ## Output: true 21 # 22 # 23 ## Example 3 24 ## 25 ## Input: @list = ([0, 0], [1, 1], [2, 3]) 26 ## Output: false 27 # 28 # 29 ## Example 4 30 ## 31 ## Input: @list = ([1, 1], [1, 1], [1, 1]) 32 ## Output: true 33 # 34 # 35 ## Example 5 36 ## 37 ## Input: @list = ([1000000, 1000000], [2000000, 2000000], [3000000, 3000000]) 38 ## Output: true 39 # 40 ############################################################ 41 ## 42 ## discussion 43 ## 44 ############################################################ 45 # 46 # Basically we need to calculate the slope of the potential straight line 47 # from the first two points in the list. Then we need to calculate the slope 48 # from the first point to each other point in the list and compare that to 49 # the first slope. If it's always the same all points are on a straight line. 50 # If it isn't then we found a point that isn't on the same straight line as 51 # the first two points so we can return "false". 52 # The rest is special case handling: If a point is the same as the first point 53 # in the list it's on every straight line that crosses this point, so we are 54 # fine. And if the x values are the same but the y values aren't then we are 55 # on a vertical line so we can't calculate the slope due to division by zero. 56 # While at it, we also do special handling for the case of a horizontal line 57 # even though that wouldn't be necessary as the slope would just be 0. 58 59 use v5.36; 60 61 straight_line([2, 1], [2, 3], [2, 5]); 62 straight_line([1, 4], [3, 4], [10, 4]); 63 straight_line([0, 0], [1, 1], [2, 3]); 64 straight_line([1, 1], [1, 1], [1, 1]); 65 straight_line([1000000, 1000000], [2000000, 2000000], [3000000, 3000000]); 66 67 sub straight_line(@list) { 68 say "Input: (" . join(", ", map { "[$_->[0], $_->[1]]" } @list) . ")"; 69 my $direction = ""; 70 my $start = shift @list; 71 my $slope; 72 foreach my $point (@list) { 73 if($point->[0] == $start->[0] and $point->[1] == $start->[1]) { 74 # the same point again - it's always on the same line 75 next; 76 } 77 if(defined($slope)) { 78 if($slope eq "v" and $point->[0] == $start->[0]) { 79 # x value is the same for a vertical slope 80 next; 81 } 82 if($slope eq "h" and $point->[1] == $start->[1]) { 83 # y value is the same for a horizontal slope 84 next; 85 } 86 if($slope == ($point->[1] - $start->[1])/($point->[0] - $start->[0]) ) { 87 # slope to this point is the same as before, so we're on the same straight line 88 next; 89 } 90 return say "Output: false"; 91 } else { 92 if($point->[0] == $start->[0]) { 93 $slope = "v"; 94 } elsif($point->[1] == $start->[1]) { 95 $slope = "h"; 96 } else { 97 $slope = ($point->[1] - $start->[1])/($point->[0] - $start->[0]); 98 } 99 } 100 } 101 say "Output: true"; 102 } 103