diff options
62 files changed, 4689 insertions, 2747 deletions
diff --git a/challenge-025/lubos-kolouch/perl/ch-1.pl b/challenge-025/lubos-kolouch/perl/ch-1.pl new file mode 100644 index 0000000000..1193b211bd --- /dev/null +++ b/challenge-025/lubos-kolouch/perl/ch-1.pl @@ -0,0 +1,41 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +my @names = + qw(audino bagon baltoy banette bidoof braviary bronzor carracosta charmeleon cresselia croagunk darmanitan deino emboar emolga exeggcute gabite girafarig gulpin haxorus heatmor heatran ivysaur jellicent jumpluff kangaskhan kricketune landorus ledyba loudred lumineon lunatone machamp magnezone mamoswine nosepass petilil pidgeotto pikachu pinsir poliwrath poochyena porygon2 porygonz registeel relicanth remoraid rufflet sableye scolipede scrafty seaking sealeo silcoon simisear snivy snorlax spoink starly tirtouga trapinch treecko tyrogue vigoroth vulpix wailord wartortle whismur wingull yamask); + +my %used; +my @sequence; + +foreach my $name (@names) { + next if $used{$name}; + my $current = $name; + my @temp = ($current); + my %temp_used = %used; + $temp_used{$current} = 1; + + while (1) { + my $found = 0; + foreach my $next (@names) { + next if $temp_used{$next}; + if ( substr( $current, -1 ) eq substr( $next, 0, 1 ) ) { + $current = $next; + push( @temp, $current ); + $temp_used{$current} = 1; + $found = 1; + last; + } + } + last unless $found; + } + + if ( scalar(@temp) > scalar(@sequence) ) { + @sequence = @temp; + } + + %used = %temp_used; +} + +print join( " -> ", @sequence ) . "\n"; diff --git a/challenge-025/lubos-kolouch/perl/ch-2.pl b/challenge-025/lubos-kolouch/perl/ch-2.pl new file mode 100644 index 0000000000..089e44615a --- /dev/null +++ b/challenge-025/lubos-kolouch/perl/ch-2.pl @@ -0,0 +1,81 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +# Define the Chaocipher alphabets +my $left_alphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ"; +my $right_alphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC"; + +sub chaocipher_encrypt { + my $message = shift; + my $ciphertext = ""; + my $left_index = 0; + my $right_index = 0; + + # Loop through each character in the message + foreach my $char ( split //, uc($message) ) { + if ( $char !~ /[A-Z]/ ) { + + # Ignore non-alphabetic characters + $ciphertext .= $char; + next; + } + + # Find the index of the character in the left alphabet + my $left_char_index = index( $left_alphabet, $char ); + + # Swap the left and right indices + ( $left_index, $right_index ) = ( $right_index, $left_index ); + + # Find the corresponding character in the right alphabet + my $right_char = + substr( $right_alphabet, ( $left_char_index + $right_index ) % 26, + 1 ); + + # Append the encrypted character to the ciphertext + $ciphertext .= $right_char; + } + + return $ciphertext; +} + +sub chaocipher_decrypt { + my $ciphertext = shift; + my $plaintext = ""; + my $left_index = 0; + my $right_index = 0; + + # Loop through each character in the ciphertext + foreach my $char ( split //, uc($ciphertext) ) { + if ( $char !~ /[A-Z]/ ) { + + # Ignore non-alphabetic characters + $plaintext .= $char; + next; + } + + # Find the index of the character in the right alphabet + my $right_char_index = index( $right_alphabet, $char ); + + # Swap the left and right indices + ( $left_index, $right_index ) = ( $right_index, $left_index ); + + # Find the corresponding character in the left alphabet + my $left_char = + substr( $left_alphabet, ( $right_char_index - $right_index ) % 26, + 1 ); + + # Append the decrypted character to the plaintext + $plaintext .= $left_char; + } + + return $plaintext; +} + +# Example usage +my $message = "Hello World!"; +my $ciphertext = chaocipher_encrypt($message); +print "Ciphertext: $ciphertext\n"; +my $plaintext = chaocipher_decrypt($ciphertext); +print "Plaintext: $plaintext\n"; diff --git a/challenge-025/lubos-kolouch/python/ch-1.py b/challenge-025/lubos-kolouch/python/ch-1.py new file mode 100644 index 0000000000..519cc6022a --- /dev/null +++ b/challenge-025/lubos-kolouch/python/ch-1.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 + +names = [ + "audino", + "bagon", + "baltoy", + "banette", + "bidoof", + "braviary", + "bronzor", + "carracosta", + "charmeleon", + "cresselia", + "croagunk", + "darmanitan", + "deino", + "emboar", + "emolga", + "exeggcute", + "gabite", + "girafarig", + "gulpin", + "haxorus", + "heatmor", + "heatran", + "ivysaur", + "jellicent", + "jumpluff", + "kangaskhan", + "kricketune", + "landorus", + "ledyba", + "loudred", + "lumineon", + "lunatone", + "machamp", + "magnezone", + "mamoswine", + "nosepass", + "petilil", + "pidgeotto", + "pikachu", + "pinsir", + "poliwrath", + "poochyena", + "porygon2", + "porygonz", + "registeel", + "relicanth", + "remoraid", + "rufflet", + "sableye", + "scolipede", + "scrafty", + "seaking", + "sealeo", + "silcoon", + "simisear", + "snivy", + "snorlax", + "spoink", + "starly", + "tirtouga", + "trapinch", + "treecko", + "tyrogue", + "vigoroth", + "vulpix", + "wailord", + "wartortle", + "whismur", + "wingull", + "yamask", +] + +used = {} +sequence = [] + +for name in names: + if name in used: + continue + + current = name + temp = [current] + temp_used = used.copy() + temp_used[current] = True + + while True: + found = False + for next_name in names: + if next_name in temp_used: + continue + + if current[-1] == next_name[0]: + current = next_name + temp.append(current) + temp_used[current] = True + found = True + break + + if not found: + break + + if len(temp) > len(sequence): + sequence = temp + + used = temp_used + +print(" -> ".join(sequence)) diff --git a/challenge-025/lubos-kolouch/python/ch-2.py b/challenge-025/lubos-kolouch/python/ch-2.py new file mode 100644 index 0000000000..2100aeb960 --- /dev/null +++ b/challenge-025/lubos-kolouch/python/ch-2.py @@ -0,0 +1,92 @@ +def chaocipher_encrypt(message: str) -> str: + """ + Encrypts a message using the Chaocipher algorithm. + + Chaocipher is a symmetric encryption algorithm that uses two mixed alphabets to + perform a double substitution on each letter of the plaintext. The two alphabets + are predetermined and fixed. + + Args: + message: The message to be encrypted. + + Returns: + The encrypted message. + """ + # Define the Chaocipher alphabets + left_alphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" + right_alphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC" + + ciphertext = "" + left_index = 0 + right_index = 0 + + # Loop through each character in the message + for char in message.upper(): + if not char.isalpha(): + # Ignore non-alphabetic characters + ciphertext += char + continue + + # Find the index of the character in the left alphabet + left_char_index = left_alphabet.index(char) + + # Swap the left and right indices + left_index, right_index = right_index, left_index + + # Find the corresponding character in the right alphabet + right_char_index = (left_char_index + right_index) % 26 + right_char = right_alphabet[right_char_index] + + # Append the encrypted character to the ciphertext + ciphertext += right_char + + return ciphertext + + +def chaocipher_decrypt(ciphertext: str) -> str: + """ + Decrypts a message that has been encrypted using the Chaocipher algorithm. + + Args: + ciphertext: The message to be decrypted. + + Returns: + The decrypted message. + """ + # Define the Chaocipher alphabets + left_alphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ" + right_alphabet = "PTLNBQDEOYSFAVZKGJRIHWXUMC" + + plaintext = "" + left_index = 0 + right_index = 0 + + # Loop through each character in the ciphertext + for char in ciphertext.upper(): + if not char.isalpha(): + # Ignore non-alphabetic characters + plaintext += char + continue + + # Find the index of the character in the right alphabet + right_char_index = right_alphabet.index(char) + + # Swap the left and right indices + left_index, right_index = right_index, left_index + + # Find the corresponding character in the left alphabet + left_char_index = (right_char_index - right_index) % 26 + left_char = left_alphabet[left_char_index] + + # Append the decrypted character to the plaintext + plaintext += left_char + + return plaintext + + +# Example usage +message = "Hello World!" +ciphertext = chaocipher_encrypt(message) +print(f"Ciphertext: {ciphertext}") +plaintext = chaocipher_decrypt(ciphertext) +print(f"Plaintext: {plaintext}") diff --git a/challenge-175/bob-lied/README b/challenge-175/bob-lied/README index c231e3a589..bd3c0f9dcf 100644 --- a/challenge-175/bob-lied/README +++ b/challenge-175/bob-lied/README @@ -1,3 +1,3 @@ -Solutions to weekly challenge 138 by Bob Lied +Solutions to weekly challenge 175 by Bob Lied -https://perlweeklychallenge.org/blog/perl-weekly-challenge-138/ +https://perlweeklychallenge.org/blog/perl-weekly-challenge-175/ diff --git a/challenge-175/bob-lied/perl/ch-1.pl b/challenge-175/bob-lied/perl/ch-1.pl new file mode 100644 index 0000000000..53c935ff84 --- /dev/null +++ b/challenge-175/bob-lied/perl/ch-1.pl @@ -0,0 +1,65 @@ +#!/usr/bin/env perl +# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu: +#============================================================================= +# ch-1.pl Perl Weekly Challenge 175 Task 1 Last Sunday +#============================================================================= +# Copyright (c) 2023, Bob Lied +#============================================================================= +# Write a script to list Last Sunday of every month in the given year. +# For example, for year 2022, we should get the following: +# 2022-01-30 2022-02-27 2022-03-27 2022-04-24 +# 2022-05-29 2022-06-26 2022-07-31 2022-08-28 +# 2022-09-25 2022-10-30 2022-11-27 2022-12-25 +#### +# This is a task for reading the documentation of the DateTime module to +# find the functions we need. +#============================================================================= + +use v5.36; + +use DateTime; + +use Getopt::Long; +my $DoTest = 0; + +GetOptions("test" => \$DoTest); +exit(!runTest()) if $DoTest; + +# Takes one argument, a year. +say join("\n", lastSunday($ARGV[0])->@*); + +sub lastSunday($year) +{ + my @sundayList; + for my $month ( 1 .. 12 ) + { + # Start at the last day of the month and back up until we + # find a Sunday. + my $d = DateTime->last_day_of_month( year => $year, month => $month); + while ( $d->day_of_week != 7 ) + { + $d->subtract( days => 1 ); + } + push @sundayList, $d->ymd(); + } + return \@sundayList; +} + +sub runTest +{ + use Test2::V0; + + is( lastSunday(2022), + [ qw( 2022-01-30 2022-02-27 2022-03-27 2022-04-24 + 2022-05-29 2022-06-26 2022-07-31 2022-08-28 + 2022-09-25 2022-10-30 2022-11-27 2022-12-25 ) ], + , "Year 2022"); + + is( lastSunday(1958), + [ qw( 1958-01-26 1958-02-23 1958-03-30 1958-04-27 + 1958-05-25 1958-06-29 1958-07-27 1958-08-31 + 1958-09-28 1958-10-26 1958-11-30 1958-12-28 ) ], + , "Year 1958"); + + done_testing; +} diff --git a/challenge-175/bob-lied/perl/ch-2.pl b/challenge-175/bob-lied/perl/ch-2.pl new file mode 100644 index 0000000000..5be328c2d5 --- /dev/null +++ b/challenge-175/bob-lied/perl/ch-2.pl @@ -0,0 +1,107 @@ +#!/usr/bin/env perl +# vim:set ts=4 sw=4 sts=4 et ai wm=0 nu: +#============================================================================= +# ch-2.pl Perl Weekly Challenge Week 175 Task 2 Totient +#============================================================================= +# Copyright (c) 2023, Bob Lied +#============================================================================= +# Write a script to generate first 20 Perfect Totient Numbers. +# Please checkout wikipedia page for more informations. +# https://en.wikipedia.org/wiki/Perfect_totient_number +# Output +# 3, 9, 15, 27, 39, 81, 111, 183, 243, 255, 327, 363, 471, 729, +# 2187, 2199, 3063, 4359, 4375, 5571 +#### +# In number theory, a perfect totient number is an integer that is equal to +# the sum of its iterated totients. That is, we apply the totient function to +# a number n, apply it again to the resulting totient, and so on, until the +# number 1 is reached, and add together the resulting sequence of numbers; if +# the sum equals n, then n is a perfect totient number. +# +# For example, there are six positive integers less than 9 and relatively +# prime to it, so the totient of 9 is 6; there are two numbers less than 6 and +# relatively prime to it, so the totient of 6 is 2; and there is one number +# less than 2 and relatively prime to it, so the totient of 2 is 1; and 9 = 6 +# + 2 + 1, so 9 is a perfect totient number. +### + +# In number theory, Euler's totient function counts the positive integers up +# to a given integer n that are relatively prime to n. In other words, it is +# the number of integers k in the range 1 ≤ k ≤ n for which the greatest +# common divisor gcd(n, k) is equal to 1. The integers k of this form +# are sometimes referred to as totatives of n. + +# For example, the totatives of n = 9 are the six numbers 1, 2, 4, 5, 7 and 8. +# They are all relatively prime to 9, but the other three numbers in this +# range, 3, 6, and 9 are not, since gcd(9, 3) = gcd(9, 6) = 3 and gcd(9, 9) = +# 9. Therefore, φ(9) = 6. As another example, φ(1) = 1 since for n = 1 the +# only integer in the range from 1 to n is 1 itself, and gcd(1, 1) = 1. + +#============================================================================= + +use v5.36; + + +# The totient function is also known as Euler's phi function, and there is an +# implementation of it in the ntheory (Math::Prime::Util) module. +use Math::Prime::Util qw/euler_phi/; + +use builtin qw/true false/; +no warnings "experimental::builtin"; + +use Getopt::Long; +my $Verbose = 0; +my $DoTest = 0; + +GetOptions("test" => \$DoTest, "verbose" => \$Verbose); +exit(!runTest()) if $DoTest; + +my $count = 0; +my $n = 2; +while ( $count < 20 && $n++ < 10_000 ) +{ + do { $count++, say $n } if isPerfectTotient($n); +} + +sub isPerfectTotient($n) +{ + my $sum = my $totient = euler_phi($n); + until ( $totient == 1 ) + { + $totient = euler_phi($totient); + $sum += $totient; + } + return $sum == $n; +} + +sub runTest +{ + use Test2::V0; + no warnings "experimental::builtin"; + + is( isPerfectTotient( 3), true, "is 3"); + is( isPerfectTotient( 4), false, "is 4"); + is( isPerfectTotient( 9), true, "is 9"); + is( isPerfectTotient( 15), true, "is 15"); + is( isPerfectTotient( 27), true, "is 27"); + is( isPerfectTotient( 39), true, "is 39"); + is( isPerfectTotient( 81), true, "is 81"); + is( isPerfectTotient( 111), true, "is 111"); + is( isPerfectTotient( 183), true, "is 183"); + is( isPerfectTotient( 243), true, "is 243"); + is( isPerfectTotient( 255), true, "is 255"); + is( isPerfectTotient( 327), true, "is 327"); + is( isPerfectTotient( 363), true, "is 363"); + is( isPerfectTotient( 471), true, "is 471"); + is( isPerfectTotient( 729), true, "is 729"); + is( isPerfectTotient(2187), true, "is 2187"); + is( isPerfectTotient(2199), true, "is 2199"); + is( isPerfectTotient(3063), true, "is 3063"); + is( isPerfectTotient(4359), true, "is 4359"); + is( isPerfectTotient(4375), true, "is 4375"); + is( isPerfectTotient(5571), true, "is 5571"); + is( isPerfectTotient(5572), false, "is 5572"); + + done_testing; +} + diff --git a/challenge-208/vamsi-meenavilli/perl/ch-1.pl b/challenge-208/vamsi-meenavilli/perl/ch-1.pl new file mode 100644 index 0000000000..cc53b2c2d8 --- /dev/null +++ b/challenge-208/vamsi-meenavilli/perl/ch-1.pl @@ -0,0 +1,93 @@ +#!/usr/bin/perl +use strict; +use warnings FATAL => 'all'; + +use List::Util qw( max ); +use Test2::V0; + +=head1 AUTHORS + +Vamsi Meenavilli + +=head1 DESCRIPTION + + Week 208: + + Task 1: Minimum Index Sum + Submitted by: Mohammad S Anwar + You are given two arrays of strings. + + Write a script to find out all common strings in the given two arrays with minimum index sum. If no common strings found returns an empty list. + + Example 1 + Input: @list1 = ("Perl", "Raku", "Love") + @list2 = ("Raku", "Perl", "Hate") + + Output: ("Perl", "Raku") + + There are two common strings "Perl" and "Raku". + Index sum of "Perl": 0 + 1 = 1 + Index sum of "Raku": 1 + 0 = 1 + Example 2 + Input: @list1 = ("A", "B", "C") + @list2 = ("D", "E", "F") + + Output: () + + No common string found, so no result. + Example 3 + Input: @list1 = ("A", "B", "C") + @list2 = ("C", "A", "B") + + Output: ("A") + + There are three common strings "A", "B" and "C". + Index sum of "A": 0 + 1 = 1 + Index sum of "B": 1 + 2 = 3 + Index sum of "C": 2 + 0 = 2 + +=cut + +is(MinimumIndexSum(["Perl", "Raku", "Love"], ["Raku", "Perl", "Hate"]), ["Raku", "Perl"], 'Test Case 1.'); +is(MinimumIndexSum(["A", "B", "C"], ["D", "E", "F"]), [], 'Test Case 2.'); +is(MinimumIndexSum(["A", "B", "C"], ["C", "A", "B"]), ["A"], 'Test Case 3.'); + +sub MinimumIndexSum { + my ($list1, $list2) = @_; + + my $list1_size = scalar(@{$list1}); + my $list2_size = scalar(@{$list2}); + + if ($list2 > $list1) { + ($list1, $list2) = ($list2, $list1); + ($list1_size, $list2_size) = ($list2_size, |
