From estrabd at yahoo.com Wed Sep 1 13:43:07 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Wed Sep 1 13:43:10 2004 Subject: [Neworleans-pm] Fwd: Perl Quiz of the Week #23 Message-ID: <1094064187.26875.203509762@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "Mark Jason Dominus" To: perl-qotw@plover.com Date: Wed, 01 Sep 2004 12:50:14 -0400 Subject: Perl Quiz of the Week #23 IMPORTANT: Please do not post solutions, hints, or other spoilers until at least 60 hours after the date of this message. Thanks. IMPORTANT: S'il vous pla?t, attendez au minimum 60 heures apr?s la date de ce message avant de poster solutions, indices ou autres r?v?lations. Merci. WICHTIG: Bitte schicken Sie keine L?sungen, Tipps oder Hinweise f?r diese Aufgabe vor Ablauf von 60 Stunden nach dem Datum dieser Mail. Danke. ---------------------------------------------------------------- Write a program, 'parens', which gets a command line argument, n', which is an integer. The program should print all the properly-balanced strings of parentheses of length 2n. For example, given the argument '3', the program should print these five lines: ((())) (()()) (())() ()(()) ()()() in some order. (The order is not important.) For the argument '1'; the output should be: () and for argument '4', the output should be: (((()))) ((()())) ((())()) ((()))() (()(())) (()()()) (()())() (())(()) (())()() ()((())) ()(()()) ()(())() ()()(()) ()()()() in some order. [ ADMIN: I'm still hoping someone will step forward to write a report about expert quiz #22. - MJD ] From estrabd at yahoo.com Thu Sep 2 09:24:18 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Thu Sep 2 09:24:33 2004 Subject: [Neworleans-pm] Fwd: This Week's Summary (per6) Message-ID: <1094135058.27394.203570292@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "The Perl 6 Summarizer" To: perl6-announce@perl.org Date: Thu, 02 Sep 2004 08:56:58 +0100 Subject: This Week's Summary NB: The links are probably broken at present. Normal service will hopefully be resumed once Google gets caught up with the perl6 lists. The Perl 6 Summary for the week ending 2004-08-27 Where does the time go? I blame folk festivals. Once I'm getting busy with the teacher training I'm going to have weekends free to write the summaries. And if you'll believe that... We start with perl6-internals. Incremental garbage collection Discussion of implementing incremental garbage collection continued. Calling conventions for unprototyped subroutines Mattia Barbon asked for some clarification of how the calling conventions work for unprototyped subroutines in IMCC. Specifically, whether IMCC was behaving as documented in the Parrot Design Document (PDD3). Leo reassured him that the TODO entry that had caused his disquiet was obsolete and that IMCC does the right thing. http://xrl.us/cw77 Compile op with return values Steve Fink asked how to go about returning something from dynamically compiled code. He, Leo and Dan went over the issues. An unnamed (and as yet unvolunteered) volunteer will probably write it all up and add it to the parrot compiler FAQ. http://xrl.us/cw78 NCI and callback functions Stephane Peiry and Leo continued to work on getting NCI callbacks working with the GTK library. They finally tracked the problem down, but it looks awfully like Stephane's going to have to reimplement the "gtk_main" loop to get everything working. Best of luck Stephane. ParrotGTK would definitely be a cool thing. http://xrl.us/cw79 Planet Parrot Robert Spier announced the creation of Planet Parrot, an aggregator of Parrot related blogs. If you have such a blog, Robert would probably be interested in hearing from you. http://xrl.us/cw8a http://planet.parrotcode.org/ GC/DOD API Leo and Dan continued to discuss and work on documenting Parrot's memory management API. http://xrl.us/cw8b NCI GC issues Dan noticed a problem with garbage collection and NCI PMCs. Leo tracked the problem down and fixed it. I love it when a plan comes together. http://xrl.us/cw8c Opinions on base behaviour Base behaviour is disgusting and should be stamped out I tell you. We have a moral duty to... Ah... Actually, the subject refers to Dan and Leo's desire to nail down the behaviour of Parrot's basic types. He outlined the issues and asked for discussion. And that's what he got. It looks like Parrot's going to have a reasonably complete set of numeric types which will allow accuracy nerds to avoid reals for as long as possible. Which will be nice. http://xrl.us/cw8d http://xrl.us/cw8e http://xrl.us/cw8f http://xrl.us/cw8g http://xrl.us/cw8h Concat, Cows & Basil Comfortably winning the "weirdest subject line of the week" award, Sam Phillips laid out some of the problems he's having implementing a Basil compiler which targets Parrot. Leo supplied answers. http://xrl.us/cw8i Low level math[s] op behaviour As well as discussing basic types, Dan opened a discussion of the proper semantics of Parrot's low level maths (yeah, he spelt it 'math', but I'm English and I'll spell it correctly) operators. In particular he proposed variants that throw exceptions if strange things happen. http://xrl.us/cw8j Benchmark stuff Joshua Gatcomb posted some patches he'd made to F to make it a little less fragile and more useful. A few days later he announced a slightly more finished set of patches (Leo had checked his original patches in rather sooner than expected). http://xrl.us/cw8k http://xrl.us/cw8m Resuscitating a mod_parrot Dan Sugalski looked upon mod_parrot and saw that it was cool, to the point of being laid out on a mortuary slab. He thought that the time had come to try and put some life back into the project, now that Parrot's so much more capable. He asked for volunteers and Jeff Horwitz seems to be (the only?) one of 'em. http://xrl.us/cw8n PMC instantiation Leo posted another of his discussion documents, this time on instantiating PMCs. No response so far. http://xrl.us/cw8o Meanwhile, in perl6-language Return with no expression. In the usual freewheeling perl6-language way, a thread entitled 'return with no expression' ended up discussion how to disambiguate a "::" which is part of "... ?? ... :: ..." expression and "::" in its role as module sigil. (According to Luke it's easy; white space is required). http://xrl.us/cw8p Synopses discussed Discussion of the draft synopses continued http://xrl.us/cw8q - Synopsis 2 POD tables? Aaron Sherman wondered if Perl 6's incarnation of POD would have support for tables. Luke wasn't overly keen on Aaron's proposed syntax, and Larry pointed out that they'd managed to use Perl 5's POD and some clever processing to write tables for the third edition of Programming Perl. Once again, it seems that everyone agrees that POD is great, but could be greater, but nobody can agree on how to *make* it greater. Me, I think Larry got it right enough. http://xrl.us/cw8r Constructors and mixins Ovid had some questions about how Constructors work in Perl 6 and about how to disambiguate methods when using Roles. Larry and Damian provided answers. http://xrl.us/cw8s Instantiation Instantiation was on Aaron Sherman's mind too. He proposed some syntactic sugar for creating objects at 'use' time. For some reason, syntactic sugar proposals do seem to create lots of discussion. http://xrl.us/cw8t Announcements, Apologies, Acknowledgements I am reliably informed that a lot of last week's links were broken. Which is odd because the code to generate them hasn't changed. It looks like the problem's down to the gateway between nntp.perl.org and groups.google.com being slightly radished at present. However, I'm going to stick with the Google links in this summary in the hopes that normal service will be returned shortly and things will get backfilled. If anyone has a handy tool for getting from a message id to an archive URL that works then I'd be happy to hear from them. If you find these summaries useful or enjoyable, please consider contributing to the Perl Foundation to help support the development of Perl. You might also like to send feedback or contributions to a 'getting Piers to OSCON 2005' fund to mailto:pdcawley@bofh.org.uk http://donate.perl-foundation.org/ -- The Perl Foundation http://dev.perl.org/perl6/ -- Perl 6 Development site Amazingly, there's a small amount of newer content on my website this week. Will wonders never cease? http://www.bofh.org.uk/ From estrabd at yahoo.com Mon Sep 6 09:44:39 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Mon Sep 6 09:44:56 2004 Subject: [Neworleans-pm] Fwd: This week's Summary Message-ID: <1094481879.28032.203785478@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "The Perl 6 Summarizer" To: perl6-announce@perl.org Date: Mon, 06 Sep 2004 15:40:17 +0100 Subject: This week's Summary The Perl 6 Summary for the week ending 2004-09-03 Another week, a free weekend, and still I haven't started writing the summary until Monday. Still, I don't actually start at college 'til next week, so that's all right then. We start with perl6-internals. Compile op with return values The discussion of how to return something from dynamically compiled code continued with Leo, Dan and Steve Fink all working to clarify and address the issues. http://xrl.us/cybq Library loading Dan started the process of nailing down Parrot's dynamic loading API so that it can be added to the embedding interface. Steve Fink and Aaron Sherman had suggestions. http://xrl.us/cybr Pathological register allocation scenarios Gregor N Purdy had asked Dan if his work compiler could be made to spit out structurally equivalent C code to the Parrot code that was breaking IMCC. His idea being that we could then see how C compilers dealt with such nastiness. Dan thought that, whilst this was a good idea, it would be too much work to implement. Gregor wasn't so sure. http://xrl.us/cybs Dan and Leo demonstrate comic timing. Again. 14:17:09 GMT Dan: PerlHash test 20 is failing? Anyone know what's up so we can fix it? 15:30:41 GMT Leo: It stopped failing at 15:55 CEST (13:55 GMT) 16:32:29 GMT Dan: D'oh! We love it when a patch comes together. http://xrl.us/cybt PMC Instantiation Leo had raised issues with the current scheme for PMC instantiation. This week Dan came through with some design which got discussed and (I think) implemented. http://xrl.us/cybu Last bits of the basic math semantics If you believe Barbie, "Math is hard". She's right, up to a point. The list's spent a couple of weeks now sorting out the design of Parrots underlying mathematical and numeric systems to make sure that maths works right (for sufficiently useful values of 'right'). This particular line of discussion covers rotations and stuff, where you're actually treating a number as a bit field. http://xrl.us/cybv Cross-compiling parrot And you thought compiling Parrot on a Win32 box was hard. Robert Schwebel wants to cross compile Parrot and isn't having a good time. Dan wasn't surprised because the Parrot build process still gets most of its information from the local perl installation which will generally be wrong when you're cross compiling. Dan noted that part of the problem is that we don't have people on the team with a need or the experience of doing cross compilation and added that he'd be thrilled if this were to change. Any patches to make things better for cross compilers will, of course, be gratefully received. http://xrl.us/cybw Proposal for a new PMC layout and more Leo's concerned that the current PMC layout isn't the Right Thing, and laid out a proposal describing some changes he thinks would be worthwhile. In essence, he argues for removing the requirement for fixed sized PMC headers and separate variable sized buffers in favour of unifying buffers and PMCs so that PMCs become variable sized, thus eliminating some time consuming indirection, and space consuming overheads. Nicholas Clark thought the proposal was interesting, but said that, since the proposed changes would be invisible to the user, he'd be far happier with a functionally complete implementation of parrot with stable, useful APIs. Dan rejected the proposal (both for technical reasons and because he agreed with Nicholas). I don't think Leo was convinced by the technical reasons, but the "Let's get the interfaces finished!" argument clinched it. http://xrl.us/cybx http://xrl.us/cyby -- Dan explains why not. Semantics for regexes Dan appears to have opened an entertaining can of worms when he outlined his view of the minimum string semantics required to support a regular expression engine and asked for comments. Boy did he get them. And boy did they run off in all sorts of strange directions. Interesting directions mind. Anyway, further down the thread, Dan, Chip Salzenburg and Patrick Michaud seemed to reach something approximating agreement about the low level semantics required. http://xrl.us/cybz TODOs and calls for volunteers Leo came up with a list of things that need fixing/implementing and asked for volunteers. These include sorting out what happens with the experimental ops, implementing "new_extended" for every PMC class and finishing up BigInt's MMD and vtable functions. He also had some proposals for how we should get the Integer classes properly implemented now we know what the semantics will be. http://xrl.us/cyb2 http://xrl.us/cyb3 http://xrl.us/cyb4 http://xrl.us/cyb5 Meanwhile, in perl6-language Roles trying to be nice Abhijit Mahabal had some questions about making roles work. Luke, Patrick & Jonathan Scott Duff set about answering them. I'm not entirely sure that any of the answers so far are enough for Abhijit, but then I'm not entirely sure that any answer could be enough. At some point you have to take things on trust and hope that nothing breaks at runtime. http://xrl.us/cyb6 Pipeline performance Rod Adams brought up some issues with the performance of 'pipelining' arrays in Perl 5 -- in general doing say "grep {...} map {...} @ary" is rather slower than writing an explicit loop. He wondered if Perl 6 would be faster. Larry's answer that all lists function lazily if they can in Perl 6 seems to imply that yes, Perl 6 will be faster. http://xrl.us/cyb7 Synopsis 9 draft 1 "Synopsis 9?" I hear you ask "But we haven't seen Apocalypse 9 yet!". Indeed we haven't, but that's not stopped Larry writing it. Synopsis 9 gives an overview of Perl 6's data structures (hopefully enough for anyone who happens to be starting work on a rough cut of a Perl 6 implementation) which will be covered in more detail when the Apocalypse itself comes out. The usual storm of discussion and general proofreading goodness went on. http://xrl.us/cyb8 The range operator Joe Gottman wondered if there would be sufficiently lazy way to generate ranges. In particular, he wanted to know if he'd be able to write "reverse (1..5)" and have Perl handle that lazily, or if he could do "5 .. 1 :by(-1)". Larry thought that, if range objects were made sufficiently smart, there would be no reason why the "reverse" approach couldn't be lazy. http://xrl.us/cyb9 Can PRE and POST be removed from program flow? John Siracusa wondered if it would be possible to turn off the PRE and POST Design By Contract hooks in production code to improve performance. (Leaving aside arguments about whether this is sensible; personally I reckon that a production environment is where you should be most worried about values that might fail the PRE/POST hooks). Larry reckoned it would be possible to simply clobber the global definitions of PRE and POST to make them no ops. This wasn't enough for John, who wanted to be able to get rid of them entirely so even the call to the no op didn't happen. So Damian showed him the obvious macros... http://xrl.us/cyca Announcements, Apologies, Acknowledgements It looks like the Google groups gateway is working again, so I'll keep with the Google style linking. If you find these summaries useful or enjoyable, please consider contributing to the Perl Foundation to help support the development of Perl. You might also like to send feedback or contributions to a 'getting Piers to OSCON 2005' fund to mailto:pdcawley@bofh.org.uk http://donate.perl-foundation.org/ -- The Perl Foundation http://dev.perl.org/perl6/ -- Perl 6 Development site Or, you can check out my website. http://www.bofh.org.uk/ From estrabd at yahoo.com Wed Sep 8 21:26:14 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Wed Sep 8 21:26:17 2004 Subject: [Neworleans-pm] Fwd: Solutions and Discussion for Perl Quiz of the Week #22 (Expert Edition) Message-ID: <1094696774.21262.203985993@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "Daniel Martin" To: perl-qotw@plover.com Date: Wed, 08 Sep 2004 22:06:47 -0400 Subject: Solutions and Discussion for Perl Quiz of the Week #22 (Expert Edition) Sample solutions and discussion Perl Quiz of The Week #22 (20040825) Write a program, 'wordladder', which gets two arguments, which are words of the same length, and which constructs and prints a "word ladder" from the first word to the second word. A word ladder from word AAA to word BBB is a sequence of dictionary words such that: 1. the first word in the sequence is word AAA 2. each word in the sequence after the first differs from the previous word in exactly one letter position 3. the last word in the sequence is word BBB For example, given the two words "love" and "hate", the program might print the word ladder: love hove have hate Or it might print: love lave have hate It might also print a longer word ladder, such as love lore lobe robe role rose lose lost most mosh moth math hath hate If the program is unable to find a word ladder, it should print an appropriate error message to the standard error, and exit with a failure status. The program should also accept an optional third argument, which, if specified, is the name of a dictionary file which contains the permissible words. If the third argument is omitted, the program should use a default dictionary. Sample word lists are available from http://perl.plover.com/qotw/words/ --------------------------------------------------- [ MJD: This week's report is a collaboration between three people. Ron Isaacson tested and timed the many solutions and wrote up a timing report. Daniel Martin read over the solutions and analyzed the algorithms used. I selected one sample solution and wrote up an explanation of how it works. My very grateful thanks to Prs. Isaacson and Martin for bailing me out of this one when I bit of far more than I could chew. I now turn you over to Pr. Martin. ] [Daniel Martin] This was a popular quiz, judging by the number of solutions. 23 solutions were submitted from 21 different people. Three solutions weren't tested for one reason or another, leaving 21 solutions to be tested and timed. Many thanks to Ron Isaacson for doing the time-testing. The overall algorithm used by each solution can be classified as follows: - "Expanding circles": 1) Start with just the word AAA as your working set. 2) Find every word which is only one letter different from something in the working set and that hasn't been seen before and make that your new working set. 3) Repeat (2) until BBB is in the working set. This solution can be viewed as Dijkstra's shortest-path algorithm applied to the specifics of this problem. (see http://en.wikipedia.org/wiki/Dijkstra's_algorithm) A variant of this has the circles expanding from both AAA and BBB, and stopping when the two sets intersect. One solution, from Rod Adams, computed each subsequent expanding circle by gathering the words that might be in the next working set and then eliminating those that were not adjacent to something in the previous working set. (It then switched to the more standard version based on an estimate as to which method would be faster) - "workqueue": 1) Place AAA in a queue. 2) Pull a word from the queue and push onto the queue all the adjacent words we haven't seen before. 3) Repeat (2) until BBB is pulled from the queue. (Variation: until BBB is about to be pushed onto the queue) This solution can be viewed as the A* algorithm applied to the specifics of this problem with no estimate of future path length. (see http://en.wikipedia.org/wiki/A-star_search_algorithm) A few people extended this by using a full-blown priority queue, with the priority of a word being (distance from w to BBB) + (length of path to w from AAA) This is the A* algorithm with a distance estimate. As before, there were also bi-directional variants that attacked the path from both ends, stopping when the words seen intersected. Yes, sometimes the classification between "workqueue" and "expanding circles" was a bit of a judgement call about how the code was organized overall. In general if - "depth first": 1) Start at AAA. 2) Pick an adjacent word that hasn't been visited yet. 3) Repeat (2) until you reach BBB or visit everything. If there are no available adjacent words, backtrack. Only two solutions attempted this. Both also sorted the adjacent words so as to first try words closer to BBB. After overall algorithm choice, there were still several other design decisions that could be made. A common source of variation was in how the dictionary was stored. Most solutions used a variation on this design: (code adapted from Colin Meyer's solution) open DICT, '<', $DICT or die "can't open $DICT: $!"; @words = grep length( $_ ) == $SIZE, map { chomp; lc } ; close DICT; for my $w ( @words ) { my @rungs = map { my $c = $w; substr( $c, $_, 1 ) = '_'; $c } 0..($SIZE-1);; push @{ $rung2word{ $_ } }, $w for @rungs; } That is, stored the dictionary as a hash of pattern => wordlist, where "pattern" is the word in question with one character replaced by an '_' (or '?' or '.' or '\0') and "wordlist" is a reference to all words with that pattern. Occasionally, the map word => patternlist would also be recorded. Storing the words in a hash that mapped each word to 1 (or some other value) was also popular. (So that keys %words was used whenever the full list of words was needed) A few stored the dictionary in a single giant array, searching through it with regexps or with Inline::C functions when finding adjacent words. There were also some non-perl solutions submitted: 1 in PIR (Parrot Intermediate Representation - assembly language for Perl 6, sort of), 2 in python, and 1 in scheme. Unfortunately, I have no PIR interpreter and neither of my scheme interpreters was able to handle the submitted scheme solution (guile chokes on the variable name with asterisks in it and mzscheme doesn't know about 'sort'). The python solutions were tested along with the others. Several of the solutions failed to check for certain edge cases. For example, if AAA == BBB, 4 solutions found no path. 3 more solutions found a path only if AAA was adjacent to something (so testing on "transubstantiationalist transubstantiationalist" showed no path for those, but testing "love love" did find a path) Also, some solutions had trouble with very large dictionaries or with long paths. At least one solution made the erroneous assumption that if AAA and BBB differ only in positions 1, 3, and 5, then all the words along the path from AAA to BBB will differ from each other only in positions 1, 3, and 5. This is shown false by the path from "axal" to "utah" in the Web2 dictionary, which among other words passes through "itch". Because of the large number of solutions, I won't go through each one and list the classification. Instead, this chart might be useful: dictionary ->|sig>wordlist|word>1|@DICT search method | | | ================================================== Expanding circles| 0 | 1 | 2 2-dir version | 5 | 0 | 1 -------------------------------------------------- workqueue | 3 | 2 | 0 + distance ver | 2 | 0 | 0 2-dir version | 0 | 1 | 0 -------------------------------------------------- depth first | 0 | 2 | 1 I didn't classify the scheme solution from Greg Bacon, nor the PIR solution from Ingo Blechschmidt. I also did not classify the perl solution sent in by David B., since I was unable to puzzle it out. (I was also unable to test it - it's doing something that eats memory like crazy.) I will note that in general, the depth first solutions all performed very poorly on this quiz, despite two of them coding crucial parts in C. The overall fastest solution was mine, the 2-direction workqueue, though not by much. Ron Isaacson's beautifully-formatted timing report is available at: http://perl.plover.com/qotw/misc/e022/report.html The raw timing data, and the submitted programs, are available at http://perl.plover.com/qotw/misc/e022/ Although the problem merely specified _a_ path from AAA to BBB, many solutions found the shortest path. Therefore, some people speculated on what the "longest shortest path" might be for different word lengths in the different dictionaries. The results can be found in the thread starting here: http://perl.plover.com/~alias/list.cgi?1:mss:2054 ---------------------------------------------------------------- [Mark Dominus] I've decided to use Zed Lopez's program as this week's sample solution. According to Ron Isaacson's report, it's consistently one of the very fastest sumbissions, and it's much shorter than the other comparably fast solutions. Part of that may be due to Zed's use of the Tree::Simple module, which provides functions that manage tree structures: #!/usr/bin/perl use strict; use warnings; use Tree::Simple; And part of it may be due to a somewhat excessively terse coding style, as seen here: my ($start_word, $destination_word, $dictionary_file) = @ARGV; die "You must specify two words of equal length" unless defined $start_word and defined $destination_word and length $start_word == length $destination_word; But on the whole I found the program straightforward and easy to understand. In Daniel Martin's classification, this was an "expanding circles" solution, of the "two directions at once variety". Pr. Lopez's program maintains two working sets of words, and operates on them alternately. On each pass, it finds all the words that are one step removed from the words in the current working set, and replaces the current working set with this new set of words. When it finds a word that is already in the *other* working set, it knows it has found a complete path. $dictionary_file ||= "/usr/share/dict/web2"; open (FH, $dictionary_file) or die "Couldn't open $dictionary_file: $!"; $start_word = lc $start_word; $destination_word = lc $destination_word; my %dict; while () { chomp; $dict{lc $_} = 1 if length $_ == length $start_word and $_ !~ /[^a-zA-Z]/; } close(FH); die "$start_word is not in dictionary" unless exists $dict{$start_word}; die "$destination_word is not in dictionary" unless exists $dict{$destination_word}; The dictionary is the usual Perl implementation of a set, with words as keys, and the values always 1. This code handles the special case if the start word and the end word being the same. Had I thought about it in advance, I might have ruled this out when I posed the problem: print "$start_word\n" and exit if $start_word eq $destination_word; $list and $next_nodes are the main data structures of the program: my ($list, $next_nodes); { my $top = Tree::Simple->new($start_word); my $bottom = Tree::Simple->new($destination_word); $list = [{$start_word => $top}, {$destination_word => $bottom}]; $next_nodes = [[$top],[$bottom]]; } The Tree::Simple objects keep track of tree structures whose roots are labeled with the start and end words; each tree node is labeled with another word. If BBB is in the start-word tree, then a word ladder from the start word to BBB can be found by tracing the path from BBB back to the root. The program's wordchain() function does this: sub word_chain { my $node = shift; my @words; while (1) { push @words, $node->getNodeValue(); last if $node->isRoot; $node = $node->getParent; } return @words; } (->getNodeValue returns the word with which the node is labeled.) $list contains exactly two hashes, one working 'down' from the source word and the other working 'up' from the destination word. Each hash maps words to the Tree::Simple objects that represent them. $next_nodes contains the two 'working sets'. The main loop of the program is: for (my $x = 0; ; $x = !$x) { $next_nodes->[$x] = find_next_nodes($next_nodes->[$x], $x); } The '$x = !$x' is a little obscure; he really means '$x = 1 - $x' here. The main loop alternates between the two working sets, replacing the old working set with the set of words adjacent to it. Calculating this new set of words is the job of find_next_nodes(): sub find_next_nodes { my ($nodes, $x) = @_; my @next_nodes; for my $node (@$nodes) { my $orig_word = $node->getNodeValue(); for (my $i = 0; $i < length $orig_word; $i++) { my $word = $orig_word; for my $char ('a'..'z') { next if $char eq substr $orig_word, $i, 1; substr $word, $i, 1, $char; This last line uses the four-argument form of substr(), which is newish. It was introduced by analogy with the four-argument form of splice(). substr($word, $i, 1, $char) locates the length-1 substring of $word at position $i, just like substr($word, $i, 1), but then replaces this substring with the contents of $char. It is just like >MJD> substr($word, $i, 1) = $char; only faster. The program has just calculated a new word, $word, that is one step removed from some word $orig_word that was in the working set. If this new word is already in the *other* working set, then a complete path has been found: # if word is in other list, we're done success($x ? ($list->[!$x]->{$word}, $node) : ($node, $list->[!$x]->{$word})) if exists $list->[!$x]->{$word}; I would have formatted this differently. I think it's clearer like this: >MJD> success($x ? ($list->[1-$x]->{$word}, $node) >MJD> : ($node, $list->[1-$x]->{$word})) >MJD> if exists $list->[1-$x]->{$word}; The success() function, which we'll see shortly, is responsible for tracing the paths from the common word back to the roots of the two trees, and generating the resulting word ladder. Its arguments are the nodes of the two trees that have the same label, with the node from the top-down tree first. If $x is true (that is, 1) then the current working set is the bottom-up one, so needs to be put second in the argument list of success(). If the program hasn't been succesful, it extends the current tree structure and the new working set: if (exists $dict{$word} and !exists $list->[$x]->{$word}) { my $child = Tree::Simple->new($word); $node->addChild($child); push @next_nodes, $child; $list->[$x]->{$word} = $child; } } } If there were no new words that could be reached from the current node, it is a dead end and is deleted from the tree structure to save memory: prune($node) if $node->isLeaf; } return \@next_nodes; } Here's prune(), which deletes the dead end. After the dead-end node is deleted, prune() checks to see if its parent is now a dead end also: sub prune { my $node = shift; while ($node->isLeaf) { die "No path exists" if $node->isRoot; my $parent = $node->getParent; $parent->removeChild($node); $node = $parent; } } The success() function was called when two nodes were found with the same label, one in each of thee trees. It uses word_chain() to find the word ladders from the common word up to the source word (at $node1) and down to the destination word (at $node2) and appends the two ladders together: sub success { my ($node1, $node2) = @_; print join "\n", (reverse word_chain($node1)), word_chain($node2), ''; exit; } The function avoids listing the common word twice because the common word is never added to the second tree. One of the arguments to success() is the node containing the common word; the other is the node in the other tree that would have been adjacent to the common-word node. Once again, thanks to everyone who participated by sending a solution or adding to the discusion, and thanks also to everyone who participated *without* sending a solution or adding to the discussion. Thanks especially to Ron Isaacson and Daniel Martin. John Trammell is working hard on the writeup of last week's parenthesis-generating quiz; I will send that along when it is ready. I hope to send out the new quiz tonight. From estrabd at yahoo.com Thu Sep 9 07:28:41 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Thu Sep 9 07:28:44 2004 Subject: [Neworleans-pm] Fwd: Perl 'Expert' Quiz of the Week #23 Message-ID: <1094732921.24424.204014001@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "Rick Measham" To: perl-qotw@plover.com Date: Wed, 08 Sep 2004 22:23:24 -0400 Subject: Perl 'Expert' Quiz of the Week #23 IMPORTANT: Please do not post solutions, hints, or other spoilers until at least 60 hours after the date of this message. Thanks. IMPORTANTE: Por favor, no envi?is soluciones, pistas, o cualquier otra cosa que pueda echar a perder la resoluci?n del problema hasta que hayan pasado por lo menos 60 horas desde el env?o de este mensaje. Gracias. WICHTIG: Bitte schicken Sie keine L?sungen, Tipps oder Hinweise f?r diese Aufgabe vor Ablauf von 60 Stunden nach dem Datum dieser Mail. Danke. VNIMANIE: Pozhalujsta ne shlite reshenija, nameki na reshenija, i voobshe lyubye podskazki v techenie po krajnej mere 60 chasov ot daty etogo soobshenija. Spasibo. Qing3 Zhu4Yi4: Qing3 Ning2 Deng3Dao4 Jie1Dao4 Ben3 Xin4Xi2 Zhi1Hou4 60 Xiao3Shi2, Zai4 Fa1Biao3 Jie3Da2, Ti2Shi4, Huo4 Qi2Ta1 Hui4 Xie4Lou4 Da2An4 De5 Jian4Yi4. Xie4Xie4. ---------------------------------------------------------------- The aim this fortnight is to write a tetris game -- a problem that should be both fun to write and fun to use. The problem is split into three milestones. Each milestone adds functionality to the game to the point where we can play each other across the internet. #----------------------------------------------------------------------- PRIMARY MILESTONE: Write a single-user tetris game. #----------------------------------------------------------------------- Tetris is a simple graphical game that can be implemented on almost any interface, from a text display to a full-blown three dimensional graphical interface. A game grid is 10 spaces wide and 20 spaces high. Gravity pulls random blocks toward the bottom of the grid until the bottom surface of any portion of the block touches another block or the bottom of the game grid. Gravity pulls blocks downward at a rate starting at one space per second (we'll call that the 'gravity-period'. The player can alter the way the block drops in four ways: - Move left: The player can move the dropping block one space to the left - Move right: The player can move the dropping block one space to the right - Move down: The player can move the dropping block one space down - Rotate: The player can rotate the block clockwise 90 degrees (optionally you may also allow an anti-clockwise rotate) The player is not limited to the number of actions they take in each gravity-period by anything other than the speed of the interface. There are seven block shapes that fall: ## @@ %% *** &&& ++++ $$$ ## @@ %% * & $ Once the block reaches ground-level another gravity-period elapses before it is cemented in place. This allows the player to move the block left or right at the last moment, as shown below. The '#' block is moved: 4|&& | |&& | 3|& ## | |&## | 2|& ## | |&## | 1+----------+ +----------+ ABCDEFGHIJ ABCDEFGHIJ Each time a complete horizonal row in the grid is completed, its contents disappear and the contents of the rows above it drop down to fill the vacated spaces. The example below shows a block landing and completing row 2. One gravity-period later, row 2 has disappeared, and rows 3 and 4 have dropped down one space: 4|&& | | | 3|&## & | |&& | 2|&##++++&&&| |&## & | 1|++++ ++++| |++++ ++++| +----------+ +----------+ ABCDEFGHIJ ABCDEFGHIJ After each 10 complete rows are deleted in this way, the difficulty level increases. Difficulty level $n's gravity-period is (1 / 1.3**($n-1)) seconds. Each completed row scores the user $c * $n where $c is the number of blocks removed at a single time (in the default grid, that would be 10 times the number of rows removed as there are 10 columns). The aim of the game is to successfully place as many blocks as possible before one of the blocks touches the top of the grid. Here's a game that's finished -- you'll note that the top '%' block touches the top of the grid: +----------+ 20| % | 19| %% | 18| % | 17| + | 16| + | 15| + | 14| + | 13| && | 12| & | 11| & | 10| + | 9| + | 8| + | 7| + | 6| & | 5| & | 4| && | 3| ## | 2| ## | 1|++++ | +----------+ ABCDEFGHIJ The player scores one point for each unit of the perimeter of the dropped shape that touches a previously dropped block or the edge of the grid. In the example game below, the '&' block was dropped onto a blank grid and scored 5 points. Then the '$' block was then dropped and scored 3 points: two points for its two contacts with the '&' block and one point for its contact with the bottom of the grid: 4| $ | 3|& $$ | 2|&&&$ | 1+----------+ ABCDEFGHIJ You may choose to use any reasonable interface that you want. It will be interesting to see solutions in ncurses, tk or anything else. (Note that I'll be testing it on MacOS-X and RedHat linux) The interface should show the entire game grid and should also show which block will drop next. Any of the above options can be changed except the block shapes. You can allow users to change the gravity-period or the grid size. However, the defaults are as above. The default action keys should be: Z - left X - right / - down ' - rotate If you have extra time, you may want to implement some of the following extensions to the project: #----------------------------------------------------------------------- EXTENSION 1 Allow two-user game play #----------------------------------------------------------------------- In this version of the quiz you will allow a second user to select which block will drop next. This selection will be from three randomly selected blocks and should be selected using the 1, 2 and 3 keys. These three pieces should be displayed in the interface. Should the second player not select a block before it is needed, one should be selected at random from the three choices. #----------------------------------------------------------------------- EXTENSION 2 Write a split engine/interface tetris game #----------------------------------------------------------------------- In this version of the quiz the interface should be split from the engine. Two interfaces should be able to link to a given engine, one for each player. (Optionally, extra interfaces may connect but only to view the game, not play) The interface should connect to the engine via a network socket. The command set should be standardised so your interface can plug into my engine or vice versa. The client will send the server commands on each keypress: LEFT RIGHT DOWN ROTATE A second client (for player 2) can send: ONE TWO THREE to indicate the selected piece. In the split game (where the two players are using different clients) there is no requirement for player 1 to see the three options given to player 2 until one becomes the 'next block'. The server will send the client diffs of the game board. The following change would be transmitted as: D03 D02 B03#B02# 4|&& | |&& | 3|& ## | |&## | 2|& ## | |&## | 1+----------+ +----------+ ABCDEFGHIJ ABCDEFGHIJ The format of the message string is: ($col,$row,$piece) =~ /([A-J])(\d\d)([\Q#@%*&+$\E])/ #----------------------------------------------------------------------- REFERENCES #----------------------------------------------------------------------- Screenshot of original tetris: http://www.mobygames.com/images/shots/original/1018986079-00.gif History of tetris (from Atari's point of view -- there was a court battle): http://www.atarihq.com/tsr/special/tetrishist.html Javascript Implementation of the game if you've never played it: http://www.js-games.de/eng/games/tetris From estrabd at yahoo.com Fri Sep 10 10:25:09 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Fri Sep 10 10:25:18 2004 Subject: [Neworleans-pm] Fwd: Solutions and Discussion for Perl Quiz of the Week #23 Message-ID: <1094829909.11714.204108392@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "John J. Trammell" To: perl-qotw@plover.com Date: Fri, 10 Sep 2004 11:11:04 -0400 Subject: Solutions and Discussion for Perl Quiz of the Week #23 Sample solutions and discussion Perl Quiz of The Week #23 (20040901) =head1 NAME qotw-r23.pod - Summary of the Perl Quiz of the Week, #23 (regular) =head1 SYNOPSIS The following programmers sent solutions to "regular" Perl Quiz #23 to the perl-qotw-discuss mailing list: Rod Adams Kester Allen Greg Bacon (5 solutions) Roger Burton West Leo Cacciari (2 solutions) Tom Coleman Jereme Corrado Andrew Dalke (Python) Jos? Alves de Castro Mark Jason Dominus Christian D?hl (2 solutions) Darren Dunham (2 solutions) Kevin Earls Shlomi Fish Bruce J. Keeler (3 solutions, 1 in C) Ronald J. Kimball Zed Lopez (2 solutions) Muir Manders (2 solutions) Daniel Martin (3 solutions) James Mastros Xavier Noria (2 solutions) Yitzchak Scott-Thoennes (4 solutions) Ariel Shaqed (2 solutions) John J. Trammell Bill Tucker (2 solutions) Matthew Walton (2 solutions, 1 in Haskell) Zsban Ambrus (Ruby) The bulk of the solutions submitted were in Perl. There was one submission in C, one in Python, one in Ruby, and one in Haskell. All tests of Perl code were run on a 2.4 GHz Intel Celeron running Debian (sarge) GNU/Linux . The Perl version used was 5.8.4. All code used in creating this summary is available for download; see http://perl.plover.com/qotw/misc/r023/ =head1 THE QUIZ The quiz text reads: Write a program, 'parens', which gets a command line argument, 'n', which is an integer. The program should print all the properly-balanced strings of parentheses of length 2n. For example, given the argument '3', the program should print these five lines: ((())) (()()) (())() ()(()) ()()() in some order. (The order is not important.) For the argument '1'; the output should be: () and for argument '4', the output should be: (((()))) ((()())) ((())()) ((()))() (()(())) (()()()) (()())() (())(()) (())()() ()((())) ()(()()) ()(())() ()()(()) ()()()() in some order. =head1 RESULTS =head2 Correctness Code output was judged on four criteria: The solution output lists only balanced strings ("B"). The solution output lists the correct number of strings ("N"). The solution output lists the strings in lexical order ("L"). The solution output lists only unique strings ("U"). Criterion "L" is optional, but included as a talking point. Programs that did not compile, or didn't approximate the invocation and the output described in the problem text were skipped. The results for the Perl code are: adams.pl skip allen.pl B N U bacon1.pl B L U bacon2.pl B N L U bacon3.pl B N L U bacon4.pl B N U bacon5.pl B N U burton_west.pl B N L U cacciari1.pl B N L U cacciari2.pl B N L U coleman.pl B L U corrado.pl B N L U dalke.py B N L U decastro.pl B L U demerphq.pl skip dominus.pl B N U duehl1.pl B N L U duehl2.pl B N L U dunham1.pl B N U dunham2.pl B N L U earls.pl L U fish.pl B N L U keeler1.pl B N U keeler2.pl B N L U kimball.pl B N L U lopez1.pl B N L U lopez2.pl B N L U manders1.pl B N U manders2.pl B N U martin1.pl B N U martin2.pl B N U martin3.pl B N L U mastros.pl B N L U noria1.pl B N U noria2.pl B N L U scott_thoennes1.pl B N U scott_thoennes2.pl B N U scott_thoennes3.pl B N U scott_thoennes4.pl B N U shaqed1.pl B N U shaqed2.pl B N U trammell.pl B N L U tucker1.pl B N L U tucker2.pl B N L U walton2.pl B N U The results for the non-Perl code are: dalke.py skip keeler3.c B N L U walton1.lhs skip zsban.rb B N L U =head1 TIMING The following timing results represent the time in seconds for each script to generate the complete output for N=0 through N=12 three times. Programs that generated incorrect output are omitted. shaqed1.pl 4.486572 martin3.pl 4.496771 shaqed2.pl 4.584533 mastros.pl 6.25906 dominus.pl 6.568825 scott_thoennes2.pl 6.592227 keeler2.pl 9.353995 scott_thoennes3.pl 9.723624 martin1.pl 10.399679 manders2.pl 10.489536 fish.pl 10.569164 manders1.pl 10.926351 walton2.pl 14.059723 lopez3.pl 15.483148 tucker1.pl 16.3078 lopez1.pl 17.085956 noria2.pl 18.488001 dalke.py 19.863028 cacciari1.pl 20.803137 tucker2.pl 23.346204 cacciari2.pl 23.992838 burton_west.pl 27.436623 scott_thoennes1.pl 28.85522 trammell.pl 35.020822 bacon5.pl 46.568366 lopez2.pl 47.324535 keeler1.pl 53.49667 noria1.pl 58.954158 dunham2.pl 60.137515 kimball.pl 62.261176 allen.pl 82.689522 bacon4.pl 85.976964 scott_thoennes4.pl 96.830828 duehl2.pl 115.1553 corrado.pl 133.964715 duehl1.pl 147.731797 dunham1.pl 259.267496 martin2.pl 1263.874676 bacon2.pl 1616.085711 =head1 ANALYSIS The many solutions included * "brute force" algorithms that produced all combinations of ) and (, then filtered out invalid strings * more subtle "brute force" algorithms based on combinations of known valid strings of shorter length * recursive solutions that built valid strings from left to right, or built long valid strings by combining shorter ones * more interesting, subtle, or complicated solutions, that I'll need more time to digest A straightforward recursive solution was posted by Shlomi Fish (fish.pl): 1 #!/usr/bin/perl -w 2 3 use strict; 4 5 my $N = shift; 6 7 sub recurse 8 { 9 my ($string, $num_opened, $num_closed) = (@_); 10 if (($num_opened == $N) && ($num_closed == $N)) 11 { 12 print "$string\n"; 13 return; 14 } 15 elsif ($num_opened < $N) 16 { 17 recurse("$string(", $num_opened+1, $num_closed); 18 } 19 if ($num_opened > $num_closed) 20 { 21 recurse("$string)", $num_opened, $num_closed+1); 22 } 23 } 24 25 recurse("", 0, 0); 26 Lines 1-5 set the stage, turning on strictures and warnings, and establishing $N as the number of matched pairs to produce. Lines 7-23 define function recurse(), clearly the meat of this solution. Function recurse() takes three arguments: => an accumumlated string => the number of "("s => the number of ")"s The if-block on line 10 decides that the string is "finished" if the number of open parens equals and the number of close parens both equal $N. Recursion stops and the solution is returned if this condition is met. The elsif-block on line 15 and the if-block on line 19 consider two possibilities: * if adding a "(" is still possibly valid, call recurse() on "$string(" * if adding a ")" is still possibly valid, call recurse() on "$string)" Line 25 begins the recursion, starting recurse() with arguments representing an empty string and no open or closed parens. Several of the submitted solutions used this algorithm, including Matthew Walton's Haskell solution. =head2 Another Recursive Solution [Mark Dominus] Several programmers observed that the set of balanced strings can be recursively describes as the smallest set that contains the empty string and also all strings of the form "(S)S", where S is another balanced string, and wrote programs to generate balanced strings by applying this transformation. Leo Cacciari and Zsban Ambrus's programs did this, for example. Here is Pr. Cacciari's program: #!/usr/bin/perl -wl use strict; my $n = shift; my @stack = qw(S); while (@stack) { my $str = pop @stack; my $nt = ($str =~ tr!S!S!); my $par = (length($str) - $nt)/2; if ($par == $n) { $str =~ s!S!!g; print $str; } elsif ($nt <= $n) { if ($nt > 1) { (my $new = $str) =~ s!S!!; push @stack,$new; } $str =~ s!S!(S)S!; push @stack,$str; } } The program does a depth-first search of the space of all strings that can be generated from 'S' by turning an 'S' into either '(S)S' or '': S / \ (S)S / \ / \ ()S ((S)S)S / \ / \ / \ / \ () ()(S)S (()S)S (((S)S)S)S / \ | / \ / \ ... ((()S)S)S ((((S)S)S)S)S / \ | | ()()S ()((S)S)S ... ... / \ | ()() ()()(S)S ... | ... Language theory tells us that the order in which the S's are replaced does not matter, so the program can replace them left-to-right. The program maintains a stack, @stack, of forms to be investigated; initially this contains only the base form 'S'. On each pass, the program pops the top form from the stack and counts the number of S's (in $nt) and the number of pairs of parentheses it contains, in $par. If the number of parentheses is correct for the desired output ($par == $n) then all remaining S's are replaced with the empty string (s!S!!g) and the form is printed. Otherwise, if the form is too big to possibly produce useful output ($nt > $n) it is discarded. If not discarded, the first S is replaced with (S)S, and the resulting form is pushed onto the stack for later processing. Also, if the form has more than one S, the first S in the original form is replaced with the empty string, and the resulting form is *also* put onto the stack. cacciari2.pl is a minor variation that avoids recalculating $nt and $par for each node by storing this information on the stack as well. Zsban Ambrus's program zsban.rb is a Ruby implementation of a similar algorithm. In Pr. Zsban's program, the strings with N pairs of parentheses are generated by selecting all possible combinations of a string I of i pairs and a string J of j pairs of parentheses, where i+j+1 = N 0 <= i,j < N and then generating the string "(I)J". Pr. Zsban's program keeps cached lists of all the strings of balanced parentheses of size < N, for time efficiency. =head2 Another algorithm [Mark Dominus] I had originally planned to do something recursive, but after tinkering a little I found a really excellent, non-obvious algorithm which has excellent speed and space performance and an extremely simple implementation: #!/usr/bin/perl -l print $_ = "()" x shift; print while s{^ ( \(+ ) ( \)+ ) \( } {"()" x (length($2) - 1) . "(" x (length($1) - length($2) + 2) . ")" }xe; A drawback of this approach is that it does not generate the output in lexicographic order; however, a minor variation (modify the right end of the string instead of the left end) *does* generate the output in lexicographic order. Alternatively, piping the output of this program through perl -ple '$_ = reverse; tr/()/)(/' is a cheap way to put the output into lexicographic order, without sorting. A detailed explanation of this algorithm is available at http://perl.plover.com/~alias/list.cgi?1:mss:2118 =head2 A Wrong Solution [John J. Trammell] I must confess, my first solution to this quiz was wrong. I was happy to find I had some company. :^) Specifically, I noticed that from the N=2 solution: (()) ()() generating the N=3 solution: ((())) (())() ()(()) (()()) ()()() was as simple as a map and a filter: @n3 = map { ("$_()","($_)","()$_") } @n2; @n3 = unique(@n3); The problem with this approach is seen at N=4, in generating the valid string: (())(()) and similar strings for N=5, etc. [ A lot of people made this mistake! - MJD ] =head1 Thanks [Mark Dominus] Many thanks to everyone who particpiated in the discussion or who sent in solutions. I was not expecting this quiz to be as popular as it was, or to see so many different solutions. Many thanks also to John J. Trammell for his work in testing and timing the submitted programs and writing the report, and, as always, to the legions of quiet programmers who did the quiz but didn't post anything about it. =cut From EmailLists at SimonDorfman.com Fri Sep 10 11:27:15 2004 From: EmailLists at SimonDorfman.com (Simon Dorfman) Date: Fri Sep 10 11:27:24 2004 Subject: [Neworleans-pm] Meeting today at 5pm Message-ID: Just a reminder... See y'all tonight. Simon http://neworleans.pm.org/ We meet the second Friday of each month, upstairs at the Fair Grinds Coffeehouse in New Orleans (3133 Ponce de Leon, a few doors down from the Whole Foods on Esplanade). The official part of the meeting is from 5pm to 7pm, but we encourage folks to socialize in the coffeehouse downstairs afterwards. Fair Grinds offers free wireless access to the Internet, so bring your favorite wi-fi toy if you want to play on-line. From donnie at solomonstreet.com Fri Sep 10 11:47:24 2004 From: donnie at solomonstreet.com (Donnie Cameron) Date: Fri Sep 10 11:47:16 2004 Subject: [Neworleans-pm] Meeting today at 5pm In-Reply-To: References: Message-ID: <4141DA9C.7020405@solomonstreet.com> Hi All, I'll certainly be there tonight, but I might be a little late. --Donnie Simon Dorfman wrote: > Just a reminder... > See y'all tonight. > Simon > > http://neworleans.pm.org/ > We meet the second Friday of each month, upstairs at the Fair Grinds > Coffeehouse in New Orleans (3133 Ponce de Leon, a few doors down from the > Whole Foods on Esplanade). > > The official part of the meeting is from 5pm to 7pm, but we encourage folks > to socialize in the coffeehouse downstairs afterwards. Fair Grinds offers > free wireless access to the Internet, so bring your favorite wi-fi toy if > you want to play on-line. > > > _______________________________________________ > NewOrleans-pm mailing list > NewOrleans-pm@mail.pm.org > http://mail.pm.org/mailman/listinfo/neworleans-pm > From dave at gnofn.org Fri Sep 10 12:17:56 2004 From: dave at gnofn.org (Dave Cash) Date: Fri Sep 10 12:18:02 2004 Subject: [Neworleans-pm] Meeting today at 5pm In-Reply-To: References: Message-ID: <20040910121639.U88271@sparkie.gnofn.org> On Fri, 10 Sep 2004, Simon Dorfman wrote: > Just a reminder... > See y'all tonight. > Simon > > http://neworleans.pm.org/ > We meet the second Friday of each month, upstairs at the Fair Grinds > Coffeehouse in New Orleans (3133 Ponce de Leon, a few doors down from the > Whole Foods on Esplanade). > > The official part of the meeting is from 5pm to 7pm, but we encourage folks > to socialize in the coffeehouse downstairs afterwards. Fair Grinds offers > free wireless access to the Internet, so bring your favorite wi-fi toy if > you want to play on-line. My idea for the meeting tonight is "Teach Joey and Simon Perl". I figured the Davids and Donnie could team teach Joey and Simon (and who ever else is a newbie to Perl) some Perl. What do y'all think? Dave /L\_/E\_/A\_/R\_/N\_/T\_/E\_/A\_/C\_/H\_/L\_/E\_/A\_/R\_/N\ Dave Cash Power to the People! Frolicking in Fields of Garlic Right On-Line! dave@gnofn.org Dig it all. From donnie at solomonstreet.com Fri Sep 10 12:27:22 2004 From: donnie at solomonstreet.com (Donnie Cameron) Date: Fri Sep 10 12:27:11 2004 Subject: [Neworleans-pm] Meeting today at 5pm In-Reply-To: <20040910121639.U88271@sparkie.gnofn.org> References: <20040910121639.U88271@sparkie.gnofn.org> Message-ID: <4141E3FA.7000402@solomonstreet.com> Good. And we can talk a little more about OO programming too. (But I thought Joey already knew how to program in Perl.) --Donnie Dave Cash wrote: > On Fri, 10 Sep 2004, Simon Dorfman wrote: > > >>Just a reminder... >>See y'all tonight. >>Simon >> >>http://neworleans.pm.org/ >>We meet the second Friday of each month, upstairs at the Fair Grinds >>Coffeehouse in New Orleans (3133 Ponce de Leon, a few doors down from the >>Whole Foods on Esplanade). >> >>The official part of the meeting is from 5pm to 7pm, but we encourage folks >>to socialize in the coffeehouse downstairs afterwards. Fair Grinds offers >>free wireless access to the Internet, so bring your favorite wi-fi toy if >>you want to play on-line. > > > My idea for the meeting tonight is "Teach Joey and Simon Perl". I > figured the Davids and Donnie could team teach Joey and Simon (and > who ever else is a newbie to Perl) some Perl. > > What do y'all think? > > Dave > > /L\_/E\_/A\_/R\_/N\_/T\_/E\_/A\_/C\_/H\_/L\_/E\_/A\_/R\_/N\ > Dave Cash Power to the People! > Frolicking in Fields of Garlic Right On-Line! > dave@gnofn.org Dig it all. > _______________________________________________ > NewOrleans-pm mailing list > NewOrleans-pm@mail.pm.org > http://mail.pm.org/mailman/listinfo/neworleans-pm > From joey at joeykelly.net Fri Sep 10 13:06:39 2004 From: joey at joeykelly.net (Joey Kelly) Date: Fri Sep 10 12:54:05 2004 Subject: [Neworleans-pm] Meeting today at 5pm In-Reply-To: <4141E3FA.7000402@solomonstreet.com> References: <20040910121639.U88271@sparkie.gnofn.org> <4141E3FA.7000402@solomonstreet.com> Message-ID: <200409101306.39236.joey@joeykelly.net> On Friday 10 September 2004 12:27 pm, Donnie Cameron spake: > Good. And we can talk a little more about OO programming too. > > (But I thought Joey already knew how to program in Perl.) Yes and no. I can stumble through it, but the syntax of the different operators is what slows me down. -- Joey Kelly < Minister of the Gospel | Linux Consultant > http://joeykelly.net "I may have invented it, but Bill made it famous." --- David Bradley, the IBM employee that invented CTRL-ALT-DEL From estrabd at yahoo.com Sat Sep 11 11:12:21 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Sat Sep 11 11:12:23 2004 Subject: [Neworleans-pm] Fwd: [ADMIN] Volunteers for older QOTW sample solutions? Message-ID: <1094919141.31090.204162395@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "Mark Jason Dominus" To: perl-qotw@plover.com Date: Sat, 11 Sep 2004 05:16:07 -0400 Subject: [ADMIN] Volunteers for older QOTW sample solutions? Now that the quiz writeups are being handled by volunteers, I thought it might be possible to find people to volunteer to fill in the missing writeups from the past. In the past, I haven't always sent out a discussion or a sample solution for every QOTW. I wanted to send out reports for each one, but sometimes I didn't have enough time or energy to do it. One time I kept putting off the report so that I could do a little more research, and then a little more, and then I never did the report at all. If you were unsure about volunteering to do a writeup, this would be an easy way to find out what it would be like. The job is the same, but there is no deadline and no time pressure. If you find that writing the report is too much work, you can quit, and, nobody will care, or even notice. If you do finish the report, it will be a completely unexpected bonus for the other mailing list subscribers. So writing one of these old reports is a no-lose opportunity for you. The quizzes that are missing reports are: "Regular" quizzes: http://perl.plover.com/qotw/r/010 (Guess-the-animal game) http://perl.plover.com/qotw/r/012 (Histogram function) http://perl.plover.com/qotw/r/015 (Greek clock) "Expert" quizzes: http://perl.plover.com/qotw/e/008 (Graham's function) http://perl.plover.com/qotw/e/009 (Interactive spelling checker) http://perl.plover.com/qotw/e/010 (Self-correcting guess-the-animal) http://perl.plover.com/qotw/e/012 (Expand escape sequences) http://perl.plover.com/qotw/e/015 ('patch') If you think you might like to try this, choose a quiz, read the quiz question, and then come up with a sample solution for it. You can do this by writing the sample solution yourself, or by looking over the old posts on the perl-qotw-discuss mailing lists to find a sample solution that someone else posted. The list is archived at: http://perl.plover.com/~alias/list.cgi/1/ http://news.gmane.org/thread.php?group=gmane.comp.lang.perl.qotw.discuss Remember that sample solutions for "regular" quizzes may only use features that are explained in "Learning Perl", by Schwartz and Phoenix. The sample solution you include should be accompanied by at least a brief description of how it works and an explanation of any design decisions that seem noteworthy. If other people posting to the -discuss list used different approaches, it would be good if you could describe them. If you're going to try to do this, you could drop me a note letting me know, but you don't have to; it's enough just to surprise me with the finished report when you're done. If you want me to give you advice, or assistance, or anything else, please don't hesitate to send me mail. All correspondence, including finished reports, should be sent to mjd@plover.com. Thanks! From estrabd at yahoo.com Thu Sep 16 13:08:56 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Thu Sep 16 13:09:01 2004 Subject: [Neworleans-pm] Fwd: Perl Quiz of the Week #24 (Turing Machine simulation) Message-ID: <1095358136.14866.204529050@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "Zed Lopez" To: perl-qotw@plover.com Date: Wed, 15 Sep 2004 10:01:18 -0400 Subject: Perl Quiz of the Week #24 (Turing Machine simulation) IMPORTANT: Please do not post solutions, hints, or other spoilers until at least 60 hours after the date of this message. Thanks. WICHTIG: Bitte schicken Sie keine L?sungen, Tipps oder Hinweise f?r diese Aufgabe vor Ablauf von 60 Stunden nach dem Datum dieser Mail. Danke. BELANGRIJK: Stuur aub geen oplossingen, hints of andere tips in de eerste 60 uur na het verzendingstijdstip van dit bericht. Waarvoor dank. VNIMANIE: Pozhalujsta ne shlite reshenija, nameki na reshenija, i voobshe lyubye podskazki v techenie po krajnej mere 60 chasov ot daty etogo soobshenija. Spasibo. UWAGA: Prosimy nie publikowac rozwiazan, dodatkowych badz pomocniczych informacjii przez co najmniej 60 godzin od daty tej wiadomosci. Dziekuje. ---------------------------------------------------------------- When computer scientists want to study what is computable, they need a model of computation that is simpler than real computers are. One model they use is called a "Turing Machine". A Turing Machine has three parts: 1. One state register which can hold a single number, called the state; the state register has a maximum size specified in advance. 2. An infinite tape of memory cells, each of which can hold a single character, and a read-write head that examines a single square at any given time. 3. A finite program, which is just a big table. For any possible number N in the register, and any character in the currently-scanned memory cell, the table says to do three things: It has a number to put into the register, replacing what was there before,; it has a new character to write into the current memory cell, replacing what was there before, and it has an instruction to the read-write head to move one space left or one space right. This may not seem like a very reasonable model of computation, but computer scientists have exhibited Turing machines that can do all the things you usually want computers to be able to do, such as performing arithmetic computations and running interpreter programs that simulate the behavior of other computers. They've also showed that a lot of obvious `improvements' to the Turing machine model, such as adding more memory tapes, random-access memory, more read-write heads, more registers, or whatever, don't actually add any power at all; anything that could be computed by such an extended machine could also have been computed by the original machine, although perhaps more slowly. Finally, a lot of other totally different models for computation turn out to be equivalent in power to the Turing machine model. Each of these models has some feature about it that suggests that it really does correspond well to our intuitive idea of what is computable. For example, the lambda calculus, a simple model of funbction construction and invocation, turns out to be able to compute everything that can be computed by Turing Machines, and nothing more. Random-access machines, which have a random-access addressible memory like an ordinary computer, also turn out to be able to compute everything that can be computed by Turing Machines, and nothing more. So there is a lot of evidence that the Turing Machine, limited though is appears, actually does capture our intuitive notion of what it means for something to be computable. For the Regular Quiz of the Week 24, we'll implement a Turing Machine. Let's say that the tape will only hold Perl "word" characters, A-Z a-z 0-9 _ And let's also say that we can give symbolic names of the form /\w+/ to the values that can be stored in the state register. Then a Turing Machine's program will be a list of instructions that look like this: SomeState 1 OtherState 0 L This means that if the Turing Machine's state register contains "SomeState", and there's a 1 in the tape square under the read/write head, it should replace the 1 with a 0, move the read/write head to the left (by one space -- it can only move one space at a time), and store "OtherState" in the state register. '#' will introduce comments, so this instruction is the same: SomeState 1 OtherState 0 L # flip-flop There is one of these state transition instructions per line. The five required elements in each instruction (old state, old tape symbol, new state, new tape symbol, and read/write head motion) are separated by one or more whitespace characters. States' labels are made of word characters. The current symbol and new symbol can be any word character (as specified in the definition of finite alphabet, above.) Blank lines or lines consisting only of a comment are acceptable, and are ignored. Your program should take two parameters: the filename of a file containing the state transition instructions, and the tape's initial contents. The filename is required. The tape is assumed to be filled with '_' characters forever in both directions on either side of the specified initial value, so an initial value argument of "123_456abc" really means "...______123_456abc______...". If the initial tape argument is omitted, the tape is assumed to be full of "_" symbols. The "_" symbols are called "blanks". If an initial value for the tape is specified, the read/write head begins over the first character of that initial value. In the example above, the read/write head is initially positioned over the "1" symbol. If no tape is specified, then the read/write head begins over one of the blanks (which, conceptually, could be any location on the tape.) Please note that the read/write head _can_ move to the left of its initial position, as the tape extends an arbitrary length in both directions. The Turing Machine's initial state is the first state mentioned in the state transition instructions (i.e. the current state defined on the first instruction line.) If, for a given state and current symbol under the read/write head, the Turing Machine does not have any instructions specified in the state transition table, it halts, and your program should print out the tape from the first non-blank character to the last non-blank character, and exit. Your program should die with an error message if it encounters a badly formatted line in the state transition instruction file. EXAMPLES: If binary_incr.tm contains: s0 1 s0 1 R # Seek right to the end of the numeral s0 0 s0 0 R s0 _ s1 _ L s1 1 s1 0 L # Scan left, changing 1s to 0's s1 0 s2 1 L # Until you find the rightmost 0 s1 _ s2 1 L # or fall off the left end of the numeral s2 1 s2 1 L # Seek left to the left end of the numeral s2 0 s2 0 L s2 _ s3 _ R # ... and then stop and your program is in tm.pl, then the output of tm.pl binary_incr.tm 0011001 should be: 0011010 (This state transition table implements incrementing a binary string by 1.) If helloworld.tm contains: s0 _ s1 h R s1 _ s2 e R s2 _ s3 l R s3 _ s4 1 R s4 _ s5 o R s5 _ s6 _ R s6 _ s7 w R s7 _ s8 o R s8 _ s9 r R s9 _ s10 l R s10 _ s11 d R then tm.pl helloworld.tm should output: hello_world if multiply.tm contains: start 1 move1right W R # mark first bit of 1st argument move1right 1 move1right 1 R # move right til past 1st argument move1right _ mark2start _ R # square between 1st and 2nd arguments found mark2start 1 move2right Y R # mark first bit of 2nd argument move2right 1 move2right 1 R # move right til past 2nd argument move2right _ initialize _ R # square between 2nd argument and answer found initialize _ backup 1 L # put a 1 at start of answer backup _ backup _ L # move back to leftmost unused bit of 1st arg backup 1 backup 1 L # ditto backup Z backup Z L # ditto backup Y backup Y L # ditto backup X nextpass X R # in position to start next pass backup W nextpass W R # ditto nextpass _ finishup _ R # if square is blank we're done. finish up nextpass 1 findarg2 X R # if square is not blank go to work. mark bit findarg2 1 findarg2 1 R # move past 1st argument findarg2 _ findarg2 _ R # square between 1st and 2nd arguments findarg2 Y testarg2 Y R # start of 2nd arg. skip this bit copy rest testarg2 _ cleanup2 _ L # if blank we are done with this pass testarg2 1 findans Z R # if not increment ans. mark bit move there findans 1 findans 1 R # still in 2nd argument findans _ atans _ R # square between 2nd argument and answer atans 1 atans 1 R # move through answer atans _ backarg2 1 L # at end of answer__write a 1 here go back backarg2 1 backarg2 1 L # move left to first unused bit of 2nd arg backarg2 _ backarg2 _ L # ditto backarg2 Z testarg2 Z R # just past it. move right and test it backarg2 Y testarg2 Y R # ditto cleanup2 1 cleanup2 1 L # move back through answer cleanup2 _ cleanup2 _ L # square between 2nd arg and answer cleanup2 Z cleanup2 1 L # restore bits of 2nd argument cleanup2 Y backup Y L # done with that. backup to start next pass finishup Y finishup 1 L # restore first bit of 2nd argument finishup _ finishup _ L # 2nd argument restored move back to 1st finishup X finishup 1 L # restore bits of 1st argument finishup W almostdone 1 L # restore first bit of 1st arg. almost done almostdone _ halt _ R # done with work. position properly and halt then tm.pl multiply.tm 1111_11111 should output: 1111_11111_1111111111111 This program implements multiplication where a quantity n is represented by n+1 1's. So the example above passes it 3 and 4, and the program writes the result, 12, represented as 13 1's, to the end of the tape. REFERENCES Turing Machines were first described by Alan Turing in his 1936 paper, "On Computable Numbers, with an Application to the Entscheidungsproblem [decision-making problem]": http://www.abelard.org/turpap2/tp2-ie.asp From shr3kst3r at gmail.com Thu Sep 16 14:04:30 2004 From: shr3kst3r at gmail.com (shrek) Date: Thu Sep 16 14:04:32 2004 Subject: [Neworleans-pm] Fwd: Perl Quiz of the Week #24 (Turing Machine simulation) In-Reply-To: <1095358136.14866.204529050@webmail.messagingengine.com> References: <1095358136.14866.204529050@webmail.messagingengine.com> Message-ID: I found this one to be alot of fun. http://www.engrowe.com/code/perl/qotw/qotw_regular_24.pl On Thu, 16 Sep 2004 13:08:56 -0500, E. Strade, B.D. wrote: > > > ===== > http://www.brettsbsd.net/~estrabd > > __________________________________ > Do you Yahoo!? > Yahoo! SiteBuilder - Free, easy-to-use web site design software > http://sitebuilder.yahoo.com > > > > ----- Original message ----- > From: "Zed Lopez" > To: perl-qotw@plover.com > Date: Wed, 15 Sep 2004 10:01:18 -0400 > Subject: Perl Quiz of the Week #24 (Turing Machine simulation) > > IMPORTANT: Please do not post solutions, hints, or other spoilers > until at least 60 hours after the date of this message. > Thanks. > > WICHTIG: Bitte schicken Sie keine L?sungen, Tipps oder Hinweise f?r > diese Aufgabe vor Ablauf von 60 Stunden nach dem Datum dieser > Mail. Danke. > > BELANGRIJK: Stuur aub geen oplossingen, hints of andere tips in de > eerste 60 uur na het verzendingstijdstip van dit > bericht. Waarvoor dank. > > VNIMANIE: Pozhalujsta ne shlite reshenija, nameki na reshenija, i > voobshe lyubye podskazki v techenie po krajnej mere 60 chasov > ot daty etogo soobshenija. Spasibo. > > UWAGA: Prosimy nie publikowac rozwiazan, dodatkowych badz pomocniczych > informacjii przez co najmniej 60 godzin od daty tej wiadomosci. > Dziekuje. > > ---------------------------------------------------------------- > > When computer scientists want to study what is computable, they need a > model of computation that is simpler than real computers are. One > model they use is called a "Turing Machine". A Turing Machine has > three parts: > > 1. One state register which can hold a single number, called the > state; the state register has a maximum size specified in > advance. > > 2. An infinite tape of memory cells, each of which can hold a > single character, and a read-write head that examines a single > square at any given time. > > 3. A finite program, which is just a big table. For any possible > number N in the register, and any character in the > currently-scanned memory cell, the table says to do three > things: It has a number to put into the register, replacing > what was there before,; it has a new character to write into > the current memory cell, replacing what was there before, and > it has an instruction to the read-write head to move one space > left or one space right. > > This may not seem like a very reasonable model of computation, but > computer scientists have exhibited Turing machines that can do all the > things you usually want computers to be able to do, such as performing > arithmetic computations and running interpreter programs that simulate > the behavior of other computers. > > They've also showed that a lot of obvious `improvements' to the Turing > machine model, such as adding more memory tapes, random-access memory, > more read-write heads, more registers, or whatever, don't actually add > any power at all; anything that could be computed by such an extended > machine could also have been computed by the original machine, > although perhaps more slowly. > > Finally, a lot of other totally different models for computation turn > out to be equivalent in power to the Turing machine model. Each of > these models has some feature about it that suggests that it really > does correspond well to our intuitive idea of what is computable. For > example, the lambda calculus, a simple model of funbction construction > and invocation, turns out to be able to compute everything that can be > computed by Turing Machines, and nothing more. Random-access > machines, which have a random-access addressible memory like an > ordinary computer, also turn out to be able to compute everything that > can be computed by Turing Machines, and nothing more. > > So there is a lot of evidence that the Turing Machine, limited though > is appears, actually does capture our intuitive notion of what it > means for something to be computable. > > For the Regular Quiz of the Week 24, we'll implement a Turing Machine. > > Let's say that the tape will only hold Perl "word" characters, > > A-Z > a-z > 0-9 > _ > > And let's also say that we can give symbolic names of the form /\w+/ > to the values that can be stored in the state register. > > Then a Turing Machine's program will be a list of instructions that > look like this: > > SomeState 1 OtherState 0 L > > This means that if the Turing Machine's state register contains > "SomeState", and there's a 1 in the tape square under the read/write > head, it should replace the 1 with a 0, move the read/write head to > the left (by one space -- it can only move one space at a time), and > store "OtherState" in the state register. > > '#' will introduce comments, so this instruction is the same: > > SomeState 1 OtherState 0 L # flip-flop > > There is one of these state transition instructions per line. The > five required elements in each instruction (old state, old tape > symbol, new state, new tape symbol, and read/write head motion) are > separated by one or more whitespace characters. > > States' labels are made of word characters. > > The current symbol and new symbol can be any word character (as > specified in > the definition of finite alphabet, above.) > > Blank lines or lines consisting only of a comment are acceptable, and > are ignored. > > Your program should take two parameters: the filename of a file > containing the state transition instructions, and the tape's initial > contents. The filename is required. > > The tape is assumed to be filled with '_' characters forever in both > directions on either side of the specified initial value, so an > initial value argument of "123_456abc" really means > "...______123_456abc______...". If the initial tape argument is > omitted, the tape is assumed to be full of "_" symbols. The "_" > symbols are called "blanks". > > If an initial value for the tape is specified, the read/write head > begins over the first character of that initial value. In the example > above, the read/write head is initially positioned over the "1" > symbol. If no tape is specified, then the read/write head begins over > one of the blanks (which, conceptually, could be any location on the > tape.) > > Please note that the read/write head _can_ move to the left of its > initial position, as the tape extends an arbitrary length in both > directions. > > The Turing Machine's initial state is the first state mentioned in the > state transition instructions (i.e. the current state defined on the > first instruction line.) > > If, for a given state and current symbol under the read/write head, > the Turing Machine does not have any instructions specified in the > state transition table, it halts, and your program should print out > the tape from the first non-blank character to the last non-blank > character, and exit. > > Your program should die with an error message if it encounters a badly > formatted line in the state transition instruction file. > > EXAMPLES: > > If binary_incr.tm contains: > > s0 1 s0 1 R # Seek right to the end of the numeral > s0 0 s0 0 R > s0 _ s1 _ L > > s1 1 s1 0 L # Scan left, changing 1s to 0's > s1 0 s2 1 L # Until you find the rightmost 0 > s1 _ s2 1 L # or fall off the left end of the numeral > > s2 1 s2 1 L # Seek left to the left end of the numeral > s2 0 s2 0 L > s2 _ s3 _ R # ... and then stop > > and your program is in tm.pl, then the output of > > tm.pl binary_incr.tm 0011001 > > should be: > > 0011010 > > (This state transition table implements incrementing a binary string > by 1.) > > If helloworld.tm contains: > > s0 _ s1 h R > s1 _ s2 e R > s2 _ s3 l R > s3 _ s4 1 R > s4 _ s5 o R > s5 _ s6 _ R > s6 _ s7 w R > s7 _ s8 o R > s8 _ s9 r R > s9 _ s10 l R > s10 _ s11 d R > > then > > tm.pl helloworld.tm > > should output: > > hello_world > > if multiply.tm contains: > > start 1 move1right W R # mark first bit of 1st argument > move1right 1 move1right 1 R # move right til past 1st > argument > move1right _ mark2start _ R # square between 1st and 2nd > arguments found > mark2start 1 move2right Y R # mark first bit of 2nd argument > move2right 1 move2right 1 R # move right til past 2nd > argument > move2right _ initialize _ R # square between 2nd argument > and answer found > initialize _ backup 1 L # put a 1 at start of answer > backup _ backup _ L # move back to leftmost unused > bit of 1st arg > backup 1 backup 1 L # ditto > backup Z backup Z L # ditto > backup Y backup Y L # ditto > backup X nextpass X R # in position to start next pass > backup W nextpass W R # ditto > nextpass _ finishup _ R # if square is blank we're done. finish > up > nextpass 1 findarg2 X R # if square is not blank go to work. > mark bit > findarg2 1 findarg2 1 R # move past 1st argument > findarg2 _ findarg2 _ R # square between 1st and 2nd arguments > findarg2 Y testarg2 Y R # start of 2nd arg. skip this bit copy > rest > testarg2 _ cleanup2 _ L # if blank we are done with this pass > testarg2 1 findans Z R # if not increment ans. mark bit move > there > findans 1 findans 1 R # still in 2nd argument > findans _ atans _ R # square between 2nd argument > and answer > atans 1 atans 1 R # move through answer > atans _ backarg2 1 L # at end of answer__write a 1 here go > back > backarg2 1 backarg2 1 L # move left to first unused bit of > 2nd arg > backarg2 _ backarg2 _ L # ditto > backarg2 Z testarg2 Z R # just past it. move right and test > it > backarg2 Y testarg2 Y R # ditto > cleanup2 1 cleanup2 1 L # move back through answer > cleanup2 _ cleanup2 _ L # square between 2nd arg and answer > cleanup2 Z cleanup2 1 L # restore bits of 2nd argument > cleanup2 Y backup Y L # done with that. backup to start next > pass > finishup Y finishup 1 L # restore first bit of 2nd argument > finishup _ finishup _ L # 2nd argument restored move back to 1st > finishup X finishup 1 L # restore bits of 1st argument > finishup W almostdone 1 L # restore first bit of 1st arg. > almost done > almostdone _ halt _ R # done with work. position properly and > halt > > then > > tm.pl multiply.tm 1111_11111 > > should output: > > 1111_11111_1111111111111 > > This program implements multiplication where a quantity n is > represented by n+1 1's. So the example above passes it 3 and 4, and > the program writes the result, 12, represented as 13 1's, to the end > of the tape. > > REFERENCES > > Turing Machines were first described by Alan Turing > in his 1936 paper, "On Computable Numbers, with an Application to the > Entscheidungsproblem [decision-making problem]": > > http://www.abelard.org/turpap2/tp2-ie.asp > > > _______________________________________________ > NewOrleans-pm mailing list > NewOrleans-pm@mail.pm.org > http://mail.pm.org/mailman/listinfo/neworleans-pm > -- "I don't care what everyone likes. Ogres are not like cakes... You dunce, irritating, miniature beast of burden. Ogres are like onions. End of story. Bye bye. See ya later..." -- Shrek From estrabd at yahoo.com Tue Sep 21 12:11:06 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Tue Sep 21 12:11:16 2004 Subject: [Neworleans-pm] Fwd: Solutions and Discussion for Perl Quiz of the Week #24 (Turing Machine simulation) Message-ID: <1095786666.3861.204841816@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "Zed Lopez" To: perl-qotw@plover.com Date: Tue, 21 Sep 2004 11:23:41 -0400 Subject: Solutions and Discussion for Perl Quiz of the Week #24 (Turing Machine simulation) Sample solutions and discussion Perl Quiz of The Week #24 (20040915) There were 14 Perl solutions, one in Python, one in Ruby, and a whole bunch of interesting Turing Machines contributed -- I was thrilled by the play this quiz inspired. Here's my solution, with annotations: #!/usr/bin/perl use strict; use warnings; my ($filename, $input) = @ARGV; die "Usage: $0 filename [input]" if !defined $filename or @ARGV > 2; Make sure the program has exactly 1 or 2 input parameters. my (%table, $state, @tape, $head); Define the Turing Machine's basic elements as global variables. my %movehead = (L => -1, R => 1); Initialize a hash for converting the state transition table's direction symbol to a value suitable for adding to an array subscript. open (FH, $filename) or die "Can't open $filename: $!"; while () { Open and start reading the state transition file. next if !/\S/ or /^\s*#/; Skip all-blank and blank-but-for-comment lines. chomp; my ($cur_state, $cur_symbol, $new_state, $new_symbol, $dir) = /^\s*(\w+)\s+(\w)\s+(\w+)\s+(\w)\s+(L|R)(?:\s*#.*)?/ or die "Bad instruction at $filename line $.: $_"; Use a complicated regexp to parse the line, error-checking at the same time. $state = $cur_state unless defined $state; Set the initial state. $table{$cur_state, $cur_symbol} = [$new_state, $new_symbol, $movehead{$dir}]; Load the %table hash with an arrayref consisting of the corresponding info. $table{$cur_state, $cur_symbol} is equivalent to $table{join $;, $cur_state, $cur_symbol}. In Perl 4, this was the usual implementation of multidimensional arrays; it can still be a convenient way to simulate a hash whose keys have multiple parts. } close (FH); die "No instructions present in $filename" unless defined $state; Die if there was no state table (which also means there's no current state.) @tape = defined $input ? split //, $input : ('_'); The tape is implemented as an ordinary Perl array, which will be extended in either direction as necessary. Initialize the tape to the input string or a single '_' character. $head = 0; Initialize $head, the current position of the tape, which will be used as a subscript to @tape. while (defined (my $instruction = $table{$state, $tape[$head]})) { This is the Turing Machine algorithm. While there is a state transition defined for the current state and the current character... my $move; ($state, $tape[$head], $move) = @$instruction; $head += $move; Change the state to the new state; write the new character to the tape; move the head. push @tape, '_' if $head > $#tape; # grow tape to the right unshift @tape, '_' and $head++ if $head < 0; # grow tape to the left Extend the tape to either direction, if necessary. } If the loop exits, there was no transition defined for the current state and current character, so the Turing Machine should halt. shift @tape while @tape and $tape[0] eq '_'; pop @tape while @tape and $tape[-1] eq '_'; Clean up '_' characters from both sides of the tape. print join '', @tape, "\n"; Print the contents of the tape. As some early respondents noted, this quiz was simpler than it might have seemed at first glimpse. A Turing Machine's definition spells out the algorithm that will drive any implementation. Two major points on which the submissions differed were the data structure of the state table and the implementation of the infinite tape. (I was happy to see the Python and Ruby submissions, but as I don't speak those languages, I'm not going to comment on their internals.) For the data structure, a hash of hashrefs whose values were arrayrefs was most popular, used by Burton West, Dominus, Ericson, Fuglerud, Modi, Nielsen, and Sanderson. For instance, from Dominus' program: $transition{$instate}{$intape} = [$outstate, $outtape, $motion{$motion}]; Instead of arrayrefs, Pletinckx, Rafferty, Tucker, and Varga used a hashref so they could name the values, as shown by Rafferty's program: $states{$start}{$input} = { end => $end, output => $output, dir => $dir }; Kimball's program, which uses only Llama Book features, used a hash whose key contains the state name and current symbol delimited by a space, and whose value was space delimited string of the next state, next symbol, and direction. $instructions{"$current_state $current_char"} = "$new_state $new_char $direction"; (This program is available at http://perl.plover.com/qotw/misc/r024/kimball.pl ) Dominus outlined some approaches to representing the infinite tape: http://perl.plover.com/~alias/list.cgi?1:mss:2230 >Getting an infinite tape is not as difficult as some people seemed to >think it would be. There are at least three techniques that occurred >to me. One would be to have > > TAPE(n) is stored in $tape[1 - 2*$n] when n < 0 > in $tape[ 2*$n] when n >= 0 > >and an alternative would use this as a backend to a tied array which >would interpret the negative subscripts transparently. > >A third way is the way I did it in this program, which I think is >simple and elegant. Most people used that third way (Dominus, Ericson, Fuglerud, Pletinckx, Quint, Sanderson, Tucker, and myself, as shown above.) [ MJD: I should have pointed out that the tied array technique can also be used in conjunction with the third approach, so that I really listed either two or four techniques, depending on how you count. ] Everyone else came up with still more ways. Burton West, Kimball, Nielsen, and Varga used a hash; Rafferty used an object based an a hash. Modi used a string. To test the programs' behavior on good programs, I used binary_incr.tm, hello_world.tm (complete with typo), and multiply.tm (unary multiplication) from the examples in the quiz, plus the binary_add, stack and parens tm's that people submitted to qotw-discuss, plus the following: echo.tm: s0 _ s1 _ R This should just echo the input string. If passed nothing, or if passed a string containing only '_' characters, it should print nothing. 0.tm: 0 1 0 1 R 0 0 0 0 R 0 _ 1 _ L 1 1 1 0 L 1 0 2 1 L 1 _ 2 1 L 2 1 2 1 L 2 0 2 0 L 2 _ 3 _ R This is binary_incr with a state named 0. As Dominus noted, if a program depends on the truth of a state name as opposed to whether it's defined, it will fail for this valid case. And two more tests suggested by discussion on qotw-discuss. nostate1.tm: A 1 B 1 L This should work the same as echo. nostate2.tm a _ b 1 R b _ c _ R c _ d _ R d _ e _ R e X stop X R If there was no input string, output 1. If the input string begins with a blank, replace the blank with a 1 and print it. Otherwise, just print the input string. Finally, I tested them on a series of invalid inputs, for which they should die: bad1.tm: a@ a b 1 R # bad state name bad2.tm: a b c d q # bad direction bad3.tm a ? b c L # bad current symbol bad4.tm a b c $ L # bad new symbol bad5.tm a b * c L # bad new state bad6.tm a a a a # no more! bad7.tm 1 2 3 4 5 6 7 # too many elements Finally, I tested them on empty.tm, which was an empty file. The specification did not make explicit what the behavior in this case should be. From the definition of a Turing Machine, I think it's most sensible to consider this an error case: a Turing Machine must have a state transition table and a current state. But I don't consider any particular behavior correct or incorrect for this case, as it wasn't defined. Some of the programs went into infinite loops. In some cases, I'm giving people credit for dying when I shouldn't because I broke out of my test program while it was running a submission that was in an infinite loop. The solutions of Dalke, Tucker, Rafferty, Ericson, Gray, Kimball, and Quint passed all of the tests. Of the remaining submissions, one didn't parse comments. A couple of them didn't correctly strip leading and trailing underscores. echo.tm posed a problem for some, as did dealing with state names of '0' or input of '0'. The nostate tms were also a common source of trouble. One went into an infinite loop if it ended with a blank tape. So though Turing Machines are simple, getting everything right in an implementation of even a simple thing isn't easy. My testing program, the tm files, the verbose results, and everyone's submissions are available from http://perl.plover.com/qotw/misc/r024/ for those who'd like to play along at home. Note that the testing program goes into infinite loops when the submissions do. Thanks to everyone who participated (including those who didn't submit solutions.) From estrabd at yahoo.com Wed Sep 22 10:04:52 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Wed Sep 22 10:05:01 2004 Subject: [Neworleans-pm] PAR - jar for perl Message-ID: <1095865492.31351.204918251@webmail.messagingengine.com> Any one ever use PAR? http://par.perl.org/index.cgi ... looks like a very awesome tool! I plan on playing with it soon, and I would love to hear about anyone's experience with it. Brett ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com From estrabd at yahoo.com Thu Sep 23 08:47:05 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Thu Sep 23 08:47:07 2004 Subject: [Neworleans-pm] Fwd: Perl 'Expert' Quiz-of-the-Week #24 (Module dependency evaluation) Message-ID: <1095947225.24888.204997536@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "Randy W. Sims" To: perl-qotw@plover.com Date: Thu, 23 Sep 2004 05:54:34 -0400 Subject: Perl 'Expert' Quiz-of-the-Week #24 (Module dependency evaluation) IMPORTANT: Please do not post solutions, hints, or other spoilers until at least 60 hours after the date of this message. Thanks. IMPORTANTE: Por favor, no envi?is soluciones, pistas, o cualquier otra cosa que pueda echar a perder la resoluci?n del problema hasta que hayan pasado por lo menos 60 horas desde el env?o de este mensaje. Gracias. WICHTIG: Bitte schicken Sie keine L?sungen, Tipps oder Hinweise f?r diese Aufgabe vor Ablauf von 60 Stunden nach dem Datum dieser Mail. Danke. BELANGRIJK: Stuur aub geen oplossingen, hints of andere tips in de eerste 60 uur na het verzendingstijdstip van dit bericht. Waarvoor dank. Qing3 Zhu4Yi4: Qing3 Ning2 Deng3Dao4 Jie1Dao4 Ben3 Xin4Xi2 Zhi1Hou4 60 Xiao3Shi2, Zai4 Fa1Biao3 Jie3Da2, Ti2Shi4, Huo4 Qi2Ta1 Hui4 Xie4Lou4 Da2An4 De5 Jian4Yi4. Xie4Xie4. ---------------------------------------------------------------- If you've ever written any modules then you are probably familiar with the concept of requirements or prerequisites. These are dependencies that must be met in order for your module to work correctly. For example, if your module uses another module then that module must be present on the user's system in order for your module to function correctly. If you've used MakeMaker then you've probably written something like: use ExtUtils::MakeMaker; WriteMakefile( NAME => 'Your::Module', VERSION_FROM => 'lib/Your/Module.pm', PREREQ_PM => { 'Test::More' => 0, 'File::Spec' => 0.82, }, ); or with Module::Build: use Module::Build; my $build = Module::Build->new( module_name => 'Your::Module', license => 'perl', requires => { 'File::Spec' => 0.82, }, build_requires => { 'Test::More' => 0, ), ); $build->create_build_script; Both of the above say tell their respective build tools that File::Spec version 0.82 or above and any version of Test::More are required. Module::Build is a little more flexible in that it lets you indicate that a module is required only during the build phase (build_requires) or that a module is recommended but not required (recommends). Further, Module::Build lets you be more specific about versions, using comparison operators. For example: requires => { 'Some::Module' => '>= 0.7, != 1.0, < 2.0', } Says that a version of Some::Module of 0.7 or greater, excluding version 1.0 and less than version 2.0 is required. However, even with Module::Build's greater flexibility there are a lot of requirements that are still not possible to describe. And some modules go to great lengths to do this dynamically. The problem with this is that it makes it more difficult for tools like CPAN.pm, CPANPLUS, and some automated tools to take advantage of without running the Makefile.PL or Build.PL file. Ideally, it would be nice to specify complex requirements in the now standard META.yml file, which contains meta data about a distribution in YAML format (http://yaml.org/). Then we could have a standard module that can read those requirements and validate them. This module could be used by Module::Build, ExtUtils::MakeMaker, CPAN.pm, CPANPLUS, and any other tool that needs to validate requirements. The types of things we would like to handle in the requirements specification are boolean expressions && (and), || (or), and ^^ (xor); grouping with parenthesis; and macro definition and expansion. An example of boolean expressions (suggested by a discussion with David Wheeler and Ken Williams on the module-build list) would be: requires => q[ (DBD::Pg && DateTime::Format::Pg) || (DBD::mysql && DateTime::Format::mysql) ] This says that we need any version of either of these two sets of modules. If we need to, we can also include version specifications: requires => q[ ( DBD::Pg > 1.1 && DateTime::Format::Pg ) || ( DBD::mysql <= 1.2 && DateTime::Format::mysql ) ] Note that when a branch of the 'or' expression evaluates to true, it is not neccessary to evaluate the remaining branches - short-circuit evaluation. However, all branches of an 'and' or 'xor' expression must be evaluated for correct error reporting. Of course we also want to remain compatible as much as possible with the old specifications. For the macros, we're mostly interested in the use of predefined macros. For example: requires => q[ ( Term::Readline::Gnu ) || ( {OSNAME} == MSWin32 && Term::Readline::Perl ) ] (A possible extension would be to add a set operator (in) for versions and any other values such as '{OSNAME} in [VMS MSWin32]' or 'Some::Module in [1.0..1.9 !1.7]'.) Other useful macros might be {MULTITHREADED}, {LARGEFILES}, etc. Finally, it can be useful to allow definition of macros to simplify expressions. For Example: requires => q[ def Pg = DBD::Pg && DateTime::Format::Pg; def mysql = DBD::mysql && DateTime::Format::mysql; {Pg} || {mysql} ] Feel free to experiment with different syntax. The only hard requirements are that it supports: boolean expressions, grouping, and predefined macros. For example, my original suggestion to Ken Williams, Module::Build's author, was something of the form: requires => { 'db_driver' => q[ {postgresql} || {mysql} ], '{postgresql}' => { 'DBD::Pg' => 0, 'DateTime::Format::Pg' => 0, }, '{mysql}' => { 'DBD::mysql' => 0, 'DateTime::Format::mysql' => 0, } This syntax makes parsing a little simpler, but otherwise allows the same features. The keys with braces around the names are not evaluated; They are definitions of macros that are only evaluated when they appear in the value of another key. This weeks quiz is to write a module (Prereq::Expr) that can take a specification of the type described above, and evaluate it to determine if the requirements are satisfied. The specification is the value assigned to the 'requires' key in the examples above. (Prereq::Expr->eval( $dist{requires} )). It can be either a hash, string, or array, whichever makes more sense. But, it should be able to handle the old style requirements. In order to determine the version of an installed module, I've extracted the routines from Module::Build and put them in a module at: http://perl.plover.com/qotw/misc/e024/Versions.pm Use it like this: use Versions; my $version = Versions->from_module('File::Spec'); or my $version = Versions->from_file('/path/to/module.pm'); To simplify comparisons, you can assume that versions are real numbers and just compare with perl's built-in numeric comparison operators. For the purpose of this quiz, it's not necessary to worry about alpha versions and all the complications of comparing versions. If you are interested, you might check out John Peacock's version and version::alphabeta modules. One of the more interesting problems with this quiz, I think, is the problem of reporting missing requirements. When you can have arbitrarily large sets of alternative modules, it's not obvious (to me) how best to notify the user in an orderly and comprehensible way. I do, of course, have an ulterior motive in this quiz. This form of complex requirements has been on the Module::Build TODO list for a long time. I'd like to submit the solutions posted, with the permission of their respective authors, to Ken Williams for possible inclusion in some form or another in a future version of Module::Build. If you want to implement this in a language other than perl, you can simply replace Versions.pm with a module/class or whatever that simply contains a list of hardcoded versions or whatever make sense for your language of choice. The important part is the expression parsing and evaluation. From dave at gnofn.org Thu Sep 23 08:55:12 2004 From: dave at gnofn.org (Dave Cash) Date: Thu Sep 23 09:48:15 2004 Subject: [Neworleans-pm] PAR - jar for perl In-Reply-To: <1095865492.31351.204918251@webmail.messagingengine.com> References: <1095865492.31351.204918251@webmail.messagingengine.com> Message-ID: <20040923085423.Y81146@sparkie.gnofn.org> On Wed, 22 Sep 2004, E. Strade, B.D. wrote: > Any one ever use PAR? http://par.perl.org/index.cgi ... looks like a > very awesome tool! I plan on playing with it soon, and I would love to > hear about anyone's experience with it. Brett, This looks very cool. I'll be interested to hear about your experiences with it. Take care, Dave /L\_/E\_/A\_/R\_/N\_/T\_/E\_/A\_/C\_/H\_/L\_/E\_/A\_/R\_/N\ Dave Cash Power to the People! Frolicking in Fields of Garlic Right On-Line! dave@gnofn.org Dig it all. From estrabd at yahoo.com Mon Sep 27 08:51:38 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Mon Sep 27 08:51:45 2004 Subject: [Neworleans-pm] Fwd: This week's summary Message-ID: <1096293098.2624.205230355@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "The Perl 6 Summarizer" To: perl6-announce@perl.org Date: Sun, 26 Sep 2004 20:47:39 +0100 Subject: This week's summary The Perl 6 Summary for the week ending 2004-09-24 So, this is my last summary before I start my teaching practice. Hopefully I've got things set up so writing the summary isn't going to interfere with that, and vice versa. This week in perl6-compiler State of Rules Discussion of the state of the Perl 6 compiler (with particular reference to the rules engine) continued. People were concerned with making sure that the rules engine that Luke and Patrick are working on would be flexible enough to cope with different languages in 'closures'. Synopsis 5 updated Ed Peschko asked that there be some way of 'turning the rules engine inside out' to make something which, given a rule, would generate strings that could match against it. Actually, this is the second time Ed asked for this, as Luke reminded him. Luke went on to implement a generator in hypothetical perl 6, which seemed to please everyone but Ed. Rod Adams wins the 'making the summarizer smile wryly' occasional prize. http://xrl.us/c8ax Meanwhile, in perl6-internals Problems Reimplementing Parrot Forth Matt Diephouse fell foul of problems with the "compile" and "compreg" opcodes in his efforts to reimplement Parrot Forth in PIR. Steve Fink made some suggestions for workarounds based on his work on writing a regular expression compiler. From further discussion, it seems that, if you're implementing a stack based language, you'd do well to manage the language's stack yourself rather than using Parrot's User stack which is interestingly scoped. http://xrl.us/c8ay "__init" not being magically called Will Coleda had some problems with a class's "__init" function not being called magically. Nobody else could reproduce the problem. After a certain amount of confusion, Will did "make realclean; perl Configure.pl; make; make test" and all was well again. If you're experiencing a weird problem, it's probably best to do the rebuild before posting to the list. Or you could fix the build system to have more accurate dependencies... http://xrl.us/c8az Incremental collector and finalization Jeff Clites had some questions about how finalizers interact with the work that Leo's been doing on implementing an incremental garbage collector for Parrot. Leo had some thoughts, but noted that there's still a problem with ordered finalization and destruction. [Your summarizer is really starting to get a feel for why old school GC types really don't like finalizers...] http://xrl.us/c8a2 Python bytecode volunteers Dan asked for volunteers to finish the task of getting python bytecode working on Parrot; he reckoned that the work was mostly done, but that neither he nor Leo have the time to go the last couple of yards. Come on people, this would definitely be a cool thing to have. http://xrl.us/c8a3 mod_parrot 0.0 Jeff Horwitz announced the release of version 0.0 of his mod_parrot Apache module. It's remarkably powerful for version 0.0 http://xrl.us/c8a4 The "compile" op and building compilers Dan had some thoughts on tidying up the spec for the "compreg" and "compile" operators and asked for comments before he nailed the spec down. Steve Fink and Leo had comments. http://xrl.us/c8a5 Misc. remarks about YAPC::EU Leo popped up to thank everyone who'd donated to The Perl Foundation and thus supported the purchase of shiny new Apple Powerbook G4 that he'd used to run his presentation at YAPC Europe in Belfast. He went on to outline some of the things he'd done and heard in Belfast, including the fact that one French teacher is using Parrot for teaching assembly language. http://xrl.us/c8a6 Parrot m4 0.0.8 Bernhard Schmalhofer announced version 0.0.8 of Parrot m4. There's no new functionality 'just' some structural improvement and tidying. http://xrl.us/c8a7 Parrot TCL Will Coleda posted a progress report on his Parrot TCL implementation which is progressing gradually towards being a full blown TCL implementation; he's working towards using special Tcl* PMCs with real TCL semantics instead of the current scheme which uses Perl PMCs. http://xrl.us/c8a8 Namespaces, Part 1 Dan posted the first part of his Namespaces spec. There was, of course, much discussion. Inevitably, there was another revision, and further discussion. http://xrl.us/c8a9 http://xrl.us/c8ba -- The revised version Towards a new call scheme Leo posted an overview of the work he was doing on Parrot's internals to get a faster calling scheme in place (as discussed endlessly). The usual perl6-internals discussion and revision process swung into action. http://xrl.us/c8bb Hello everybody Remember the French teacher that Leo mentioned? Well, the man himself, Christian Aperghis-Tramoni popped up on the list and pointed everyone at his work so far, and asked for help in finding more information. If anyone would like to translate Christian's work from French to English... http://xrl.us/c8bc Bits of introspection Leo announced that he'd started work on adding more introspection features to Parrot, accessible through the "interpinfo" op. All of which looks very cool. http://xrl.us/c8bd Why lexical pads Klaas-Jan wondered why Parrot had support for lexical pads, as he thought that PIR's ".local" syntax was good enough... Several people explained (essentially, lexical pads are "really" handy, bordering on the essential, when you're implementing a language with closures). http://xrl.us/c8be Meanwhile, in perl6-language Discussion of various synopses continued. Larry can be very persuasive when he's right. Michele Dondi is a chap. Trying to run a thread across multiple mailing lists is the sort of thing that annoys a summarizer. You have to write something before it goes in the core. Patrick hopes to have a first cut at the Perl 6 rules engine available within a couple of weeks. Pipeline Performance Luke showed off Perl 6's little known "gather {...; take ... }" construct in some example code. People were impressed. http://xrl.us/c8bf Unary dot and custom control Luke Palmer wondered about topicalization and scope in: method foo () { preserve { .bar; } } In particular, he hoped that the topic that ".bar" sees is the topic that's lexically current. Larry set his mind to rest. (Well, he set my mind to rest). http://xrl.us/c8bg attributes/methods on sigils Michele Dondi wondered if sigils could be "(sort of special) operators ... thus allowing attributes/methods or even adverbs". Larry's response was superbly deadpan. http://xrl.us/c8bh The usual footer Hmm... maybe I should trying doing the perl6-language summary like that every week; it's certainly quicker to write like that. Let me know what you think. If you find these summaries useful or enjoyable, please consider contributing to the Perl Foundation to help support the development of Perl. You might also like to send feedback or contributions to a 'getting Piers to OSCON 2005' fund to mailto:pdcawley@bofh.org.uk http://donate.perl-foundation.org/ -- The Perl Foundation http://dev.perl.org/perl6/ -- Perl 6 Development site Or, you can check out my website. http://www.bofh.org.uk/ From estrabd at yahoo.com Mon Sep 27 23:11:42 2004 From: estrabd at yahoo.com (E. Strade, B.D.) Date: Mon Sep 27 23:11:44 2004 Subject: [Neworleans-pm] Fwd: Solutions and Discussion for Perl Quiz of the Week #12 (Histograms) Message-ID: <1096344702.11960.205287865@webmail.messagingengine.com> ===== http://www.brettsbsd.net/~estrabd __________________________________ Do you Yahoo!? Yahoo! SiteBuilder - Free, easy-to-use web site design software http://sitebuilder.yahoo.com ----- Original message ----- From: "John J. Trammell" To: perl-qotw@plover.com Date: Mon, 27 Sep 2004 23:07:57 -0400 Subject: Solutions and Discussion for Perl Quiz of the Week #12 (Histograms) Sample solutions and discussion Perl Quiz of The Week #12 (20030212) [ This is a writeup of a very old quiz for which I never posted a report. I hope to be able to fill in the other missing reports in the coming months. Thanks to John J. Trammell for doing it. -MJD ] NAME qotw-r12-summary.pod - summary of "regular" Perl Quiz of the Week #12 SYNOPSIS The following programmers participated in Quiz 12: James Edward Gray II Kurt Hutchinson David Kershaw Brian King Not a Number Riccardo Perotti Marcelo Ramos John Trammell (late) Their code is available from http://perl.plover.com/qotw/misc/r012/ THE QUIZ The quiz text reads: You'll write functions for displaying histograms (bar charts). We'll use these to display the output from next week's quiz. You're build one function, 'histogram()', whose arguments will be a list of numbers. The function should construct a bar chart and then return a list of strings which, if printed, would display the numbers suitably. For example, histogram(1, 4, 2, 8, 5, 7) might return the following list of strings: " *\n", " * *\n", " * *\n", " ***\n", " * ***\n", " * ***\n", " *****\n", "******\n" when printed, these strings look like this: * * * * * *** * *** * *** ***** ****** The behavior of 'histogram' will be controlled by several global variables. $HISTOGRAM_WIDTH and $HISTOGRAM_HEIGHT will specify the width and height of the result. The output should be scaled to fit in a rectangle with $HISTOGRAM_HEIGHT rows and $HISTOGRAM_WIDTH rows. The bars themselves will be made up of the character $HISTOGRAM_CHAR, which must be a string of length 1. If any of the $HISTOGRAM_ variables are undefined, the function should use reasonable defaults. ISSUES Output Scaling and/or Truncation The main issue with this Quiz was discussed in a thread started by Andy Bach, archived at: http://perl.plover.com/~alias/list.cgi?1:mss:1292 The crux of the issue is this text from the Quiz: $HISTOGRAM_WIDTH and $HISTOGRAM_HEIGHT will specify the width and height of the result. The output should be scaled to fit in a rectangle with $HISTOGRAM_HEIGHT rows and $HISTOGRAM_WIDTH rows. Although all were in agreement that output should not exceed the dimensions specified by $HISTOGRAM_WIDTH and $HISTOGRAM_HEIGHT (see below however), there was some disagreement about whether $HISTOGRAM_WIDTH and $HISTOGRAM_HEIGHT were to be the *exact* width and height, or the *maximum* width and height. Also at issue was the correct behavior in the case where the number of arguments in the histogram() function call was greater than $HISTOGRAM_WIDTH. Arguments were made for and against truncating the histogram rather than making the output width greater than $HISTOGRAM_WIDTH. Miscellaneous Issues The following issues were also mentioned but not discussed at length: * how and whether to represent negative values * what to do with fractional inputs * horizontal vs. vertical histogram orientation * other alternate formatting suggestions (truncation, etc.) Little discussion regarding these issues ensued, although the solution offered by Kurt Hutchinson did handle representation of negative numbers. [This puzzles me, since the histograms I was taught in school always represented the "count" of something in a "bin". Certainly there can be bar graphs with negative values on the vertical axis, but I wouldn't call that a histogram. - JJT "Histogram" is from Greek "histos", meaning a beam or a mast. A histogram is therefore a drawing of beams or masts, and is nothing more or less than a bar chart. - MJD ] EXAMPLE An example solution is listed below (with slight modifications), courtesy of Brian King. sub histogram { my @list = @_; my @response = (); my $x_scale = 1; # horizontal scaling factor my $y_scale = 1; # vertical scaling factor my $max_value = 0; # greatest value (tallest bar) in @list $HISTOGRAM_WIDTH ||= 0; $HISTOGRAM_HEIGHT ||= 0; $HISTOGRAM_CHAR ||= 'H'; $HISTOGRAM_CHAR = unpack('a1',$HISTOGRAM_CHAR); # must be 1 char long. # determine y scaling factor. Increase $HISTOGRAM_HEIGHT # if what we got is too big to fit. foreach( @list ){ if( $_ > $max_value ){ $max_value = $_; } } if($max_value > $HISTOGRAM_HEIGHT){ $HISTOGRAM_HEIGHT = $max_value; } $y_scale = int($HISTOGRAM_HEIGHT / $max_value); # determine x scaling factor. Increase $HISTOGRAM_WIDTH # if we got too many values to fit. Can't just omit some... if( $HISTOGRAM_WIDTH < $#list ){ $HISTOGRAM_WIDTH = $#list; } $x_scale = int($HISTOGRAM_WIDTH / $#list); # build @response, based on @list and scaling factors. # iterate over @list $HISTOGRAM_HEIGHT times. # for each element in @list, if ($_ * scaling factor) is > # current position in the histogram (one less than the y-value of the graph), # then append $x_scale number of $HISTOGRAM_CHAR to the current element # of @response. Otherwise, append $x_scale number of spaces. for( my $i=0; $i<$HISTOGRAM_HEIGHT; $i++ ){ foreach(@list){ if( $_ * $y_scale > $i ){ $response[$i] .= $HISTOGRAM_CHAR x $x_scale; } else{ $response[$i] .= ' ' x $x_scale; } } $response[$i] .= "\n"; } return reverse @response; } Comments on this solution: * $HISTOGRAM_HEIGHT is increased, rather than truncating data * $HISTOGRAM_WIDTH is increased, rather than truncating data * vertical scaling only occurs if $HISTOGRAM_HEIGHT is at least twice as large as the largest input value * horizontal scaling only occurs if $HISTOGRAM_WIDTH is at least twice the number of input values * the histogram is constructed by looping over horizontal histogram slices from bottom to top. Vertical scaling is accomplished by comparing the vertical histogram position $i to a rescaled input value ($_ * $y_scale), and setting the output "pixel" accordingly. Horizontal scaling is accomplished by scaling this pixel by the calculated value $x_scale.