#!/usr/bin/env perl use 5.014; use warnings; use Time::HiRes qw/time/; use Benchmark qw/cmpthese timethese/; use Inline 'C'; sub hash_pack($) { join '', sort unpack '(A10)*', shift } sub hash_re($) { join '', sort $_[0] =~ /(\d{10})/g } sub hash_substr($) { my @nums; my $s = shift; while ($s) { push @nums, substr($s,0,10); $s = substr($s,10); } join '',sort @nums; } # Only considers first 3 numbers sub hash_substr2($) { join '', sort substr($_[0],0,10),substr($_[0],10,10),substr($_[0],20,10); } my @funcs = map { "hash_$_" } qw/pack re substr substr2 c/; my @strings = qw/512567000151256700025125670003 512567000251256700015125670003 512567000351256700015125670002/; for my $s (@strings) { printf "%12s(%s) => %s\n", $_, $s, eval "$_(\$s)" for @funcs; } my $s = $strings[0]; cmpthese timethese(-5, { map { $_ => "$_('$s')" } @funcs }); __END__ __C__ /* Try our own splitter sort. This swaps the numbers in-place * as necessary to obtain a sorted order. */ #include #define SIZE 10 #define strswap(s1,s2,size) { \ int i; \ for (i = 0; i < size; i++) { \ s1[i] = s1[i] ^ s2[i]; \ s2[i] = s1[i] ^ s2[i]; \ s1[i] = s1[i] ^ s2[i]; \ } \ } char * hash_c(char *str) { char *n0 = str; char *n1 = str + SIZE; char *n2 = str + SIZE + SIZE; if (strncmp(n0, n1, SIZE) > 0) strswap(n0, n1, SIZE); if (strncmp(n1, n2, SIZE) > 0) strswap(n1, n2, SIZE); if (strncmp(n0, n1, SIZE) > 0) strswap(n0, n1, SIZE); return str; }