# Perl Weekly Challenge 120.

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

# Task 1: Swap Odd/Even bits

``````Submitted by: Mohammad S Anwar
You are given a positive integer \$N less than or equal to 255.

Write a script to swap the odd positioned bit with even
positioned bit and print the decimal equivalent of the new
binary representation.

Example
Input: \$N = 101
Output: 154

Binary representation of the given number is 01 10 01 01.
The new binary representation after the odd/even swap is 10 01
10 10.
The decimal equivalent of 10011010 is 154.

Input: \$N = 18
Output: 33

Binary representation of the given number is 00 01 00 10.
The new binary representation after the odd/even swap is 00 10
00 01.
The decimal equivalent of 100001 is 33.
``````

I can get the even and odd bits by applying the `&` operator with masks that have only even or odd bits on: `10101010=>170` is an 8 bit binary number with all odd bits set (counting right to left from 0) while `01010101=>85` has all even bits set. Then I can shift the odd bits left and the even bits right and combine them with `|` to get the result. The program is a one liner:

``````perl -E 'say "Input: \$_, Output: ",\
(((\$_&170)>>1) |((\$_&85)<<1)) for @ARGV' 101 18
``````

Results:

``````Input: 101, Output: 154
Input: 18, Output: 33
``````

The full version:

``````# Perl weekly challenge 120
# Task 1: Swap odd/even bits
#
use strict;
use warnings;
use v5.12;
use List::Util qw(all);
my \$odd=170; # 10101010
my \$even=85; # 01010101

say "Input: \$_, Output: ",
0<=\$_<=255?(((\$_&\$odd)>>1) |((\$_&\$even)<<1)):"Invalid"
for @ARGV;
``````

Example:

``````./ch-1.pl 101 18 300
``````

Results:

``````Input: 101, Output: 154
Input: 18, Output: 33
Input: 300, Output: Invalid
``````

``````Submitted by: Mohammad S Anwar
You are given time \$T in the format hh:mm.

Write a script to find the smaller angle formed by the hands
of an analog clock at a given time.

HINT: A analog clock is divided up into 12 sectors. One sector
represents 30 degree (360/12 = 30).

Example
Input: \$T = '03:10'
Output: 35 degree

The distance between the 2 and the 3 on the clock is 30
degree.
For the 10 minutes i.e. 1/6 of an hour that have passed.
The hour hand has also moved 1/6 of the distance between the 3
and the 4, which adds 5 degree (1/6 of 30).
The total measure of the angle is 35 degree.

Input: \$T = '04:00'
Output: 120 degree
``````

The angle moved by the minutes hand is proportional to the minutes. The angle moved by the hours hand is proportional to the hour+the fraction of hour corresponding to the minutes. So the solution to the problem is simply obtained using modular arithmetic. If the angle is too large, I substract it from a full turn. This allows a one liner solution.

``````perl -E 'for(@ARGV){\$_=~m/^(\d?\d):(\d\d)\$/ or next; \$a=(30*(\$1+\$2/60)-\$2*6)%360;\
say "Input: \$_, Output: ", \$a>180?360-\$a:\$a;}' 03:10 04:00
``````

Results:

``````Input: 03:10, Output; 35
Input: 04:00, Output; 120
``````

The full version

``````# Perl weekly challenge 120
#
use strict;
use warnings;
use v5.12;

for(@ARGV){
say "Wrong format: \$_", next
unless \$_=~m/^(\d?\d):(\d\d)\$/
&& 0<=\$1<=24 && 0<=\$1<60; # <24?
my \$angle=(30*(\$1+\$2/60)-\$2*6)%360;
\$angle=360-\$angle if \$angle>180;
say "Input: \$_, Output: \$angle";
}
``````

Examples:

``````./ch-2.pl 03:10 04:00
``````

Results:

``````Input: 03:10, Output: 35
Input: 04:00, Output: 120
``````

Other examples:

``````./ch-2.pl 15:10 16:00 16:40
``````

Results:

``````Input: 15:10, Output: 35
Input: 16:00, Output: 120
Input: 16:40, Output: 100
``````
Written on July 7, 2021