Seize the greatness
Tags: perl, python, theweeklychallenge
Published: 2023-10-08 12:01:13

## Weekly Challenge 237

Each week Mohammad S. Anwar sends out [The Weekly Challenge](https://theweeklychallenge.org/), a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.

[Challenge](https://theweeklychallenge.org/blog/perl-weekly-challenge-237/), [My solutions](https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-237/sgreen)

## Task 1: Seize The Day

### Task

Given a year, a month, a weekday of month, and a day of week (1 (Mon) .. 7 (Sun)), print the day.

### My solution

Thankfully all languages have modules for date manipulation. For Python that is the [date](https://docs.python.org/3/library/datetime.html#date-objects) object from datetime module.

I use the following steps to come to the solution.

1. Work out the day of week for the first day of the month. This is stored in a variable `first_weekday` where 1 is Monday, and 7 is Sunday.
1. Work out the day of month for the first day of week. We do this by subtracting the specified day of week from `first_weekday`. If this value is negative, add 7 days.
1. Add the requires number of weeks. As we already know the first occurrence of the day of week, we add 7 days less than the 'weekday of month' value.
1. Add the days to the variable in the first step. If this is in the same month, print the day of month. Otherwise print `0`.

```python
dte = date(year, month, 1)
first_weekday = dte.isoweekday()

add_days = dofw - first_weekday
if add_days < 0:
    add_days += 7

add_days += (week-1) * 7

new_date = dte + timedelta(days=add_days)
if new_date.month != dte.month or new_date.year != dte.year:
    print(0)
else:
    print(new_date.day)
```

The Perl solution is very similar and uses the [Date::Calc](https://metacpan.org/pod/Date::Calc) module. Unlike DateTime, this is not object orientated. In this case, I manually calculate the day of month, and check that it is not greater than the days in the month.

### Examples

```bash
$ ./ch-1.py 2024 4 3 2
16

$ ./ch-1.py 2025 10 2 4
9

$ ./ch-1.py 2026 8 5 3
0
```

## Task 2: Maximize Greatness

### Task

You are given an array of integers.

Write a script to permute the give array such that you get the maximum possible greatness.

To determine greatness, `nums[i] < perm[i]` where `0 <= i < nums.length`.

### My solution

This is one of those tasks where optimization is going to lead to a faster response. There are three million permutations for 10 digits, and over 6 billion for 13 digits.

Thankfully we don't need to calculate all of them!

For this task, I order the numbers in reverse (highest value first), and put this in a list (array in Perl) called `sorted_ints`. For each number, I take off the highest value lower than it, and remove it from the `ints` list. I continue until there are no lower numbers.

```python
for i in sorted_ints:
    if min(ints) >= i:
        break

    m = max(j for j in ints if j < i)
    idx = ints.index(m)
    del ints[idx]

    count += 1
```

The Perl solution is a transliteration of the Python code.

### Examples

```bash
$ ./ch-2.py 1 3 5 2 1 3 1
4

$ ./ch-2.py 1 2 3 4
3
```