aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorE7-87-83 <fungcheokyin@gmail.com>2021-03-01 10:11:54 +0800
committerE7-87-83 <fungcheokyin@gmail.com>2021-03-01 10:11:54 +0800
commit27fe1354da313c53aa35aff5149585fd57085dec (patch)
tree0e1b7b24391d3234f5c68ef6bf0013f28885099b
parent366566d511cad8b2fc5d0a5684a7873b41b7caf7 (diff)
downloadperlweeklychallenge-club-27fe1354da313c53aa35aff5149585fd57085dec.tar.gz
perlweeklychallenge-club-27fe1354da313c53aa35aff5149585fd57085dec.tar.bz2
perlweeklychallenge-club-27fe1354da313c53aa35aff5149585fd57085dec.zip
directory
-rw-r--r--challenge-100/adam-russell/ch-1.dat1
-rw-r--r--challenge-100/duncan-c-white/perl/mkTypes200
-rw-r--r--challenge-101/cheok-yin-fung/perl/ch-1.pl147
3 files changed, 348 insertions, 0 deletions
diff --git a/challenge-100/adam-russell/ch-1.dat b/challenge-100/adam-russell/ch-1.dat
new file mode 100644
index 0000000000..a32a4347a4
--- /dev/null
+++ b/challenge-100/adam-russell/ch-1.dat
@@ -0,0 +1 @@
+1234567890
diff --git a/challenge-100/duncan-c-white/perl/mkTypes b/challenge-100/duncan-c-white/perl/mkTypes
new file mode 100644
index 0000000000..c15c733c43
--- /dev/null
+++ b/challenge-100/duncan-c-white/perl/mkTypes
@@ -0,0 +1,200 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use lib qw(/homes/dcw/lib/perl5/DCW);
+use Datadec;
+
+my $posexpr = q(
+PosExpr = I( int n ) "$1"
+ or N( string name ) "$1"
+ or NO( string name, char op, int n ) "$1$2$3"
+);
+
+my $extra = q!
+
+my $debug = 0;
+sub setdebug { my($d) = @_; $debug = $d; }
+
+#
+# my($pe,$leftover) = parse($input);
+# Parse $input, a string starting with a position expression,
+# delivering the position expression in $pe and the leftover
+# input in $leftover. Die screaming if no well formed pos expr
+# can be found at the start of $input.
+# A position expression is either \d+ or name or name '+'|'-' \d+
+# The internal form of a posexpr is ['I', int const] or ['N', name]
+# or ['NO', name, +-, offset]
+#
+sub parse ($)
+{
+ my( $input ) = @_;
+ if( $input =~ s/^(\d+)\s*// )
+ {
+ return ( PosExpr->I($1), $input );
+ }
+ $input =~ s/^(\w+)\s*// ||
+ die "bad input in pos expr $input, name expected\n";
+ my $name = $1;
+ if( $input =~ s/^([\+-])\s*(\d+)\s*// )
+ {
+ return ( PosExpr->NO($name,$1,$2), $input );
+ }
+ return ( PosExpr->N($name), $input );
+}
+
+#
+# my $pos = $pe->eval($poshash);
+# Evaluate the given PosExpr $pe, using %$poshash
+# for name lookup. Returns the actual position (a number).
+#
+sub eval ($$)
+{
+ my( $self, $poshash ) = @_;
+ if( $self->kind eq 'I' )
+ {
+ return $self->I;
+ } elsif( $self->kind eq 'N' )
+ {
+ my $name = $self->N;
+ die "error in PosExpr::eval($self): ".
+ "no such name $name in poshash ". Dumper($poshash)
+ unless exists $poshash->{$name};
+ return $poshash->{$name};
+ } else # if( $self->kind eq 'NO' )
+ {
+ my ($name, $op, $n) = $self->NO;
+ die "error in PosExpr::eval($self): ".
+ "no such name $name in poshash ". Dumper($poshash)
+ unless exists $poshash->{$name};
+ die "error in PosExpr::eval($self): bad op $op\n" unless
+ $op eq '+' || $op eq '-';
+ $n = - $n if $op eq '-';
+ return $poshash->{$name} + $n;
+ }
+}
+
+
+
+!;
+
+open( my $fh, '>', "PosExpr.pm" ) || die;
+say $fh gen_datatype( $posexpr, $extra );
+
+close($fh);
+
+my $api = q(
+API = F( string lit, string name ) "F '$1' -> $2"
+ or L( string lit, string name ) "L '$1' -> $2"
+ or M( string lit, posexpr atorafter, string name ) "M '$1' $2 -> $3"
+ or T( posexpr pe1, string op, posexpr pe2 ) "T $1$2$3"
+ or C( int mn, posexpr pe1, posexpr pe2) "C $1 $2 $3"
+);
+
+$extra = q%
+
+my $debug = 0;
+sub setdebug { my($d) = @_; $debug = $d; }
+
+#
+# my @api = parse( $input );
+# Parse $input, a string containing a comma-separated sequence
+# of Abstract Pattern Instructions, return the list of apis.
+# Die screaming if parsing fails.
+# For example, matching the pattern a*e is represented by the
+# following api string:
+# F'a'->pa,L'e'->plast,Tplast>pa-1,C0 pa+1 plast-1
+# The individual api forms are:
+# F'str'->name
+# L'str'->name
+# M'str' posexpr->name
+# Tposexpr ('>'|'=') posexpr
+# C\d+ posexpr [posexpr]
+# where posexpr = \d+ or name or name '+'|'-' \d+
+#
+sub parse ($)
+{
+ my( $input ) = @_;
+ my @result;
+ while( $input )
+ {
+ # F'str'->name
+ if( $input =~ s/^F\s*// )
+ {
+ $input =~ s/^'([^']+)'\s*->\s*(\w+)// ||
+ die "bad input $input in F..\n";
+ my $api = API->F($1, $2);
+ say "debug: parsed api $api, rest input $input"
+ if $debug;
+ push @result, $api;
+ }
+ # L'str'->name
+ elsif( $input =~ s/^L\s*// )
+ {
+ $input =~ s/^'([^']+)'\s*->\s*(\w+)// ||
+ die "bad input $input in L..\n";
+ my $api = API->L($1, $2);
+ say "debug: parsed api $api, rest input $input"
+ if $debug;
+ push @result, $api;
+ }
+ # M'str' posexpr->name
+ elsif( $input =~ s/^M\s*// )
+ {
+ $input =~ s/^'([^']+)'\s+// ||
+ die "bad input $input in M..\n";
+ my $str = $1;
+ (my $pe,$input) = PosExpr::parse($input);
+ die "bad input $input in M$str $pe...\n"
+ unless $input =~ s/^\s*->\s*(\w+)//;
+ my $pname = $1;
+ my $api = API->M($str, $pe, $pname);
+ say "debug: parsed api $api, rest input $input"
+ if $debug;
+ push @result, $api;
+ }
+ # Tposexpr ('>'|'=') posexpr
+ elsif( $input =~ s/^T\s*// )
+ {
+ (my $pe,$input) = PosExpr::parse($input);
+ $input =~ s/^(>|=)// ||
+ die "bad input $input in T$pe, > or = expected\n";
+ my $op = $1;
+ (my $pe2,$input) = PosExpr::parse($input);
+ my $api = API->T($pe, $op, $pe2);
+ say "debug: parsed api $api, rest input $input"
+ if $debug;
+ push @result, $api;
+ }
+ # C\d+ posexpr [posexpr]
+ elsif( $input =~ s/^C\s*// )
+ {
+ $input =~ s/^(\d+)\s*// ||
+ die "bad input $input in C.. integer expected\n";
+ my $mn = $1;
+ (my $pe,$input) = PosExpr::parse($input);
+ $input =~ s/^\s*//;
+
+ # second posexpr is optional:
+ # present if next ch is not ','
+ my $pe2 = $pe;
+ if( $input ne '' && $input !~ /^,/ )
+ {
+ ($pe2,$input) = PosExpr::parse($input);
+ }
+ my $api = API->C($mn, $pe, $pe2);
+ say "debug: parsed api $api, rest input $input"
+ if $debug;
+ push @result, $api;
+ }
+ $input =~ s/^\s*,\s*//;
+ }
+ die "bad input $input, non empty but not F|L|M|T|C..\n" if $input;
+ return @result;
+}
+%;
+
+
+open( $fh, '>', "API.pm" ) || die;
+say $fh gen_datatype( $api, $extra );
+close($fh);
diff --git a/challenge-101/cheok-yin-fung/perl/ch-1.pl b/challenge-101/cheok-yin-fung/perl/ch-1.pl
new file mode 100644
index 0000000000..50af192610
--- /dev/null
+++ b/challenge-101/cheok-yin-fung/perl/ch-1.pl
@@ -0,0 +1,147 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+# The Weekly Challenge #101 Task 1 Pack a Spiral
+# Usage: ch-1.pl [items]
+# modify from my code for challenge #088 "Spiral Matrix"
+
+use List::Util qw/max/;
+
+
+sub my_printf {
+ print " " x ( $_[1] - (length $_[0]) );
+ print $_[0];
+}
+
+sub closest_factorization {
+ my $num = $_[0];
+ my $factor1 = 1;
+ my $factor2 = 1;
+ for my $int ( 1 .. $num ) {
+ if ($num % $int == 0) {
+ $factor1 = $factor2;
+ $factor2 = $int;
+ }
+ last if $factor1 * $factor2 >= $num;
+ }
+
+ if ($factor1*$factor1 != $num) {
+ return ($factor1, $factor2);
+ } else
+ {
+ return ($factor1, $factor1);
+ }
+}
+
+
+sub print_matrix_ad {
+ my @mat = @{$_[0]};
+ my $M = scalar @mat;
+ my $N = scalar @{$mat[0]};
+
+ my @columnlength;
+ for my $i (0..$N-1) {$columnlength[$i] = 1;}
+ for my $i (0..$N-1) {
+ for my $j (0..$M-1) {
+ $columnlength[$i] = max($columnlength[$i], 1+ (length $mat[$j]->[$i]));
+ }
+ }
+
+ for my $j (0..$M-1) {
+ for my $i (0..$N-1) {
+ my_printf($mat[$j]->[$i], $columnlength[$i]);
+ }
+ print "\n";
+ }
+
+}
+
+
+sub matrixize_anticlockwise {
+ my @list = @{$_[0]};
+ my $M = $_[1];
+ my $N = $_[2];
+ my @mat;
+ my @helper_mat;
+
+#BEGIN: special case handling: the numbers of entries is prime
+ if ($M == 1) {return \@list;}
+#END: special case handling
+
+
+ my @row_dir = ( 0, -1, 0, +1 );
+ my @col_dir = ( +1, 0, -1, 0 );
+
+ my ($r, $c) = ( $M-1 , 0);
+ ${$mat[$r]}[$c] = $list[0];
+ ${$helper_mat[$r]}[$c] = 1;
+
+ my @numbering = (
+ [1..$N-1],
+ [$N..$N+$M-2],
+ [$N+$M-1..$N+$M+$N-3],
+ [$N+$M+$N-2..($M-1)*2+($N-1)*2-1]
+ );
+
+ my $count = 1;
+ for my $q (0..3) {
+ for (@{$numbering[$q]}) {
+ $r += $row_dir[$q];
+ $c += $col_dir[$q];
+
+ ${$mat[$r]}[$c] = $list[$count];
+ ${$helper_mat[$r]}[$c] = 1;
+
+ $count++;
+ }
+ }
+
+ my $time_now = 3;
+ my $success_click = undef;
+ while ($count < $M*$N) {
+ if ($success_click) {
+ $r += $row_dir[$time_now];
+ $c += $col_dir[$time_now];
+ if (!defined ${$helper_mat[$r]}[$c] )
+ {
+ ${$mat[$r]}[$c] = $list[$count];
+ ${$helper_mat[$r]}[$c] = 1;
+ $success_click = 1;
+ $count++;
+ } else
+ {
+ $success_click = undef;
+ $r -= $row_dir[$time_now];
+ $c -= $col_dir[$time_now];
+ }
+ } else
+ {
+ $time_now = ($time_now+1) % 4;
+ $success_click = 1;
+ }
+ }
+ return @mat;
+}
+
+
+# MAIN BODY
+if ($ARGV[0]) {
+ my @items = @ARGV;
+ my $num_of_items = scalar @items;
+ my @test = matrixize_anticlockwise( \@items, closest_factorization($num_of_items) );
+ print_matrix_ad([@test]);
+}
+
+
+=pod
+
+@items = (1..60);
+
+ 24 23 22 21 20 19 18 17 16 15
+ 25 46 45 44 43 42 41 40 39 14
+ 26 47 60 59 58 57 56 55 38 13
+ 27 48 49 50 51 52 53 54 37 12
+ 28 29 30 31 32 33 34 35 36 11
+ 1 2 3 4 5 6 7 8 9 10
+
+=cut