# PERL WEEKLY CHALLENGE – 048

This is my 18th week participating into the weekly challenge.

### Survivor

There are 50 people standing in a circle in position 1 to 50. The person standing at position 1 has a sword. He kills the next person i.e. standing at position 2 and pass on the sword to the immediate next i.e. person standing at position 3. Now the person at position 3 does the same and it goes on until only one survives.

This was quite and interesting problem to model.

I decided to model the people as a circular array containing their initial position. I modelled the sword so it always stays at position 0 and we move the people accordingly.

When a kill happens we just remove the index from the array, and when a switch happens we just move the person to the end of the array.

So at Interval 1 this is what the array looks like
1 2 3 4 .. 50

At interval 2 it’s this:
3 4 5 6 …… 50 1

At interval 3 it’s this:
5 6 7 8 …. 50 1 3

At interval 4 it’s this
7 8 9 10 … 50 1 3 5

Etc …

We just run until we have only one person left.

#### Perl 5 solution

``````#!/usr/bin/perl
# Test: ./ch-1
use strict;
use warnings;
use feature qw /say/;

# Populate the people with position_number
my @people;
\$people[\$_] = \$_ + 1 for (0..49);

# See who lives
kill_and_switch(\@people) while (scalar(@people > 1));
say \$people[0] . " is still alive";

# Kill and Switch
sub kill_and_switch {
my \$people = shift;

# switch
push @\$people, shift @\$people;

# kill
shift @\$people;
}
``````

Output

``37 is still alive``

#### Raku solution

``````# Test: perl6 ch-1.p6
sub MAIN() {
my @people = 1..50;
kill-and-switch(@people) while (@people.elems > 1);
say @people[0] ~" is still alive";
}

# Kill and Switch
sub kill-and-switch(@people) {
# switch
push @people, shift @people;

# kill
shift @people;
}
``````

Output

``37 is still alive``

### Palindrome Dates

Write a script to print all Palindrome Dates between 2000 and 2999. The format of date is mmddyyyy. For example, the first one was on October 2, 2001 as it is represented as 10022001.

For this one, it’s a matter of finding an object to loop through each date and checking if the date string is a palindrome.

I used Time::Piece for perl 5

and

Date for Raku.

#### Perl 5 solution

``````#!/usr/bin/perl
# test: perl ch-2.pl
use strict;
use warnings;
use Time::Piece;
use Time::Seconds;
use feature qw /say/;

my \$current_date = Time::Piece->strptime('01-01-2000', '%m-%d-%Y');
my \$end_date     = Time::Piece->strptime('12-31-2999', '%m-%d-%Y');

while (\$current_date < \$end_date) {
my \$date_string = \$current_date->strftime('%m%d%Y');
say \$date_string if (\$date_string eq reverse(\$date_string));
\$current_date = \$current_date + ONE_DAY;
}
``````

Output

``````10022001
01022010
11022011
02022020
12022021
03022030
04022040
05022050
06022060
07022070
08022080
09022090
10122101
01122110
11122111
02122120
12122121
03122130
04122140
05122150
06122160
07122170
08122180
09122190
10222201
01222210
11222211
02222220
12222221
03222230
04222240
05222250
06222260
07222270
08222280
09222290``````

#### Raku solution

``````# Test: perl6 ch-2.p6
use v6.d;

sub MAIN () {
my \$current_date  = Date.new(2000, 1, 1);
my \$end_date = Date.new(2999, 12, 31);

while (\$current_date < \$end_date) {
# Format month and day
my \$month = (\$current_date.month < 10) ??
'0' ~ \$current_date.month !!
\$current_date.month;

my \$day   = (\$current_date.day < 10) ??
'0' ~ \$current_date.day !!
\$current_date.day;

# Date String
my \$date_string = \$month ~ \$day ~ \$current_date.year;

# Output the datestring if it's a palindrome
say \$date_string
if (\$date_string eq \$date_string.flip);

# Next Day
\$current_date = \$current_date + 1;
}
}
``````

Output

``````10022001
01022010
11022011
02022020
12022021
03022030
04022040
05022050
06022060
07022070
08022080
09022090
10122101
01122110
11122111
02122120
12122121
03122130
04122140
05122150
06122160
07122170
08122180
09122190
10222201
01222210
11222211
02222220
12222221
03222230
04222240
05222250
06222260
07222270
08222280
09222290``````