diff options
| author | Lubos Kolouch <lubos@kolouch.net> | 2025-02-03 09:29:39 +0100 |
|---|---|---|
| committer | Lubos Kolouch <lubos@kolouch.net> | 2025-02-03 09:29:39 +0100 |
| commit | 1c8596d40a325a56de55b1c1f1e06f530041efc0 (patch) | |
| tree | 1b50f487c0c98f565acf06cfe27c7e64a27352c9 | |
| parent | 75cad926933996bff61b6684c63344fddbb4ea79 (diff) | |
| download | perlweeklychallenge-club-1c8596d40a325a56de55b1c1f1e06f530041efc0.tar.gz perlweeklychallenge-club-1c8596d40a325a56de55b1c1f1e06f530041efc0.tar.bz2 perlweeklychallenge-club-1c8596d40a325a56de55b1c1f1e06f530041efc0.zip | |
LK: Perl and Python solutions for Challenge 307
| -rw-r--r-- | challenge-307/lubos-kolouch/perl/ch-1.pl | 58 | ||||
| -rw-r--r-- | challenge-307/lubos-kolouch/perl/ch-2.pl | 62 | ||||
| -rw-r--r-- | challenge-307/lubos-kolouch/python/ch-1.py | 56 | ||||
| -rw-r--r-- | challenge-307/lubos-kolouch/python/ch-2.py | 57 |
4 files changed, 233 insertions, 0 deletions
diff --git a/challenge-307/lubos-kolouch/perl/ch-1.pl b/challenge-307/lubos-kolouch/perl/ch-1.pl new file mode 100644 index 0000000000..ded26ca1cb --- /dev/null +++ b/challenge-307/lubos-kolouch/perl/ch-1.pl @@ -0,0 +1,58 @@ +#!/usr/bin/perl +use strict; +use warnings; +use Test::More tests => 4; + +=head1 NAME + +check_order.pl - Rearrange an array in increasing order and return differing indices + +=head1 SYNOPSIS + + perl check_order.pl + +=head1 DESCRIPTION + +This script defines a function that accepts an array reference of integers. +It sorts the array in increasing order and returns the indices where the sorted array +differs from the original. + +=head2 check_order + + my $diff_indices_ref = check_order($ints_ref); + +This function takes an array reference of integers and returns an array reference +containing the indices at which the sorted array differs from the original. + +=cut + +sub check_order { + my ($ints_ref) = @_; + my @original = @$ints_ref; + my @sorted = sort { $a <=> $b } @original; + my @diff_indices; + for my $i ( 0 .. $#original ) { + if ( $original[$i] != $sorted[$i] ) { + push @diff_indices, $i; + } + } + return \@diff_indices; +} + +# Unit tests + +my $result; + +$result = check_order( [ 5, 2, 4, 3, 1 ] ); +is_deeply( $result, [ 0, 2, 3, 4 ], 'Test example 1' ); + +$result = check_order( [ 1, 2, 1, 1, 3 ] ); +is_deeply( $result, [ 1, 3 ], 'Test example 2' ); + +$result = check_order( [ 3, 1, 3, 2, 3 ] ); +is_deeply( $result, [ 0, 1, 3 ], 'Test example 3' ); + +$result = check_order( [ 1, 2, 3, 4, 5 ] ); +is_deeply( $result, [], 'Test already sorted' ); + +done_testing(); diff --git a/challenge-307/lubos-kolouch/perl/ch-2.pl b/challenge-307/lubos-kolouch/perl/ch-2.pl new file mode 100644 index 0000000000..8ef06deec6 --- /dev/null +++ b/challenge-307/lubos-kolouch/perl/ch-2.pl @@ -0,0 +1,62 @@ +#!/usr/bin/perl +use strict; +use warnings; +use Test::More tests => 4; + +=head1 NAME + +find_anagrams.pl - Drop consecutive anagrams and return the count of the final list + +=head1 DESCRIPTION + +This script applies the rule: whenever two consecutive words are anagrams, +drop the first word and keep the second. This is repeated until no such pair exists. +According to this rule, any contiguous block of anagrams will collapse to a single word. + +=head2 sorted_word + + my $sorted = sorted_word($word); + +Returns the characters of the word sorted in increasing order. + +=head2 find_anagrams + + my $final_count = find_anagrams(\@words); + +Processes the list iteratively and returns the count of words remaining. +=cut + +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 ; $i < @list - 1 ; $i++ ) { + if ( sorted_word( $list[$i] ) eq sorted_word( $list[ $i + 1 ] ) ) { + + # drop the first word of the pair + splice( @list, $i, 1 ); + $changed = 1; + last; # restart scanning from beginning + } + } + } + return scalar @list; +} + +# Unit tests for the iterative (fully applied) rule: +is( find_anagrams( [ "acca", "dog", "god", "perl", "repl" ] ), + 3, 'Test example 1' ); +is( find_anagrams( [ "abba", "baba", "aabb", "ab", "ab" ] ), + 2, 'Test example 2' ); +is( find_anagrams( [ "abc", "cab", "bca" ] ), 1, 'Test simple chain' ); +is( find_anagrams( [ "word", "drow", "word", "word" ] ), + 1, 'Test repeating words' ); + +done_testing(); diff --git a/challenge-307/lubos-kolouch/python/ch-1.py b/challenge-307/lubos-kolouch/python/ch-1.py new file mode 100644 index 0000000000..256255aeba --- /dev/null +++ b/challenge-307/lubos-kolouch/python/ch-1.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +""" +Module to check the order of an integer list. +""" + +import unittest + +IntList = list[int] + + +def check_order(ints: IntList) -> list[int]: + """ + Rearranges the list in increasing order and returns the indices where the sorted list + differs from the original list. + + Args: + ints (List[int]): The list of integers. + + Returns: + List[int]: A list of indices where the sorted list differs from the original. + """ + sorted_ints = sorted(ints) + differences: list[int] = [] + for i, (orig, sorted_val) in enumerate(zip(ints, sorted_ints)): + if orig != sorted_val: + differences.append(i) + return differences + + +if __name__ == "__main__": + + class TestCheckOrder(unittest.TestCase): + + def test_example1(self): + input_list = [5, 2, 4, 3, 1] + expected = [0, 2, 3, 4] + self.assertEqual(check_order(input_list), expected) + + def test_example2(self): + input_list = [1, 2, 1, 1, 3] + expected = [1, 3] + self.assertEqual(check_order(input_list), expected) + + def test_example3(self): + input_list = [3, 1, 3, 2, 3] + expected = [0, 1, 3] + self.assertEqual(check_order(input_list), expected) + + def test_already_sorted(self): + input_list = [1, 2, 3, 4, 5] + expected = [] + self.assertEqual(check_order(input_list), expected) + + +if __name__ == "__main__": + unittest.main() diff --git a/challenge-307/lubos-kolouch/python/ch-2.py b/challenge-307/lubos-kolouch/python/ch-2.py new file mode 100644 index 0000000000..a7124d14d6 --- /dev/null +++ b/challenge-307/lubos-kolouch/python/ch-2.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +""" +Module to process a list of words by dropping consecutive anagrams. +Applies the rule iteratively: +if two consecutive words are anagrams, drop the first word. +A contiguous block of anagrams will collapse to a single word. +""" + +import unittest + + +def sorted_word(word: str) -> str: + return ''.join(sorted(word)) + + +def find_anagrams(words: list[str]) -> int: + """ + Iteratively remove the first word from any consecutive pair of anagrams. + + Args: + words (List[str]): The list of words. + + Returns: + int: The count of words remaining after processing. + """ + lst = words[:] # work on a copy + 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 # restart from beginning + return len(lst) + + +if __name__ == "__main__": + + class TestFindAnagrams(unittest.TestCase): + + def test_example1(self): + self.assertEqual( + find_anagrams(["acca", "dog", "god", "perl", "repl"]), 3) + + def test_example2(self): + self.assertEqual( + find_anagrams(["abba", "baba", "aabb", "ab", "ab"]), 2) + + def test_simple_chain(self): + self.assertEqual(find_anagrams(["abc", "cab", "bca"]), 1) + + def test_repeating_words(self): + self.assertEqual(find_anagrams(["word", "drow", "word", "word"]), + 1) + + unittest.main() |
