diff options
| author | Mohammad Sajid Anwar <Mohammad.Anwar@yahoo.com> | 2024-09-20 21:41:30 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-20 21:41:30 +0100 |
| commit | 3e17f1ea271e23c7de72df4eb4aea9d7dad3fc30 (patch) | |
| tree | d498bac59295b195cd4dbc0a78d6c971de44d4c2 | |
| parent | 07577d023429c3210d3f25ac142a136f4b773c76 (diff) | |
| parent | ea3681793dbe32012a6d3ea2824b1f59452958eb (diff) | |
| download | perlweeklychallenge-club-3e17f1ea271e23c7de72df4eb4aea9d7dad3fc30.tar.gz perlweeklychallenge-club-3e17f1ea271e23c7de72df4eb4aea9d7dad3fc30.tar.bz2 perlweeklychallenge-club-3e17f1ea271e23c7de72df4eb4aea9d7dad3fc30.zip | |
Merge pull request #10876 from packy/master
Challenge 287 solutions by Packy Anderson
| -rw-r--r-- | challenge-287/packy-anderson/README.md | 2 | ||||
| -rw-r--r-- | challenge-287/packy-anderson/blog.txt | 1 | ||||
| -rwxr-xr-x | challenge-287/packy-anderson/elixir/ch-1.exs | 135 | ||||
| -rwxr-xr-x | challenge-287/packy-anderson/elixir/ch-2.exs | 45 | ||||
| -rwxr-xr-x | challenge-287/packy-anderson/perl/ch-1.pl | 91 | ||||
| -rwxr-xr-x | challenge-287/packy-anderson/perl/ch-2.pl | 49 | ||||
| -rwxr-xr-x | challenge-287/packy-anderson/python/ch-1.py | 87 | ||||
| -rwxr-xr-x | challenge-287/packy-anderson/python/ch-2.py | 53 | ||||
| -rwxr-xr-x | challenge-287/packy-anderson/raku/ch-1.raku | 89 | ||||
| -rwxr-xr-x | challenge-287/packy-anderson/raku/ch-2.raku | 49 |
10 files changed, 600 insertions, 1 deletions
diff --git a/challenge-287/packy-anderson/README.md b/challenge-287/packy-anderson/README.md index 6669e4dd9b..221e5be870 100644 --- a/challenge-287/packy-anderson/README.md +++ b/challenge-287/packy-anderson/README.md @@ -22,4 +22,4 @@ ## Blog Post -[Perl Weekly Challenge: Spammer Game](https://packy.dardan.com/b/R9) +[Perl Weekly Challenge: Strong but Valid](https://packy.dardan.com/b/RU) diff --git a/challenge-287/packy-anderson/blog.txt b/challenge-287/packy-anderson/blog.txt new file mode 100644 index 0000000000..9492dc9875 --- /dev/null +++ b/challenge-287/packy-anderson/blog.txt @@ -0,0 +1 @@ +https://packy.dardan.com/b/RU
\ No newline at end of file diff --git a/challenge-287/packy-anderson/elixir/ch-1.exs b/challenge-287/packy-anderson/elixir/ch-1.exs new file mode 100755 index 0000000000..741d2afeee --- /dev/null +++ b/challenge-287/packy-anderson/elixir/ch-1.exs @@ -0,0 +1,135 @@ +#!/usr/bin/env elixir + +defmodule PWC do + defp countHas(has, data) when has != 0, do: data + + defp countHas(_, data) do + # we need to add a character of this type + data = Map.put(data, :changes, data[:changes]+1) + + if data[:replacements] > 0 do + # if we have characters that need to be REPLACED, + # we don't need to add to the string length to + # make the change + Map.put(data, :replacements, data[:replacements]-1) + else + # we need to add characters to make the change + Map.put(data, :length, data[:length]+1) + end + end + + defp putIf(map, condition, _, _) when not condition, + do: map + + defp putIf(map, _, key, value) do + Map.put(map, key, value) + end + + def strongPassword(str) do + data = %{ + hasUpper: 0, + hasLower: 0, + hasDigit: 0, + runs: [] + } + + chars = String.graphemes(str) + + {_, data} = + Enum.map_reduce(chars, data, fn char, data -> + # identify runs of characters + runs = data[:runs] + runs = cond do + # we have no previous run of characters, or the last + # character of the last run doesn't match this character + length(runs) == 0 + or + List.last(runs) |> String.last != char -> + runs ++ [ char ] + + # append the latest character to the run + true -> + List.replace_at(runs, -1, List.last(runs) <> char) + end + + # put the runs back in the data map + data = Map.put(data, :runs, runs) + + # count the character classes we're interested in + # and return the data map to Enum.map_reduce/3 + { + char, + cond do + Regex.match?(~r/\p{Lu}/u, char) -> + Map.put(data, :hasUpper, data[:hasUpper]+1) + Regex.match?(~r/\p{Ll}/u, char) -> + Map.put(data, :hasLower, data[:hasLower]+1) + Regex.match?(~r/\p{N}/u, char) -> + Map.put(data, :hasDigit, data[:hasDigit]+1) + end + } + end) + + # count how many characters need to be REPLACED + {_, replacements} = + Enum.map_reduce(data[:runs], 0, fn run, replacements -> + { + run, + if String.length(run) >= 3 do + replacements + trunc(String.length(run) / 3) + else + replacements + end + } + end) + + # store some more stuff in our data map + data = data + |> Map.put(:changes, 0) + |> Map.put(:length, String.length(str)) + |> Map.put(:replacements, replacements) + + hasList = [ + data[:hasUpper], data[:hasLower], data[:hasDigit] + ] + + # figure out how many changes are needed + {_, data} = + Enum.map_reduce(hasList, data, fn has, data -> + { has, countHas(has, data) } + end) + + data + |> putIf(data[:length] < 6, :changes, + data[:changes] + 6 - data[:length] ) + |> putIf(data[:replacements] > 0, :changes, + data[:changes] + data[:replacements]) + |> Map.get(:changes) + end + + def solution(str) do + IO.puts("Input: $str = \"#{str}\"") + IO.puts("Output: #{strongPassword(str)}") + end +end + +IO.puts("Example 1:") +PWC.solution("a") + +IO.puts("\nExample 2:") +PWC.solution("aB2") + +IO.puts("\nExample 3:") +PWC.solution("PaaSW0rd") + +IO.puts("\nExample 4:") +PWC.solution("Paaasw0rd") + +IO.puts("\nExample 5:") +PWC.solution("aaaaa") + +IO.puts("\nExample 6:") +PWC.solution("aaaaaabbbb") + +IO.puts("\nExample 7:") +PWC.solution("voilÀ३") diff --git a/challenge-287/packy-anderson/elixir/ch-2.exs b/challenge-287/packy-anderson/elixir/ch-2.exs new file mode 100755 index 0000000000..1e0e309a27 --- /dev/null +++ b/challenge-287/packy-anderson/elixir/ch-2.exs @@ -0,0 +1,45 @@ +#!/usr/bin/env elixir + +defmodule PWC do + def top() do + ~r/ + ^ + (?: + [+-]? \p{N}+ (?: [eE] (?: [+-]? \p{N}+ ) )? + | + [+-]? (?: \p{N}+ \. | \p{N}+ \. \p{N}+ | \. \p{N}+ ) + (?: [eE] (?: [+-]? \p{N}+ ) )? + ) + $ + /ux + end + + def solution(str) do + IO.puts("Input: $str = \"#{str}\"") + IO.puts("Output: #{ String.match?(str, top()) }") + end +end + +IO.puts("Example 1:") +PWC.solution("1") + +IO.puts("\nExample 2:") +PWC.solution("a") + +IO.puts("\nExample 3:") +PWC.solution(".") + +IO.puts("\nExample 4:") +PWC.solution("1.2e4.2") + +IO.puts("\nExample 5:") +PWC.solution("-1.") + +IO.puts("\nExample 6:") +PWC.solution("+1E-8") + +IO.puts("\nExample 7:") +PWC.solution(".44") + +IO.puts("\nExample 8:") +PWC.solution("-३.१") diff --git a/challenge-287/packy-anderson/perl/ch-1.pl b/challenge-287/packy-anderson/perl/ch-1.pl new file mode 100755 index 0000000000..75e3f41ea0 --- /dev/null +++ b/challenge-287/packy-anderson/perl/ch-1.pl @@ -0,0 +1,91 @@ +#!/usr/bin/env perl +use v5.40; +use utf8; +binmode STDOUT, ':utf8'; + +sub strongPassword($str) { + my ($hasUpper, $hasLower, $hasDigit, @runs) = (0, 0, 0); + + foreach my $char ( split //, $str ) { + # identify runs of characters + if (@runs == 0 || substr($runs[-1],-1,1) ne $char) { + # we have no previous run of characters, or the last + # character of the last run doesn't match this character + push @runs, $char; + } + else { + # append the latest character to the run + $runs[-1] .= $char; + } + + # count the character classes we're interested in + if ($char =~ /\p{Lu}/) { $hasUpper++ } + elsif ($char =~ /\p{Ll}/) { $hasLower++ } + elsif ($char =~ /\p{N}/) { $hasDigit++ } + } + + # count how many characters need to be REPLACED + my $replacements = 0; + foreach my $run ( @runs ) { + # the run isn't 3 or more characters + next unless length($run) >= 3; + # we need one replacement per multiple of 3 + $replacements += int(length($run) / 3); + } + + # figure out how many changes are needed + my $changes = 0; + my $length = length($str); + + foreach my $has ($hasUpper, $hasLower, $hasDigit) { + if ($has == 0) { + $changes++; # we need to add a character of this type + + # if we have characters that need to be REPLACED, we don't + # need to add to the string length to make the change + if ($replacements > 0) { + $replacements--; + } + else { + # we need to add characters to make the change + $length++; + } + } + } + if ($length < 6) { + # not enough characters, we need MORE! + $changes += 6 - $length; + } + if ($replacements > 0) { + # if we need more replacements, add them to the total + $changes += $replacements; + } + + return $changes; +} + +sub solution($str) { + say qq{Input: \$str = "$str"}; + say 'Output: ' . strongPassword($str); +} + +say "Example 1:"; +solution("a"); + +say "\nExample 2:"; +solution("aB2"); + +say "\nExample 3:"; +solution("PaaSW0rd"); + +say "\nExample 4:"; +solution("Paaasw0rd"); + +say "\nExample 5:"; +solution("aaaaa"); + +say "\nExample 6:"; +solution("aaaaaabbbb"); + +say "\nExample 7:"; +solution("voilÀ३"); diff --git a/challenge-287/packy-anderson/perl/ch-2.pl b/challenge-287/packy-anderson/perl/ch-2.pl new file mode 100755 index 0000000000..ee2c005ec8 --- /dev/null +++ b/challenge-287/packy-anderson/perl/ch-2.pl @@ -0,0 +1,49 @@ +#!/usr/bin/env perl +use v5.40; +use utf8; +binmode STDOUT, ':utf8'; + +my $sign = qr/ [+\-] /x; + +my $digits = qr/ \d+ /x; + +my $integerNumber = qr/ $sign? $digits /x; + +my $decimalNumber = qr/ + $sign? (?: $digits\. | $digits\.$digits | \.$digits) +/x; + +my $exponent = qr/(?: [eE] $integerNumber )/x; + +my $TOP = qr/ + ^ (?: $integerNumber$exponent? | $decimalNumber$exponent? ) $ +/x; + +sub solution($str) { + say qq{Input: \$str = "$str"}; + say 'Output: ' . ($str =~ /$TOP/ ? 'True' : 'False'); +} + +say "Example 1:"; +solution("1"); + +say "\nExample 2:"; +solution("a"); + +say "\nExample 3:"; +solution("."); + +say "\nExample 4:"; +solution("1.2e4.2"); + +say "\nExample 5:"; +solution("-1."); + +say "\nExample 6:"; +solution("+1E-8"); + +say "\nExample 7:"; +solution(".44"); + +say "\nExample 8:"; +solution("-३.१")
\ No newline at end of file diff --git a/challenge-287/packy-anderson/python/ch-1.py b/challenge-287/packy-anderson/python/ch-1.py new file mode 100755 index 0000000000..f6f70a80c7 --- /dev/null +++ b/challenge-287/packy-anderson/python/ch-1.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python + +import regex + +def strongPassword(str): + hasUpper = 0 + hasLower = 0 + hasDigit = 0 + runs = [] + + for char in str: + # identify runs of characters + if len(runs) == 0 or runs[-1][-1] != char: + # we have no previous run of characters, or the last + # character of the last run doesn't match this character + runs.append(char) + else: + # append the latest character to the run + runs[-1] += char + + # count the character classes we're interested in + if regex.match(r"\p{Lu}", char): + hasUpper += 1 + elif regex.match(r"\p{Ll}", char): + hasLower += 1 + elif regex.match(r"\p{N}", char): + hasDigit += 1 + + # count how many characters need to be REPLACED + replacements = 0 + for run in runs: + # if the run is 3 or more characters + if len(run) >= 3: + # we need one replacement per multiple of 3 + replacements += int(len(run) / 3) + + # figure out how many changes are needed + changes = 0 + length = len(str) + + for has in [hasUpper, hasLower, hasDigit]: + if has == 0: + changes += 1 # we need to add a character of this type + + # if we have characters that need to be REPLACED, we don't + # need to add to the string length to make the change + if replacements > 0: + replacements -= 1 + else: + # we need to add characters to make the change + length += 1 + + if length < 6: + # not enough characters, we need MORE! + changes += 6 - length + + if replacements > 0: + # if we need more replacements, add them to the total + changes += replacements + + return changes + + +def solution(str): + print(f'Input: $str = "{str}"') + print(f'Output: {strongPassword(str)}') + +print('Example 1:') +solution("a") + +print('\nExample 2:') +solution("aB2") + +print('\nExample 3:') +solution("PaaSW0rd") + +print('\nExample 4:') +solution("Paaasw0rd") + +print('\nExample 5:') +solution("aaaaa") + +print('\nExample 6:') +solution("aaaaaabbbb") + +print('\nExample 7:') +solution("voilÀ३") diff --git a/challenge-287/packy-anderson/python/ch-2.py b/challenge-287/packy-anderson/python/ch-2.py new file mode 100755 index 0000000000..7a21d88a20 --- /dev/null +++ b/challenge-287/packy-anderson/python/ch-2.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +import re + +sign = r'[+\-]' + +digits = r'\d+' + +integerNumber = fr' {sign}? {digits} ' + +decimalNumber = fr""" + {sign}? (?: {digits}\. | {digits}\.{digits} | \.{digits} ) +""" + +exponent = fr'(?:[eE]{integerNumber})' + +TOP = re.compile(fr""" + ^ (?: + {integerNumber}{exponent}? | + {decimalNumber}{exponent}? + ) $ + """, + re.VERBOSE +) + +def solution(str): + print(f'Input: $str = "{str}"') + match = True if re.search(TOP, str) else False + print(f'Output: {match}') + +print('Example 1:') +solution("1") + +print('\nExample 2:') +solution("a") + +print('\nExample 3:') +solution(".") + +print('\nExample 4:') +solution("1.2e4.2") + +print('\nExample 5:') +solution("-1.") + +print('\nExample 6:') +solution("+1E-8") + +print('\nExample 7:') +solution(".44") + +print('\nExample 8:') +solution("-३.१") diff --git a/challenge-287/packy-anderson/raku/ch-1.raku b/challenge-287/packy-anderson/raku/ch-1.raku new file mode 100755 index 0000000000..e7d743eabc --- /dev/null +++ b/challenge-287/packy-anderson/raku/ch-1.raku @@ -0,0 +1,89 @@ +#!/usr/bin/env raku +use v6; + +sub strongPassword($str) { + my ($hasUpper, $hasLower, $hasDigit, @runs) = (0, 0, 0); + + for $str.comb -> $char { + # identify runs of characters + if (@runs == 0 || @runs[*-1].substr(*-1,1) ne $char) { + # we have no previous run of characters, or the last + # character of the last run doesn't match this character + @runs.push($char); + } + else { + # append the latest character to the run + @runs[*-1] ~= $char; + } + + # count the character classes we're interested in + if ($char ~~ / <:Lu> /) { $hasUpper++ } + elsif ($char ~~ / <:Ll> /) { $hasLower++ } + elsif ($char ~~ / <:N> /) { $hasDigit++ } + } + + # count how many characters need to be REPLACED + my $replacements = 0; + for @runs -> $run { + # the run isn't 3 or more characters + next unless $run.chars >= 3; + # we need one replacement per multiple of 3 + $replacements += ($run.chars / 3).Int; + } + + # figure out how many changes are needed + my $changes = 0; + my $length = $str.chars; + + for [$hasUpper, $hasLower, $hasDigit] -> $has { + if ($has == 0) { + $changes++; # we need to add a character of this type + + # if we have characters that need to be REPLACED, we don't + # need to add to the string length to make the change + if ($replacements > 0) { + $replacements--; + } + else { + # we need to add characters to make the change + $length++; + } + } + } + if ($length < 6) { + # not enough characters, we need MORE! + $changes += 6 - $length; + } + if ($replacements > 0) { + # if we need more replacements, add them to the total + $changes += $replacements; + } + + return $changes; +} + +sub solution($str) { + say qq{Input: \$str = "$str"}; + say 'Output: ' ~ strongPassword($str); +} + +say "Example 1:"; +solution("a"); + +say "\nExample 2:"; +solution("aB2"); + +say "\nExample 3:"; +solution("PaaSW0rd"); + +say "\nExample 4:"; +solution("Paaasw0rd"); + +say "\nExample 5:"; +solution("aaaaa"); + +say "\nExample 6:"; +solution("aaaaaabbbb"); + +say "\nExample 7:"; +solution("voilÀ३"); diff --git a/challenge-287/packy-anderson/raku/ch-2.raku b/challenge-287/packy-anderson/raku/ch-2.raku new file mode 100755 index 0000000000..9fcfac737b --- /dev/null +++ b/challenge-287/packy-anderson/raku/ch-2.raku @@ -0,0 +1,49 @@ +#!/usr/bin/env raku +use v6; + +grammar IsNumber { + rule TOP { [ + <integerNumber><exponent>? | <decimalNumber><exponent>? + ] } + + token sign { <[ + \- ]> } + + token digits { \d+ } + + token integerNumber { <sign>? <digits> } + + token decimalNumber { + <sign>? [ <digits> '.' | <digits> '.' <digits> | '.' <digits> ] + } + + token exponent { [ "e" | "E" ] <integerNumber> } +} + +sub solution($str) { + say qq{Input: \$str = "$str"}; + say 'Output: ' ~ (IsNumber.parse($str) ?? True !! False); +} + +say "Example 1:"; +solution("1"); + +say "\nExample 2:"; +solution("a"); + +say "\nExample 3:"; +solution("."); + +say "\nExample 4:"; +solution("1.2e4.2"); + +say "\nExample 5:"; +solution("-1."); + +say "\nExample 6:"; +solution("+1E-8"); + +say "\nExample 7:"; +solution(".44"); + +say "\nExample 8:"; +solution("-३.१")
\ No newline at end of file |
