The Weekly Challenge ‐ Perl and Raku

CY's Take on The Weekly Challenge #118 Task 1

If you want to challenge yourself on programming, especially on Perl and/or Raku, go to https://perlweeklychallenge.org, code the latest challenges, submit codes on-time (by GitHub or email).

Do tell me, if I am wrong or you strongly oppose my statements!

It's time for challenges in Week #118 !


Task 1: Binary Palindrome

Task statement in one-line: Given a positive integer $N in base-10, determine whether it is a palindrome in base-2.

Looking at others' codes on Week #117, I have also learn the oct for a handy transform integer to base-2 string! I referred to the Perl Cookbook and use pack-unpack, which I have still not understood. Oooooops...

Let's come back to the Task 1 of this week. I implemented a &divmod similar to that in Ruby(but not OO, a big difference as Ruby is pure-OO language) and think it's useful and tiddying stuff, well.

Without testing, I proceeded to write other code components, and the codes are:

my $r = $ARGV[0] || 0;
print binpali($r),"\n";



sub binpali {
    my @d = dec2binarr($_[0])->@*;
    return (join "", @d) eq (join "", reverse @d) ? 1 : 0;
}


sub dec2binarr {
    my $s = $_[0];
    my $i = 0;
    my @digit;
    while ($s != 0) {
        ($s, $digit[$i] ) = divmod($s)->@*;
        $i++;
    }
    return [@digit];
}
(I intentionally hide the details of &divmod for blogpost.)

Started test with the integer 3. The terminal output is negative. So I modified the code to see what happens. I decided to print $i in &dec2binarr and printed the binary string. The terminal gave me this string:

00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000011

And the $i ran to as large as 1077. How about $N = 2? $i ran to 1076 and also something with many zeros and end with 10. What happens?

Then I checked $digit[$i]:

# $i $digit[$i]
1 1
2 0.5
3 0.25
4 0.125
5 0.0625
#...
1066 2.52961610670718e-321
1067 1.26480805335359e-321
1068 6.32404026676796e-322
1069 3.16202013338398e-322
1070 1.58101006669199e-322
1071 7.90505033345994e-323
1072 3.95252516672997e-323
1073 1.97626258336499e-323
1074 9.88131291682493e-324
1075 4.94065645841247e-324
1076 0
00000000000000000000000
...
00000000000000000000000
000000000 #end with 10 

I think the readers are able to guess where goes wrong on my first attempt.

Initial &divmod:

sub divmod {
    my $num = $_[0];
    return [$num / 2 , $num % 2];
}

Corrected &divmod:

sub divmod {
    my $num = $_[0];
    return [int $num / 2 , $num % 2];
}

Finally I am back to the practice of providing test cases with Perl standard test suite (here: Test::More), for reviewers or other coders to validate my code. Initially, I tried many times with oct 0b1001001 before realizing it should be oct "0b1001001".

Stay alert and healthy! □

link for full codes: ch-1.pl

link to blogpost for Task 2 "Adventure of Knight"


Contact on twitter: @e7_87.

Created Date: 26th June, 2021; last updated: 27th June, 2021.