DEV Community

Simon Green
Simon Green

Posted on

Nested beauty

Weekly Challenge 300

Each week Mohammad S. Anwar sends out The Weekly Challenge, 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, My solutions

With this being the three hundredth challenge, let me personally thank Mohammad for all the work he does each week on behalf of everyone in Team PWC.

Task 1: Beautiful Arrangement

Task

You are given a positive integer, $int.

Write a script to return the number of beautiful arrangements that you can construct.

A permutation of n integers, 1-indexed, is considered a beautiful arrangement if for every i (1 <= i <= n) either of the following is true:

  1. perm[i] is divisible by i
  2. i is divisible by perm[i]

My solution

For this task, I use the permutations function from the itertool module to work through all permutations.

Then it's just a matter of determining if this permutation meets the specified criteria. If it doesn't, I move to the next permutation. If it does, I add one to the count variable.

def beautiful_arrangement(n: list) -> str:
    count = 0

    for p in permutations(range(1, n+1)):
        for i in range(n):
            if p[i] % (i+1) != 0 and (i+1) % p[i] != 0:
                break
        else:
            count += 1

    return count
Enter fullscreen mode Exit fullscreen mode

There may be a more efficient way to compute the results that doesn't involve brute force. My code would become very inefficient on larger numbers. I didn't not spend any time investigating this.

Examples

$ ./ch-1.py 1
1

$ ./ch-1.py 2
2

$ ./ch-1.py 10
700
Enter fullscreen mode Exit fullscreen mode

Task 2: Nested Array

Task

You are given an array of integers, @ints of length n containing permutation of the numbers in the range [0, n - 1].

Write a script to build a set, set[i] = ints[i], ints[ints[i]], ints[ints[ints[i]]], ..., subjected to the following rules:

  1. The first element in set[i] starts with the selection of elements ints[i].
  2. The next element in set[i] should be ints[ints[i]], and then ints[ints[ints[i]]], and so on.
  3. We stop adding right before a duplicate element occurs in set[i].

My solution

This is relatively straight forward. I start with a variable called longest_set, set to 0. I then iterate through each starting position and set the this_set list to be the first item of the set (i.e ints[i]). I keep adding to this set while ints[this_set[-1]] does not appear in the this_set list. After this is done, I compare the length of the this_set list against the longest_set value. If it is greater, I update the longest_set value.

def nested_array(ints: list) -> int:
    longest_set = 0

    for start in range(len(ints)):
        this_set = [ints[start]]

        while ints[this_set[-1]] not in this_set:
            this_set.append(ints[this_set[-1]])

        if longest_set < len(this_set):
            longest_set = len(this_set)

    return longest_set
Enter fullscreen mode Exit fullscreen mode

Examples

$ ./ch-2.py 5 4 0 3 1 6 2
4

$ ./ch-2.py 0 1 2
1

$ ./ch-2.py 1 2 0 4 5 2
5
Enter fullscreen mode Exit fullscreen mode

Top comments (0)