-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstates.lua
More file actions
133 lines (114 loc) · 2.63 KB
/
states.lua
File metadata and controls
133 lines (114 loc) · 2.63 KB
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
local M = {}
M.mid = nil
M.minBound = nil
M.maxBound = nil
function M.setMid(mid)
M.mid = mid
end
function M.setBounds(minBound, maxBound)
M.minBound = minBound
M.maxBound = maxBound
end
local function isInteger(value)
return value ~= nil and math.tointeger(value) ~= nil
end
local function safePow(base, exp)
if not isInteger(exp) then
return nil
end
exp = math.tointeger(exp)
if exp < 0 then
return nil
end
if base == 0 and exp == 0 then
return nil
end
return base ^ exp
end
-- operations
local ops = {
["+"] = function(a, b) return a + b end,
["a-b"] = function(a, b) return a - b end,
["b-a"] = function(a, b) return b - a end,
["*"] = function(a, b) return a * b end,
["a/b"] = function(a, b) return (b ~= 0 and a % b == 0) and a / b or nil end,
["b/a"] = function(a, b) return (a ~= 0 and b % a == 0) and b / a or nil end,
["a^b"] = function(a, b) return safePow(a, b) end,
["b^a"] = function(a, b) return safePow(b, a) end
}
-- given numbers a, b, return all binary ops
function M.calc(a, b)
local results = {}
local seen = {}
for op, func in pairs(ops) do
local result = func(a, b)
if isInteger(result) then
result = math.tointeger(result)
if not seen[result] then
seen[result] = true
results[#results + 1] = result
end
end
end
return results
end
function M.key(nums)
local tmp = {}
for i = 1, #nums do
tmp[i] = math.tointeger(nums[i])
end
table.sort(tmp)
return table.concat(tmp, ",")
end
function M.scoreState(nums)
local scores = {}
for i = 1, #nums do
scores[i] = math.abs(M.mid - nums[i])
end
local sum = 0
for _, v in ipairs(scores) do
sum = sum + v
end
return sum
end
function M.newState(nums, parent)
parent = parent or { score = 0 }
return {
raw = nums,
key = M.key(nums),
score = M.scoreState(nums),
rscore = parent.score - M.scoreState(nums),
depth = parent.depth and parent.depth + 1 or 0
}
end
function M.searchNextDepth(state)
local results = {}
local nums = state.raw
local n = #nums
for i = 1, n - 1 do
for j = i + 1, n do
local a, b = nums[i], nums[j]
for _, r in ipairs(M.calc(a, b)) do
local nextNums = {}
for k = 1, n do
if k ~= i and k ~= j then
nextNums[#nextNums + 1] = nums[k]
end
end
nextNums[#nextNums + 1] = r
results[#results + 1] = M.newState(nextNums, state)
end
end
end
return results
end
function M.canReach(state, min, max)
if min == nil or max == nil then
return true
end
if min > max then
return false
end
return true
end
return M