From 2efac178f2b76e3afa2f45e91e288469805ab1b1 Mon Sep 17 00:00:00 2001 From: Lubos Kolouch Date: Mon, 16 Sep 2024 09:52:28 +0200 Subject: Challenge 287 LK Perl Python --- challenge-287/lubos-kolouch/perl/ch-1.pl | 71 +++++++++++++++++++++++++++ challenge-287/lubos-kolouch/perl/ch-2.pl | 79 ++++++++++++++++++++++++++++++ challenge-287/lubos-kolouch/python/ch-1.py | 59 ++++++++++++++++++++++ challenge-287/lubos-kolouch/python/ch-2.py | 75 ++++++++++++++++++++++++++++ 4 files changed, 284 insertions(+) create mode 100644 challenge-287/lubos-kolouch/perl/ch-1.pl create mode 100644 challenge-287/lubos-kolouch/perl/ch-2.pl create mode 100644 challenge-287/lubos-kolouch/python/ch-1.py create mode 100644 challenge-287/lubos-kolouch/python/ch-2.py diff --git a/challenge-287/lubos-kolouch/perl/ch-1.pl b/challenge-287/lubos-kolouch/perl/ch-1.pl new file mode 100644 index 0000000000..f79b745639 --- /dev/null +++ b/challenge-287/lubos-kolouch/perl/ch-1.pl @@ -0,0 +1,71 @@ +#!/usr/bin/perl +use strict; +use warnings; +use Test::More tests => 5; + +=pod + +=head1 DESCRIPTION + +This script determines the minimum number of steps required to make a given string a strong password based on the following criteria: + +- At least 6 characters long. +- Contains at least one lowercase letter, one uppercase letter, and one digit. +- Does not contain three repeating characters in a row. + +=head1 FUNCTIONS + +=head2 strong_password_steps($s) + +Calculates the minimum number of steps required to make the string a strong password. + +=over 4 + +=item * C<$s> - The input string. + +=back + +Returns the minimum number of steps as an integer. + +=cut + +sub strong_password_steps { + my ($s) = @_; + my $missing_types = 3; + $missing_types-- if $s =~ /[a-z]/; + $missing_types-- if $s =~ /[A-Z]/; + $missing_types-- if $s =~ /\d/; + + my $repeats_to_fix = 0; + my $i = 2; + my $n = length($s); + while ($i < $n) { + if (substr($s, $i, 1) eq substr($s, $i - 1, 1) and substr($s, $i - 1, 1) eq substr($s, $i - 2, 1)) { + my $repeat_len = 3; + while ($i + 1 < $n and substr($s, $i + 1, 1) eq substr($s, $i, 1)) { + $repeat_len++; + $i++; + } + $repeats_to_fix += int($repeat_len / 3); + } + $i++; + } + + my $total_steps; + if ($n >= 6) { + $total_steps = ($missing_types > $repeats_to_fix) ? $missing_types : $repeats_to_fix; + } else { + my $insertions_needed = 6 - $n; + my $sum = $missing_types + $repeats_to_fix; + $total_steps = ($sum > $insertions_needed) ? $sum : $insertions_needed; + } + return $total_steps; +} + +# Tests +is(strong_password_steps("a"), 5, 'Example 1'); +is(strong_password_steps("aB2"), 3, 'Example 2'); +is(strong_password_steps("PaaSW0rd"), 0, 'Example 3'); +is(strong_password_steps("Paaasw0rd"), 1, 'Example 4'); +is(strong_password_steps("aaaaa"), 3, 'Example 5'); + diff --git a/challenge-287/lubos-kolouch/perl/ch-2.pl b/challenge-287/lubos-kolouch/perl/ch-2.pl new file mode 100644 index 0000000000..f72e9cb595 --- /dev/null +++ b/challenge-287/lubos-kolouch/perl/ch-2.pl @@ -0,0 +1,79 @@ +#!/usr/bin/perl +use strict; +use warnings; +use Test::More tests => 7; + +=pod + +=head1 DESCRIPTION + +This script determines if the given string is a valid number based on specific rules. + +A valid number is defined as: + +- An integer number followed by an optional exponent. +- A decimal number followed by an optional exponent. + +An integer number is defined with an optional sign '-' or '+' followed by digits. + +=head1 DEFINITIONS + +=head2 Decimal Number + +A decimal number is defined with an optional sign '-' or '+' followed by one of the following: + +- Digits followed by a dot '.'. +- Digits followed by a dot '.' followed by digits. +- A dot '.' followed by digits. + +=head2 Exponent + +An exponent is defined with an exponent notation 'e' or 'E' followed by an integer number. + +=head1 FUNCTIONS + +=head2 is_valid_number($s) + +Determines if the given string is a valid number. + +=over 4 + +=item * C<$s> - The input string. + +=back + +Returns 1 if valid, 0 otherwise. + +=cut + +sub is_valid_number { + my ($s) = @_; + my $pattern = qr/ + ^ # Start of string + [+-]? # Optional sign + ( + ( # Decimal numbers + \d+\.\d* # Digits followed by dot and optional digits + | + \.\d+ # Dot followed by digits + | + \d+\. # Digits followed by dot + ) + | + \d+ # Integer numbers + ) + ([eE][+-]?\d+)? # Optional exponent + $ # End of string + /x; + return $s =~ $pattern ? 1 : 0; +} + +# Unit Tests +is(is_valid_number("1"), 1, 'Example 1'); +is(is_valid_number("a"), 0, 'Example 2'); +is(is_valid_number("."), 0, 'Example 3'); +is(is_valid_number("1.2e4.2"),0, 'Example 4'); +is(is_valid_number("-1."), 1, 'Example 5'); +is(is_valid_number("+1E-8"), 1, 'Example 6'); +is(is_valid_number(".44"), 1, 'Example 7'); + diff --git a/challenge-287/lubos-kolouch/python/ch-1.py b/challenge-287/lubos-kolouch/python/ch-1.py new file mode 100644 index 0000000000..9593c70beb --- /dev/null +++ b/challenge-287/lubos-kolouch/python/ch-1.py @@ -0,0 +1,59 @@ +import unittest + + +def strong_password_steps(s: str) -> int: + """ + Calculates the minimum number of steps required to make the given string a strong password. + + A strong password must: + - Be at least 6 characters long. + - Contain at least one lowercase letter, one uppercase letter, and one digit. + - Not contain three repeating characters in a row. + + Args: + s (str): The input password string. + + Returns: + int: The minimum number of steps required to make the password strong. + """ + import re + missing_types = 3 + if re.search(r'[a-z]', s): + missing_types -= 1 + if re.search(r'[A-Z]', s): + missing_types -= 1 + if re.search(r'\d', s): + missing_types -= 1 + + repeats_to_fix = 0 + i = 2 + n = len(s) + while i < n: + if s[i] == s[i - 1] == s[i - 2]: + repeat_len = 3 + while i + 1 < n and s[i + 1] == s[i]: + repeat_len += 1 + i += 1 + repeats_to_fix += repeat_len // 3 + i += 1 + + if n >= 6: + total_steps = max(missing_types, repeats_to_fix) + else: + total_steps = max(missing_types + repeats_to_fix, 6 - n) + return total_steps + + +# Unit Tests +class TestStrongPassword(unittest.TestCase): + + def test_examples(self): + self.assertEqual(strong_password_steps("a"), 5, 'Example 1') + self.assertEqual(strong_password_steps("aB2"), 3, 'Example 2') + self.assertEqual(strong_password_steps("PaaSW0rd"), 0, 'Example 3') + self.assertEqual(strong_password_steps("Paaasw0rd"), 1, 'Example 4') + self.assertEqual(strong_password_steps("aaaaa"), 3, 'Example 5') + + +if __name__ == "__main__": + unittest.main() diff --git a/challenge-287/lubos-kolouch/python/ch-2.py b/challenge-287/lubos-kolouch/python/ch-2.py new file mode 100644 index 0000000000..f302b7360a --- /dev/null +++ b/challenge-287/lubos-kolouch/python/ch-2.py @@ -0,0 +1,75 @@ +import re +from typing import Any +import unittest + + +def is_valid_number(s: str) -> bool: + """ + Determines if the given string is a valid number based on specific rules. + + A valid number is defined as: + - An integer number followed by an optional exponent. + - A decimal number followed by an optional exponent. + + An integer number is defined with an optional sign '-' or '+' followed by digits. + + Decimal Number: + - An optional sign '-' or '+' followed by one of the following: + - Digits followed by a dot '.'. + - Digits followed by a dot '.' followed by digits. + - A dot '.' followed by digits. + + Exponent: + - An exponent is defined with an exponent notation 'e' or 'E' followed by an integer number. + + Args: + s (str): The input string. + + Returns: + bool: True if the string is a valid number, False otherwise. + """ + pattern = r""" + ^ # Start of string + [+-]? # Optional sign + ( + ( # Decimal numbers + \d+\.\d* # Digits followed by dot and optional digits + | + \.\d+ # Dot followed by digits + | + \d+\. # Digits followed by dot + ) + | + \d+ # Integer numbers + ) + ([eE][+-]?\d+)? # Optional exponent + $ # End of string + """ + regex = re.compile(pattern, re.VERBOSE) + return bool(regex.match(s)) + + +# Unit Tests +class TestValidNumber(unittest.TestCase): + + def test_examples(self): + self.assertEqual(is_valid_number("1"), True, 'Example 1') + self.assertEqual(is_valid_number("a"), False, 'Example 2') + self.assertEqual(is_valid_number("."), False, 'Example 3') + self.assertEqual(is_valid_number("1.2e4.2"), False, 'Example 4') + self.assertEqual(is_valid_number("-1."), True, 'Example 5') + self.assertEqual(is_valid_number("+1E-8"), True, 'Example 6') + self.assertEqual(is_valid_number(".44"), True, 'Example 7') + + def test_additional(self): + self.assertEqual(is_valid_number("6e6.5"), False, + 'Exponent with decimal') + self.assertEqual(is_valid_number(""), False, 'Empty string') + self.assertEqual(is_valid_number("123"), True, 'Integer number') + self.assertEqual(is_valid_number("-."), False, + 'Negative dot without digits') + self.assertEqual(is_valid_number("1e"), False, 'Incomplete exponent') + + +if __name__ == "__main__": + unittest.main() -- cgit