Brandon’s Notepad

January 30, 2012

Getting Google Maps

Filed under: How-To,Online Tools,Perl,Programming — Brandon @ 4:08 pm
Tags: , , , , , , , , ,

So, I’d like to have a current traffic map delivered to my e-mail at the precise moment I’m leaving work for the day. Call me lazy, but this is the sort of thing that can be automated pretty easily and I don’t want to go look it up, I want it delivered. Someday, I’ll get around to setting this up, but as they say, a journey begins with a single step. In this case, the step is to find a way a good to download Google Maps with a script. For now, that is the scope of this post.


Here’s some initial research to plow through:
Mapki: Google Map Parameters Best reference so far!
Google Static Maps API*
A PERL/Wget solution
A Python script
MapTileCacher in PERL
In Bash
Discussion on Google blocking tile downloads

* On 2/7/2012, I tried using the Google Static Maps API and received Error 400 (malformed or illegal request) when using the URL described therein. I have had more luck using Google Maps directly to frame the map, getting the (perma)link, and tweaking the parameters.


January 13, 2012

Single Keystroke Menu Using Term::ReadKey

Filed under: Perl — Brandon @ 11:55 am
Tags: ,

Using Term::ReadKey, you can implement a console menu/prompt that accepts a single keystroke. There are many similar implementations of ReadKey available on the Web. This one is in the form of a reusable subroutine. Only valid options are accepted and the choice is returned to the calling script for futher use. It does not convert the choice to upper- or lower-case, because sometimes it is nice to have both options available.


The Subroutine

This code can be placed in a script or in a separate module.

 1: use Term::ReadKey;
 2:
 3: sub getPromptOption ($$)
 4: {
 5: 	my $prompt  = shift;
 6:	my $options = shift;
 7:	my $choice;
 8:
 9:	ReadMode 'cbreak';
10:	print $prompt;
11:	$choice = ReadKey(0) until $choice =~ m/[$options]/;
12:	ReadMode 'normal';
13:	return $choice;
14: }

Obviously, the Term::ReadKey must be loaded first (line 1). The getPromptOption() subroutine accepts two mandatory parameters as indicated by the declared prototype (line 3). Additional field-validation logic may be desired, but is omitted here for brevity. The terminal’s “read” mode is changed to cbreak, which accepts a single character as input (line 9). The prompt that was passed into the subroutine is printed on the screen (line 10) and then the program enters a loop that reads characters from keyboard input until one of the valid options is entered (line 11). Once a valid key has been pressed, the read mode is returned to normal mode (input accepted until the Enter key is pressed; line 12) and the chosen option is returned to the calling logic (line 13).

Usage

This is a very contrived routine that illustrates the use of the subroutine described above. It allows the user to increment or decrement a current value.

 1. my $i = 0;
 2. my $action = '';
 3. print "Current value: $i\n\n";
 4. until ( $action =~ m/[Xx]/ ) {
 5.	$action = getPromptOption(
 6.		"Select Action: [I]ncr, [D]ecr, or E[X]it",
 7.		"IiDdXx"
 8.	);
 9.	$i++ if ( $action =~ m/[Ii]/ );
10.	$i-- if ( $action =~ m/[Dd]/ );
11.	print "\n\nCurrent value: $i\n\n";
12. }

The iterator (“$i”) is set to an initial value of zero (line 1) and the next action flag (“$action”) set to null (line 2). The current value is printed on the screen (line 3) so that the user knows what it is. Next, the user is prompted to increment or decrement the value, or to exit the program (lines 5-8). If the user chooses to change the value by pressing the “i” key (line 9) or the “d” key (line 10), then the value is printed again on the screen for the benefit of the user (line 11). If the user presses the “x” key, the loop ends (line 4) and process control flows out to the end of the script. Please notice that both the upper- and lower-cases are valid options (line 7), but that the program is indifferent to which is used (lines 4, 9, 10).


January 10, 2012

Tie::File Examples

Filed under: Perl — Brandon @ 3:07 pm
Tags: ,

Using Tie::File, you can operate directly on a text file as an array. This provides random access to lines in a file and allows for speedy manipulation of very large files since the file itself is not loaded into memory. The following are some examples with explanation as to how they work. (Yes, these examples are extremely rudimentary and a bit redundant at that; this is because I like to have complete examples at my fingertips to use as base templates when I need them for real programming work.)


The Data File

Any ASCII text file can be used with the following examples. I use “myfile.txt” for illustrative purposes, and for me, it is a twenty-line file that contains consecutive numbers on each line (line 1 is “1″, line 2 is “2″, etc.). The following code creates this data file and quickly resets it as needed.

1: open (OUT,">myfile.txt");
2: print OUT join("\n",1..20);
3: close OUT;

Basic Example

This is a very basic example for using Tie::File. It just prints the contents of an array on the screen.

1: use Tie::File;
2: my @records;
3: tie @records, 'Tie::File', "myfile.txt";
4: print join ( "\n", @records );
5: untie @records;

The module must first be loaded using the use function (line 1). Next, an array is defined that will be tied to the file (line 2). The tie command is where the magic happens (line 3). Now the lines in the file can be operated upon as though they were just elements in an array. The print/join function is a common way to print an array tot he screen (line 4). The untie function releases the file (line 5), though this is often omitted due to laziness.

Direct Access

Reading a file and printing records is only so much fun. Here’s an example of how to change a single line in the file directly.

1: use Tie::File;
2: my @records;
3: tie @records, 'Tie::File', "myfile.txt";
4: $records[9] = "foo";
5: print join ( "\n", @records );
6: untie @records;

This is the same code as before, except that line 4 has been injected. It is a simple assignment that changes the tenth line of the file to “foo”. Remember that PERL arrays are zero-based, so $records[9] is actually the tenth element in the array.

Autochomp

Notice that newlines must either be chomped on input or readded for output. This is handled automatically.

Windows Newlines

Here’s an interesting trick if you are using PERL on Windows. Consider the following code.

1: use Tie::File;
2: my @records;
3: tie @records, 'Tie::File', "myfile.txt";
4: $records[9] = "foo\nbar";
5: print join ( "\n", @records );
6: untie @records;

Adding a newline character (“\n”) to the array element value will only embed it in the string. Inspect the file afterward, and find that no new line has been created in the file, even though it appears from the screen output that one had been added. Since line endings in Windows are two characters instead of one, carriage-return and linefeed, you must prepend the other character (“\r”).

1: use Tie::File;
2: my @records;
3: tie @records, 'Tie::File', "myfile.txt";
4: $records[9] = "foo\r\nbar";
5: print join ( "\n", @records );
6: untie @records;

Now the file does show an additional line. Of course, there are much better ways of doing this.

Changing Record Separators

Much like the RS and ORS variables in AWK, the record separator can be changed to any text string. This is done when the file is tied. Only this line is presented here.

1: tie @records, 'Tie::File', "myfile.txt", recsep => 'zap';

Now, the file will be separated into records on every occurence of the string ‘zap’. I don’t want to spend the time to write and test a working example for this, as the need for this sort of thing may never arise in my work. It was just interesting to note.

Splicing

To remove one or more lines from a tied file, use the splice command.

1: use Tie::File;
2: my ( @records, @removed );
3: tie @records, 'Tie::File', "myfile.txt";
4: @removed = splice(@records,1,3);
5: print join ( "\n", @records );
6: untie @records;

Again, this is the same code we’ve been using, except an additional array has been declared (line 2) and the splice command has been introduced to remove the second, third, and fourth lines from the file (line 4). The first parameter of the splice function is the array, the second is the offset from the beginning of the array (one element), and the third is the length of the slice to be removed (three elements).

Here’s how elements can be replaced.

1: use Tie::File;
2: my ( @records, @removed );
3: tie @records, 'Tie::File', "myfile.txt";
4: @removed = splice(@records,1,3,26);
5: print join ( "\n", @records );
6: untie @records;

The same records are removed as above, but one new element has been inserted in their place with a value of 26.

Push, Pop, Shift, Unshift

All of these functions have splice equivalents, but they can be used as they normally would to manipulate the tied file.

Iteration

Random access is nice, but sometimes it is necessary to iterate through the records in a file. The following illustrates how to print the contents of the array to the screen by iteration instead of using print/join.

1. use Tie::File;
2. my ( @records, $record );
3. tie @records, 'Tie::File', "myfile.txt";
4. foreach $record ( @records ) { print "$record\n"; }
5: untie @records;

In addition to declaring the array, a record scalar is defined (line 2). The foreach iterator is used as one would expect to traverse through the array from beginning to end. A for loop could have been used just as easily.


August 23, 2011

Slurping Files In Perl

Filed under: Perl — Brandon @ 10:57 am
Tags: , ,

“Slurping” is a technical term that means to import an entire file into memory at one time. This is typically done when the data imported will not be changed, because it is static lookup data for example, or because you want to protect the contents of the file from accidental corruption. I use this technique often and was going to write a how-to post, but it seems that Uri Guttman has already posted an excellent treatment of this topic on the Perl.com blog titled Perl Slurp-Eaze.


February 26, 2010

Using The Windows Clipboard in Perl

Filed under: Perl — Brandon @ 11:05 am

The following snippet illustrates the use of the Win32::Clipboard module.

use Win32::Clipboard;
$clip = Win32::Clipboard();
print "Type your name: ";
$input = <>
chomp $input;
$clip->Set("Hello, $input!");
print "You may now paste!\n";

June 30, 2009

Using Perl Hashes

Filed under: Perl — Brandon @ 10:00 pm

A hash, or associative array, is basically an array that has a textual key instead of a numeric key. Any Perl reference will explain basic usage, but the following is a compilation of items that I almost always have to look up if I have not coded in Perl for a while. A few “tricks” that I’ve learnt over time have been included as well.

Things to Remember

Creating Hashes. Hashes can be created using various methods. Below is the syntax for several options. Each method produces exactly the same result, a hash in which numeric values ’1′ and ’2′ are referenced by their textual equivalents.

%numbers = (); # Create an empty hash.
$numbers{one} = 1; $numbers{two} = 2; # Set one at a time.
%numbers = (one,1,two,2); # Use barewords for key/value pairs.
%numbers = ('one','1','two','2'); # Quote if key or value has spaces.
%numbers = qw(one 1 two 2); # Use a quoted-word list.
%numbers = (one => 1,two => 2); # Force strings on the left.
@numbers{one,two} = (1,2); # In non-intuitive array context.
@numbers{@keys} = @values; # Logical extention of the above.
map { $_ = ++$i } @numbers{one,two}; # Something to ponder.

Elements Existing & Defined.
The ‘exists’ function returns true if they specified key exists in the specified hash, whereas the ‘defined’ function determines if the value of the element has been defined.

The following two commands report the statuses of the key and the value of $hash{$key}:

exists($hash{$key})  ? print 'Exists, and ' : print 'Does not exist, and ';
defined($hash{$key}) ? print 'is defined.'  : print 'is not defined.';

Running these lines only should result in:

Does not exist, and is not defined.

Prepending the the following line, setting the element to an undefined value:

$hash{$key} = undef;

should result in:

Exists, and is not defined.

Prepending the the following line, setting the element to a null value:

$hash{$key} = '';

should result in:

Exists, and is defined.

General Note About Data Structures. Hashes are often used to represent data entities, but how they are used dictates perspective. Consider the following:

  • A simple hash can be analogous to a simple data table and the hash’s key to the table’s primary key. For example, %phone_numbers represents the same thing as a table called “Phone Numbers” and $phone_numbers{‘Bob’} = 555-1234 represents a record in that data table which we now know contains at least two fields, “Name” (pk) & “Number”. Additional fields in the table that (of course) relate to the same key must be stored in a different hash.
  • A hash of (anonymous) hashes eliminates the need to use multiple named hashes to represent fields. For example, %contacts can represent the “Contacts” table in the database, $contacts{‘Bob’} represents the row uniquely identified by the primary key ‘Bob’, and $contacts{‘Bob’}{‘address’}, $contacts{‘Bob’}{‘home phone’}, $contacts{‘Bob’}{‘work phone’}, $contacts{‘Bob’}{‘mobile phone’}, and $contacts{‘Bob’}{‘birthday’} represent the various fields in that table.
  • A hash of arrays can represent a set of named lists. For example, the %lists hash may include $lists{‘To Do’}, $lists{‘Shopping’} & $lists{‘Calls To Make’}. If each of these were a simple string element, this hash wouldn’t be very useful; however, if each contains an array reference, then elements can be pushed, popped, shifted, unshifted, and even grepped, sliced & spliced as needed.
  • Larger structures are simply combinations of these smaller structures. For example, returning to the %contacts example above, $contacts{‘Bob’}{‘call log’} could be an array containing string elements, each noting the date and a brief description of a call to Bob. The first would be referenced as $contacts{‘Bob’}{‘call log’}[0], the second as $contacts{‘Bob’}{‘call log’}[1], and so forth.

Creation of these types of structures is covered next.

Hash of Hashes. Three different methods are used here to create such a structure, though all of the methods for creating hashes as explained above can apply.

# Using anonymous hash constructor.  Structure engineered from the start.
%numbers = (
     german => {
          one => ein,
          two => zwei
     }
);

# Using the constructor inline.  Structure segments built only when needed.
$numbers{spanish} = {
     one => uno,
     two => dos
};

# Using named hashes.  Least efficient and least intuitive.
%french = (
     one => un,
     two => deux
);
$numbers{french} = \%french;

The following code snippet will do two things: illustrate how to reference elements within the structure and prove that the %numbers hash was built according to expectations.

print "Languages: " . join(', ',keys %numbers) . "\n";
foreach $lang (keys %numbers) {
     print "Numbers in $lang:\n";
     foreach $num (keys %{$numbers{$lang}}) {
          print "\t$num == $numbers{$lang}{$num}\n";
     }
}

Let’s interpret this clause from line 5 of the snippet: $numbers{$lang}{$num}. The way to read this is that the first segment, $numbers{$lang}, is translated into a hash reference (a pointer for C programmers), which is used in turn to resolve the second segment, HASH(0×123456){$num}. In the loop on the preceding line, the $numbers{$lang} hash reference is being placed (or “cast”) into hash context using the %{} construct because the keys function expects a hash reference as a parameter.

Hashes of Arrays. Here is one way to create an array as a hash elements and then push values to it.

# Using anonymous array constructor.
%numbers = (
     English => ["zero", "one", "two", "three"],
     German => ["null", "ein", "zwei", "drei"],
     Spanish => ["cero", "uno", "dos", "tres"]
);

# Using push and quoted words.
push(@{$numbers{French}}, qw/ zero un deux trois/);

As with hashes of hashes above, other methods are available, such as using references to named arrays. These have been omitted for brevity. Note the casting of the element into an array context: @{$numbers{French}}. Here is a snippet of code to validate the contents:

foreach $k (sort keys(%numbers)) {
	print "$k numbers are " . join(', ',@{$numbers{$k}}) . ", etc.\n";
}



Hash Tricks

Sort Unique. On multiple occasions, I’ve had the need to remove duplicate values from an array. In the Unix shell, a sort -u works nicely, but Perl’s sort doesn’t work quite that way. Instead of programming this in place each time, I’ve often written a subroutine similar to this one:

sub sort_unique {
     my %h; my $k;
     foreach $k (@_) {
          $h{$k}++;
     }
     return(sort keys(%h));
}

The subroutine accepts a simple list as input. In a loop, elements of the list are used as keys for an internal hash. With each pass, the value of the corresponding hash element is incremented. The list of hash keys is sorted and returned as a list. Strictly speaking, the sorting isn’t mandatory, but otherwise, the keys will be returned in an arbitrary order. A side-benefit that may be exploited is that the number of occurances of each list item is known once the input list is traversed.

Please see this page from the perl.com FAQ for some shorter and more efficient alternatives. Here are modularized variants of options (b):

sub sort_unique {
     undef my %h;
     return sort grep(!$h{$_}++, @_);
}

and (d):

sub sort_unique {
     undef my %h;
     @h{@_} = ();
     return sort keys %h;
}

Again, the sort is optional but nice.



Theme: Rubric. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.