-
Notifications
You must be signed in to change notification settings - Fork 1
/
goodMap.go
148 lines (137 loc) · 3.64 KB
/
goodMap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package main
import (
"fmt"
)
type GoodList struct {
first *GoodNode
last *GoodNode
}
type GoodNode struct {
id uint64
value float64
prev *GoodNode
next *GoodNode
mapRef *GoodList
}
type WalkFn func(id uint64, value float64) bool
func NewList() *GoodList {
newList := GoodList{nil, nil}
return &newList
}
// AddItem inserts the node into the GoodList with lazy sorting
func (goodList *GoodList) AddItem(item uint64, valu float64) (newValue float64, err error) {
fmt.Println("Adding", item)
// Find insert or update
newNode := GoodNode{
id: item,
prev: nil,
next: nil,
value: valu,
mapRef: goodList,
}
if goodList.first == nil { // First item
newNode.value = valu
goodList.first = &newNode
goodList.last = &newNode
return newNode.value, nil
} else if goodList.first.value < valu { // Replace first node
tempNode := goodList.first
goodList.first = &newNode
goodList.last = tempNode
newNode.next = tempNode
tempNode.prev = &newNode
return newNode.value, nil
} else {
tempNode := goodList.first
// if tempNode.id == item { // Check if first node
// tempNode.value = valu
// return tempNode.value, nil
// }
higherNode := tempNode // Keep track of last spot where value is higher if updating to move up
for tempNode.next != nil { // Leave on end of list or next is item
if tempNode.next.id == item {
break
}
// TODO: Break when I get to value 1 so we can insert there and not walk to end
tempNode = tempNode.next
if tempNode.value < higherNode.value { // The node we will need to place after
higherNode = tempNode.prev
}
}
if tempNode.next == nil { // Append to end of list
tempNode.next = &newNode
newNode.prev = tempNode
goodList.last = &newNode
newNode.value = valu
return newNode.value, nil
} else {
updateNode := tempNode.next
// Check if higherNode same as tempNode
// Manual adjust
if tempNode.value > updateNode.value && higherNode.value >= tempNode.value {
higherNode = tempNode
}
if higherNode != tempNode {
tempNode.next = updateNode.next
// Check if last node
if updateNode.next != nil {
updateNode.next.prev = tempNode
}
higherNode.next.prev = updateNode
updateNode.next = higherNode.next
updateNode.prev = higherNode
higherNode.next = updateNode
} else {
if higherNode.value < updateNode.value+1 {
higherNode.next = updateNode.next
if updateNode.next != nil {
updateNode.next.prev = higherNode
}
updateNode.next = higherNode
if higherNode.prev != nil {
updateNode.prev = higherNode.prev
} else { // First node in list
goodList.first = updateNode
updateNode.prev = nil
}
higherNode.prev = updateNode
}
}
updateNode.value = valu
return updateNode.value, nil
}
}
}
func GoodListFromArray(arr []uint64, vals []float64) (*GoodList, error) {
newList := GoodList{nil, nil}
for idx, item := range arr {
_, err := newList.AddItem(item, vals[idx])
if err != nil {
return nil, err
}
}
return &newList, nil
}
// WalkFn walks the list. Return whether to keep walking.
func (goodList *GoodList) Walk(walkFn WalkFn) {
tempNode := goodList.first
if goodList.first == nil {
return
}
for tempNode != nil {
keepGoing := walkFn(tempNode.id, tempNode.value)
if keepGoing == false { // If false returned
return
}
tempNode = tempNode.next
}
}
// ToString returns a string of "(id, value), (id, value)..."
func (goodList *GoodList) ToString() string {
theString := "-"
goodList.Walk(func(id uint64, value float64) bool {
theString = fmt.Sprintf("%v(%v, %v)-", theString, id, value)
return true
})
return theString
}