In this article, I will tackle two challenges from the Perl Weekly Challenge #287: strengthening weak passwords and validating numbers. I will provide solutions for both tasks, showcasing implementations in Perl and Go.
The first task is to determine the minimum number of changes needed to make a password strong. The criteria for a strong password are:
#!/usr/bin/perl use strict; use warnings; use List::Util 'max'; # Function to count groups of three or more repeating characters sub count_repeats { my ($str) = @_; my $repeats = 0; # Find repeating characters and count the required changes while ($str =~ /(.)\1{2,}/g) { $repeats += int(length($&) / 3); } return $repeats; } # Function to calculate the minimum steps to create a strong password sub minimum_steps_to_strong_password { my ($str) = @_; my $length = length($str); # Check if the password contains the required character types my $has_lower = $str =~ /[a-z]/; my $has_upper = $str =~ /[A-Z]/; my $has_digit = $str =~ /\d/; # Calculate the number of types needed my $types_needed = !$has_lower + !$has_upper + !$has_digit; my $repeats = count_repeats($str); # Return the minimum steps based on the length of the password return ($length < 6) ? max(6 - $length, $types_needed) : $types_needed + $repeats; } 1;
use strict; use warnings; use Test::More; require "./ch-1.pl"; my @tests = ( ["a", 5], ["aB2", 3], ["PaaSW0rd", 0], ["Paaasw0rd", 1], ["aaaaa", 2], ); foreach my $test (@tests) { my ($input, $expected) = @$test; my $result = minimum_steps_to_strong_password($input); is($result, $expected, "Input: '$input'"); } done_testing();
package main import ( "regexp" ) func countRepeats(password string) int { repeats := 0 count := 1 for i := 1; i < len(password); i++ { if password[i] == password[i-1] { count++ } else { repeats += count / 3 count = 1 } } repeats += count / 3 return repeats } func minimumStepsToStrongPassword(password string) int { length := len(password) // Use regex to check for character types hasLower := regexp.MustCompile(`[a-z]`).MatchString(password) hasUpper := regexp.MustCompile(`[A-Z]`).MatchString(password) hasDigit := regexp.MustCompile(`\d`).MatchString(password) // Calculate the number of types needed typesNeeded := boolToInt(!hasLower) + boolToInt(!hasUpper) + boolToInt(!hasDigit) repeats := countRepeats(password) // Return the minimum steps based on the length of the password if length < 6 { return max(6-length, typesNeeded) } return typesNeeded + repeats } func boolToInt(b bool) int { if b { return 1 } return 0 } func max(a, b int) int { if a > b { return a } return b }
package main import ( "testing" ) func TestMinimumStepsToStrongPassword(t *testing.T) { tests := []struct { password string expected int }{ {"a", 5}, {"aB2", 3}, {"PaaSW0rd", 0}, {"Paaasw0rd", 1}, {"aaaaa", 2}, } for _, test := range tests { result := minimumStepsToStrongPassword(test.password) if result != test.expected { t.Errorf("For password '%s', expected %d but got %d", test.password, test.expected, result) } } }
The second task involves validating numbers. The goal is to determine whether a given string represents a valid number. The criteria for a valid number are:
#!/usr/bin/perl use strict; use warnings; sub is_valid_number { my ($str) = @_; # Regex for valid numbers my $regex = qr{ ^ # Start of the string [+-]? # Optional sign (?: # Start of the number group \d+ # Integer: at least one digit (?: # Start of the optional decimal part \. # Decimal point \d* # Followed by zero or more digits )? # Group is optional | # or \. # Just a decimal point \d+ # Followed by one or more digits ) # End of the number group (?: # Start of the optional exponent group [eE] # 'e' or 'E' [+-]? # Optional sign \d+ # Followed by one or more digits )? # Exponent is optional $ # End of the string }x; # Return 1 for valid, 0 for invalid return $str =~ $regex ? 1 : 0; } 1;
#!/usr/bin/perl use strict; use warnings; use Test::More; require './ch-2.pl'; # Define test cases my @test_cases = ( ["1", 1, 'Valid integer'], ["a", 0, 'Invalid input'], [".", 0, 'Single dot'], ["1.2e4.2", 0, 'Invalid exponent'], ["-1.", 1, 'Valid decimal'], ["+1E-8", 1, 'Valid scientific notation'], [".44", 1, 'Valid decimal starting with dot'], ); # Loop through test cases and run tests foreach my $case (@test_cases) { my $result = is_valid_number($case->[0]); is($result, $case->[1], $case->[2]); } done_testing();
package main import ( "regexp" ) // isValidNumber checks if the given string is a valid number. func isValidNumber(str string) bool { regex := `^[+-]?((\d+(\.\d*)?)|(\.\d+))([eE][+-]?\d+)?$` matched, _ := regexp.MatchString(regex, str) return matched }
package main import ( "testing" ) func TestIsValidNumber(t *testing.T) { testCases := []struct { input string expected bool }{ {"1", true}, {"a", false}, {".", false}, {"1.2e4.2", false}, {"-1.", true}, {"+1E-8", true}, {".44", true}, } for _, tc := range testCases { result := isValidNumber(tc.input) if result != tc.expected { t.Errorf("isValidNumber(%q) = %v; expected %v", tc.input, result, tc.expected) } } }
These solutions provide effective methods for evaluating password strength and validating the correctness of numbers. The complete code for both tasks is available on GitHub.
以上がPerl と Go でのパスワードの強度と番号の検証を調べるの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。