Skip to content

Commit 7fe34af

Browse files
committed
simplify api
1 parent c5e1056 commit 7fe34af

File tree

4 files changed

+57
-100
lines changed

4 files changed

+57
-100
lines changed

README.md

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,21 @@ Example
1010
-------
1111
You can use diff.Ints and diff.Runes
1212

13-
d := &diff.Runes{[]rune("sögen"), []rune("mögen")}
14-
d.Diff() // returns []Changes{{0,0,1,1}}
13+
diff.Runes([]rune("sögen"), []rune("mögen")) // returns []Changes{{0,0,1,1}}
1514

16-
or you can implement diff.Interface and use diff.Diff(data)
15+
or you can implement diff.Data
1716

1817
type MixedInput struct {
1918
A []int
2019
B []string
2120
}
22-
func (m *MixedInput) N() int {
23-
return len(m.A)
24-
}
25-
func (m *MixedInput) M() int {
26-
return len(m.B)
27-
}
28-
func (m *MixedInput) Equal(a, b int) bool {
29-
return m.A[a] == len(m.B[b])
21+
func (m *MixedInput) Equal(i, j int) bool {
22+
return m.A[i] == len(m.B[j])
3023
}
3124

25+
and call
26+
27+
m := &MixedInput{..}
28+
diff.Diff(len(m.A), len(m.B), m)
29+
3230
Documentation at http://go.pkgdoc.org/github.com/mb0/diff

diff.go

Lines changed: 20 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,54 +6,34 @@
66
// The algorithm is described in "An O(ND) Difference Algorithm and its Variations", Eugene Myers, Algorithmica Vol. 1 No. 2, 1986, pp. 251-266.
77
package diff
88

9-
// A type that satisfies diff.Interface can be diffed by this package.
9+
// A type that satisfies diff.Data can be diffed by this package.
1010
// It typically has two sequences A and B of comparable elements.
11-
type Interface interface {
12-
// N is the number of elements in A, called once
13-
N() int
14-
// M is the number of elements in B, called once
15-
M() int
16-
// Equal returns whether the elements at a and b are considered equal.
17-
// Called repeatedly with 0<=a<N and 0<=b<M
18-
Equal(a, b int) bool
11+
type Data interface {
12+
// Equal returns whether the elements at i and j are considered equal.
13+
Equal(i, j int) bool
1914
}
2015

21-
// Ints attaches diff.Interface methods to an array of two int slices
22-
type Ints [2][]int
23-
24-
func (i *Ints) N() int {
25-
return len(i[0])
26-
}
27-
func (i *Ints) M() int {
28-
return len(i[1])
29-
}
30-
func (i *Ints) Equal(a, b int) bool {
31-
return i[0][a] == i[1][b]
32-
}
33-
func (i *Ints) Diff() []Change {
34-
return Diff(i)
16+
// Ints returns the difference of two int slices
17+
func Ints(a, b []int) []Change {
18+
return Diff(len(a), len(b), &ints{a, b})
3519
}
3620

37-
// Runes attaches diff.Interface methods to an array of two rune slices
38-
type Runes [2][]rune
21+
type ints struct{ a, b []int }
3922

40-
func (r *Runes) N() int {
41-
return len(r[0])
42-
}
43-
func (r *Runes) M() int {
44-
return len(r[1])
45-
}
46-
func (r *Runes) Equal(a, b int) bool {
47-
return r[0][a] == r[1][b]
48-
}
49-
func (r *Runes) Diff() []Change {
50-
return Diff(r)
23+
func (d *ints) Equal(i, j int) bool { return d.a[i] == d.b[j] }
24+
25+
// Runes returns the difference of two rune slices
26+
func Runes(a, b []rune) []Change {
27+
return Diff(len(a), len(b), &runes{a, b})
5128
}
5229

30+
type runes struct{ a, b []rune }
31+
32+
func (d *runes) Equal(i, j int) bool { return d.a[i] == d.b[j] }
33+
5334
// Diff returns the differences of data.
54-
func Diff(data Interface) []Change {
55-
n := data.N()
56-
m := data.M()
35+
// data.Equal is called repeatedly with 0<=i<n and 0<=j<m
36+
func Diff(n, m int, data Data) []Change {
5737
c := &context{data: data}
5838
if n > m {
5939
c.flags = make([]byte, n)
@@ -74,7 +54,7 @@ type Change struct {
7454
}
7555

7656
type context struct {
77-
data Interface
57+
data Data
7858
flags []byte // element bits 1 delete, 2 insert
7959
max int
8060
// forward and reverse d-path endpoint x components

diff_test.go

Lines changed: 27 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,70 +10,54 @@ import (
1010

1111
type testcase struct {
1212
name string
13-
data *Ints
13+
a, b []int
1414
res []Change
1515
}
1616

1717
var tests = []testcase{
1818
{"shift",
19-
&Ints{
20-
{1, 2, 3},
21-
{0, 1, 2, 3},
22-
},
19+
[]int{1, 2, 3},
20+
[]int{0, 1, 2, 3},
2321
[]Change{{0, 0, 0, 1}},
2422
},
2523
{"push",
26-
&Ints{
27-
{1, 2, 3},
28-
{1, 2, 3, 4},
29-
},
24+
[]int{1, 2, 3},
25+
[]int{1, 2, 3, 4},
3026
[]Change{{3, 3, 0, 1}},
3127
},
3228
{"unshift",
33-
&Ints{
34-
{0, 1, 2, 3},
35-
{1, 2, 3},
36-
},
29+
[]int{0, 1, 2, 3},
30+
[]int{1, 2, 3},
3731
[]Change{{0, 0, 1, 0}},
3832
},
3933
{"pop",
40-
&Ints{
41-
{1, 2, 3, 4},
42-
{1, 2, 3},
43-
},
34+
[]int{1, 2, 3, 4},
35+
[]int{1, 2, 3},
4436
[]Change{{3, 3, 1, 0}},
4537
},
4638
{"all changed",
47-
&Ints{
48-
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
49-
{10, 11, 12, 13, 14},
50-
},
39+
[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
40+
[]int{10, 11, 12, 13, 14},
5141
[]Change{
5242
{0, 0, 10, 5},
5343
},
5444
},
5545
{"all same",
56-
&Ints{
57-
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
58-
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
59-
},
46+
[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
47+
[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
6048
[]Change{},
6149
},
6250
{"wrap",
63-
&Ints{
64-
{1},
65-
{0, 1, 2, 3},
66-
},
51+
[]int{1},
52+
[]int{0, 1, 2, 3},
6753
[]Change{
6854
{0, 0, 0, 1},
6955
{1, 2, 0, 2},
7056
},
7157
},
7258
{"snake",
73-
&Ints{
74-
{0, 1, 2, 3, 4, 5},
75-
{1, 2, 3, 4, 5, 6},
76-
},
59+
[]int{0, 1, 2, 3, 4, 5},
60+
[]int{1, 2, 3, 4, 5, 6},
7761
[]Change{
7862
{0, 0, 1, 0},
7963
{6, 5, 0, 1},
@@ -83,10 +67,8 @@ var tests = []testcase{
8367
// first two traces differ from fig.1
8468
// it still is a lcs and ses path
8569
{"paper fig. 1",
86-
&Ints{
87-
{1, 2, 3, 1, 2, 2, 1},
88-
{3, 2, 1, 2, 1, 3},
89-
},
70+
[]int{1, 2, 3, 1, 2, 2, 1},
71+
[]int{3, 2, 1, 2, 1, 3},
9072
[]Change{
9173
{0, 0, 1, 1},
9274
{2, 2, 1, 0},
@@ -98,7 +80,7 @@ var tests = []testcase{
9880

9981
func TestDiffAB(t *testing.T) {
10082
for _, test := range tests {
101-
res := test.data.Diff()
83+
res := Ints(test.a, test.b)
10284
if len(res) != len(test.res) {
10385
t.Error(test.name, "expected length", len(test.res), "for", res)
10486
continue
@@ -120,7 +102,7 @@ func TestDiffBA(t *testing.T) {
120102
{7, 5, 0, 1},
121103
}
122104
for _, test := range tests {
123-
res := Diff(&Ints{test.data[1], test.data[0]})
105+
res := Ints(test.b, test.a)
124106
if len(res) != len(test.res) {
125107
t.Error(test.name, "expected length", len(test.res), "for", res)
126108
continue
@@ -137,14 +119,17 @@ func TestDiffBA(t *testing.T) {
137119

138120
func BenchmarkDiff(b *testing.B) {
139121
t := tests[len(tests)-1]
122+
d := &ints{t.a, t.b}
123+
n, m := len(d.a), len(d.b)
140124
for i := 0; i < b.N; i++ {
141-
t.data.Diff()
125+
Diff(n, m, d)
142126
}
143127
}
144128

145129
func BenchmarkDiffRunes(b *testing.B) {
146-
data := &Runes{[]rune("1231221"), []rune("321213")}
130+
d := &runes{[]rune("1231221"), []rune("321213")}
131+
n, m := len(d.a), len(d.b)
147132
for i := 0; i < b.N; i++ {
148-
Diff(data)
133+
Diff(n, m, d)
149134
}
150135
}

example_test.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,6 @@ type MixedInput struct {
2121
B []string
2222
}
2323

24-
func (m *MixedInput) N() int {
25-
return len(m.A)
26-
}
27-
func (m *MixedInput) M() int {
28-
return len(m.B)
29-
}
3024
func (m *MixedInput) Equal(a, b int) bool {
3125
return m.A[a] == names[m.B[b]]
3226
}
@@ -36,7 +30,7 @@ func ExampleInterface() {
3630
[]int{1, 2, 3, 1, 2, 2, 1},
3731
[]string{"three", "two", "one", "two", "one", "three"},
3832
}
39-
changes := diff.Diff(m)
33+
changes := diff.Diff(len(m.A), len(m.B), m)
4034
for _, c := range changes {
4135
fmt.Println("change at", c.A, c.B)
4236
}

0 commit comments

Comments
 (0)