aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-287/aplgr/.gitignore1
-rw-r--r--challenge-287/aplgr/README1
-rw-r--r--challenge-287/aplgr/blog.txt1
-rw-r--r--challenge-287/aplgr/go/ch-1.go56
-rw-r--r--challenge-287/aplgr/go/ch-1_test.go25
-rw-r--r--challenge-287/aplgr/go/ch-2.go12
-rw-r--r--challenge-287/aplgr/go/ch-2_test.go27
-rw-r--r--challenge-287/aplgr/perl/ch-1.pl37
-rw-r--r--challenge-287/aplgr/perl/ch-1.t20
-rw-r--r--challenge-287/aplgr/perl/ch-2.pl34
-rw-r--r--challenge-287/aplgr/perl/ch-2.t25
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();