Task 1: Check Order
You are given an array of integers, @ints.
Write a script to re-arrange the given array in increasing order and return the indices where it differs from the original array.
Example 1
Input: @ints = (5, 2, 4, 3, 1)
Output: (0, 2, 3, 4)
Before: (5, 2, 4, 3, 1)
After : (1, 2, 3, 4, 5)
Example 2
Input: @ints = (1, 2, 1, 1, 3)
Output: (1, 3)
Before: (1, 2, 1, 1, 3)
After : (1, 1, 1, 2, 3)
Example 3
Input: @ints = (3, 1, 3, 2, 3)
Output: (0, 1, 3)
Before: (3, 1, 3, 2, 3)
After : (1, 2, 3, 3, 3)
Logic
Sort the array, then compare element-by-element with the original. Collect indices where the values differ. Simple O(n log n) approach.
Perl Solution
ch-1.pl
#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 4;
sub check_order {
my ($ints_ref) = @_;
my @original = @$ints_ref;
my @sorted = sort { $a <=> $b } @original;
my @diff_indices;
for my $i (0 .. $#original) {
push @diff_indices, $i if $original[$i] != $sorted[$i];
}
return \@diff_indices;
}
is_deeply(check_order([5,2,4,3,1]), [0,2,3,4], 'Ex1');
is_deeply(check_order([1,2,1,1,3]), [1,3], 'Ex2');
is_deeply(check_order([3,1,3,2,3]), [0,1,3], 'Ex3');
is_deeply(check_order([1,2,3,4,5]), [], 'Sorted');
Python Solution
ch-1.py
def check_order(ints: list[int]) -> list[int]:
sorted_ints = sorted(ints)
return [i for i, (a, b) in enumerate(zip(ints, sorted_ints)) if a != b]
Task 2: Find Anagrams
You are given a list of words, @words.
Write a script to find any two consecutive words and if they are anagrams, drop the first word and keep the second. Continue until no more consecutive anagrams exist. Return the count of the final list.
Example 1
Input: @words = ("acca", "dog", "god", "perl", "repl")
Output: 3
Step 1: "dog" and "god" are anagrams, drop "dog" => ("acca", "god", "perl", "repl")
Step 2: "perl" and "repl" are anagrams, drop "perl" => ("acca", "god", "repl")
Example 2
Input: @words = ("abba", "baba", "aabb", "ab", "ab")
Output: 2
Step 1: "abba" and "baba" are anagrams, drop "abba" => ("baba", "aabb", "ab", "ab")
Step 2: "baba" and "aabb" are anagrams, drop "baba" => ("aabb", "ab", "ab")
Step 3: "ab" and "ab" are anagrams, drop first "ab" => ("aabb", "ab")
Logic
Iteratively scan the list for consecutive anagram pairs. When found, remove the first word and restart from the beginning. Two words are anagrams if their sorted character sequences are identical. The process continues until a full pass finds no consecutive anagrams.
Perl Solution
ch-2.pl
#!/usr/bin/perl
use strict;
use warnings;
use Test::More tests => 4;
sub sorted_word {
my ($word) = @_;
return join '', sort split //, $word;
}
sub find_anagrams {
my ($words_ref) = @_;
my @list = @$words_ref;
my $changed = 1;
while ($changed) {
$changed = 0;
for my $i (0 .. $#list - 1) {
if (sorted_word($list[$i]) eq sorted_word($list[$i+1])) {
splice(@list, $i, 1);
$changed = 1;
last;
}
}
}
return scalar @list;
}
is(find_anagrams(["acca","dog","god","perl","repl"]), 3, 'Ex1');
is(find_anagrams(["abba","baba","aabb","ab","ab"]), 2, 'Ex2');
is(find_anagrams(["abc","cab","bca"]), 1, 'Chain');
is(find_anagrams(["word","drow","word","word"]), 1, 'Repeating');
Python Solution
ch-2.py
def sorted_word(word: str) -> str:
return ''.join(sorted(word))
def find_anagrams(words: list[str]) -> int:
lst = words[:]
changed = True
while changed:
changed = False
for i in range(len(lst) - 1):
if sorted_word(lst[i]) == sorted_word(lst[i + 1]):
lst.pop(i)
changed = True
break
return len(lst)