#!/usr/bin/perl use strict; use warnings; { use bytes; my %lookup; my @reverse; my $scale; BEGIN { my $x = 0; my @chars = (' ', 0..9, 'A'..'Z'); keys %lookup = 65_536; # preallocate hash buckets for my $i (@chars) { for my $j (@chars) { for my $k (@chars) { $lookup{ $i.$j.$k } = $x; $reverse[$x++] = $i.$j.$k; } } } $scale = $x; } # Functions using multiplication... sub alphanum_to_bytes_M { my $head = $lookup{ substr($_[0], 0, 3) }; my $tail = $lookup{ substr($_[0], 3, 3) }; my $n = ($head * $scale) + $tail; pack(N => $n) } sub bytes_to_alphanum_M { my $n = unpack(N => $_[0]); my $head = int($n / $scale); my $tail = $n - ($head * $scale); $reverse[$head] . $reverse[$tail] } # Functions using bitshifting... { use integer; sub alphanum_to_bytes_B { my $head = $lookup{ substr($_[0], 0, 3) }; my $tail = $lookup{ substr($_[0], 3, 3) }; pack(nn => $head, $tail) } sub bytes_to_alphanum_B { join q{}, @reverse[ unpack(nn => $_[0]) ] } } # Function to pretty-print byte strings for display purposes... sub show_bytes { my ($str) = @_; sprintf 'bytes[%s]', join q{ }, map { sprintf('%02x', ord(substr($str, $_, 1))) } 0 .. length($str)-1 } } my @lines = ; print "MULTIPLICATION:\n"; foreach (@lines) { my $b; chomp; printf( "'%s' => '%s' => '%s'\n", $_, show_bytes($b = alphanum_to_bytes_M($_)), bytes_to_alphanum_M($b), ); } print "BIT SHIFTING:\n"; foreach (@lines) { my $b; chomp; printf( "'%s' => '%s' => '%s'\n", $_, show_bytes($b = alphanum_to_bytes_B($_)), bytes_to_alphanum_B($b), ); } __DATA__ 0 1 A Z ABCDEF ABCDEG ZAAAAA ZZZZZZ