diff options
| author | dcw <d.white@imperial.ac.uk> | 2019-12-23 00:00:09 +0000 |
|---|---|---|
| committer | dcw <d.white@imperial.ac.uk> | 2019-12-23 00:00:09 +0000 |
| commit | 625d6bf4334dea9edbc3ae0e4c71b5313c0e841e (patch) | |
| tree | b86de41ef7a8645f4f23b279ce73cd4c9cb446c5 /challenge-039 | |
| parent | 12ed341626fbd6dc58f959286555fc5026bea58d (diff) | |
| download | perlweeklychallenge-club-625d6bf4334dea9edbc3ae0e4c71b5313c0e841e.tar.gz perlweeklychallenge-club-625d6bf4334dea9edbc3ae0e4c71b5313c0e841e.tar.bz2 perlweeklychallenge-club-625d6bf4334dea9edbc3ae0e4c71b5313c0e841e.zip | |
ran out of time to get a Postscript code generator working (to show RPN) so here's part 1 - the guestbook question - instead
Diffstat (limited to 'challenge-039')
| -rw-r--r-- | challenge-039/duncan-c-white/README | 80 | ||||
| -rw-r--r-- | challenge-039/duncan-c-white/perl5/Tuple.pm | 85 | ||||
| -rwxr-xr-x | challenge-039/duncan-c-white/perl5/ch-1.pl | 151 | ||||
| -rw-r--r-- | challenge-039/duncan-c-white/perl5/guestbook | 9 | ||||
| -rw-r--r-- | challenge-039/duncan-c-white/perl5/guestbook2 | 4 |
5 files changed, 287 insertions, 42 deletions
diff --git a/challenge-039/duncan-c-white/README b/challenge-039/duncan-c-white/README index bbaa601b99..8fe990172f 100644 --- a/challenge-039/duncan-c-white/README +++ b/challenge-039/duncan-c-white/README @@ -1,51 +1,47 @@ -Challenge 1: "Date Finder - -Create a script to accept a 7 digits number, where the first -number can only be 1 or 2. The second and third digits can be -anything 0-9. The fourth and fifth digits corresponds to the month -i.e. 01,02,03....11,12. And the last 2 digits respresents the days in -the month i.e. 01,02,03....29,30,31. Your script should validate if -the given number is valid as per the rule and then convert into human -readable format date. - -RULES - -1) If 1st digit is 1, then prepend 20 otherwise 19 to the 2nd and 3rd - digits to make it 4-digits year. - -2) The 4th and 5th digits together should be a valid month. - -3) The 6th and 7th digits together should be a valid day for the above month. - -For example, the given number is 2230120, it should print 1923-01-20. +Challenge 1: "A guest house had a policy that the light remain ON as +long as the at least one guest is in the house. There is guest book +which tracks all guest in/out time. Write a script to find out how long +in minutes the light were ON. + +Guest Book + +1) Alex IN: 09:10 OUT: 09:45 +2) Arnold IN: 09:15 OUT: 09:33 +3) Bob IN: 09:22 OUT: 09:55 +4) Charlie IN: 09:25 OUT: 10:05 +5) Steve IN: 09:33 OUT: 10:01 +6) Roger IN: 09:44 OUT: 10:12 +7) David IN: 09:57 OUT: 10:23 +8) Neil IN: 10:01 OUT: 10:19 +9) Chris IN: 10:10 OUT: 11:00 " -My notes: sounds rather straightforward, with or without date manipulation -modules. Reuse the "number of days in the month" code. +My notes: Nice question. Looks reasonably straightforward, especially if +we may assume that the IN times are in time order (as they are in the example +data above, and would naturally be in a physical guest book, where each person +writes their name and "IN" time in the first free row. -Challenge 2: "Word Game +Probably need to store the "OUT times that haven't happened yet" as +future-time diary events a la Discrete Event Simulation.. Core idea is: +store a set of users IN at the current time, and modify the set as time +passes. Think I have a Delta Time queue Perl module somewhere to reuse. -Lets assume we have tiles as listed below, with an alphabet (A..Z) -printed on them. Each tile has a value, e.g. A (1 point), B (4 points) -etc. You are allowed to draw 7 tiles from the lot randomly. Then try -to form a word using the 7 tiles with maximum points altogether. You -don't have to use all the 7 tiles to make a word. You should try to -use as many tiles as possible to get the maximum points. -For example, A (x8) means there are 8 tiles with letter A. +Challenge 2: "Write a script to demonstrate Reverse Polish +notation(RPN). Checkout https://en.wikipedia.org/wiki/Reverse_Polish_notation +for more information about RPN. (Contributed by Andrezgz) " -1 point: A (x8), G (x3), I (x5), S (x7), U (x5), X (x2), Z (x5) +My notes: That's pretty open ended - but on the other hand I know RPN +very well over the years so that gives quite some scope to play:-) +An RPN evaluator, or a coventional expression->RPN translator, would +be obvious tools to build, the evaluator in particular is trivial to +do and a great opportunity to use callback functions. -2 points: E (x9), J (x3), L (x3), R (x3), V (x3), Y (x5) - -3 points: F (x3), D (x3), P (x5), W (x5) - -4 points: B (x5), N (x4) - -5 points: T (x5), O (x3), H (x3), M (x4), C (x4) - -10 points: K (x2), Q (x2) -" +BTW, almost any script in Postscript would demonstrate RPN as Postscript +is totally RPN-based, so this may is a great opportunity to go for +Postscript again:-) -My notes: So not scrabble then:-) +I spent quite a lot of time trying to build a tiny language and translate +it to Perl and Postscript, in order to show RPN in the Postscript version, +but I ran out of time; maybe another time.. diff --git a/challenge-039/duncan-c-white/perl5/Tuple.pm b/challenge-039/duncan-c-white/perl5/Tuple.pm new file mode 100644 index 0000000000..0f151e03cb --- /dev/null +++ b/challenge-039/duncan-c-white/perl5/Tuple.pm @@ -0,0 +1,85 @@ +package Tuple; + +# jan2017: added deepclone() method. + +use strict; +use warnings; +use Data::Dumper; + +# +# usage: use Tuple; (mainly OO) +# or: use Tuple qw(tuple); (convenience function too) + +use Exporter 'import'; +our @EXPORT_OK = qw(tuple); + + +# exported convenience functions +sub tuple (@) { return Tuple->new(@_); } + + +# +# my $trip = Tuple->new( @elements ): +# Construct a new Tuple with the given values. +# +sub new ($@) +{ + my( $class, @elements ) = @_; + my $tuple = bless [@elements], $class; + return $tuple; +} + + +# +# my @elements = $tuple->detuple: +# Return the array of elements from the tuple. +# +sub detuple ($) +{ + my( $tuple ) = @_; + die "Tuple->detuple: bad tuple object",Dumper($tuple),"\n" + unless defined $tuple && ref($tuple) eq "Tuple"; + return @$tuple; +} + +# +# $tuple->append( $v ); +# Append $v as an extra field in $tuple (so a 3-tuple becomes a 4-tuple) +# +sub append ($$) +{ + my( $self, $v ) = @_; + push @$self, $v; +} + + + +use overload '""' => \&as_string; + +# +# my $str = $tuple->as_string(): +# Produce a printable string form of the given tuple. +# +sub as_string ($) +{ + my( $tuple ) = @_; + my $str = join(',', @$tuple); + return "($str)"; +} + + +# +# my $newtuple = $tuple->deepclone; +# deepclone the given tuple $tuple, calling each item's deepclone +# method and building and returning a new identical tuple with +# no shared items.. +# ONLY CALL THIS IF ALL ITEMS ON $tuple "can" deepclone! +# +sub deepclone ($) +{ + my( $self ) = @_; + return Tuple->new( map { $_->deepclone } @$self ); +} + + +1; diff --git a/challenge-039/duncan-c-white/perl5/ch-1.pl b/challenge-039/duncan-c-white/perl5/ch-1.pl new file mode 100755 index 0000000000..db1c8e5fab --- /dev/null +++ b/challenge-039/duncan-c-white/perl5/ch-1.pl @@ -0,0 +1,151 @@ +#!/usr/bin/perl +# +# Challenge 1: "A guest house had a policy that the light remain ON as +# long as the at least one guest is in the house. There is guest book +# which tracks all guest in/out time. Write a script to find out how long +# in minutes the light were ON. +# +# Guest Book +# +# 1) Alex IN: 09:10 OUT: 09:45 +# 2) Arnold IN: 09:15 OUT: 09:33 +# 3) Bob IN: 09:22 OUT: 09:55 +# 4) Charlie IN: 09:25 OUT: 10:05 +# 5) Steve IN: 09:33 OUT: 10:01 +# 6) Roger IN: 09:44 OUT: 10:12 +# 7) David IN: 09:57 OUT: 10:23 +# 8) Neil IN: 10:01 OUT: 10:19 +# 9) Chris IN: 10:10 OUT: 11:00 +# " +# +# My notes: Nice question. Looks reasonably straightforward, especially if +# we may assume that the IN times are in time order (as they are in the example +# data above, and would naturally be in a physical guest book, where each person +# writes their name and "IN" time in the first free row. +# +# Simpler version: When manually checking the answer, I realised that I didn't +# need the "future-time diary events", the callbacks, the "set of users who +# are in". I don't need to know WHO is IN @ time T only whether or not ANYONE +# is. This simpler algorithm REQUIRES that the IN times are in time order. +# + +use v5.10; # to get "say" +use strict; +use warnings; +use Function::Parameters; +use Data::Dumper; + +use lib qw(.); +use Tuple qw(tuple); + +die "Usage: ch-1.pl GUEST_BOOK_FILENAME]\n" unless @ARGV==1; +my $filename = shift; + + +# +# my $t = t2i( $time ); +# Convert $time, a 24-hour clock hh:mm string, into an integer $t, +# specifically 60*hh + mm. +# +fun t2i( $time ) +{ + $time =~ /^(\d+):(\d+)$/; + my( $h, $m ) = ( $1, $2 ); + return 60*$h+$m; +} + + +# +# my @data = parse_guestbook( $filename ); +# Given the $filename of the file containing the guest book data, +# open and read the data from the guestbook file ($filename) (dying +# if you can't open the guestbook), build and return @data, a list +# of (person, timein, timeout) tuples. +# +fun parse_guestbook( $filename ) +{ + open( my $fh, '<', $filename ) || die "can't open $filename\n"; + my @result; + while( <$fh> ) + { + chomp; + # format is: 1) Alex IN: 09:10 OUT: 09:45 + /^\s*\d+\)\s+(\w+)\s+IN:\s+(\S+)\s+OUT:\s+(\S+)\s*$/ || + die "bad format '$_' at line $. in $filename\n"; + my( $name, $intime, $outtime ) = ( $1, $2, $3 ); + push @result, tuple( $name, $intime, $outtime ); + #say "name=$name, intime=$intime, outtime=$outtime"; + } + close( $fh ); + return @result; +} + + +my @data = parse_guestbook( $filename ); +#die Dumper \@data; + +# now, to calculate the number of minutes that the house light is ON +# (which in time happens whenever the house is NON EMPTY), run through +# the @data, maintaining the people set. + +my $totaltime = 0; # total time house is non empty (in minutes) +my $lighton = 0; # is light on? +my $lightonuntil = "00:00"; # if light is on, until when? (hh:mm format) + +foreach my $tuple (@data) +{ + my( $name, $intime, $outtime ) = $tuple->detuple; + my $it = t2i( $intime ); + my $ot = t2i( $outtime ); + my $delta = $ot - $it; + say "$name enters house at $intime, leaves at $outtime"; + + unless( $lighton ) + { + $lightonuntil = $outtime; + $lighton = 1; + $totaltime += $delta; + say "Light on for $delta minutes ". + "(from $intime until $outtime), ". + "so totaltime $totaltime"; + next; + } + + # we already know the light is on until $lightonuntil + # now we now that name is IN from $intime to $outtime + + # lou is lights on until (but in minutes since midnight) + my $lou = t2i($lightonuntil); + + if( $it <= $lou ) + { + # ok: light on ..lightonuntil and + # also on from intime(<=lightonuntil)..outtime: + + # if outtime > lightonuntil then: + # extend light on from lightonuntil until new outtime, + if( $ot > $lou ) + { + # now know light is on from $lou to $ot: + my $extraontime = $ot - $lou; + $totaltime += $extraontime; + my $from = $lightonuntil; + $lightonuntil = $outtime; + say "Light on for another $extraontime minutes ". + "(from $from until $outtime), ". + "totaltime now $totaltime"; + } + } else + { + # (light on ..lightonuntil and on intime(>lightonuntil)..outtime: + # so light OFF from lightonuntil .. intime + # THEN ON from intime..outtime: that's $delta + $lightonuntil = $outtime; + $totaltime += $delta; + say "Light on for $delta minutes ". + "(from $intime until $outtime), ". + "totaltime now $totaltime"; + } +} + +say "\nLight was on for $totaltime minutes"; diff --git a/challenge-039/duncan-c-white/perl5/guestbook b/challenge-039/duncan-c-white/perl5/guestbook new file mode 100644 index 0000000000..a2467461cd --- /dev/null +++ b/challenge-039/duncan-c-white/perl5/guestbook @@ -0,0 +1,9 @@ +1) Alex IN: 09:10 OUT: 09:45 +2) Arnold IN: 09:15 OUT: 09:33 +3) Bob IN: 09:22 OUT: 09:55 +4) Charlie IN: 09:25 OUT: 10:05 +5) Steve IN: 09:33 OUT: 10:01 +6) Roger IN: 09:44 OUT: 10:12 +7) David IN: 09:57 OUT: 10:23 +8) Neil IN: 10:01 OUT: 10:19 +9) Chris IN: 10:10 OUT: 11:00 diff --git a/challenge-039/duncan-c-white/perl5/guestbook2 b/challenge-039/duncan-c-white/perl5/guestbook2 new file mode 100644 index 0000000000..1345ead1bd --- /dev/null +++ b/challenge-039/duncan-c-white/perl5/guestbook2 @@ -0,0 +1,4 @@ +1) Alex IN: 09:10 OUT: 09:45 +2) Arnold IN: 09:15 OUT: 09:33 +3) Bob IN: 09:22 OUT: 09:55 +4) Charlie IN: 10:00 OUT: 10:30 |
