-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patheliminate.lua
158 lines (141 loc) · 4.4 KB
/
eliminate.lua
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
149
150
151
152
153
154
155
156
157
158
-- 消除方向: 横向和纵向
local Direction = {
HORIZONTAL = { tag = "h", x = -1, y = 0 },
VERTICAL = { tag = "v", x = 0, y = 1 },
}
-- 用于递归获取连续相同颜色的点
-- 正向
local POSITIVE = 1
-- 反向
local REVERSE = -1
-- 消除最小数量
local ELIMINATE_MIN_COUNT = 3
local function log(fmt, ...)
print(string.format(fmt, ...))
end
local function getPoint(matrix, x, y)
return matrix[y] and matrix[y][x]
end
local function nextContinuousPoint(matrix, ret, point, direction, positiveOrReverse)
local x, y = direction.x * positiveOrReverse, direction.y * positiveOrReverse
log("(%s,%s)->(%s,%s)", point.x, point.y, point.x + x, point.y + y)
local nextPoint = getPoint(matrix, point.x + x, point.y + y)
if nextPoint then
if nextPoint.color == point.color then
if nil == nextPoint[direction.tag] then
table.insert(ret, nextPoint)
nextContinuousPoint(matrix, ret, nextPoint, direction, positiveOrReverse)
else
return false
end
else
log("Different colors")
return true
end
else
log("Point is not exist")
return true
end
end
local function getContinuousPoints(matrix, point, direction)
local ret = {}
log("\ngetContinuousPoints point(%s,%s)", point.x, point.y)
log("\ndirection(%s:%s,%s)", direction.tag, direction.x * POSITIVE, direction.y * POSITIVE)
nextContinuousPoint(matrix, ret, point, direction, POSITIVE)
log("\ndirection(%s:%s,%s)", direction.tag, direction.x * REVERSE, direction.y * REVERSE)
nextContinuousPoint(matrix, ret, point, direction, REVERSE)
if next(ret) then
return ret
else
-- 这里可以回收 ret
return nil
end
end
local function add(ret, point)
if not point.mark then
local x, y = point.x, point.y
ret[y] = ret[y] or {}
ret[y][x] = point
point.mark = true
end
end
local DirectionList = { Direction.HORIZONTAL, Direction.VERTICAL }
local function eliminate(matrix, ret, point)
for _, direction in pairs(DirectionList) do
local tag = direction.tag
if nil == point[direction.tag] then
local points = getContinuousPoints(matrix, point, direction)
if points then
-- 连续的点没有包括自己,所以要减 1
if #points >= ELIMINATE_MIN_COUNT - 1 then
-- 把自己加入到结果中,并且标记这个方向已经ok
add(ret, point)
point[tag] = true
-- 把其他点加入到结果中,并且标记这个方向已经ok
for i, p in ipairs(points) do
add(ret, p)
p[tag] = true
end
for i, p in ipairs(points) do
eliminate(matrix, ret, p)
end
else
for i, p in ipairs(points) do
p[tag] = false
end
end
else
point[tag] = false
end
end
end
end
--[[
将配置转换为矩阵
为了直观,将配置的表转换为下面这样的坐标系
{
^
| {1, 1, 1, 1, 1, 1, 1},
| {1, 2, 2, 2, 1, 1, 1},
| {1, 1, 1, 1, 1, 1, 1},
| {1, 2, 2, 1, 1, 1, 1},
| {1, 1, 1, 1, 1, 1, 1},
————————————————————————————>
}
]]
local function convertMatrix(config)
local matrix = {}
local ySize = #config
for i, xl in ipairs(config) do
local y = ySize - i + 1
local t = {}
matrix[y] = t
for x, color in ipairs(xl) do
t[x] = { x = x, y = y, color = color }
end
end
return matrix
end
local matrix = convertMatrix {
{1, 1, 1, 1, 1, 1, 1},
{1, 2, 2, 2, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1},
{1, 2, 2, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1},
}
local ret = {}
eliminate(matrix, ret, getPoint(matrix, 2, 4))
local function dump(result)
for y = 5, 1, -1 do
local t = {}
for x = 1, 7 do
if result[y] and result[y][x] then
table.insert(t, "o")
else
table.insert(t, "x")
end
end
log(table.concat(t, " "))
end
end
dump(ret)