vladlev 1.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ef4a27d86e0e99dc06744c8978b02a8b21764690
4
+ data.tar.gz: e25a238dddd9e9fec5d4a3ac711ab130a78bdcd0
5
+ SHA512:
6
+ metadata.gz: e987312d3687d68e2e0311ec74fd888486999d70a46c769d35bc0c8919576d464b0b61b081fc67fc862c5134274be925787c42c267a3bc783bebd6482dcd36ad
7
+ data.tar.gz: cfbdc192c0f479680e3059b756971b499fc7ef3eea8eeac1e86cc7e0d60a9eea71fe55abb000026691fdbba0322b96676834951399ba8d7988959b2cbe6f3ab6
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.out
2
+ *.so
3
+ *.swp
4
+ .bundle
5
+ Gemfile.lock
6
+ coverage
7
+ pkg/*
8
+ tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --order rand
3
+ --format RSpec::Pride
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ Vladlev
2
+ ===========
3
+
4
+ An implementation of the levenshtein distance algorithm for ruby using FFI
5
+
6
+ ## Installation
7
+
8
+ Add this line to your gemfile and then run `bundle` to install
9
+
10
+ gem 'vladlev'
11
+
12
+ ## Usage
13
+
14
+ Vladlev will calculate the levenshtein distance between two strings. The levenshtein distance is the number of transforms necessary to transform one string to be idential to the other. A transform is defined as an addition, deletion, or alteration of a single character in a string.
15
+
16
+ In order to calculate the distance
17
+
18
+ Vladlev.distance("string1", "string2")
19
+ >> 1
20
+
21
+ Vladlev also includes a 3 parameter version of the distance method. The third parameter is "maximum distance", which tells Vladlev to stop calculation once the distance becomes greater than this parameter.
22
+
23
+ In order to use this optimization
24
+
25
+ Vladlev.distance("string1234567890", "string1", 1)
26
+ >> 16
27
+
28
+ Vladlev.distance("string1234567890", "string1", 999)
29
+ >> 9
30
+
31
+ When given a pair of strings such that the distance between the two strings is greater than the "maximum distance" paramter, Vladlev will return the length of the longest string rather than spend the effort of calculating the distance when you know that you are not interested in the result.
32
+
33
+ ## Development
34
+
35
+ Vladlev uses rake-compiler for a build tool
36
+
37
+ bundle exec rake compile
38
+
39
+ bundle exec rake clean
40
+
41
+ For an agressive clean of compiled files, you can do this
42
+
43
+ bundle exec rake clobber
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'rubygems/package_task'
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/clean'
5
+
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ spec = Gem::Specification.load('vladlev.gemspec')
10
+
11
+ Gem::PackageTask.new(spec) do |pkg|
12
+ end
13
+
14
+ if RUBY_PLATFORM =~ /java/
15
+ require 'rake/javaextensiontask'
16
+ Rake::JavaExtensionTask.new('levenshtein', spec)
17
+ else
18
+ require 'rake/extensiontask'
19
+ Rake::ExtensionTask.new('levenshtein', spec)
20
+ end
21
+
22
+ task :default => :spec
data/ext/.DS_Store ADDED
Binary file
@@ -0,0 +1,66 @@
1
+ public class LevenshteinDistance {
2
+ private static int minimum(int a, int b, int c) {
3
+ return Math.min(Math.min(a, b), c);
4
+ }
5
+
6
+ public static int distance(String str1, String str2, long maximumDistance) {
7
+ boolean brokeMax = false;
8
+ int rowMinimum;
9
+ int cost;
10
+ String longestString = (str1.length() > str2.length()) ? str1 : str2;
11
+ String shortestString = (str1.length() > str2.length()) ? str2 : str1;
12
+
13
+ if (shortestString.equals(longestString)) {
14
+ return 0;
15
+ } else if (longestString.length() - shortestString.length() > maximumDistance) {
16
+ return longestString.length();
17
+ } else if (shortestString.length() == 0 || longestString.length() == 0) {
18
+ return longestString.length();
19
+ }
20
+
21
+ int[] workingGrid = new int[shortestString.length() + 1];
22
+ int[] calculationGrid = new int[shortestString.length() + 1];
23
+ int[] tempGrid;
24
+
25
+ for (int i = 0; i <= shortestString.length(); i++) {
26
+ calculationGrid[i] = i;
27
+ }
28
+
29
+ for (int i = 1; i <= longestString.length(); i++) {
30
+ rowMinimum = workingGrid[0] = calculationGrid[0] + 1;
31
+
32
+ for (int j = 1; j <= shortestString.length(); j++) {
33
+ cost = (shortestString.charAt(j-1) == longestString.charAt(i-1)) ? 0 : 1;
34
+ workingGrid[j] = minimum(calculationGrid[j]+1, workingGrid[j-1]+1, calculationGrid[j-1]+cost);
35
+ rowMinimum = (workingGrid[j] < rowMinimum) ? workingGrid[j] : rowMinimum;
36
+ }
37
+
38
+ if (rowMinimum > maximumDistance) {
39
+ brokeMax = true;
40
+ break;
41
+ }
42
+
43
+ tempGrid = workingGrid;
44
+ workingGrid = calculationGrid;
45
+ calculationGrid = tempGrid;
46
+ }
47
+
48
+ return brokeMax ? longestString.length() : calculationGrid[shortestString.length()];
49
+ }
50
+
51
+ public static int distance(String str1, String str2) {
52
+ return distance(str1, str2, 9999);
53
+ }
54
+
55
+ public static float normalized_distance(String str1, String str2) {
56
+ return normalized_distance(str1, str2, 9999);
57
+ }
58
+
59
+ public static float normalized_distance(String str1, String str2, long maximumDistance) {
60
+ int maxStringLength = (str1.length() > str2.length()) ? str1.length() : str2.length();
61
+ if(maxStringLength == 0) {
62
+ return 0;
63
+ }
64
+ return distance(str1, str2, maximumDistance) / (float)maxStringLength;
65
+ }
66
+ }
@@ -0,0 +1,5 @@
1
+ unless RUBY_PLATFORM =~ /java/
2
+ require 'mkmf'
3
+
4
+ create_makefile('levenshtein')
5
+ end
@@ -0,0 +1,118 @@
1
+ #include <string.h>
2
+ #include <stdio.h>
3
+ #include <stdlib.h>
4
+
5
+ #ifndef TRUE
6
+ #define TRUE 1
7
+ #define FALSE 0
8
+ #endif
9
+
10
+ #define ALLOC malloc
11
+ #define FREE free
12
+
13
+ /* Used to swap calc and work grids while looping */
14
+ #define LV_SWAP(t, a, b) { t = a; a = b; b = t;}
15
+ #define LV_MIN(a, b, c) ((a <= b) ? ((a <= c) ? a : c) : ((b <= c) ? b : c));
16
+
17
+ /* using a structure that will be filled on init with the variables that will makeup the distance constraints */
18
+ typedef struct{
19
+ char* a;
20
+ char* b;
21
+ int a_length;
22
+ int b_length;
23
+ int maximum_allowable_distance;
24
+ } LevenConstraints;
25
+
26
+ int levenshtein_intern(LevenConstraints* leven)
27
+ {
28
+ /* Check the minimum distance to keep from calculating anything when it isn't really needed
29
+ * Efficient use of the levenshtein call includes a maximum_allowable_distance (or distance threshold) */
30
+ if ((leven->b_length - leven->a_length) > leven->maximum_allowable_distance || (leven->a_length == 0 || leven->b_length == 0)) {
31
+ return (int)leven->b_length;
32
+ }
33
+
34
+ /* no reason to run levenshtein when equal */
35
+ if (leven->a_length == leven->b_length && strcmp(leven->a, leven->b) == 0) {
36
+ return (int)0;
37
+ }
38
+
39
+ leven->a_length++;
40
+ leven->b_length++;
41
+
42
+ int x, *grid_odd, *grid_even, i, j, cost, row_min, distance, *work_grid, *calc_grid, *tmp;
43
+ unsigned int broke_max = FALSE;
44
+
45
+ grid_even = ALLOC(sizeof(int) * (leven->a_length));
46
+ grid_odd = ALLOC(sizeof(int) * (leven->a_length));
47
+
48
+ if(grid_even == NULL || grid_odd == NULL) {
49
+ return (int)9999; /* error occured - cannot allocate memory */
50
+ }
51
+
52
+ work_grid = grid_odd;
53
+ calc_grid = grid_even;
54
+
55
+ for(x = 0; x < leven->a_length; x++)
56
+ grid_even[x] = x;
57
+
58
+ for(i = 1; i < leven->b_length; i++) {
59
+ row_min = work_grid[0] = calc_grid[0] + 1;
60
+
61
+ for(j = 1; j < leven->a_length; j++) {
62
+ cost = (leven->a[j-1] == leven->b[i-1]) ? 0 : 1;
63
+ work_grid[j] = LV_MIN(calc_grid[j]+1, work_grid[j-1]+1, calc_grid[j-1] + cost);
64
+ row_min = (work_grid[j] < row_min) ? work_grid[j] : row_min;
65
+ }
66
+
67
+ if(row_min > leven->maximum_allowable_distance) {
68
+ broke_max = TRUE;
69
+ break;
70
+ }
71
+
72
+ LV_SWAP(tmp, work_grid, calc_grid);
73
+ }
74
+
75
+ distance = (broke_max == TRUE) ? (leven->b_length - 1) : calc_grid[leven->a_length-1];
76
+
77
+ FREE(grid_odd);
78
+ FREE(grid_even);
79
+
80
+ return (int) distance;
81
+ }
82
+
83
+ int levenshtein_extern(char* a, char* b, int max_distance)
84
+ {
85
+ int a_len = (a == NULL) ? 0 : strlen(a);
86
+ int b_len = (b == NULL) ? 0 : strlen(b);
87
+
88
+ LevenConstraints* leven = malloc(sizeof(LevenConstraints));
89
+ leven->a = (a_len > b_len) ? b : a;
90
+ leven->b = (a_len > b_len) ? a : b;
91
+ leven->a_length = strlen(leven->a);
92
+ leven->b_length = strlen(leven->b);
93
+
94
+ int distance = leven->b_length;
95
+
96
+ if(max_distance < 0) {
97
+ max_distance = (a_len > b_len) ? a_len : b_len;
98
+ }
99
+
100
+ leven->maximum_allowable_distance = max_distance;
101
+
102
+ distance = levenshtein_intern(leven);
103
+ FREE(leven);
104
+
105
+ return distance;
106
+ }
107
+
108
+ float normalized_levenshtein_extern(char* a, char* b, int max_distance)
109
+ {
110
+ int a_len = (a == NULL) ? 0 : strlen(a);
111
+ int b_len = (b == NULL) ? 0 : strlen(b);
112
+
113
+ int max_string_length = (a_len > b_len) ? a_len : b_len;
114
+ if(max_string_length == 0) {
115
+ return 0;
116
+ }
117
+ return (float)levenshtein_extern(a, b, max_distance) / max_string_length;
118
+ }
Binary file
Binary file
@@ -0,0 +1,49 @@
1
+ module Vladlev
2
+ class Levenshtein
3
+ def self.distance(str1, str2, maximum_allowable_distance = 9999)
4
+ shortest_string = (str1.size > str2.size) ? str1 : str2
5
+ longest_string = (str1.size > str2.size) ? str2 : str1
6
+ broke_max = false
7
+
8
+ if longest_string == shortest_string
9
+ return 0
10
+ elsif longest_string.size - shortest_string.size > maximum_allowable_distance
11
+ return shortest_string.size
12
+ elsif longest_string.size == 0 || shortest_string.size == 0
13
+ return shortest_string.size
14
+ end
15
+
16
+ calculation_grid = Array.new(longest_string.size)
17
+ working_grid = Array.new(longest_string.size)
18
+
19
+ longest_string.size.times { |position| calculation_grid[position] = position }
20
+
21
+ (1...shortest_string.size).each do |i|
22
+ row_minimum = working_grid[0] = calculation_grid[0] + 1
23
+
24
+ (1...longest_string.size).each do |j|
25
+ cost = (longest_string[j - 1] == shortest_string[i - 1]) ? 0 : 1
26
+ working_grid[j] = [calculation_grid[j] + 1, working_grid[j - 1] + 1, calculation_grid[j - 1] + cost].min
27
+ row_minimum = (working_grid[j] < row_minimum) ? working_grid[j] : row_minimum
28
+ end
29
+
30
+ if row_minimum > maximum_allowable_distance
31
+ broke_max = true
32
+ break
33
+ end
34
+
35
+ temp_grid = working_grid
36
+ working_grid = calculation_grid
37
+ calculation_grid = temp_grid
38
+ end
39
+
40
+ return broke_max ? shortest_string.size : calculation_grid[longest_string.size - 1]
41
+ end
42
+
43
+ def self.normalized_distance(str1, str2, maximum_allowable_distance = 9999)
44
+ longest_string_length = (str1 > str2) ? str1.length : str2.length
45
+ return 0 if longest_string_length == 0
46
+ distance / longest_string_length
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,3 @@
1
+ module Vladlev
2
+ VERSION = '1.0.0'
3
+ end
data/lib/vladlev.rb ADDED
@@ -0,0 +1,86 @@
1
+ module Vladlev
2
+ def self.relative_exists?(filename)
3
+ File.exists?(File.join(File.dirname(__FILE__), filename))
4
+ end
5
+
6
+ JRUBY_NATIVE = RUBY_PLATFORM =~ /java/ && relative_exists?('levenshtein.jar')
7
+ C_EXT_NATIVE = !JRUBY_NATIVE &&
8
+ (relative_exists?('levenshtein.bundle') || relative_exists?('levenshtein.so'))
9
+
10
+ if JRUBY_NATIVE
11
+ require 'java'
12
+ require File.join(File.dirname(__FILE__), 'levenshtein.jar')
13
+
14
+ # Calculate the levenshtein distance between two strings
15
+ #
16
+ # @param [String] first string to compare
17
+ # @param [String] second string to compare
18
+ # @return [Integer] the levenshtein distance between the strings
19
+ def self._internal_distance(str1, str2, max)
20
+ Java::LevenshteinDistance.distance(str1, str2, max)
21
+ end
22
+
23
+ def self._normalized_distance(str1, str2, max)
24
+ Java::LevenshteinDistance.normalized_distance(str1, str2, max)
25
+ end
26
+ elsif C_EXT_NATIVE
27
+ require 'ffi'
28
+ extend ::FFI::Library
29
+
30
+ native_file_path = case
31
+ when relative_exists?('levenshtein.bundle') then
32
+ File.join(File.dirname(__FILE__), 'levenshtein.bundle')
33
+ else
34
+ File.join(File.dirname(__FILE__), 'levenshtein.so')
35
+ end
36
+
37
+ ffi_lib native_file_path
38
+ attach_function :levenshtein_extern, [:pointer, :pointer, :int32], :int32
39
+ attach_function :normalized_levenshtein_extern, [:pointer, :pointer, :int32], :float
40
+
41
+ # Calculate the levenshtein distance between two strings
42
+ #
43
+ # @param [String] first string to compare
44
+ # @param [String] second string to compare
45
+ # @return [Integer] the levenshtein distance between the strings
46
+ def self._internal_distance(str1, str2, max)
47
+ self.levenshtein_extern(str1, str2, max)
48
+ end
49
+
50
+ def self._normalized_distance(str1, str2, max)
51
+ self.normalized_levenshtein_extern(str1, str2, max)
52
+ end
53
+ else
54
+ require 'vladlev/levenshtein'
55
+ warn <<-PURE_RUBY
56
+ Could not load C extension or Java Extension for Vladlev
57
+ Will utilize pure ruby version which is significantly
58
+ slower for many comparisons.
59
+ PURE_RUBY
60
+
61
+ # Calculate the levenshtein distance between two strings
62
+ #
63
+ # @param [String] first string to compare
64
+ # @param [String] second string to compare
65
+ # @return [Integer] the levenshtein distance between the strings
66
+ def self._internal_distance(str1, str2, max)
67
+ ::Vladlev::Levenshtein.distance(str1, str2, max)
68
+ end
69
+ end
70
+
71
+ def self.distance(str1, str2, max = 9999)
72
+ return 0 if str1.nil? && str2.nil?
73
+ return str2.size if str1.nil?
74
+ return str1.size if str2.nil?
75
+
76
+ self._internal_distance(str1, str2, max)
77
+ end
78
+
79
+ def self.get_normalized_distance(str1, str2, max = 9999)
80
+ return 0 if str1.nil? && str2.nil?
81
+ return str2.size if str1.nil?
82
+ return str1.size if str2.nil?
83
+
84
+ self._normalized_distance(str1, str2, max)
85
+ end
86
+ end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe Vladlev do
4
+ specify{ Vladlev.distance("hello", "hello").should equal(0) }
5
+ specify{ Vladlev.distance("", "").should equal(0) }
6
+ specify{ Vladlev.distance("hello", "jello").should equal(1) }
7
+ specify{ Vladlev.distance("hella", "hello").should equal(1) }
8
+ specify{ Vladlev.distance("hello", "jell").should equal(2) }
9
+ specify{ Vladlev.distance("lo", "jello").should equal(3) }
10
+ specify{ Vladlev.distance("jello", "lo").should equal(3) }
11
+ specify{ Vladlev.distance("", "jello").should equal("jello".length) }
12
+ specify{ Vladlev.distance("jello", "").should equal("jello".length) }
13
+ specify{ Vladlev.distance("hello"*2, "jello"*2).should equal(2) }
14
+ specify{ Vladlev.distance("hello"*2, "jelo"*2).should equal(4) }
15
+ specify{ Vladlev.distance("hello"*2, "jell"*2).should equal(4) }
16
+ specify{ Vladlev.distance("hello"*4, "jello"*4).should equal(4) }
17
+ specify{ Vladlev.distance("hello"*8, "jello"*8).should equal(8) }
18
+ specify{ Vladlev.distance("hello"*16, "jello"*16).should equal(16) }
19
+ specify{ Vladlev.distance("hello"*32, "jello"*32).should equal(32) }
20
+ specify{ Vladlev.distance("hello"*64, "jello"*64).should equal(64) }
21
+ specify{ Vladlev.distance("hello"*128, "jello"*128).should equal(128) }
22
+ specify{ Vladlev.distance("hello"*256, "jello"*256).should equal(256) }
23
+ specify{ Vladlev.distance("hello"*512, "jello"*512).should equal(512) }
24
+
25
+ describe "threshold" do
26
+ specify{ Vladlev.distance("hello"*100, "jello"*100, 10).should equal(500) }
27
+ specify{ Vladlev.distance("hello"*100, "jello"*100, 99).should equal(500) }
28
+ specify{ Vladlev.distance("hello"*100, "jello"*100, 100).should equal(100) }
29
+ specify{ Vladlev.distance("hello"*100, "jello"*100, 1000).should equal(100) }
30
+ end
31
+
32
+ describe "long strings" do
33
+ specify{ Vladlev.distance("hello"*200, "jello"*200).should equal(200) }
34
+ specify{ Vladlev.distance("hello"*500, "jello"*500).should equal(500) }
35
+ specify{ Vladlev.distance("hello"*750, "jello"*750).should equal(750) }
36
+ specify{ Vladlev.distance("hello"*950, "jello"*950).should equal(950) }
37
+ end
38
+
39
+ describe "threshold long strings" do
40
+ specify{ Vladlev.distance("hello"*2000, "jello"*2000, 10).should equal(5*2000) }
41
+ specify{ Vladlev.distance("hello"*5000, "jello"*5000, 10).should equal(5*5000) }
42
+ specify{ Vladlev.distance("hello"*7500, "jello"*7500, 10).should equal(5*7500) }
43
+ specify{ Vladlev.distance("hello"*9500, "jello"*9500, 10).should equal(5*9500) }
44
+ end
45
+
46
+ describe "special chars" do
47
+ specify{ Vladlev.distance("*&^%$", "").should equal(5) }
48
+ specify{ Vladlev.distance("", ",./>?").should equal(5) }
49
+ specify{ Vladlev.distance('*&^%$+_=-)(*&^%$#@!~123456789', '*&^%$+_=-)(*&^%$#@!~').should equal(9) }
50
+ specify{ Vladlev.distance('*&^%$+_=-)(*&^%$#@!~', "").should equal(20) }
51
+ end
52
+
53
+ describe "normalized distance" do
54
+ specify{ expect(Vladlev.get_normalized_distance("hi", "high", 1)).to eq(1.0) }
55
+ specify{ expect(Vladlev.get_normalized_distance("hi", "high")).to eq(0.5) }
56
+ specify{ expect(Vladlev.get_normalized_distance("hello", "hello")).to eq(0.0) }
57
+ specify{ expect(Vladlev.get_normalized_distance("goodnight", "goodnite")).to eq(0.3333333432674408) }
58
+ specify{ expect(Vladlev.get_normalized_distance("", "goodbye")).to eq(1.0) }
59
+ specify{ expect(Vladlev.get_normalized_distance("goodbye", "")).to eq(1.0) }
60
+ specify{ expect(Vladlev.get_normalized_distance("", "")).to eq(0.0) }
61
+ end
62
+
63
+ describe '#distance' do
64
+ context "when given two strings to match" do
65
+ it "returns the distance" do
66
+ string1 = "lorem ipsum"
67
+ string2 = "borem ipsum"
68
+ described_class.distance(string1, string2).should eq(1)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ require 'simplecov'
5
+ SimpleCov.start do
6
+ add_filter 'spec/'
7
+ end
8
+
9
+ Bundler.require(:default, :development, :test)
10
+
11
+ require 'pry'
data/vladlev.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'vladlev/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'vladlev'
7
+ s.version = Vladlev::VERSION
8
+ s.summary = 'Levenshtein matching algorithm for ruby using C'
9
+ s.description = 'Levenshtein matching algorithm for ruby using C with an FFI extension'
10
+ s.authors = ["Brian Stien"]
11
+ s.email = 'dev@moneydesktop.com'
12
+ s.homepage = 'https://git.moneydesktop.com/dev/vladlev.git'
13
+
14
+ if defined?(JRUBY_VERSION)
15
+ s.platform = 'java'
16
+ else
17
+ s.extensions = ['ext/levenshtein/extconf.rb']
18
+ s.add_runtime_dependency 'ffi'
19
+ end
20
+
21
+ s.add_development_dependency 'rake'
22
+ s.add_development_dependency 'rspec'
23
+ s.add_development_dependency 'rspec-pride'
24
+ s.add_development_dependency 'pry'
25
+ s.add_development_dependency 'geminabox'
26
+ s.add_development_dependency 'simplecov'
27
+ s.add_development_dependency 'rake-compiler'
28
+
29
+ s.files = `git ls-files`.split("\n")
30
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
31
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
32
+ s.require_paths - ["lib"]
33
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vladlev
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: java
6
+ authors:
7
+ - Brian Stien
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-11-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '>='
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ name: rake
20
+ prerelease: false
21
+ type: :development
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ name: rspec
34
+ prerelease: false
35
+ type: :development
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ name: rspec-pride
48
+ prerelease: false
49
+ type: :development
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ name: pry
62
+ prerelease: false
63
+ type: :development
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ name: geminabox
76
+ prerelease: false
77
+ type: :development
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ name: simplecov
90
+ prerelease: false
91
+ type: :development
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ name: rake-compiler
104
+ prerelease: false
105
+ type: :development
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Levenshtein matching algorithm for ruby using C with an FFI extension
112
+ email: dev@moneydesktop.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - .gitignore
118
+ - .rspec
119
+ - Gemfile
120
+ - README.md
121
+ - Rakefile
122
+ - ext/.DS_Store
123
+ - ext/levenshtein/LevenshteinDistance.java
124
+ - ext/levenshtein/extconf.rb
125
+ - ext/levenshtein/levenshtein.c
126
+ - lib/levenshtein.bundle
127
+ - lib/levenshtein.jar
128
+ - lib/vladlev.rb
129
+ - lib/vladlev/levenshtein.rb
130
+ - lib/vladlev/version.rb
131
+ - spec/lib/levenshtein_spec.rb
132
+ - spec/spec_helper.rb
133
+ - vladlev.gemspec
134
+ homepage: https://git.moneydesktop.com/dev/vladlev.git
135
+ licenses: []
136
+ metadata: {}
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - '>='
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubyforge_project:
153
+ rubygems_version: 2.4.5
154
+ signing_key:
155
+ specification_version: 4
156
+ summary: Levenshtein matching algorithm for ruby using C
157
+ test_files:
158
+ - spec/lib/levenshtein_spec.rb
159
+ - spec/spec_helper.rb