adamcrussell

Perl Weekly Challenge 027

Part 1

ch-1.pl
ch-1.pl

What I Did

Using a well known formula [1] I computed the intersection from the four given points. Perhaps the greatest complexity in this code was the handling of the points on the command line. The input format given in this week's challenge required some escaping in the shell and a bit of parsing to get everything organized in an easily usable way.

Sample Run

$ perl perl5/ch-1.pl \(0,0\) \(9,9\) \(0,9\) \(9,0\)
(0, 0)--(9, 9) and (0, 9)--(9, 0) intersect at (4.5, 4.5)

Part 2

Audit.pm
Audit.pm
ch-2.pl
ch-2.pl

What I Did

This part of the challenge stumped me for a while! After a bunch of thought I decided that a source filter would do the trick! I've never used this particular feature of Perl but Filter::Simple made the implementation of the filter itself somewhat straightforward. The filter itself is in Audit.pm. What it does is use a regular expression to identify scalar variables and appends a call to audit() after the nearest semicolon. For example, let's say we have these lines:

    my $a = 0;
   $a = 2 + 2;

the filter will change them to appear as

    my $a = 0; audit($a);
   $a = 2 + 2; audit($a);

This will log the values of the variable in a hash (%Log) keyed by the variable name itself. There are a few other functions that do some convenient things like clear %Log or print the contents of %Log in a formatted way. If you want to see what objects actually contain you'll want to use pretty_print_log() vs print_log(), see the example output below for what the differences are. Note that pretty_print_log() simply wraps Data::Dump's pp() since that did not seem like an appealing wheel to re-invent!

As I was finalizing my submission I had a few final thoughts on this.

  • The name Audit seems to be already taken on CPAN. Since I have no interest in distributing this I think that's OK. My Audit.pm exists solely for this purpose. Hopefully nobody will be confused by the overlap with the name I chose for this small project.
  • I did not test this very much. It seems fairly robust but surely some corner cases exist where this approach will break down!
  • The warnings about the use of source filters seem accurate. That is, unless very clearly documented and understood when used I can see how there is opportunity for significant errors to be introduced into your code in subtle and confusing ways.

Sample Run

$ perl -I perl5 perl5/ch-2.pl

$test0: undef, 2, 3
$test1: bless({
# tied Tie::ExtraHash
A => "B",
}, "Class::Hash"), bless({
# tied Tie::ExtraHash
B => "C",
}, "Class::Hash"), bless({
# tied Tie::ExtraHash
C => "D",
}, "Class::Hash")

Note: If we instead had simply used Audit::print_log() this is what would have been the output. We see that the object references have been changed but do not see the values within the objects.

$test0: undef, 2, 3
$test1: Class::Hash=HASH(0x7fde390b2a70), Class::Hash=HASH(0x7fde38014920), Class::Hash=HASH(0x7fde38014b18)

References

[1]http://www.ambrsoft.com/MathCalc/Line/TwoLinesIntersection/TwoLinesIntersection.htm 

Comments for this post were locked by the author