The Weekly Challenge 389

Reorder Notes and ZigZag Subarray

Task 1: Reorder Notes

You are given an array [composer, notes, permutation]. Reconstruct the melody by using each permutation value as the destination position of the corresponding note. Use no explicit for, foreach, or while loops. Output each result as COMPOSER => reordered notes.

Example Output

Input: $melody = ['Bach', ['C', 'D', 'E', 'F#', 'G', 'A', 'B'], [7, 1, 6, 2, 5, 3, 4]] Output: BACH => D F# A B G E C Input: $melody = ['Beethoven', ['C', 'D', 'F#', 'G', 'Ab'], [1, 3, 5, 2, 4]] Output: BEETHOVEN => C G D Ab F#

Logic

Each note's 1-based destination index is specified in the permutation array. To reconstruct the melody without explicit loops, we sort the note indices 0 .. N-1 based on their target destination in perm, slice the notes array by the sorted indices, join the reordered notes with spaces, and prepend the uppercase composer name.

Perl Solution

ch-1.pl

sub reorder_notes ($melody) { my ( $composer, $notes, $perm ) = @$melody; my @sorted_indices = sort { $perm->[$a] <=> $perm->[$b] } 0 .. $#$notes; my @reordered = @{$notes}[@sorted_indices]; return uc($composer) . ' => ' . join( ' ', @reordered ); }

Python Solution

ch-1.py

def reorder_notes(melody: list) -> str: """Reorder notes according to 1-based destination permutation. :param melody: [composer, notes, permutation] :return: Formatted string 'COMPOSER => reordered notes' """ composer, notes, perm = melody reordered = [note for _, note in sorted(zip(perm, notes))] return f"{composer.upper()} => {' '.join(reordered)}"

Task 2: ZigZag Subarray

You are given an array of integers. Write a script to find the length of the longest contiguous subarray where the numbers alternate between strictly increasing and strictly decreasing (a ZigZag pattern).

Example Output

Input: @nums = (9, 4, 2, 10, 7, 8, 8, 1, 9) Output: 5 (Subarray: 4, 2, 10, 7, 8) Input: @nums = (1, 7, 4, 9, 2, 5) Output: 6 (Subarray: 1, 7, 4, 9, 2, 5)

Logic

Iterate through adjacent pairs in a single linear pass $O(N)$ and compute the direction sign (+1 for increasing, -1 for decreasing, 0 for equal). Equal adjacent numbers break the pattern and reset the current length to 1. Alternating directions increase the sequence length. Repeated directions (e.g. two increases in a row) reset the current length to 2 (since any two distinct adjacent numbers form a valid ZigZag subarray of length 2). Track and return the maximum length encountered.

Perl Solution

ch-2.pl

sub longest_zigzag_subarray (@nums) { my $n = scalar @nums; return 0 if $n == 0; return 1 if $n == 1; my $max_len = 1; my $curr_len = 1; my $last_diff = 0; for my $i ( 1 .. $#nums ) { my $diff = $nums[$i] <=> $nums[ $i - 1 ]; if ( $diff == 0 ) { $curr_len = 1; $last_diff = 0; } elsif ( $last_diff == 0 || $diff == -$last_diff ) { $curr_len++; $last_diff = $diff; } else { # Same direction twice in a row (e.g. up-up or down-down) $curr_len = 2; $last_diff = $diff; } $max_len = $curr_len if $curr_len > $max_len; } return $max_len; }

Python Solution

ch-2.py

def longest_zigzag_subarray(nums: list[int]) -> int: """Return the length of the longest contiguous ZigZag subarray. :param nums: List of integers. :return: Length of the longest ZigZag subarray. """ n = len(nums) if n == 0: return 0 if n == 1: return 1 max_len = 1 curr_len = 1 last_diff = 0 for i in range(1, n): if nums[i] > nums[i - 1]: diff = 1 elif nums[i] < nums[i - 1]: diff = -1 else: diff = 0 if diff == 0: curr_len = 1 last_diff = 0 elif last_diff == 0 or diff == -last_diff: curr_len += 1 last_diff = diff else: # Same direction twice in a row (e.g. up-up or down-down) curr_len = 2 last_diff = diff if curr_len > max_len: max_len = curr_len return max_len