(function(root, factory){
  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
    define(function(){
      return factory(root);
    });
  } else if (typeof module == 'object' && module && module.exports) {
    module.exports = factory(root);
  } else {
    root.Levenshtein = factory(root);
  }
}(this, function(root){

  var forEach;
  // Generics
  if ( ! Array.forEach ) {
    forEach = function ( array, iterator, context ) {
      iterator = context
        ? iterator.bind( context )
        : iterator
      Array.prototype.forEach.call( array, iterator )
    }
  } else {
    forEach = Array.forEach;
  }

  // Levenshtein distance
  function Levenshtein( str_m, str_n ) { var previous, current, matrix
    // Constructor
    matrix = this._matrix = []

    // Sanity checks
    if ( str_m == str_n )
      return this.distance = 0
    else if ( str_m == '' )
      return this.distance = str_n.length
    else if ( str_n == '' )
      return this.distance = str_m.length
    else {
      // Danger Will Robinson
      previous = [ 0 ]
      forEach( str_m, function( v, i ) { i++, previous[ i ] = i } )

      matrix[0] = previous
      forEach( str_n, function( n_val, n_idx ) {
        current = [ ++n_idx ]
        forEach( str_m, function( m_val, m_idx ) {
          m_idx++
          if ( str_m.charAt( m_idx - 1 ) == str_n.charAt( n_idx - 1 ) )
            current[ m_idx ] = previous[ m_idx - 1 ]
          else
            current[ m_idx ] = Math.min
              ( previous[ m_idx ]     + 1   // Deletion
              , current[  m_idx - 1 ] + 1   // Insertion
              , previous[ m_idx - 1 ] + 1   // Subtraction
              )
        })
        previous = current
        matrix[ matrix.length ] = previous
      })

      return this.distance = current[ current.length - 1 ]
    }
  }

  Levenshtein.prototype.toString = Levenshtein.prototype.inspect = function inspect ( no_print ) { var matrix, max, buff, sep, rows
    matrix = this.getMatrix()
    max = matrix.reduce( function( m, o ) {
      return Math.max( m, o.reduce( Math.max, 0 ) )
    }, 0 )
    buff = Array( ( max + '' ).length ).join( ' ' )

    sep = []
    while ( sep.length < (matrix[0] && matrix[0].length || 0) )
      sep[ sep.length ] = Array( buff.length + 1 ).join( '-' )
    sep = sep.join( '-+' ) + '-'

    rows = matrix.map( function( row ) { var cells
      cells = row.map( function( cell ) {
        return ( buff + cell ).slice( - buff.length )
      })
      return cells.join( ' |' ) + ' '
    })

    return rows.join( "\n" + sep + "\n" )
  }

  Levenshtein.prototype.getMatrix = function () {
    return this._matrix.slice()
  }

  Levenshtein.prototype.valueOf = function() {
    return this.distance
  }

  return Levenshtein

}));

@@ -352,75 +352,157 @@
 %0A%0A  
-var forEach;%0A  // Generics%0A  if ( ! Array.forEach ) %7B%0A    forEach =
+function forEach( array, fn ) %7B var i, length%0A    i = -1%0A    length = array.length%0A    while ( ++i %3C length )%0A      fn( array%5B i %5D, i, array )%0A  %7D%0A%0A 
  fun
@@ -507,16 +507,19 @@
 unction 
+map
 ( array,
@@ -523,143 +523,238 @@
 ay, 
-iterator, context ) %7B%0A      iterator = context%0A        ? iterator.bind( context
+fn ) %7B var result%0A    result = Array( array.length )%0A    forEach( array, function ( val, i, array ) %7B%0A      result.push( fn( val, i, array )
  )%0A    
+%7D)%0A
     
-: iterator%0A      Array.prototype.
+return result%0A  %7D%0A%0A  function reduce( array, fn, accumulator ) %7B%0A    
 forEach
-.call
 ( ar
@@ -762,64 +762,105 @@
 ay, 
-iterator )%0A    %7D%0A  %7D else %7B%0A    forEach = Array.forEach;
+function( val, i, array ) %7B%0A      accumulator = fn( val, i, array )%0A    %7D)%0A    return accumulator
 %0A  %7D
@@ -2240,23 +2240,16 @@
 x = 
-matrix.
 reduce( 
 func
@@ -2244,16 +2244,23 @@
 reduce( 
+matrix,
 function
@@ -2300,17 +2300,18 @@
  m, 
-o.
 reduce(
+ o,
  Mat
@@ -2578,17 +2578,18 @@
 = ma
-trix.map(
+p( matrix,
  fun
@@ -2631,16 +2631,17 @@
 s = 
-row.
 map(
+ row,
  fun

Add `forEach`, `map` and `reduce` for ES3 support