# Regex::Fuzzy.pm
# $Id: Fuzzy.pm,v 0.01 2005/03/04 17:38:42 jkister Exp $
# Copyright (c) 2005 Jeremy Kister.
# Released under Perl's Artistic License.

$Regex::Fuzzy::VERSION = "0.01";

=head1 NAME

Regex::Fuzzy - Utility to match strings via fuzzy regular expressions

=head1 SYNOPSIS

use Regex::Fuzzy;

my $result = Regex::Fuzzy::Compare(string => $string, regex => $regex);

	
=head1 DESCRIPTION

C<Regex::Fuzzy> provides a C<Compare> function for checking a string
against a fuzzy regex.

=head1 CONSTRUCTOR

my $result = Regex::Fuzzy::Compare(string => $string,
                                   regex  => $regex,
                                   debug  => $debug);

=over 4

B<debug> - Print debugging info to STDERR (0=Off, 1=On).

=head1 RETURN VALUE

Here are a list of return codes and what they mean:

=item 0 The supplied regex did not match the string.

=item 1 The supplied regex matched the string, without fuzz.

=item 2 The supplied regex matched the string, with fuzz.

=item 3 Syntax error.

=head1 EXAMPLES

  use Regex::Fuzzy;

  my $string = 'V--1.@--G.R^^a';
  my $regex = 'viagra';

  my $result = Regex::Fuzzy::Compare(string=>$string,regex=>$regex);
  if($result == 2){
    print "Regex matched (with fuzz)\n";
  }elsif($result == 1){
    print "Regex matched (without fuzz)\n";
  }else{
    print "Regex did not match\n";
  }

=head1 CAVEATS


=head1 RESTRICTIONS

=head1 AUTHOR

Jeremy Kister - http://jeremy.kister.net/

=cut

package Regex::Fuzzy;

use strict;

sub Version { $Regex::Fuzzy::VERSION }

sub Compare {
	my %arg = @_;
	return 3 unless $arg{string};
	return 3 unless $arg{regex};

	return 1 if($arg{string} =~ /$arg{regex}/);

	my %fuzz = (a => 'a@',                    c => 'cks', 
	            e => 'e3',                    g => 'gyjq',
	            i => 'i1l!|j', j => 'jigyq',  k => 'kc',   l => 'li1!|',
	            m => 'mn',     n => 'nm',     o => 'o0uew', 
	            q => 'qgjy',                  s => 'sc5z$', t => 't+',
	            u => 'uo0v',   v => 'vu()\/',
	            y => 'ygjq',

	            0 => '0o',     1 => '1il!|',              3 => '3e',
	                           5 => '5s',
		         

	            '!' => '!i1l|', '@' => '@a', '-' => '=-_ ', '"' => '\"\'',
	);

	my $regex;
	foreach my $letter (split //, $arg{regex}){
		if(exists($fuzz{$letter})){
			$regex .= "[$fuzz{$letter}]";
		}else{
			$regex .= $letter;
		}
		$regex .= '{1,3}.{0,4}';
	}

	warn "built regex: /${regex}/i\n" if($arg{debug});

	if($arg{string} =~ /\Q$regex\E/i){
		return 2;
	}else{
		return 0;
	}
}


1;
