Perl Weekly Challenge : Week 48
Tags: raku, challenge
Published: 2020-02-17 12:10:34

---
title: Perl Weekly Challenge : Week 48
published: true
description: My thoughts on the Perl Weekly Challenge
tags: raku, challenge
---

I've decided I'm going to try blogging about my attempts at the [Perl Weekly Challenge](https://perlweeklychallenge.org/) which I've been doing since it started. Generally I do my challenge in [Raku](https://raku.org/) the language formally known as Perl6.

[This weeks challenge](https://perlweeklychallenge.org/blog/perl-weekly-challenge-048/) has a couple of fun parts. If you've not tried it yet you might want to come back after you have.

## Challenge 1

So I'd seen a video on this before it's called [the Josephus Problem](https://www.youtube.com/watch?v=uCsD3ZGzMgE) so I knew there was a mathematical solution to it.... but I couldn't remember it.

As is often the way I went a bit above and beyond and worked out a function to give the survivor number for any number of swordsmen. My thinking about it was simple. Get a list of number from 1 to 50, take the first two from the front. The first survives the second is dead. Put the survivor at the end of the list. Repeat until you have 1 survivor :

    #| Calculate the survivor of the swordsmen suicide pact
    multi sub MAIN(
        UInt $swords = 50, #= Number of swordsmen (default 50)
    ) {
        my @men = [1..$swords];
        while ( @men.elems > 1 ) {
            my ( $alive, $dead ) = @men.splice(0,2);
            @men.push($alive);
        }

        say "Survivor of $swords is number {@men[0]}";
    }

With that I was able to run the test for lots of different value and worked out the mathematical solution. Given a number of swordsmen (s) we find p where p < s and p is a power of 2. Then the number of the survivor is the nth odd number where n = s - p. 

For example for s = 50, p = 32 and n is the 18th odd number (indexed on 0) which is 37.

The code for this :

    #| Calculate mathematically
    multi sub MAIN(
        "math", 
        UInt $swords = 50, #= Number of swordsmen
    ) {
        my $low-power = (1,* * 2...*).first(* > $swords) div 2;
        say "Survivor of $swords is number {(1,3,5...*)[$swords - $low-power]}";
    }

Couple of fun uses of Raku [sequences](https://docs.raku.org/language/operators#index-entry-sequence_operator) one to generate the powers of 2 and the second to generate the list of odd numbers.

## Challenge 2

For challenge 2 I initially worked on the theory I'll look at every date between 2020-01-01 and 2999-12-31 and look for palindromes. Turns out... that's a lot of days (357937 to be exact) and it take a while. Even when you use `.hyper` to thread the tests over multiple cores. But then I had a thought.

If I went through every month and day combination that's 12 x 31 (we'll worry about out of range values in a second) and that's only 372 to check. If we take the month and day and flip it to get a year if we can check it's valid and it's between our start and end dates. 

    #| Find the palendromic numbers (writen mmddyyy) between 2000-01-01 and 2999-01-01
    sub MAIN() {
        my sub df( Date $d) {
            # Bleh American dates
            sprintf "%02d%02d%04d", .month, .day, .year given $d;
        }
    
        constant START = Date.new(2000,1,1,formatter => &df);
        constant END = Date.new(2999,12,31, formatter => &df);
    
        my @out;
    
        for (1..12) -> $month {
            for (1..31) -> $day {
                my $date;
                my $year = sprintf( "%02d%02d", $month, $day ).flip;
                try {
                    $date = Date.new($year,$month,$day,formatter => &df);
                }
                next unless $date;
                next unless START <= $date <= END;
                @out.push($date);
            }
        }
    
        .say for @out.sort;
    }

I hope that all makes sense. Feel free to drop a comment if you've got questions or thoughts.