-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutil.gd
143 lines (106 loc) · 4.18 KB
/
util.gd
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
class_name Util
extends Node
# Utility class, autoloaded
class Pair:
var first
var second
func _init(first, second):
self.first = first
self.second = second
func _to_string() -> String:
return "Pair.new(%s, %s)" % [first, second]
static func free_all_children(node: Node):
for child in node.get_children():
child.free()
static func queue_free_all_children(node: Node):
for child in node.get_children():
child.queue_free()
static func filled_array(value, size: int) -> Array:
var array = []
array.resize(size)
array.fill(value)
return array
static func splice_string(string: String, start: int, end: int, replacement: String = "") -> String:
return string.substr(0, start) + replacement + string.substr(end)
static func replace_all_by_function(string: String, regex: RegEx, function: Callable) -> String:
var result = regex.search(string)
while result != null:
var replacement = function.call(result)
string = splice_string(string, result.get_start(), result.get_end(), replacement)
result = regex.search(string)
return string
static func max_by(array: Array, less_than: Callable):
if len(array) == 0:
return null # No elements in array, so no maximum
return array.reduce(func (acc, b):
if less_than.call(acc, b):
return b
else:
return acc)
static func min_by(array: Array, less_than: Callable):
return max_by(array, func (a, b):
return less_than.call(b, a))
static func max_on(array: Array, key: Callable):
return max_by(array, func (a, b):
return key.call(a) < key.call(b))
static func sum(array: Array):
return array.reduce(func (a, b): return a + b, 0)
# Takes an array and acts like Array.reduce(method, accum), but at
# each iteration, stop_condition is invoked with one argument (the
# current accumulator). If stop_condition returns true, iteration
# stops immediately and the current accumulator is true. In this way,
# this function can short-circuit.
static func reduce_while(array: Array, method: Callable, stop_condition: Callable, accum = null):
if accum == null:
accum = array[0]
array = array.slice(1)
for element in array:
if stop_condition.call(accum):
break
accum = method.call(accum, element)
return accum
# As reduce_while but with `await`able method and stop_condition.
static func reduce_while_async(array: Array, method: Callable, stop_condition: Callable, accum = null):
if accum == null:
accum = array[0]
array = array.slice(1)
for element in array:
if await stop_condition.call(accum):
break
accum = await method.call(accum, element)
return accum
static func find_if(array: Array, predicate: Callable):
for i in range(len(array)):
if predicate.call(array[i]):
return i
return null
static func normalize_angle(angle: float) -> float:
return fmod(fmod(angle, 2 * PI) + 2 * PI, 2 * PI)
# Merges all of the keys from the right dictionary into the left one,
# modifying the left dictionary in-place. If a key exists in both
# dictionaries, then `merge_function` is called with the key and both
# values, to determine a merged value to store in the left dictionary.
static func merge_dicts_in_place(left: Dictionary, right: Dictionary, merge_function: Callable) -> void:
for key in right.keys():
if key in left:
left[key] = merge_function.call(key, left[key], right[key])
else:
left[key] = right[key]
# Stops when the end of the shorter array is reached.
static func zip(left: Array, right: Array) -> Array:
var result = []
for i in range(min(len(left), len(right))):
result.push_back(Pair.new(left[i], right[i]))
return result
static func ncr(n: int, r: int) -> int:
if r > n or r < 0:
return 0
if 2 * r > n:
return ncr(n, n - r) # Use symmetry property: nCr(n, r) = nCr(n, n - r)
var numerator = 1
var denominator = 1
for i in range(r):
numerator *= (n - i)
denominator *= (i + 1)
@warning_ignore("integer_division")
return numerator / denominator