diff options
| author | dcw <d.white@imperial.ac.uk> | 2020-02-06 20:20:07 +0000 |
|---|---|---|
| committer | dcw <d.white@imperial.ac.uk> | 2020-02-06 20:20:07 +0000 |
| commit | a32c231818e654edf91d31076bf6001725c219bc (patch) | |
| tree | 6cfa4d5cf992626149e76d22add8021fedc7188d /challenge-046 | |
| parent | ee0d2ae41449f68b3ac874e526c6b140e7d3e909 (diff) | |
| download | perlweeklychallenge-club-a32c231818e654edf91d31076bf6001725c219bc.tar.gz perlweeklychallenge-club-a32c231818e654edf91d31076bf6001725c219bc.tar.bz2 perlweeklychallenge-club-a32c231818e654edf91d31076bf6001725c219bc.zip | |
imported my solutions, including the second one in postscript to get on the guest page again:-)
Diffstat (limited to 'challenge-046')
| -rw-r--r-- | challenge-046/duncan-c-white/README | 60 | ||||
| -rwxr-xr-x | challenge-046/duncan-c-white/perl/ch-1.pl | 79 | ||||
| -rwxr-xr-x | challenge-046/duncan-c-white/perl/ch-2.pl | 61 | ||||
| -rw-r--r-- | challenge-046/duncan-c-white/postscript/ch-2.ps | 192 |
4 files changed, 371 insertions, 21 deletions
diff --git a/challenge-046/duncan-c-white/README b/challenge-046/duncan-c-white/README index e8d0698436..8a4cac1fc2 100644 --- a/challenge-046/duncan-c-white/README +++ b/challenge-046/duncan-c-white/README @@ -1,34 +1,52 @@ -Task 1: "Square Secret Code: +Task 1: "Cryptic Message: -The square secret code mechanism first removes any space from the original -message. Then it lays down the message in a row of 8 columns. The coded -message is then obtained by reading down the columns going left to right. +The communication system of an office is broken and messages received +are not completely reliable. To send the message Hello 6 times, it ended +up sending these following: -For example, the message is "The quick brown fox jumps over the lazy dog". +H x l 4 ! +c e - l o +z e 6 l g +H W l v R +q 9 m # o -Then the message would be laid out as below: +Similarly another day we received a message repeatedly like below: -thequick -brownfox -jumpsove -rthelazy -dog +P + 2 l ! a t o +1 e 8 0 R $ 4 u +5 - r ] + a > / +P x w l b 3 k \ +2 e 3 5 R 8 y u +< ! r ^ ( ) k 0 -The code message would be as below: +Write a script to decrypt the above repeated message (one message repeated +6 times). -tbjrd hruto eomhg qwpe unsl ifoa covz kxey - -Write a script that accepts a message from command line and prints the -equivalent coded message. +HINT: Look for characters repeated in a particular position in all six +messages received. " -My notes: sounds trivial, let's write the decoder as well. +My notes: ah, so pick maxfreq letter in each column? -Task #2: "Source Dumper: +Task #2: "Is the room open? -Write a script that dumps its own source code. For example, say, the script name is ch-2.pl then the following command should returns nothing. +There are 500 rooms in a hotel with 500 employees having keys to all the +rooms. The first employee opened main entrance door of all the rooms. The +second employee then closed the doors of room numbers 2,4,6,8,10 and +so on to 500. The third employee then closed the door if it was opened +or opened the door if it was closed of rooms 3,6,9,12,15 and so on to +500. Similarly the fourth employee did the same as the third but only +room numbers 4,8,12,16 and so on to 500. This goes on until all employees +has had a turn. -$ perl ch-2.pl | diff - ch-2.pl +Write a script to find out all the rooms still open at the end. " -My notes: trivial if we're allowed to use $0. +My notes: sounds pretty easy, two nested for loops, but one of those questions +where I can't predict in advance what the answer will be. + +But having written the naive roomopen[r] based solution, I find that the +answer is: the open rooms are all the room numbers that are exact squares! +I'm not sure why, but I then implemented that more directly, with no +arrays. I then translated that into Postscript too, see the postscript +directory:-) diff --git a/challenge-046/duncan-c-white/perl/ch-1.pl b/challenge-046/duncan-c-white/perl/ch-1.pl new file mode 100755 index 0000000000..7939f8c141 --- /dev/null +++ b/challenge-046/duncan-c-white/perl/ch-1.pl @@ -0,0 +1,79 @@ +#!/usr/bin/perl +# +# +# Task 1: "Cryptic Message: +# +# The communication system of an office is broken and messages received +# are not completely reliable. If we sent the message Hello 6 times, it +# might end up sending these following corrupt messsages: +# +# H x l 4 ! +# c e - l o +# z e 6 l g +# H W l v R +# q 9 m # o +# +# Similarly another day we received a message repeatedly like below: +# +# P + 2 l ! a t o +# 1 e 8 0 R $ 4 u +# 5 - r ] + a > / +# P x w l b 3 k \ +# 2 e 3 5 R 8 y u +# < ! r ^ ( ) k 0 +# +# Write a script to decrypt the above repeated message (one message repeated +# 6 times). +# +# HINT: Look for characters repeated in a particular position in all six +# messages received. +# " +# +# My notes: ah, so pick maxfreq letter in each column? +# invoke as: +# ./ch-1.pl 'Hxl4!' 'ce-lo' 'ze6lg' 'HWlvR' 'q9m#o' +# result: Hello +# +# ./ch-1.pl 'P+2l\!ato' '1e80R$4u' '5-r]+a>/' \ +# 'Pxwlb3k\' '2e35R8yu' '<\!r^()k0' +# result: PerlRaku +# + +use feature 'say'; +use strict; +use warnings; +use Data::Dumper; + +die "Usage: mergemsg M1 M2 M3....\n" unless @ARGV>1; + +my @freq; # array of bags + +foreach my $msg (@ARGV) +{ + my @letter = split( //, $msg ); + foreach my $i (0..$#letter) + { + $freq[$i] //= {}; + $freq[$i]{$letter[$i]}++; + } +} + +#die Dumper \@freq; + +my $result = ""; +foreach my $i (0..$#freq) +{ + my $max = -1; + my $let = ''; + my $href = $freq[$i]; + while( my($l,$f) = each %$href ) + { + if( $f > $max ) + { + $max = $f; + $let = $l; + } + } + $result .= $let; +} +say $result; diff --git a/challenge-046/duncan-c-white/perl/ch-2.pl b/challenge-046/duncan-c-white/perl/ch-2.pl new file mode 100755 index 0000000000..d6320f2a4e --- /dev/null +++ b/challenge-046/duncan-c-white/perl/ch-2.pl @@ -0,0 +1,61 @@ +#!/usr/bin/perl +# +# Task #2: "Is the room open? +# +# There are 500 rooms in a hotel with 500 employees having keys to all the +# rooms. The first employee opened main entrance door of all the rooms. The +# second employee then closed the doors of room numbers 2,4,6,8,10 and +# so on to 500. The third employee then closed the door if it was opened +# or opened the door if it was closed of rooms 3,6,9,12,15 and so on to +# 500. Similarly the fourth employee did the same as the third but only +# room numbers 4,8,12,16 and so on to 500. This goes on until all employees +# has had a turn. +# +# Write a script to find out all the rooms still open at the end. +# " +# +# My notes: sounds pretty easy, two nested for loops, but it's one of those +# questions where I can't predict what the answer will be. +# Wow! the answer is: all the squares! Let's find out why.. +# + +use feature 'say'; +use strict; +use warnings; + +die "Usage: ch-2.pl [Nrooms]\n" if @ARGV>1; +my $n = shift // 500; + +# all rooms open initially [we don't use element 0] +my @roomopen = ( 0, (1) x $n ); + +say "naive answer:"; +foreach my $empl (2..$n) +{ + for( my $room=$empl; $room<=$n; $room+=$empl ) + { + #say "debug: empl=$empl, room=$room, roomopen? $roomopen[$room]"; + $roomopen[$room] = 1-$roomopen[$room]; + } +} + +my @open = grep { $roomopen[$_] } 0..$n; +say join(',', @open); + +# ok, so a room no R is open at the end if the number of factors of R, +# including 1 and R, is ODD: + +say "odd-factors answer:"; +my @sq; +foreach my $r (1..$n) +{ + my $odd = 1; + foreach my $i (2..$r) + { + $odd = ! $odd if $r % $i == 0; + } + push @sq, $r if $odd; +} +say join(',', @sq); + +say "but why are the squares the only numbers with an odd number of factors?"; diff --git a/challenge-046/duncan-c-white/postscript/ch-2.ps b/challenge-046/duncan-c-white/postscript/ch-2.ps new file mode 100644 index 0000000000..032bfd82d0 --- /dev/null +++ b/challenge-046/duncan-c-white/postscript/ch-2.ps @@ -0,0 +1,192 @@ +%!PS-Adobe-3.0 +%%Pages: 1 +%%EndComments +% +% Task #2: "Is the room open? +% +% There are 500 rooms in a hotel with 500 employees having keys to all the +% rooms. The first employee opened main entrance door of all the rooms. The +% second employee then closed the doors of room numbers 2,4,6,8,10 and +% so on to 500. The third employee then closed the door if it was opened +% or opened the door if it was closed of rooms 3,6,9,12,15 and so on to +% 500. Similarly the fourth employee did the same as the third but only +% room numbers 4,8,12,16 and so on to 500. This goes on until all employees +% has had a turn. +% +% Write a script to find out all the rooms still open at the end. +% " +% + + +% Debugging.... + +% const debuglm: left margin of debug messages +/debuglm 0.5 72 mul def + +% const debugtop: top of debug messages - 11 inches up. +/debugtop 11 72 mul def + +% const debugdown: how far to go down each line +/debugdown 20 def + + +% debugorigin(): +% move to debugging origin +/debugorigin +{ + debuglm debugtop moveto + (Debugging log:) show + newline +} bind def + + +% debugnv( name, value ); +% display name and value on a debug line. +% keep this as it's so much simpler than debug() below +% and also debug() has commented out invocations to +% this throughout it:-) +/debugnv +{ + % initially: stack top: value, name + 30 0 rmoveto + exch % stack top: name, value + show % show name, stack top: value + (: ) show + 80 string cvs show % show convert_to_string(value) + newline +} bind def + + +% debugsay( string, array_of_pairs ); +% display a single message, combining the initial string and then +% every pair of items (variable,string) in <array> with no separators. +% eg debugsay( (x:), [ x (, y:) y (, z:) z ()] ) produces +% "x: value_of_x, y: value_of_y, z: value_of_z" +/debugsay +{ + 6 dict begin % next N items defined are in a local dictionary + /array exch def % localize parameter name, removing it from stack + /initstr exch def % localize parameter name, removing it from stack + /len 0 def % local variable - length of array + /pos 0 def % local variable - position in array + /name () def % local variable - an array element + /value () def % local variable - next array element + + 30 0 rmoveto + + /len array length def + + initstr 80 string cvs show + + % for pos = 0 to $#array step 2 + 0 2 len 1 sub + { + /pos exch def +% (pos) pos debugnv + + % $name = $array[$pos]; + /name array pos get def +% (name) name debugnv + + % $value = $array[$pos+1]; + /value array pos 1 add get def +% (value) value debugnv + + name 80 string cvs show + value 80 string cvs show + } for + + newline + + end % local dictionary destroyed here + +} def + + +% newline(); +% go to left margin of next line for debug messages +/newline +{ + currentpoint debugdown sub % decrement Y pos + exch pop % drop old X + debuglm exch % form (debuglm,Y) on stack + moveto % go there! +} def + + +% str = i2s(n): +% convert n to a string +/i2s +{ + 20 string cvs +} def + + +% result = append( string1, string2 ) +% Concatenates two strings together. Some languages +% already know how to do stuff like this!!! +/append +{ + % Initial stack: s1 s2 <-- top of stack + 2 copy % s1 s2 s1 s2 + length % s1 s2 s1 len(s2) + exch % s1 s2 len(s2) s1 + length add % s1 s2 len(s1)+len(s2) + string dup % s1 s2 r r + 4 2 roll % r r s1 s2 + 2 index % r r s1 s2 r + 0 % r r s1 s2 r 0 + 3 index % r r s1 s2 r 0 s1 + putinterval % strcpy( r+0, s1 ) + % r r s1 s2 + exch % r r s2 s1 + length % r r s2 len(s1) + exch % r r len(s1) s2 + putinterval % strcpy( r+len(s1), s2 ) + % return r +} bind def + + +%%Page: 1 1 +%%PageOrientation: Portrait + +/Helvetica-Bold findfont 13 scalefont setfont + +debugorigin + +% n = 500 +/n 500 def + +% say "answer:" +(answer:) [] debugsay + +% for r = 1 to n +1 1 n +{ + /r exch def + + % odd=1 + /odd 1 def + + % for i = 2 to r + 2 1 r + { + /i exch def + % if r % i == 0? + r i mod 0 eq + { + % odd = 1-odd + /odd 1 odd sub def + } if + } for + + % if odd + odd 1 eq + { + % say "$r" + () [r ()] debugsay + } if +} for + + +showpage |
