Perl Weekly Challenge 367.

My solutions (task 1 and task 2 ) to the The Weekly Challenge - 367.

Task 1: Max Odd Binary

Submitted by: Mohammad Sajid Anwar
You are given a binary string that has at least one ‘1’.

Write a script to rearrange the bits in such a way that the
resulting binary number is the maximum odd binary number
and return the resulting binary string. The resulting string
can have leading zeros.

Example 1
Input: $str = "1011"
Output: "1101"

"1101" is max odd binary (13).

Example 2
Input: $str = "100"
Output: "001"

"001" is max odd binary (1).

Example 3
Input: $str = "111000"
Output: "110001"

Example 4
Input: $str = "0101"
Output: "1001"

Example 5
Input: $str = "1111"
Output: "1111"


The solution is quite simple: move one 1 to the rightmost position to make the result odd. Move all the other ones to the leftmost positions to get the largest possible number. A simple way to do this is to first move all 1’s to the left of all 0’s by repeatedly substituting ‘01’ by ‘10’, and finally moving the leftmost 1 to the rightmost position. This may be done with a oneliner.

Examples:

perl -E '
for(@ARGV){$i=$_;1 while s/01/10/g;s/^1(.*)$/${1}1/; say "$i -> $_"}
' 1011 100 111000 0101 1111

Results:

1011 -> 1101
100 -> 001
111000 -> 110001
0101 -> 1001
1111 -> 1111

An alternative is to count ones and zeroes and then print the resulting groups.

perl -E '
for(@ARGV){$z=length()-($o=grep$_,split"");say "$_ -> ",1 x--$o,0 x$z,1}
' 1011 100 111000 0101 1111

Results:

1011 -> 1101
100 -> 001
111000 -> 110001
0101 -> 1001
1111 -> 1111

The full code is:

 1  # Perl weekly challenge 367
 2  # Task 1:  Max Odd Binary
 3  #
 4  # See https://wlmb.github.io/2026/03/30/PWC367/#task-1-max-odd-binary
 5  use v5.36;
 6  use feature "try";
 7  die <<~"FIN" unless @ARGV;
 8      Usage: $0 B0 B1...
 9      to find the largest odd binary number from the binary
10      digits in the binary string Bn
11      FIN
12  for(@ARGV){
13      try {
14          die "Only 0's and 1's allowed: $_" unless /^[01]*$/;
15          die "At least one 1 required: $_" unless /1/;
16          my $ones = grep $_, split "";
17          my $zeroes=length()-$ones;
18          say "$_ -> ", "1" x ($ones-1), "0" x $zeroes, "1";
19      }
20      catch($e){ warn $e; }
21  }
22  

Examples:

./ch-1.pl 1011 100 111000 0101 1111

Results:

1011 -> 1101
100 -> 001
111000 -> 110001
0101 -> 1001
1111 -> 1111

Task 2: Conflict Events

Submitted by: Mohammad Sajid Anwar
You are given two events start and end time.

Write a script to find out if there is a conflict between
the two events. A conflict happens when two events have
some non-empty intersection.

Example 1
Input: @event1 = ("10:00", "12:00")
       @event2 = ("11:00", "13:00")
Output: true

Both events overlap from "11:00" to "12:00".

Example 2
Input: @event1 = ("09:00", "10:30")
       @event2 = ("10:30", "12:00")
Output: false

Event1 ends exactly at 10:30 when Event2 starts.
Since the problem defines intersection as non-empty, exact
boundaries touching is not a conflict.

Example 3
Input: @event1 = ("14:00", "15:30")
       @event2 = ("14:30", "16:00")
Output: true

Both events overlap from 14:30 to 15:30.

Example 4
Input: @event1 = ("08:00", "09:00")
       @event2 = ("09:01", "10:00")
Output: false

There is a 1-minute gap from "09:00" to "09:01".

Example 5
Input: @event1 = ("23:30", "00:30")
       @event2 = ("00:00", "01:00")
Output: true

They overlap from "00:00" to "00:30".


I first convert all times to minutes, to facilitate the comparisons. The linear intervals (a,b) and (c,d) overlap if c<b and a<d. However, these intervals are in a circle. It is possible that b<a or d<c, which may be fixed by adding 24*60=1440 minutes. Furthermore, it may be necessary to shift one of the intervals by + or -1440 before making the comparisons. This fits a three-liner.

Examples:

perl -E '
$d=1440;for(@ARGV){@m=map{($h,$m)=split":";60*$h+$m}split" ";do{$m[$_+1]
+=$d if$m[$_]>$m[$_+1]}for(0,2);say"$_ -> ",c(0,@m)||c($d,@m)||c(-$d,@m)?
"T":"F";}sub c($o,@m){$m[0]+$o<$m[3]&&$m[1]+$o>$m[2]}
' "10:00 12:00 11:00 13:00" "09:00 10:30 10:30 12:00" "14:00 15:30 14:30 16:00" \
  "08:00 09:00 09:01 10:00" "23:30 00:30 00:00 01:00"

Results:

10:00 12:00 11:00 13:00 -> T
09:00 10:30 10:30 12:00 -> F
14:00 15:30 14:30 16:00 -> T
08:00 09:00 09:01 10:00 -> F
23:30 00:30 00:00 01:00 -> T

The full code is:

 1  # Perl weekly challenge 367
 2  # Task 2:  Conflict Events
 3  #
 4  # See https://wlmb.github.io/2026/03/30/PWC367/#task-2-conflict-events
 5  use v5.36;
 6  use feature qw(try);
 7  die <<~"FIN" unless @ARGV;
 8      Usage: $0 E0 E1...
 9      to find if the events En are conflicting, where
10      En is a space separated string of four times
11      "T0 T1 T2 T3", each of the form HH:MM. T0 and T1 are
12      starting and ending times for one event, T2 and T3 correspond
13      to the second event
14      FIN
15  my $day=24*60;
16  for(@ARGV){
17      try {
18          die "Wrong format: $_" unless /^\s*((\d\d):(\d\d)(\s|$)){4}$/;
19          my @minutes = map {my ($hour,$min) = split":"; 60*$hour + $min} split" ";
20          do{$minutes[$_+1] +=$day if $minutes[$_] > $minutes[$_+1]} for(0,2);
21          my $result = overlap(0, @minutes)
22              || overlap($day, @minutes)
23              || overlap(-$day,@minutes);
24          say "$_ -> ", $result?"True":"False";
25      }
26      catch($e){warn $e; }
27  }
28  
29  sub overlap($offset, $w, $x, $y, $z){
30      $w + $offset < $z && $x + $offset >$y
31  }

Examples:

./ch-2.pl "10:00 12:00 11:00 13:00" "09:00 10:30 10:30 12:00" "14:00 15:30 14:30 16:00" \
          "08:00 09:00 09:01 10:00" "23:30 00:30 00:00 01:00"

Results:

10:00 12:00 11:00 13:00 -> True
09:00 10:30 10:30 12:00 -> False
14:00 15:30 14:30 16:00 -> True
08:00 09:00 09:01 10:00 -> False
23:30 00:30 00:00 01:00 -> True

/;

Written on March 30, 2026