|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Weekly Challenge #333: Back in the Saddle Again" |
| 4 | +author: "Dave Jacoby" |
| 5 | +date: "2025-08-07 17:33:09 -0400" |
| 6 | +categories: "" |
| 7 | +--- |
| 8 | + |
| 9 | +Welcome to [_**Weekly Challenge #333!**_](https://theweeklychallenge.org/blog/perl-weekly-challenge-333/) It's been a while since I've done this. It's good to be back. |
| 10 | + |
| 11 | +### Task 1: Straight Line |
| 12 | + |
| 13 | +> Submitted by: Mohammad Sajid Anwar |
| 14 | +> You are given a list of co-ordinates. |
| 15 | +> |
| 16 | +> Write a script to find out if the given points make a straight line. |
| 17 | +
|
| 18 | +#### Let's Talk About It |
| 19 | + |
| 20 | +Here's my thought: We're comparing the angle of every pair of points. We're doing the nested loop thing, and if you've done points **a** and **b** once, there's no reason to do them twice, so **b** starts at **a+1**. |
| 21 | + |
| 22 | +(I'm seeing now that I could've popped the first one and compared it with every other. _C'est la vie._) |
| 23 | + |
| 24 | +So, the comparison goes to angles. The angle from `0,0` to `1,1` is given by `atan2(1-0,1-0)` and is `0.785398163397448` radians or 45 degrees. Reverse the order and you get `-2.35619449019234` radians or -135 degrees. Rather than stress getting the correct order, I do both, storing them in a hash. If we get 1 key, it's `0` because it's all the same point, and that counts. If we get 2 keys, that's both directions and that counts. And if there's more, that means they're not all in the same line, and that's a false. |
| 25 | + |
| 26 | +#### Show Me The Code |
| 27 | + |
| 28 | +```perl |
| 29 | +#!/usr/bin/env perl |
| 30 | + |
| 31 | +use strict; |
| 32 | +use warnings; |
| 33 | +use experimental qw{ say state postderef signatures }; |
| 34 | + |
| 35 | +my @examples = ( |
| 36 | + |
| 37 | + [ [ 2, 1 ], [ 2, 3 ], [ 2, 5 ] ], |
| 38 | + [ [ 1, 4 ], [ 3, 4 ], [ 10, 4 ] ], |
| 39 | + [ [ 0, 0 ], [ 1, 1 ], [ 2, 3 ] ], |
| 40 | + [ [ 1, 1 ], [ 1, 1 ], [ 1, 1 ] ], |
| 41 | + [ [ 1000000, 1000000 ], [ 2000000, 2000000 ], [ 3000000, 3000000 ] ], |
| 42 | +); |
| 43 | + |
| 44 | +for my $input (@examples) { |
| 45 | + my $output = straight_line( $input->@* ); |
| 46 | + my $str = join ',', map { qq{[$_]} } map { join ', ', $_->@* } $input->@*; |
| 47 | + say <<"END"; |
| 48 | + Input: \@str = ($str) |
| 49 | + Output: $output |
| 50 | +END |
| 51 | +} |
| 52 | + |
| 53 | +sub straight_line (@array) { |
| 54 | + my %angles; |
| 55 | + for my $i ( 0 .. $#array ) { |
| 56 | + my $k = $array[$i]; |
| 57 | + for my $j ( $i + 1, $#array ) { |
| 58 | + next unless $i != $j; |
| 59 | + next unless defined $array[$j]; |
| 60 | + my $l = $array[$j]; |
| 61 | + my $a1 = find_angle( $k, $l ); |
| 62 | + my $a2 = find_angle( $l, $k ); |
| 63 | + $angles{$a1} = 1; |
| 64 | + $angles{$a2} = 1; |
| 65 | + } |
| 66 | + } |
| 67 | + return scalar keys %angles <= 2 ? 'true' : 'false'; |
| 68 | +} |
| 69 | + |
| 70 | +sub find_angle ( $p1, $p2 ) { |
| 71 | + return atan2( |
| 72 | + $p1->[1] - $p2->[1], $p1->[0] - $p2->[0] |
| 73 | + ); |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +```text |
| 78 | +$ ./ch-1.pl |
| 79 | + Input: @str = ([2, 1],[2, 3],[2, 5]) |
| 80 | + Output: true |
| 81 | +
|
| 82 | + Input: @str = ([1, 4],[3, 4],[10, 4]) |
| 83 | + Output: true |
| 84 | +
|
| 85 | + Input: @str = ([0, 0],[1, 1],[2, 3]) |
| 86 | + Output: false |
| 87 | +
|
| 88 | + Input: @str = ([1, 1],[1, 1],[1, 1]) |
| 89 | + Output: true |
| 90 | +
|
| 91 | + Input: @str = ([1000000, 1000000],[2000000, 2000000],[3000000, 3000000]) |
| 92 | + Output: true |
| 93 | +``` |
| 94 | + |
| 95 | +### Task 2: Duplicate Zeros |
| 96 | + |
| 97 | +> Submitted by: Mohammad Sajid Anwar |
| 98 | +> You are given an array of integers. |
| 99 | +> |
| 100 | +> Write a script to duplicate each occurrence of zero, shifting the remaining elements to the right. The elements beyond the length of the original array are not written. |
| 101 | +
|
| 102 | +#### Let's Talk About It |
| 103 | + |
| 104 | +This is copying an array piece by piece, except: |
| 105 | + |
| 106 | +- when there's a zero, we copy it twice |
| 107 | +- we _never_ go past the length of the original array |
| 108 | + |
| 109 | +I *could* handwave it, like `return @output[0..$#input]` or the like, but no, we're going to police ourselves twice: when copying `input[i]` and when adding the subsequent zero. |
| 110 | + |
| 111 | +#### Show Me The Code |
| 112 | + |
| 113 | +```perl |
| 114 | +#!/usr/bin/env perl |
| 115 | + |
| 116 | +use strict; |
| 117 | +use warnings; |
| 118 | +use experimental qw{ say state postderef signatures }; |
| 119 | + |
| 120 | +my @examples = ( |
| 121 | + |
| 122 | + [ 1, 0, 2, 3, 0, 4, 5, 0 ], |
| 123 | + [ 1, 2, 3 ], |
| 124 | + [ 1, 2, 3, 0 ], |
| 125 | + [ 0, 0, 1, 2 ], |
| 126 | + [ 1, 2, 0, 3, 4 ], |
| 127 | + |
| 128 | +); |
| 129 | + |
| 130 | +for my $input (@examples) { |
| 131 | + my $str = join ',', $input->@*; |
| 132 | + my @output = duplicate_zeroes( $input->@* ); |
| 133 | + my $output = join ',', @output; |
| 134 | + say <<"END"; |
| 135 | + Input: \@str = ($str) |
| 136 | + Output: ($output) |
| 137 | +END |
| 138 | +} |
| 139 | + |
| 140 | +sub duplicate_zeroes (@ints) { |
| 141 | + my @output; |
| 142 | + my $l = $#ints; |
| 143 | + for my $i ( 0 .. $l ) { |
| 144 | + my $n = $ints[$i]; |
| 145 | + my $o = $#output; |
| 146 | + push @output, $n if $#output < $l; |
| 147 | + push @output, $n if $n == 0 && $#output < $l; |
| 148 | + } |
| 149 | + return @output; |
| 150 | +} |
| 151 | +``` |
| 152 | + |
| 153 | +```text |
| 154 | +$ ./ch-2.pl |
| 155 | + Input: @str = (1,0,2,3,0,4,5,0) |
| 156 | + Output: (1,0,0,2,3,0,0,4) |
| 157 | +
|
| 158 | + Input: @str = (1,2,3) |
| 159 | + Output: (1,2,3) |
| 160 | +
|
| 161 | + Input: @str = (1,2,3,0) |
| 162 | + Output: (1,2,3,0) |
| 163 | +
|
| 164 | + Input: @str = (0,0,1,2) |
| 165 | + Output: (0,0,0,0) |
| 166 | +
|
| 167 | + Input: @str = (1,2,0,3,4) |
| 168 | + Output: (1,2,0,0,3) |
| 169 | +``` |
| 170 | + |
| 171 | +#### If you have any questions or comments, I would be glad to hear it. Ask me on [Mastodon](https://mastodon.xyz/@jacobydave) or [make an issue on my blog repo.](https://github.com/jacoby/jacoby.github.io) |
0 commit comments