-
Notifications
You must be signed in to change notification settings - Fork 4
/
locals.go
132 lines (113 loc) · 3.21 KB
/
locals.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
package washeet
import (
"fmt"
"math"
)
var (
letters = [...]byte{'A', 'B', 'C', 'D', 'E', 'F', 'G',
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}
)
func minInt64(n1 int64, n2 int64) int64 {
result := n1
if n2 < n1 {
result = n2
}
return result
}
func maxInt64(n1 int64, n2 int64) int64 {
result := n1
if n2 > n1 {
result = n2
}
return result
}
func col2ColLabel(nCol int64) string {
label := string(letters[nCol%26])
for {
nCol /= 26
if nCol == 0 {
break
}
if nCol%26 == 0 {
label = string(letters[25]) + label
nCol -= 26
} else {
label = string(letters[(nCol%26)-1]) + label
}
}
return label
}
func row2RowLabel(nRow int64) string {
return fmt.Sprintf("%d", nRow+1)
}
// Assumes intervalArray is sorted of course.
// Assumes all intervals are non-empty ( intervalArray[a] != intervalArray[b] )
func getIntervalIndex(val float64, intervalArray []float64) (index int64) {
// Result for out of bound cases
index = -1
// There must be at least one interval, so there must be at least 2 elements !
if len(intervalArray) < 2 {
return
}
// Note : intervalArray has len(intervalArray) - 1 intervals.
lowIntervalIdx, highIntervalIdx := int64(0), int64(len(intervalArray)-2)
// intervalArray[lowIntervalIdx] is the first interval's start point
// intervalArray[highIntervalIdx+1] is the last interval's end point
if val <= intervalArray[lowIntervalIdx] || intervalArray[highIntervalIdx+1] < val {
return
}
// Do binary search to find the right interval
itercount := 0
for lowIntervalIdx < highIntervalIdx {
if itercount >= 10 {
// fallback to binary search
index = (lowIntervalIdx + highIntervalIdx) / 2
} else {
// specialized version for our interval search where an interval is of the form (start, end]
index = lowIntervalIdx - 1 + int64(math.Ceil(
(val-intervalArray[lowIntervalIdx])*float64(highIntervalIdx-lowIntervalIdx)/
(intervalArray[highIntervalIdx]-intervalArray[lowIntervalIdx])))
// **Invariants**
// 1. "val > intervalArray[lowIntervalIdx]"
// so index >= lowIntervalIdx
//
// 2. "val <= intervalArray[highIntervalIdx+1]"
// But index need not be less than highIntervalIdx+1 at this point.
if index > highIntervalIdx {
// This happens only if val > intervalArray[highIntervalIdx]
// This combined with invariant-2, correct final interval index is highIntervalIdx
index = highIntervalIdx
return
}
// Now index >= lowIntervalIdx and index <= highIntervalIdx
}
thisIntervalStart := intervalArray[index]
thisIntervalEnd := intervalArray[index+1]
if thisIntervalStart < val && val <= thisIntervalEnd {
// Found the interval where val lies
return
}
if val <= thisIntervalStart {
highIntervalIdx = index - 1
} else { // val > thisIntervalEnd
lowIntervalIdx = index + 1
}
itercount++
if lowIntervalIdx == highIntervalIdx {
// From the 2 invariants, the correct solution is obvious.
// No need to iterate further.
index = highIntervalIdx
return
}
}
// Can end up here if one of the assumptions are violated.
index = -1
return
}
func getInOrder(val1, val2 int64) (int64, int64) {
if val1 <= val2 {
return val1, val2
}
return val2, val1
}