diff options
| -rw-r--r-- | challenge-287/aplgr/.gitignore | 1 | ||||
| -rw-r--r-- | challenge-287/aplgr/README | 1 | ||||
| -rw-r--r-- | challenge-287/aplgr/blog.txt | 1 | ||||
| -rw-r--r-- | challenge-287/aplgr/go/ch-1.go | 56 | ||||
| -rw-r--r-- | challenge-287/aplgr/go/ch-1_test.go | 25 | ||||
| -rw-r--r-- | challenge-287/aplgr/go/ch-2.go | 12 | ||||
| -rw-r--r-- | challenge-287/aplgr/go/ch-2_test.go | 27 | ||||
| -rw-r--r-- | challenge-287/aplgr/perl/ch-1.pl | 37 | ||||
| -rw-r--r-- | challenge-287/aplgr/perl/ch-1.t | 20 | ||||
| -rw-r--r-- | challenge-287/aplgr/perl/ch-2.pl | 34 | ||||
| -rw-r--r-- | challenge-287/aplgr/perl/ch-2.t | 25 |
11 files changed, 239 insertions, 0 deletions
diff --git a/challenge-287/aplgr/.gitignore b/challenge-287/aplgr/.gitignore new file mode 100644 index 0000000000..780010228f --- /dev/null +++ b/challenge-287/aplgr/.gitignore @@ -0,0 +1 @@ +go.mod
\ No newline at end of file diff --git a/challenge-287/aplgr/README b/challenge-287/aplgr/README new file mode 100644 index 0000000000..5bd6a6b0cb --- /dev/null +++ b/challenge-287/aplgr/README @@ -0,0 +1 @@ +Solution by André Plöger. diff --git a/challenge-287/aplgr/blog.txt b/challenge-287/aplgr/blog.txt new file mode 100644 index 0000000000..bd05da501f --- /dev/null +++ b/challenge-287/aplgr/blog.txt @@ -0,0 +1 @@ +https://dev.to/aplgr/exploring-password-strength-and-number-validation-in-perl-and-go-529p
\ No newline at end of file diff --git a/challenge-287/aplgr/go/ch-1.go b/challenge-287/aplgr/go/ch-1.go new file mode 100644 index 0000000000..fcdf370d5b --- /dev/null +++ b/challenge-287/aplgr/go/ch-1.go @@ -0,0 +1,56 @@ +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 +} diff --git a/challenge-287/aplgr/go/ch-1_test.go b/challenge-287/aplgr/go/ch-1_test.go new file mode 100644 index 0000000000..8139b0a5cd --- /dev/null +++ b/challenge-287/aplgr/go/ch-1_test.go @@ -0,0 +1,25 @@ +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) + } + } +} diff --git a/challenge-287/aplgr/go/ch-2.go b/challenge-287/aplgr/go/ch-2.go new file mode 100644 index 0000000000..91b1aa0917 --- /dev/null +++ b/challenge-287/aplgr/go/ch-2.go @@ -0,0 +1,12 @@ +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 +} diff --git a/challenge-287/aplgr/go/ch-2_test.go b/challenge-287/aplgr/go/ch-2_test.go new file mode 100644 index 0000000000..fde09eeb16 --- /dev/null +++ b/challenge-287/aplgr/go/ch-2_test.go @@ -0,0 +1,27 @@ +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) + } + } +} diff --git a/challenge-287/aplgr/perl/ch-1.pl b/challenge-287/aplgr/perl/ch-1.pl new file mode 100644 index 0000000000..d03cb04c3a --- /dev/null +++ b/challenge-287/aplgr/perl/ch-1.pl @@ -0,0 +1,37 @@ +#!/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; diff --git a/challenge-287/aplgr/perl/ch-1.t b/challenge-287/aplgr/perl/ch-1.t new file mode 100644 index 0000000000..40a36948c9 --- /dev/null +++ b/challenge-287/aplgr/perl/ch-1.t @@ -0,0 +1,20 @@ +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(); diff --git a/challenge-287/aplgr/perl/ch-2.pl b/challenge-287/aplgr/perl/ch-2.pl new file mode 100644 index 0000000000..6e715effd1 --- /dev/null +++ b/challenge-287/aplgr/perl/ch-2.pl @@ -0,0 +1,34 @@ +#!/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;
\ No newline at end of file diff --git a/challenge-287/aplgr/perl/ch-2.t b/challenge-287/aplgr/perl/ch-2.t new file mode 100644 index 0000000000..52f219f588 --- /dev/null +++ b/challenge-287/aplgr/perl/ch-2.t @@ -0,0 +1,25 @@ +#!/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(); |
