diff options
| author | dcw <d.white@imperial.ac.uk> | 2019-10-13 23:30:01 +0100 |
|---|---|---|
| committer | dcw <d.white@imperial.ac.uk> | 2019-10-13 23:30:01 +0100 |
| commit | 8d6b78cae9bccfbb16bf79c58544f3b65716cbe3 (patch) | |
| tree | 5f57743b31ecd4e3ebbd631d29f9c906407541d3 /challenge-029 | |
| parent | a62eda85606f9705d85659a8f596b135099f7a8c (diff) | |
| download | perlweeklychallenge-club-8d6b78cae9bccfbb16bf79c58544f3b65716cbe3.tar.gz perlweeklychallenge-club-8d6b78cae9bccfbb16bf79c58544f3b65716cbe3.tar.bz2 perlweeklychallenge-club-8d6b78cae9bccfbb16bf79c58544f3b65716cbe3.zip | |
imported my solutions..
Diffstat (limited to 'challenge-029')
| -rw-r--r-- | challenge-029/duncan-c-white/README | 34 | ||||
| -rwxr-xr-x | challenge-029/duncan-c-white/perl5/ch-1.pl | 153 | ||||
| -rwxr-xr-x | challenge-029/duncan-c-white/perl5/ch-2.pl | 62 |
3 files changed, 234 insertions, 15 deletions
diff --git a/challenge-029/duncan-c-white/README b/challenge-029/duncan-c-white/README index 75c9f80743..b00307c5eb 100644 --- a/challenge-029/duncan-c-white/README +++ b/challenge-029/duncan-c-white/README @@ -1,19 +1,23 @@ -Challenge 1: "Write a script to check the file content without explicitly -reading the content. It should accept file name with path as command -line argument and print 'The file content is binary.' or else 'The file -content is ascii.' accordingly." +Challenge 1: "Write a script to demonstrate brace expansion. For example, +script would take command line argument Perl {Daily,Weekly,Monthly,Yearly} +Challenge and should expand it and print like below: -My notes: That's bafflingly unclear! Without "explicitly" reading -the content, does that imply "implicitly" reading it is ok, or that -we're really not supposed to read the content at all. In the former -case, I guess we can run "file" and parse the outout. In the latter -case, unless there's some magic metadata somewhere else, that only -leaves file extensions. In that case, we just need a hash of file -extension -> binary/ascii choices. Dull. + Perl Daily Challenge + Perl Weekly Challenge + Perl Monthly Challenge + Perl Yearly Challenge +My notes: Nested braces may be slightly tricky, first I tried a recursive +function to find and expand the innermost {}, but that produced the +right output in a weird order, with duplicates. +Instead, try a state machine to track the locations of the outer level +elements {,}. Extract $before, $after and an array of alternatives @alt, +then recombine them, until there are no { left. -Challenge 2: "Write a script to display Digital Clock. Feel free to be -as creative as you can when displaying digits. We expect bare minimum -something like '14:10:11'" -My notes: Sounds like a job for Tk:-) +Challenge 2: "Write a script to demonstrate calling a C function. It +could be any user defined or standard C function." + +My notes: Hmm, either XS or Inline::C. I've never used either:-) +Wrote simple sqrt routine (algorithm: squaring the rectangle) in C, +wrote the same in Perl, then used Benchmark to benchmark both versions. diff --git a/challenge-029/duncan-c-white/perl5/ch-1.pl b/challenge-029/duncan-c-white/perl5/ch-1.pl new file mode 100755 index 0000000000..8d3e89243a --- /dev/null +++ b/challenge-029/duncan-c-white/perl5/ch-1.pl @@ -0,0 +1,153 @@ +#!/usr/bin/perl +# +# Challenge 1: "Write a script to demonstrate brace expansion. For example, +# script would take command line argument Perl {Daily,Weekly,Monthly,Yearly} +# Challenge and should expand it and print like below: +# +# Perl Daily Challenge +# Perl Weekly Challenge +# Perl Monthly Challenge +# Perl Yearly Challenge +# +# My notes: Nested braces may be slightly tricky, first I tried a recursive +# function to find and expand the innermost {}, but that produced the +# right output in a weird order, with duplicates. +# Instead, try a state machine to track the locations of the outer level +# elements {,}. Extract $before, $after and an array of alternatives @alt, +# then recombine them, until there are no { left. +# + +use v5.10; # to get "say" +use strict; +use warnings; +use Function::Parameters; +use Data::Dumper; + +die "Usage: ch-1.pl STRING+\n" unless @ARGV == 1; +my $string = shift; + +my @strings = expand_braces( $string ); +#my @pos = find_outermost_posns( $string ); +#say Dumper \@pos; +say for @strings; + + +# +# my @strings = expand_braces( $string ); +# Expand brace pairs in $string, giving an array of strings. +# +fun expand_braces( $string ) +{ + my @pos = find_outermost_posns( $string ); + #say Dumper \@pos; + return ( $string ) if @pos==0; + my( $before, $after, @alt ) = extract_pieces( $string, @pos ); + #die "debug: before=$before, after=$after, alt=@alt\n"; + my @result; + foreach my $alt (@alt) + { + my $s = $before.$alt.$after; + push @result, expand_braces( $s ); + } + return @result; +} + + +# +# my( $before, $after, @alt ) = extract_pieces( $string, @pos ); +# Extract the before part of $string, and the after +# part, and the array of altneratives. +# +fun extract_pieces( $string, @pos ) +{ + my( $p, $c ) = @{shift @pos}; + die "extrace_pieces: first pos $p, char $c not {\n" unless $c eq '{'; + my $before = substr($string,0,$p); + #print "debug: before=$before, p=$p, c=$c\n"; + my $start = $p; + my @alt; + my $after; + foreach my $pc (@pos) + { + my( $p, $c ) = @$pc; + if( $c eq ',' || $c eq '}' ) + { + my $frag = substr($string,$start+1,$p-$start-1); + push @alt, $frag; + $start = $p; + if( $c eq '}' ) + { + $after = substr($string,$p+1); + #print "debug: before=$before, after=$after, alt=@alt\n"; + return ( $before, $after, @alt ); + } + } + } + die "extrace_pieces: no } found{\n"; +} + + +# +# my @pos = find_outermost_posns( $string ); +# Locate the char positions in $string of: +# any '{', ',', '}' characters (not nested). +# Return the array of char positions, or an +# empty array if the string doesn't contain +# a '{'. +# +# How? a state machine to track the locations of the outer level {,}: +# +# s0: NOTE POS and enter s1 when '{' +# s1: N=1; enter s2 when '{' +# NOTE POS when ',' +# NOTE pos and enter s0 when '}' +# s2: N++ when '{' +# N--; enter s1 if N==0 when '}' +# +fun find_outermost_posns( $string ) +{ + my @result; + my $state = 0; + my $state2n = 0; + for( my $pos = 0; $pos < length($string); $pos++ ) + { + my $ch = substr($string,$pos,1); + #print "debug: pos=$pos, ch=$ch, state=$state, state2n=$state2n\n"; + if( $state == 0 ) # not in { + { + if( $ch eq '{' ) + { + push @result, [ $pos, $ch ]; + $state = 1; + } + } elsif( $state == 1 ) # inside exactly one { + { + if( $ch eq ',' ) + { + push @result, [ $pos, $ch ]; + } elsif( $ch eq '{' ) + { + $state2n = 1; + $state = 2; + } elsif( $ch eq '}' ) + { + push @result, [ $pos, $ch ]; + $state = 0; + } + } elsif( $state == 2 ) # inside >1 { + { + if( $ch eq '{' ) + { + $state2n++; + } elsif( $ch eq '}' ) + { + $state2n--; + if( $state2n == 0 ) + { + $state = 1; + } + } + } + } + return @result; +} diff --git a/challenge-029/duncan-c-white/perl5/ch-2.pl b/challenge-029/duncan-c-white/perl5/ch-2.pl new file mode 100755 index 0000000000..2a5d21b0c5 --- /dev/null +++ b/challenge-029/duncan-c-white/perl5/ch-2.pl @@ -0,0 +1,62 @@ +#!/usr/bin/perl +# +# Challenge 2: "Write a script to demonstrate calling a C function. It +# could be any user defined or standard C function." +# +# My notes: Hmm, either XS or Inline::C. I've never used either:-) +# Wrote simple sqrt routine (algorithm: squaring the rectangle) in C, +# wrote the same in Perl, then used Benchmark to benchmark both versions. +# + +use v5.10; # for "say" +use strict; +use warnings; +#use Data::Dumper; +use Function::Parameters; +use Benchmark qw(:all); + +use Inline 'C'; + + +fun perl_sqrt( $x ) +{ + my $EPSILON = 0.00001; + my $w=1.0; + for(;;) + { + my $h=$x/$w; + last if abs($h-$w)<$EPSILON; + $w = ($w+$h)/2; + } + return $w; +} + + +#greet('thingy'); +#greet(42); +#greet(4.6); +my $sc = c_sqrt( 145 ); +my $sp = perl_sqrt( 145 ); +print "sqrt(145)=$sc by C, =$sp by perl\n"; + +timethese( 10000000, + { + "C" => sub { c_sqrt(145); }, + "perl" => sub { perl_sqrt(145); } + } ); +__END__ +__C__ +void greet(SV* sv_name) { + printf("Hello %s!\n", SvPV(sv_name, PL_na)); +} +double c_sqrt( double x ) { + #define EPSILON 0.00001 + double w=1.0; + for(;;) + { + double h=x/w; + if( fabs(h-w)<EPSILON ) break; + w = (w+h)/2; + } + return w; +} |
