Fix empty LIS

This commit is contained in:
Roman Vishnevskii 2017-05-10 18:51:13 +07:00
commit e88f9e4c96
2 changed files with 28 additions and 9 deletions

View file

@ -1,6 +1,6 @@
## Karax -- Single page applications for Nim.
import dom, vdom, jstrutils, components, jdict, tables
import dom, vdom, jstrutils, components, jdict
export dom.Event
@ -184,6 +184,9 @@ proc print(s: cstring, ident: int) =
# kout cstring(result)
proc longestIncreasingSubsequence(a: seq[int]): seq[int] =
if len(a) == 0:
return @[]
result.add 0
var parent = newSeq[int](len(a))
for i in 0..<len(a):
@ -216,6 +219,10 @@ proc longestIncreasingSubsequence(a: seq[int]): seq[int] =
dec pos
proc updateElement(parent, current: Node, newNode, oldNode: VNode, ident: int = 0) =
if newNode.key != -1:
kout cstring($newNode.key)
if oldNode.key != -1:
kout cstring($oldNode.key)
newNode.dom = oldNode.dom
if not equalsShallow(newNode, oldNode):
detach(oldNode)
@ -317,6 +324,10 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode, ident: int =
if not isKeyed:
break
if rightNew - leftNew + 1 + rightOld - leftOld + 1 == 0:
isKeyed = false
if isKeyed:
if rightNew > leftNew:
# remove redundant old nodes
@ -325,14 +336,22 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode, ident: int =
detach(oldNode[i])
else:
# permute elements using LIS
var positionByKey = newTable[VKey, int]()
var positionByKey = newJDict[VKey, int]()
var positions = newSeq[int]()
for i in leftOld..rightOld:
positionByKey[oldNode[i].key] = i
for i in leftNew..rightNew:
if positionByKey.hasKey(newNode[i].key):
if positionByKey.contains(newNode[i].key):
positions.add positionByKey[newNode[i].key]
#if len(positions) > 0:
# kout cstring("new segment len = " & $(rightNew - leftNew + 1))
# kout cstring("old segment len = " & $(rightOld - leftOld + 1))
# var t = ""
# for i in 0..<len(positions):
# t.add($positions[i] & " ")
# kout cstring(t)
var lis = longestIncreasingSubsequence(positions)
var lisPos = 0
var isNotRedundant = newSeq[bool](rightOld - leftOld + 1)
@ -344,14 +363,14 @@ proc updateElement(parent, current: Node, newNode, oldNode: VNode, ident: int =
updateElement(current, oldNode[index].dom, newNode[i], oldNode[index], ident + 1)
inc lisPos
else:
if positionByKey.hasKey(newNode[i].key):
if positionByKey.contains(newNode[i].key):
var oldPos = positionByKey[newNode[i].key]
isNotRedundant[oldPos - leftOld] = true
current.insertBefore(oldNode[oldPos].dom, oldNode[index].dom)
else:
current.insertBefore(vnodeToDom(newNode[i]), oldNode[index].dom)
else:
if positionByKey.hasKey(newNode[i].key):
if positionByKey.contains(newNode[i].key):
var oldPos = positionByKey[newNode[i].key]
isNotRedundant[oldPos - leftOld] = true
current.appendChild(oldNode[oldPos].dom)

View file

@ -83,16 +83,16 @@ proc test4() =
timeout = setTimeout(check4, 20)
proc check5() =
let result = checkOrder(@[0, 1, 3, 5, 4, 5])
let result = checkOrder(@[0, 1, 3, 5, 4, 8])
if result:
results.add cstring"test5 - OK"
else:
results.add cstring"test5 - FAIL"
# result: 0 1 3 5 4 5
# result: 0 1 3 5 4 8
proc test5() =
results.add cstring"test5 started"
entries = @[cstring("0"), cstring("1"), cstring("3"), cstring("5"), cstring("4"), cstring("5") ]
entries = @[cstring("0"), cstring("1"), cstring("3"), cstring("5"), cstring("4"), cstring("8") ]
redraw()
timeout = setTimeout(check5, 20)
@ -127,7 +127,7 @@ proc test7() =
proc createEntry(id: int): VNode =
result = buildHtml():
button(id="" & $id):
button(id="" & $id, key = id):
text $id
proc createDom(): VNode =