Home >Backend Development >Golang >Exploring Password Strength and Number Validation in Perl and Go
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.
The above is the detailed content of Exploring Password Strength and Number Validation in Perl and Go. For more information, please follow other related articles on the PHP Chinese website!