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