aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2024-09-20 21:41:30 +0100
committerGitHub <noreply@github.com>2024-09-20 21:41:30 +0100
commit3e17f1ea271e23c7de72df4eb4aea9d7dad3fc30 (patch)
treed498bac59295b195cd4dbc0a78d6c971de44d4c2
parent07577d023429c3210d3f25ac142a136f4b773c76 (diff)
parentea3681793dbe32012a6d3ea2824b1f59452958eb (diff)
downloadperlweeklychallenge-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.md2
-rw-r--r--challenge-287/packy-anderson/blog.txt1
-rwxr-xr-xchallenge-287/packy-anderson/elixir/ch-1.exs135
-rwxr-xr-xchallenge-287/packy-anderson/elixir/ch-2.exs45
-rwxr-xr-xchallenge-287/packy-anderson/perl/ch-1.pl91
-rwxr-xr-xchallenge-287/packy-anderson/perl/ch-2.pl49
-rwxr-xr-xchallenge-287/packy-anderson/python/ch-1.py87
-rwxr-xr-xchallenge-287/packy-anderson/python/ch-2.py53
-rwxr-xr-xchallenge-287/packy-anderson/raku/ch-1.raku89
-rwxr-xr-xchallenge-287/packy-anderson/raku/ch-2.raku49
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