diff options
| author | Jörg Sommrey <28217714+jo-37@users.noreply.github.com> | 2021-02-10 08:01:13 +0100 |
|---|---|---|
| committer | Jörg Sommrey <28217714+jo-37@users.noreply.github.com> | 2021-02-10 08:01:13 +0100 |
| commit | 80405987586c08463eb9807a47a30aedf70304fd (patch) | |
| tree | 9011a406d5f76ad1691718898c1991de53d96560 /challenge-099 | |
| parent | 61c0f26bb7721579308a879449efe6b45a4c7451 (diff) | |
| parent | 764ae14f048a05b24215e12758b4ba2841afd53a (diff) | |
| download | perlweeklychallenge-club-80405987586c08463eb9807a47a30aedf70304fd.tar.gz perlweeklychallenge-club-80405987586c08463eb9807a47a30aedf70304fd.tar.bz2 perlweeklychallenge-club-80405987586c08463eb9807a47a30aedf70304fd.zip | |
Merge branch 'master' into contrib
Diffstat (limited to 'challenge-099')
44 files changed, 1056 insertions, 2 deletions
diff --git a/challenge-099/e-choroba/perl/ch-1.pl b/challenge-099/e-choroba/perl/ch-1.pl new file mode 100755 index 0000000000..46a0adc6e0 --- /dev/null +++ b/challenge-099/e-choroba/perl/ch-1.pl @@ -0,0 +1,22 @@ +#!/usr/bin/perl +use warnings; +use strict; + +sub pattern_match { + my ($string, $pattern) = @_; + $pattern = quotemeta $pattern; + s/\\\?/./g, s/\\\*/.*/g for $pattern; + return $string =~ /^$pattern$/ ? 1 : 0 +} + +use Test::More tests => 8; + +is pattern_match('abcde', 'a*e'), 1, 'Example 1'; +is pattern_match('abcde', 'a*d'), 0, 'Example 2'; +is pattern_match('abcde', '?b*d'), 0, 'Example 3'; +is pattern_match('abcde', 'a*c?e'), 1, 'Example 4'; + +is pattern_match('abcde', 'a*'), 1, 'Trailing star'; +is pattern_match('abcde', '*de'), 1, 'Leading star'; +is pattern_match('abcde', 'a*c*e'), 1, 'Two stars'; +is pattern_match('(a!)b{c}$1d', '(?!)b{?}$1*'), 1, 'No injection'; diff --git a/challenge-099/e-choroba/perl/ch-1a.pl b/challenge-099/e-choroba/perl/ch-1a.pl new file mode 100755 index 0000000000..ffd3e6075e --- /dev/null +++ b/challenge-099/e-choroba/perl/ch-1a.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl +use warnings; +use strict; + +sub pattern_match { + my ($string, $pattern) = @_; + return 1 if "" eq $string . $pattern; + + my ($string_first, $string_rest) = $string =~ /(.)(.*)/; + my ($pattern_first, $pattern_rest) = $pattern =~ /(.)(.*)/; + + my $action = { + '?' => sub { + return 0 unless length $pattern; + return pattern_match($string_rest, $pattern_rest) + }, + '*' => sub { + for my $pos (1 .. length $string) { + return 1 + if pattern_match(substr($string, $pos), $pattern_rest); + } + return 0 + }, + }->{ $pattern_first // "" } || sub { + return 0 if ($pattern_first // "") ne ($string_first // ""); + + return pattern_match($string_rest, $pattern_rest) + }; + return $action->() +} + +use Test::More tests => 8; + +is pattern_match('abcde', 'a*e'), 1, 'Example 1'; +is pattern_match('abcde', 'a*d'), 0, 'Example 2'; +is pattern_match('abcde', '?b*d'), 0, 'Example 3'; +is pattern_match('abcde', 'a*c?e'), 1, 'Example 4'; + +is pattern_match('abcde', 'a*'), 1, 'Trailing star'; +is pattern_match('abcde', '*de'), 1, 'Leading star'; +is pattern_match('abcde', 'a*c*e'), 1, 'Two stars'; +is pattern_match('(a!)b{c}$1d', '(?!)b{?}$1*'), 1, 'Random garbage'; diff --git a/challenge-099/e-choroba/perl/ch-2.pl b/challenge-099/e-choroba/perl/ch-2.pl new file mode 100755 index 0000000000..d32a396c8d --- /dev/null +++ b/challenge-099/e-choroba/perl/ch-2.pl @@ -0,0 +1,53 @@ +#!/usr/bin/perl +use warnings; +use strict; + +# Count the subsequences. +sub unique_subsequence { + my ($string, $subsequence) = @_; + if (1 == length $subsequence) { + my $count = () = $string =~ /\Q$subsequence/g; + return $count + } + my $char = substr $subsequence, 0, 1, ""; + my ($count, $pos) = (0, 0); + $count += unique_subsequence(substr($string, $pos++), $subsequence) + while -1 != ($pos = index $string, $char, $pos); + return $count +} + +# Return all the possible positions that match the subsequence. +sub show_unique_subsequence { + my ($string, $subsequence) = @_; + my @solutions; + for my $sub_pos (0 .. length($subsequence) - 1) { + my $sub_char = substr $subsequence, $sub_pos, 1; + my $str_pos = 0; + my @partial; + push @partial, $str_pos++ + while -1 != ($str_pos = index $string, $sub_char, $str_pos); + @solutions = map { + my $solution = $_; + map { $_ > $solution->[-1] ? [@$solution, $_] : () } @partial; + } @solutions; + @solutions = map [$_], @partial unless @solutions; # First character. + } + return \@solutions +} + +use Test::More tests => 6; + +is unique_subsequence('littleit', 'lit'), 5, 'Example 1'; +is unique_subsequence('london', 'lon'), 3, 'Example 2'; +is unique_subsequence('london', 'par'), 0, 'Zero'; + + +is_deeply show_unique_subsequence('littleit', 'lit'), + [[0, 1, 2], [0, 1, 3], [0, 1, 7], [0, 6, 7], [4, 6, 7]], + 'Show Example 1'; + +is_deeply show_unique_subsequence('london', 'lon'), + [[0, 1, 2], [0, 1, 5], [0, 4, 5]], + 'Show Example 2'; + +is_deeply show_unique_subsequence('london', 'par'), [], 'Show Zero'; diff --git a/challenge-099/gustavo-chaves/perl/ch-1.pl b/challenge-099/gustavo-chaves/perl/ch-1.pl new file mode 100755 index 0000000000..a11b6d7390 --- /dev/null +++ b/challenge-099/gustavo-chaves/perl/ch-1.pl @@ -0,0 +1,42 @@ +#!/usr/bin/env perl + +# https://perlweeklychallenge.org/blog/perl-weekly-challenge-099/ +# TASK #1 › Pattern Match + +use 5.030; +use warnings; + +my ($S, $P) = @ARGV; + +say "Pattern: '$P'"; + +say match($P, $S) ? "Matches: " : "Does not match: ", "'$S'"; + +sub match { + my ($pattern, $string) = @_; + + my ($s, $p) = (0, 0); + + CHAR: + while ($p < length($pattern) && $s < length($string)) { + my $c = substr($pattern, $p, 1); + + if ($c eq '?') { + ++$s; + ++$p; + } elsif ($c eq '*') { + my $patterntail = substr($pattern, $p+1); + for (my $i=$s; $i < length($string); ++$i) { + return 1 if match($patterntail, substr($string, $i)); + } + return 0; + } elsif ($c eq substr($string, $s, 1)) { + ++$s; + ++$p; + } else { + return 0; + } + } + + return $p == length($pattern) && $s == length($string); +} diff --git a/challenge-099/gustavo-chaves/perl/ch-2.pl b/challenge-099/gustavo-chaves/perl/ch-2.pl new file mode 100755 index 0000000000..25f36ff228 --- /dev/null +++ b/challenge-099/gustavo-chaves/perl/ch-2.pl @@ -0,0 +1,28 @@ +#!/usr/bin/env perl + +# https://perlweeklychallenge.org/blog/perl-weekly-challenge-099/ +# TASK #2 › Unique Subsequence + +use 5.030; +use warnings; + +my ($S, $T) = @ARGV; + +sub matches { + my ($s, $t) = @_; + + return 1 if $t == length($T); + + my $matches = 0; + + my $c = substr($T, $t, 1); + foreach my $i ($s .. length($S)-1) { + if ($c eq substr($S, $i, 1)) { + $matches += matches($i+1, $t+1); + } + } + + return $matches; +} + +say matches(0, 0); diff --git a/challenge-099/luca-ferrari/blog-1.txt b/challenge-099/luca-ferrari/blog-1.txt new file mode 100644 index 0000000000..57e7046809 --- /dev/null +++ b/challenge-099/luca-ferrari/blog-1.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2021/02/08/PerlWeeklyChallenge99.html#task1 diff --git a/challenge-099/luca-ferrari/blog-2.txt b/challenge-099/luca-ferrari/blog-2.txt new file mode 100644 index 0000000000..8247db63d4 --- /dev/null +++ b/challenge-099/luca-ferrari/blog-2.txt @@ -0,0 +1 @@ +https://fluca1978.github.io/2021/02/08/PerlWeeklyChallenge99.html#task2 diff --git a/challenge-099/luca-ferrari/raku/ch-1.p6 b/challenge-099/luca-ferrari/raku/ch-1.p6 new file mode 100644 index 0000000000..570a3b0c66 --- /dev/null +++ b/challenge-099/luca-ferrari/raku/ch-1.p6 @@ -0,0 +1,10 @@ +#!raku + +sub MAIN( Str $S, Str $P ) { + # substitute every ? to match a single char + # and every * to match a stream of chars + # and add anchors + my $regexp = '^' ~ $P.subst( '*', '.*' ).subst( '?', '.' ) ~ '$'; + { say 1; exit; } if $S ~~ / <$regexp> /; + say 0; +} diff --git a/challenge-099/luca-ferrari/raku/ch-2.p6 b/challenge-099/luca-ferrari/raku/ch-2.p6 new file mode 100644 index 0000000000..a25a297500 --- /dev/null +++ b/challenge-099/luca-ferrari/raku/ch-2.p6 @@ -0,0 +1,15 @@ +#!raku + +sub MAIN( Str $S, Str $T ) { + my $counter = 0; + my $regexp = $T.comb.join( '.*' ); + + # overlapping search + given $S { + for m:exhaustive/ <$regexp> / -> $match { + $counter++; + } + } + + say $counter; +} diff --git a/challenge-099/mark-anderson/raku/ch-1.raku b/challenge-099/mark-anderson/raku/ch-1.raku new file mode 100644 index 0000000000..84ea24421b --- /dev/null +++ b/challenge-099/mark-anderson/raku/ch-1.raku @@ -0,0 +1,13 @@ +#!/usr/bin/env raku +use Test; +plan 4; + +is pattern-match("abcde", "a*e"), 1; +is pattern-match("abcde", "a*d"), 0; +is pattern-match("abcde", "?b*d"), 0; +is pattern-match("abcde", "a*c?e"), 1; + +sub pattern-match($S, $P) +{ + ($S ~~ / ^ <{ $P.trans: <? *> => <. .*> }> $ /).Bool.UInt; +} diff --git a/challenge-099/mark-anderson/raku/ch-2.raku b/challenge-099/mark-anderson/raku/ch-2.raku new file mode 100644 index 0000000000..88bf596ded --- /dev/null +++ b/challenge-099/mark-anderson/raku/ch-2.raku @@ -0,0 +1,11 @@ +#!/usr/bin/env raku +use Test; +plan 2; + +is unique-subsequences("littleit", "lit"), 5; +is unique-subsequences("london", "lon"), 3; + +sub unique-subsequences($S, $T) +{ + +($S ~~ m:ex/ <{ $T.comb.join(" .* ") }> /); +} diff --git a/challenge-099/polettix/blog.txt b/challenge-099/polettix/blog.txt new file mode 100644 index 0000000000..a44ed25ad8 --- /dev/null +++ b/challenge-099/polettix/blog.txt @@ -0,0 +1 @@ +https://github.polettix.it/ETOOBUSY/2021/02/10/pwc099-pattern-match/ diff --git a/challenge-099/polettix/blog1.txt b/challenge-099/polettix/blog1.txt new file mode 100644 index 0000000000..28712cb9a1 --- /dev/null +++ b/challenge-099/polettix/blog1.txt @@ -0,0 +1 @@ +https://github.polettix.it/ETOOBUSY/2021/02/11/pwc099-unique-subsequence/ diff --git a/challenge-099/polettix/perl/ch-1.pl b/challenge-099/polettix/perl/ch-1.pl new file mode 100644 index 0000000000..8a298e5b33 --- /dev/null +++ b/challenge-099/polettix/perl/ch-1.pl @@ -0,0 +1,16 @@ +#!/usr/bin/env perl +use 5.024; +use warnings; +use experimental qw< postderef signatures >; +no warnings qw< experimental::postderef experimental::signatures >; + +sub pattern_match ($S, $T) { + $T = join '', + map { $_ eq '*' ? '.*' : $_ eq '?' ? '.' : quotemeta($_) } + split m{([*?])}mxs, $T; + return $S =~ m{\A$T\z}mxs ? 1 : 0; +} + +my $string = shift // 'abcde'; +my $pattern = shift // 'a*e'; +say pattern_match($string, $pattern); diff --git a/challenge-099/polettix/perl/ch-2.pl b/challenge-099/polettix/perl/ch-2.pl new file mode 100644 index 0000000000..97e816815d --- /dev/null +++ b/challenge-099/polettix/perl/ch-2.pl @@ -0,0 +1,31 @@ +#!/usr/bin/env perl +use 5.024; +use warnings; +use experimental qw< postderef signatures >; +no warnings qw< experimental::postderef experimental::signatures >; + +sub unique_subsequence ($S, $T) { + my $lenT = length $T or return 1; + my $lenS = length $S or return 0; + my $first = substr $T, 0, 1, ''; + --$lenT; + my $s = 0; # sum + my $p = 0; # search start position + while (($p < $lenS) && (my $i = index $S, $first, $p) >= $p) { + $s += unique_subsequence(substr($S, $i), $T) if $lenS - $i >= $lenT; + $p = $i + 1; + } + return $s; +} + +sub unique_subsequence_rx ($S, $T) { + $T = join '.*', split m{}mxs, $T; + my $count = 0; + 1 while $S =~ m{$T(?{++$count})(?!)}; + return $count; +} + +my $string = shift // 'littleit'; +my $subsequence = shift // 'lit'; +say unique_subsequence($string, $subsequence); +say unique_subsequence_rx($string, $subsequence); diff --git a/challenge-099/roger-bell-west/perl/ch-1.pl b/challenge-099/roger-bell-west/perl/ch-1.pl new file mode 100755 index 0000000000..e509782c9b --- /dev/null +++ b/challenge-099/roger-bell-west/perl/ch-1.pl @@ -0,0 +1,23 @@ +#! /usr/bin/perl + +use strict; +use warnings; + +use Test::More tests => 4; + +is(pm('abcde','a*e'),1,'example 1'); +is(pm('abcde','a*d'),0,'example 2'); +is(pm('abcde','?b*d'),0,'example 3'); +is(pm('abcde','a*c?e'),1,'example 4'); + +sub pm { + my $text=shift; + my $match=shift; + (my $re=$match) =~ s/\?/./g; + $re =~ s/\*/.*/g; + $re='^'.$re.'$'; + if ($text =~ /$re/) { + return 1; + } + return 0; +} diff --git a/challenge-099/roger-bell-west/perl/ch-2.pl b/challenge-099/roger-bell-west/perl/ch-2.pl new file mode 100755 index 0000000000..0097d4dcb9 --- /dev/null +++ b/challenge-099/roger-bell-west/perl/ch-2.pl @@ -0,0 +1,47 @@ +#! /usr/bin/perl + +use strict; +use warnings; + +use Test::More tests => 2; + +is(us('littleit','lit'),5,'example 1'); +is(us('london','lon'),3,'example 2'); + +use List::Util qw(sum); + +sub us { + my $text=shift; + my $match=shift; + my %s; + { + my $i=0; + foreach my $c (split '',$text) { + push @{$s{$c}},$i; + $i++; + } + } + my @j; + foreach my $c (split '',$match) { + if (exists $s{$c}) { + push @j,$s{$c}; + } else { + return 0; + } + } + my @o=(1) x scalar @{$j[0]}; + foreach my $m (1..$#j) { + my @n; + foreach my $bi (0..$#{$j[$m]}) { + my $t=0; + foreach my $ai (0..$#{$j[$m-1]}) { + if ($j[$m-1][$ai] < $j[$m][$bi]) { + $t+=$o[$ai]; + } + } + push @n,$t; + } + @o=@n; + } + return sum(@o); +} diff --git a/challenge-099/roger-bell-west/python/ch-1.py b/challenge-099/roger-bell-west/python/ch-1.py new file mode 100755 index 0000000000..8a3140e45e --- /dev/null +++ b/challenge-099/roger-bell-west/python/ch-1.py @@ -0,0 +1,37 @@ +#! /usr/bin/python3 + +import re + +def pm(text,match): + rl=list() + rl.append("^") + for c in match: + if c == '?': + rl.append(".") + elif c == '*': + rl.append(".*") + else: + rl.append(c) + rl.append("$") + rls=''.join(rl) + if re.match(rls,text): + return 1 + return 0 + +import unittest + +class TestPm(unittest.TestCase): + + def test_ex1(self): + self.assertEqual(pm('abcde','a*e'),1,'example 1') + + def test_ex2(self): + self.assertEqual(pm('abcde','a*d'),0,'example 2') + + def test_ex3(self): + self.assertEqual(pm('abcde','?b*d'),0,'example 3') + + def test_ex4(self): + self.assertEqual(pm('abcde','a*c?e'),1,'example 4') + +unittest.main() diff --git a/challenge-099/roger-bell-west/python/ch-2.py b/challenge-099/roger-bell-west/python/ch-2.py new file mode 100755 index 0000000000..2acef1cb02 --- /dev/null +++ b/challenge-099/roger-bell-west/python/ch-2.py @@ -0,0 +1,39 @@ +#! /usr/bin/python3 + +from collections import defaultdict + +def us(text,match): + s=defaultdict(list) + for i,c in enumerate(text): + s[c].append(i) + j=list() + for c in match: + if c in s: + j.append(s[c]) + else: + return 0 + o=list(); + for i in range(len(j[0])): + o.append(1) + for m in range(1,len(j)): + n=list() + for bi in range(len(j[m])): + t=0 + for ai in range(len(j[m-1])): + if j[m-1][ai] < j[m][bi]: + t += o[ai] + n.append(t) + o=n + return sum(o) + +import unittest + +class TestUs(unittest.TestCase): + + def test_ex1(self): + self.assertEqual(us('littleit','lit'),5,'example 1') + + def test_ex2(self): + self.assertEqual(us('london','lon'),3,'example 2') + +unittest.main() diff --git a/challenge-099/roger-bell-west/raku/ch-1.p6 b/challenge-099/roger-bell-west/raku/ch-1.p6 new file mode 100755 index 0000000000..5f49b4248b --- /dev/null +++ b/challenge-099/roger-bell-west/raku/ch-1.p6 @@ -0,0 +1,20 @@ +#! /usr/bin/perl6 + +use Test; + +plan 4; + +is(pm('abcde','a*e'),1,'example 1'); +is(pm('abcde','a*d'),0,'example 2'); +is(pm('abcde','?b*d'),0,'example 3'); +is(pm('abcde','a*c?e'),1,'example 4'); + +sub pm($text,$match) { + (my $re=$match) ~~ s:g/\?/./; + $re ~~ s:g/\*/.*/; + $re='^' ~ $re ~ '$'; + if ($text ~~ /<$re>/) { + return 1; + } + return 0; +} diff --git a/challenge-099/roger-bell-west/raku/ch-2.p6 b/challenge-099/roger-bell-west/raku/ch-2.p6 new file mode 100755 index 0000000000..ed5478ce07 --- /dev/null +++ b/challenge-099/roger-bell-west/raku/ch-2.p6 @@ -0,0 +1,45 @@ +#! /usr/bin/perl6 + +use Test; + +plan 2; + +is(us('littleit','lit'),5,'example 1'); +is(us('london','lon'),3,'example 2'); + +sub us($text,$match) { + my %s; + { + my $i=0; + for $text.comb -> $c { + unless %s{$c} { + %s{$c}=Array.new; + } + push %s{$c},$i; + $i++; + } + } + my @j; + for $match.comb -> $c { + if (%s{$c}:exists) { + push @j,%s{$c}; + } else { + return 0; + } + } + my @o=(1) xx @j[0].elems; + for 1..@j.elems-1 -> $m { + my @n; + for 0..@j[$m].elems-1 -> $bi { + my $t=0; + for 0..@j[$m-1].elems-1 -> $ai { + if (@j[$m-1][$ai] < @j[$m][$bi]) { + $t+=@o[$ai]; + } + } + push @n,$t; + } + @o=@n; + } + return sum(@o); +} diff --git a/challenge-099/roger-bell-west/ruby/ch-1.rb b/challenge-099/roger-bell-west/ruby/ch-1.rb new file mode 100755 index 0000000000..7f3e75e2d0 --- /dev/null +++ b/challenge-099/roger-bell-west/ruby/ch-1.rb @@ -0,0 +1,33 @@ +#! /usr/bin/ruby + +def pm(text,match) + re='^' + match + '$' + re=re.gsub(/\?/,'.') + re=re.gsub(/\*/,'.*') + if text =~ Regexp.new(re) then + return 1 + end + return 0 +end + +require 'test/unit' + +class TestPm < Test::Unit::TestCase + + def test_ex1 + assert_equal(1,pm('abcde','a*e')) + end + + def test_ex2 + assert_equal(0,pm('abcde','a*d')) + end + + def test_ex3 + assert_equal(0,pm('abcde','?b*d')) + end + + def test_ex4 + assert_equal(1,pm('abcde','a*c?e')) + end + +end diff --git a/challenge-099/roger-bell-west/ruby/ch-2.rb b/challenge-099/roger-bell-west/ruby/ch-2.rb new file mode 100755 index 0000000000..056e59ba25 --- /dev/null +++ b/challenge-099/roger-bell-west/ruby/ch-2.rb @@ -0,0 +1,48 @@ +#! /usr/bin/ruby + +def us(text,match) + s=Hash.new + text.split(//).each_with_index do |c,i| + unless s[c] then + s[c]=Array.new + end + s[c].push(i) + end + j=Array.new; + match.split(//).each do |c| + if s.has_key?(c) then + j.push(s[c]) + else + return 0 + end + end + o=Array.new([1] * j[0].length) + 1.upto(j.length-1) do |m| + n=Array.new + 0.upto(j[m].length-1) do |bi| + t=0 + 0.upto(j[m-1].length-1) do |ai| + if j[m-1][ai] < j[m][bi] then + t += o[ai] + end + end + n.push(t) + end + o=n + end + return o.sum +end + +require 'test/unit' + +class TestUs < Test::Unit::TestCase + + def test_ex1 + assert_equal(5,us('littleit','lit')) + end + + def test_ex2 + assert_equal(3,us('london','lon')) + end + +end diff --git a/challenge-099/roger-bell-west/rust/ch-1.rs b/challenge-099/roger-bell-west/rust/ch-1.rs new file mode 100755 index 0000000000..d3fe36b15c --- /dev/null +++ b/challenge-099/roger-bell-west/rust/ch-1.rs @@ -0,0 +1,47 @@ +use regex::Regex; + +// Cargo.toml needs: +// [dependencies] +// regex = "1" + +#[test] +fn test_ex1() { + assert_eq!(pm("abcde","a*e"),1); +} + +#[test] +fn test_ex2() { + assert_eq!(pm("abcde","a*d"),0); +} + +#[test] +fn test_ex3() { + assert_eq!(pm("abcde","?b*d"),0); +} + +#[test] +fn test_ex4() { + assert_eq!(pm("abcde","a*c?e"),1,"example 4"); +} + +fn pm(text: &str,mat: &str) -> u8 { + let mut rl: Vec<char>=vec![]; + rl.push('^'); + for c in mat.chars() { + if c == '?' { + rl.push('.'); + } else if c == '*' { |
