2017-07-15 21:49:08 +02:00
|
|
|
package treerack
|
2017-06-25 17:51:08 +02:00
|
|
|
|
2017-11-02 20:49:49 +01:00
|
|
|
type results struct {
|
2017-11-06 11:41:00 +01:00
|
|
|
noMatch []*idSet
|
|
|
|
match [][]int
|
|
|
|
isPending [][]int
|
2017-07-17 21:58:03 +02:00
|
|
|
}
|
|
|
|
|
2017-12-31 17:34:10 +01:00
|
|
|
func ensureOffsetInts(ints [][]int, offset int) [][]int {
|
|
|
|
if len(ints) > offset {
|
|
|
|
return ints
|
2017-06-25 17:51:08 +02:00
|
|
|
}
|
|
|
|
|
2017-12-31 17:34:10 +01:00
|
|
|
if cap(ints) > offset {
|
|
|
|
ints = ints[:offset+1]
|
|
|
|
return ints
|
2017-07-15 23:00:43 +02:00
|
|
|
}
|
|
|
|
|
2017-12-31 17:34:10 +01:00
|
|
|
ints = ints[:cap(ints)]
|
|
|
|
for i := len(ints); i <= offset; i++ {
|
|
|
|
ints = append(ints, nil)
|
2017-11-04 22:08:15 +01:00
|
|
|
}
|
2017-12-31 17:34:10 +01:00
|
|
|
|
|
|
|
return ints
|
|
|
|
}
|
|
|
|
|
|
|
|
func ensureOffsetIDs(ids []*idSet, offset int) []*idSet {
|
|
|
|
if len(ids) > offset {
|
|
|
|
return ids
|
|
|
|
}
|
|
|
|
|
|
|
|
if cap(ids) > offset {
|
|
|
|
ids = ids[:offset+1]
|
|
|
|
return ids
|
|
|
|
}
|
|
|
|
|
|
|
|
ids = ids[:cap(ids)]
|
|
|
|
for i := len(ids); i <= offset; i++ {
|
|
|
|
ids = append(ids, nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
return ids
|
2017-11-04 22:08:15 +01:00
|
|
|
}
|
2017-07-17 23:59:26 +02:00
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
func (r *results) setMatch(offset, id, to int) {
|
2017-12-31 17:34:10 +01:00
|
|
|
r.match = ensureOffsetInts(r.match, offset)
|
2017-11-06 11:14:28 +01:00
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
for i := 0; i < len(r.match[offset]); i += 2 {
|
|
|
|
if r.match[offset][i] != id || r.match[offset][i+1] != to {
|
2017-07-17 23:59:26 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
return
|
2017-06-25 17:51:08 +02:00
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
r.match[offset] = append(r.match[offset], id, to)
|
2017-07-29 18:40:22 +02:00
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
func (r *results) setNoMatch(offset, id int) {
|
|
|
|
if len(r.match) > offset {
|
|
|
|
for i := 0; i < len(r.match[offset]); i += 2 {
|
|
|
|
if r.match[offset][i] != id {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-31 17:34:10 +01:00
|
|
|
r.noMatch = ensureOffsetIDs(r.noMatch, offset)
|
2017-11-04 22:08:15 +01:00
|
|
|
if r.noMatch[offset] == nil {
|
|
|
|
r.noMatch[offset] = &idSet{}
|
2017-07-30 02:35:51 +02:00
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
r.noMatch[offset].set(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *results) hasMatchTo(offset, id, to int) bool {
|
|
|
|
if len(r.match) <= offset {
|
2017-07-30 02:35:51 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
for i := 0; i < len(r.match[offset]); i += 2 {
|
|
|
|
if r.match[offset][i] != id {
|
2017-07-30 02:35:51 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
if r.match[offset][i+1] == to {
|
2017-07-30 02:35:51 +02:00
|
|
|
return true
|
|
|
|
}
|
2017-07-29 18:40:22 +02:00
|
|
|
}
|
|
|
|
|
2017-07-30 02:35:51 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
func (r *results) longestMatch(offset, id int) (int, bool) {
|
|
|
|
if len(r.match) <= offset {
|
2017-07-29 18:40:22 +02:00
|
|
|
return 0, false
|
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
var found bool
|
|
|
|
to := -1
|
|
|
|
for i := 0; i < len(r.match[offset]); i += 2 {
|
|
|
|
if r.match[offset][i] != id {
|
2017-07-29 18:40:22 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
if r.match[offset][i+1] > to {
|
|
|
|
to = r.match[offset][i+1]
|
2017-07-29 18:40:22 +02:00
|
|
|
}
|
2017-10-28 16:54:06 +02:00
|
|
|
|
|
|
|
found = true
|
2017-07-29 18:40:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return to, found
|
2017-06-25 17:51:08 +02:00
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
func (r *results) longestResult(offset, id int) (int, bool, bool) {
|
|
|
|
if len(r.noMatch) > offset && r.noMatch[offset] != nil && r.noMatch[offset].has(id) {
|
|
|
|
return 0, false, true
|
2017-07-16 23:15:42 +02:00
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
to, ok := r.longestMatch(offset, id)
|
|
|
|
return to, ok, ok
|
2017-07-16 23:15:42 +02:00
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
func (r *results) dropMatchTo(offset, id, to int) {
|
|
|
|
for i := 0; i < len(r.match[offset]); i += 2 {
|
|
|
|
if r.match[offset][i] != id {
|
2017-07-30 02:35:51 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2017-11-04 22:08:15 +01:00
|
|
|
if r.match[offset][i+1] == to {
|
|
|
|
r.match[offset][i] = -1
|
2017-07-30 02:35:51 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2017-07-16 23:15:42 +02:00
|
|
|
}
|
2017-11-06 11:14:28 +01:00
|
|
|
|
2017-11-06 11:41:00 +01:00
|
|
|
func (r *results) resetPending() {
|
|
|
|
r.isPending = nil
|
2017-11-06 11:14:28 +01:00
|
|
|
}
|
|
|
|
|
2017-11-06 11:41:00 +01:00
|
|
|
func (r *results) pending(offset, id int) bool {
|
|
|
|
if len(r.isPending) <= id {
|
2017-11-06 11:14:28 +01:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-11-06 11:41:00 +01:00
|
|
|
for i := range r.isPending[id] {
|
|
|
|
if r.isPending[id][i] == offset {
|
2017-11-06 11:14:28 +01:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-11-06 11:41:00 +01:00
|
|
|
func (r *results) markPending(offset, id int) {
|
2017-12-31 17:34:10 +01:00
|
|
|
r.isPending = ensureOffsetInts(r.isPending, id)
|
2017-11-06 11:41:00 +01:00
|
|
|
for i := range r.isPending[id] {
|
|
|
|
if r.isPending[id][i] == -1 {
|
|
|
|
r.isPending[id][i] = offset
|
2017-11-06 11:14:28 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-06 11:41:00 +01:00
|
|
|
r.isPending[id] = append(r.isPending[id], offset)
|
2017-11-06 11:14:28 +01:00
|
|
|
}
|
|
|
|
|
2017-11-06 11:41:00 +01:00
|
|
|
func (r *results) unmarkPending(offset, id int) {
|
|
|
|
for i := range r.isPending[id] {
|
|
|
|
if r.isPending[id][i] == offset {
|
|
|
|
r.isPending[id][i] = -1
|
2017-11-06 11:14:28 +01:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|