make editdistance work with --styleCheck:error
This commit is contained in:
parent
78174857f8
commit
dc0bbba3fa
1 changed files with 108 additions and 108 deletions
|
|
@ -22,158 +22,158 @@ proc editDistance*(a, b: string): int {.noSideEffect.} =
|
||||||
return editDistance(b, a)
|
return editDistance(b, a)
|
||||||
# strip common prefix
|
# strip common prefix
|
||||||
var
|
var
|
||||||
i_start = 0 ## The character starting index of the first rune in both strings ``a`` and ``b``
|
iStart = 0 ## The character starting index of the first rune in both strings ``a`` and ``b``
|
||||||
i_next_a = 0
|
iNextA = 0
|
||||||
i_next_b = 0
|
iNextB = 0
|
||||||
rune_a, rune_b: Rune
|
runeA, runeB: Rune
|
||||||
len_runes_a = 0 ## The number of relevant runes in string ``a``.
|
lenRunesA = 0 ## The number of relevant runes in string ``a``.
|
||||||
len_runes_b = 0 ## The number of relevant runes in string ``b``.
|
lenRunesB = 0 ## The number of relevant runes in string ``b``.
|
||||||
block commonPrefix:
|
block commonPrefix:
|
||||||
# ``a`` is the shorter string
|
# ``a`` is the shorter string
|
||||||
while i_start < len(a):
|
while iStart < len(a):
|
||||||
i_next_a = i_start
|
iNextA = iStart
|
||||||
a.fastRuneAt(i_next_a, rune_a, doInc = true)
|
a.fastRuneAt(iNextA, runeA, doInc = true)
|
||||||
i_next_b = i_start
|
iNextB = iStart
|
||||||
b.fastRuneAt(i_next_b, rune_b, doInc = true)
|
b.fastRuneAt(iNextB, runeB, doInc = true)
|
||||||
if rune_a != rune_b:
|
if runeA != runeB:
|
||||||
inc(len_runes_a)
|
inc(lenRunesA)
|
||||||
inc(len_runes_b)
|
inc(lenRunesB)
|
||||||
break
|
break
|
||||||
i_start = i_next_a
|
iStart = iNextA
|
||||||
var
|
var
|
||||||
# we know that we are either at the start of the strings
|
# we know that we are either at the start of the strings
|
||||||
# or that the current value of rune_a is not equal to rune_b
|
# or that the current value of runeA is not equal to runeB
|
||||||
# => start search for common suffix after the current rune (``i_next_*``)
|
# => start search for common suffix after the current rune (``i_next_*``)
|
||||||
i_end_a = i_next_a ## The exclusive upper index bound of string ``a``.
|
iEndA = iNextA ## The exclusive upper index bound of string ``a``.
|
||||||
i_end_b = i_next_b ## The exclusive upper index bound of string ``b``.
|
iEndB = iNextB ## The exclusive upper index bound of string ``b``.
|
||||||
i_current_a = i_next_a
|
iCurrentA = iNextA
|
||||||
i_current_b = i_next_b
|
iCurrentB = iNextB
|
||||||
block commonSuffix:
|
block commonSuffix:
|
||||||
var
|
var
|
||||||
add_runes_a = 0
|
addRunesA = 0
|
||||||
add_runes_b = 0
|
addRunesB = 0
|
||||||
while i_current_a < len(a) and i_current_b < len(b):
|
while iCurrentA < len(a) and iCurrentB < len(b):
|
||||||
i_next_a = i_current_a
|
iNextA = iCurrentA
|
||||||
a.fastRuneAt(i_next_a, rune_a)
|
a.fastRuneAt(iNextA, runeA)
|
||||||
i_next_b = i_current_b
|
iNextB = iCurrentB
|
||||||
b.fastRuneAt(i_next_b, rune_b)
|
b.fastRuneAt(iNextB, runeB)
|
||||||
inc(add_runes_a)
|
inc(addRunesA)
|
||||||
inc(add_runes_b)
|
inc(addRunesB)
|
||||||
if rune_a != rune_b:
|
if runeA != runeB:
|
||||||
i_end_a = i_next_a
|
iEndA = iNextA
|
||||||
i_end_b = i_next_b
|
iEndB = iNextB
|
||||||
inc(len_runes_a, add_runes_a)
|
inc(lenRunesA, addRunesA)
|
||||||
inc(len_runes_b, add_runes_b)
|
inc(lenRunesB, addRunesB)
|
||||||
add_runes_a = 0
|
addRunesA = 0
|
||||||
add_runes_b = 0
|
addRunesB = 0
|
||||||
i_current_a = i_next_a
|
iCurrentA = iNextA
|
||||||
i_current_b = i_next_b
|
iCurrentB = iNextB
|
||||||
if i_current_a >= len(a): # ``a`` exhausted
|
if iCurrentA >= len(a): # ``a`` exhausted
|
||||||
if i_current_b < len(b): # ``b`` not exhausted
|
if iCurrentB < len(b): # ``b`` not exhausted
|
||||||
i_end_a = i_current_a
|
iEndA = iCurrentA
|
||||||
i_end_b = i_current_b
|
iEndB = iCurrentB
|
||||||
inc(len_runes_a, add_runes_a)
|
inc(lenRunesA, addRunesA)
|
||||||
inc(len_runes_b, add_runes_b)
|
inc(lenRunesB, addRunesB)
|
||||||
while true:
|
while true:
|
||||||
b.fastRuneAt(i_end_b, rune_b)
|
b.fastRuneAt(iEndB, runeB)
|
||||||
inc(len_runes_b)
|
inc(lenRunesB)
|
||||||
if i_end_b >= len(b): break
|
if iEndB >= len(b): break
|
||||||
elif i_current_b >= len(b): # ``b`` exhausted and ``a`` not exhausted
|
elif iCurrentB >= len(b): # ``b`` exhausted and ``a`` not exhausted
|
||||||
i_end_a = i_current_a
|
iEndA = iCurrentA
|
||||||
i_end_b = i_current_b
|
iEndB = iCurrentB
|
||||||
inc(len_runes_a, add_runes_a)
|
inc(lenRunesA, addRunesA)
|
||||||
inc(len_runes_b, add_runes_b)
|
inc(lenRunesB, addRunesB)
|
||||||
while true:
|
while true:
|
||||||
a.fastRuneAt(i_end_a, rune_a)
|
a.fastRuneAt(iEndA, runeA)
|
||||||
inc(len_runes_a)
|
inc(lenRunesA)
|
||||||
if i_end_a >= len(a): break
|
if iEndA >= len(a): break
|
||||||
block specialCases:
|
block specialCases:
|
||||||
# trivial cases:
|
# trivial cases:
|
||||||
if len_runes_a == 0: return len_runes_b
|
if lenRunesA == 0: return lenRunesB
|
||||||
if len_runes_b == 0: return len_runes_a
|
if lenRunesB == 0: return lenRunesA
|
||||||
# another special case:
|
# another special case:
|
||||||
if len_runes_a == 1:
|
if lenRunesA == 1:
|
||||||
a.fastRuneAt(i_start, rune_a, doInc = false)
|
a.fastRuneAt(iStart, runeA, doInc = false)
|
||||||
var i_current_b = i_start
|
var iCurrentB = iStart
|
||||||
while i_current_b < i_end_b:
|
while iCurrentB < iEndB:
|
||||||
b.fastRuneAt(i_current_b, rune_b, doInc = true)
|
b.fastRuneAt(iCurrentB, runeB, doInc = true)
|
||||||
if rune_a == rune_b: return len_runes_b - 1
|
if runeA == runeB: return lenRunesB - 1
|
||||||
return len_runes_b
|
return lenRunesB
|
||||||
# common case:
|
# common case:
|
||||||
var
|
var
|
||||||
len1 = len_runes_a + 1
|
len1 = lenRunesA + 1
|
||||||
len2 = len_runes_b + 1
|
len2 = lenRunesB + 1
|
||||||
row: seq[int]
|
row: seq[int]
|
||||||
let half = len_runes_a div 2
|
let half = lenRunesA div 2
|
||||||
newSeq(row, len2)
|
newSeq(row, len2)
|
||||||
var e = i_start + len2 - 1 # end marker
|
var e = iStart + len2 - 1 # end marker
|
||||||
# initialize first row:
|
# initialize first row:
|
||||||
for i in 1 .. (len2 - half - 1): row[i] = i
|
for i in 1 .. (len2 - half - 1): row[i] = i
|
||||||
row[0] = len1 - half - 1
|
row[0] = len1 - half - 1
|
||||||
i_current_a = i_start
|
iCurrentA = iStart
|
||||||
var
|
var
|
||||||
char2p_i = -1
|
char2pI = -1
|
||||||
char2p_prev: int
|
char2pPrev: int
|
||||||
for i in 1 .. (len1 - 1):
|
for i in 1 .. (len1 - 1):
|
||||||
i_next_a = i_current_a
|
iNextA = iCurrentA
|
||||||
a.fastRuneAt(i_next_a, rune_a)
|
a.fastRuneAt(iNextA, runeA)
|
||||||
var
|
var
|
||||||
char2p: int
|
char2p: int
|
||||||
D, x: int
|
diff, x: int
|
||||||
p: int
|
p: int
|
||||||
if i >= (len1 - half):
|
if i >= (len1 - half):
|
||||||
# skip the upper triangle:
|
# skip the upper triangle:
|
||||||
let offset = i + half - len1
|
let offset = i + half - len1
|
||||||
if char2p_i == i:
|
if char2pI == i:
|
||||||
b.fastRuneAt(char2p_prev, rune_b)
|
b.fastRuneAt(char2pPrev, runeB)
|
||||||
char2p = char2p_prev
|
char2p = char2pPrev
|
||||||
char2p_i = i + 1
|
char2pI = i + 1
|
||||||
else:
|
else:
|
||||||
char2p = i_start
|
char2p = iStart
|
||||||
for j in 0 ..< offset:
|
for j in 0 ..< offset:
|
||||||
rune_b = b.runeAt(char2p)
|
runeB = b.runeAt(char2p)
|
||||||
inc(char2p, rune_b.size)
|
inc(char2p, runeB.size)
|
||||||
char2p_i = i + 1
|
char2pI = i + 1
|
||||||
char2p_prev = char2p
|
char2pPrev = char2p
|
||||||
p = offset
|
p = offset
|
||||||
rune_b = b.runeAt(char2p)
|
runeB = b.runeAt(char2p)
|
||||||
var c3 = row[p] + (if rune_a != rune_b: 1 else: 0)
|
var c3 = row[p] + (if runeA != runeB: 1 else: 0)
|
||||||
inc(char2p, rune_b.size)
|
inc(char2p, runeB.size)
|
||||||
inc(p)
|
inc(p)
|
||||||
x = row[p] + 1
|
x = row[p] + 1
|
||||||
D = x
|
diff = x
|
||||||
if x > c3: x = c3
|
if x > c3: x = c3
|
||||||
row[p] = x
|
row[p] = x
|
||||||
inc(p)
|
inc(p)
|
||||||
else:
|
else:
|
||||||
p = 1
|
p = 1
|
||||||
char2p = i_start
|
char2p = iStart
|
||||||
D = i
|
diff = i
|
||||||
x = i
|
x = i
|
||||||
if i <= (half + 1):
|
if i <= (half + 1):
|
||||||
# skip the lower triangle:
|
# skip the lower triangle:
|
||||||
e = len2 + i - half - 2
|
e = len2 + i - half - 2
|
||||||
# main:
|
# main:
|
||||||
while p <= e:
|
while p <= e:
|
||||||
dec(D)
|
dec(diff)
|
||||||
rune_b = b.runeAt(char2p)
|
runeB = b.runeAt(char2p)
|
||||||
var c3 = D + (if rune_a != rune_b: 1 else: 0)
|
var c3 = diff + (if runeA != runeB: 1 else: 0)
|
||||||
inc(char2p, rune_b.size)
|
inc(char2p, runeB.size)
|
||||||
inc(x)
|
inc(x)
|
||||||
if x > c3: x = c3
|
if x > c3: x = c3
|
||||||
D = row[p] + 1
|
diff = row[p] + 1
|
||||||
if x > D: x = D
|
if x > diff: x = diff
|
||||||
row[p] = x
|
row[p] = x
|
||||||
inc(p)
|
inc(p)
|
||||||
# lower triangle sentinel:
|
# lower triangle sentinel:
|
||||||
if i <= half:
|
if i <= half:
|
||||||
dec(D)
|
dec(diff)
|
||||||
rune_b = b.runeAt(char2p)
|
runeB = b.runeAt(char2p)
|
||||||
var c3 = D + (if rune_a != rune_b: 1 else: 0)
|
var c3 = diff + (if runeA != runeB: 1 else: 0)
|
||||||
inc(x)
|
inc(x)
|
||||||
if x > c3: x = c3
|
if x > c3: x = c3
|
||||||
row[p] = x
|
row[p] = x
|
||||||
i_current_a = i_next_a
|
iCurrentA = iNextA
|
||||||
result = row[e]
|
result = row[e]
|
||||||
|
|
||||||
proc editDistanceAscii*(a, b: string): int {.noSideEffect.} =
|
proc editDistanceAscii*(a, b: string): int {.noSideEffect.} =
|
||||||
|
|
@ -220,7 +220,7 @@ proc editDistanceAscii*(a, b: string): int {.noSideEffect.} =
|
||||||
for i in 1 .. len1 - 1:
|
for i in 1 .. len1 - 1:
|
||||||
var char1 = a[i + s - 1]
|
var char1 = a[i + s - 1]
|
||||||
var char2p: int
|
var char2p: int
|
||||||
var D, x: int
|
var diff, x: int
|
||||||
var p: int
|
var p: int
|
||||||
if i >= len1 - half:
|
if i >= len1 - half:
|
||||||
# skip the upper triangle:
|
# skip the upper triangle:
|
||||||
|
|
@ -231,33 +231,33 @@ proc editDistanceAscii*(a, b: string): int {.noSideEffect.} =
|
||||||
inc(p)
|
inc(p)
|
||||||
inc(char2p)
|
inc(char2p)
|
||||||
x = row[p] + 1
|
x = row[p] + 1
|
||||||
D = x
|
diff = x
|
||||||
if x > c3: x = c3
|
if x > c3: x = c3
|
||||||
row[p] = x
|
row[p] = x
|
||||||
inc(p)
|
inc(p)
|
||||||
else:
|
else:
|
||||||
p = 1
|
p = 1
|
||||||
char2p = 0
|
char2p = 0
|
||||||
D = i
|
diff = i
|
||||||
x = i
|
x = i
|
||||||
if i <= half + 1:
|
if i <= half + 1:
|
||||||
# skip the lower triangle:
|
# skip the lower triangle:
|
||||||
e = len2 + i - half - 2
|
e = len2 + i - half - 2
|
||||||
# main:
|
# main:
|
||||||
while p <= e:
|
while p <= e:
|
||||||
dec(D)
|
dec(diff)
|
||||||
var c3 = D + ord(char1 != b[char2p + s])
|
var c3 = diff + ord(char1 != b[char2p + s])
|
||||||
inc(char2p)
|
inc(char2p)
|
||||||
inc(x)
|
inc(x)
|
||||||
if x > c3: x = c3
|
if x > c3: x = c3
|
||||||
D = row[p] + 1
|
diff = row[p] + 1
|
||||||
if x > D: x = D
|
if x > diff: x = diff
|
||||||
row[p] = x
|
row[p] = x
|
||||||
inc(p)
|
inc(p)
|
||||||
# lower triangle sentinel:
|
# lower triangle sentinel:
|
||||||
if i <= half:
|
if i <= half:
|
||||||
dec(D)
|
dec(diff)
|
||||||
var c3 = D + ord(char1 != b[char2p + s])
|
var c3 = diff + ord(char1 != b[char2p + s])
|
||||||
inc(x)
|
inc(x)
|
||||||
if x > c3: x = c3
|
if x > c3: x = c3
|
||||||
row[p] = x
|
row[p] = x
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue