搜索优化,增加L形搜索
This commit is contained in:
parent
da60965471
commit
ab8704d323
|
@ -33,7 +33,7 @@ func TestMatch3(t *testing.T) {
|
||||||
return &Item[int]{t: t}
|
return &Item[int]{t: t}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
var match3 = NewMatch3[int, *Item[int]](9, 9,
|
var match3 = NewMatch3[int, *Item[int]](3, 3,
|
||||||
options...,
|
options...,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -50,9 +50,9 @@ func TestMatch3(t *testing.T) {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
links := match3.links.Get(40)
|
links := match3.links.Get(4)
|
||||||
linkItem := match3.matrix.m[match3.positions[40][0]][match3.positions[40][1]]
|
linkItem := match3.matrix.m[match3.positions[4][0]][match3.positions[4][1]]
|
||||||
fmt.Println("LINK", linkItem.t, match3.positions[40])
|
fmt.Println("LINK", linkItem.t, match3.positions[4])
|
||||||
|
|
||||||
for y := 0; y < match3.GetHeight(); y++ {
|
for y := 0; y < match3.GetHeight(); y++ {
|
||||||
for x := 0; x < match3.GetWidth(); x++ {
|
for x := 0; x < match3.GetWidth(); x++ {
|
||||||
|
@ -72,7 +72,7 @@ func TestMatch3(t *testing.T) {
|
||||||
xys = append(xys, match3.positions[guid])
|
xys = append(xys, match3.positions[guid])
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, rect := range g2d.SearchNotRepeatFullRectangle(xys...) {
|
for _, rect := range g2d.SearchNotRepeatFullRectangle(2, 2, xys...) {
|
||||||
fmt.Println(fmt.Sprintf("找到矩形: TopLeft: (%d, %d), BottomRight: (%d, %d)", rect[0][0], rect[0][1], rect[1][0], rect[1][1]))
|
fmt.Println(fmt.Sprintf("找到矩形: TopLeft: (%d, %d), BottomRight: (%d, %d)", rect[0][0], rect[0][1], rect[1][0], rect[1][1]))
|
||||||
}
|
}
|
||||||
fmt.Println("耗时", time.Since(now))
|
fmt.Println("耗时", time.Since(now))
|
||||||
|
@ -86,4 +86,14 @@ func TestMatch3(t *testing.T) {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
fmt.Println("耗时", time.Since(now))
|
fmt.Println("耗时", time.Since(now))
|
||||||
|
|
||||||
|
now = time.Now()
|
||||||
|
for _, rect := range g2d.SearchNotRepeatRightAngle(4, xys...) {
|
||||||
|
fmt.Print("找到L形:")
|
||||||
|
for _, points := range rect {
|
||||||
|
fmt.Print(fmt.Sprintf("{%d, %d}", points[0], points[1]))
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
fmt.Println("耗时", time.Since(now))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package g2d
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/kercylan98/minotaur/utils/g2d/shape"
|
"github.com/kercylan98/minotaur/utils/g2d/shape"
|
||||||
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MatrixShapeSearchResult[Mark any] struct {
|
type MatrixShapeSearchResult[Mark any] struct {
|
||||||
|
@ -141,75 +142,183 @@ func SearchNotRepeatCross(xys ...[2]int) (result [][][2]int) {
|
||||||
record := map[int]map[int]bool{}
|
record := map[int]map[int]bool{}
|
||||||
for x := 0; x < len(rectangleShape); x++ {
|
for x := 0; x < len(rectangleShape); x++ {
|
||||||
for y := 0; y < len(rectangleShape[0]); y++ {
|
for y := 0; y < len(rectangleShape[0]); y++ {
|
||||||
record[x] = map[int]bool{y: true}
|
record[x] = map[int]bool{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, xy := range xys {
|
for _, xy := range xys {
|
||||||
var points [][2]int
|
var points [][2]int
|
||||||
var records [][2]int
|
|
||||||
var find = map[int]bool{}
|
var find = map[int]bool{}
|
||||||
x, y := PositionArrayToXY(xy)
|
x, y := PositionArrayToXY(xy)
|
||||||
x = x + (0 - left)
|
x = x + (0 - left)
|
||||||
y = y + (0 - top)
|
y = y + (0 - top)
|
||||||
// 搜索四个方向
|
// 搜索四个方向
|
||||||
for sx := x - 1; sx >= 0; sx-- {
|
for sx := x - 1; sx >= 0; sx-- {
|
||||||
if record[sx][y] || !rectangleShape[sx][y] {
|
if !rectangleShape[sx][y] {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
find[1] = true
|
find[1] = true
|
||||||
points = append(points, [2]int{sx + left, y + top})
|
points = append(points, [2]int{sx + left, y + top})
|
||||||
records = append(records, [2]int{sx, y})
|
|
||||||
}
|
}
|
||||||
if !find[1] {
|
if !find[1] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for sx := x + 1; sx < len(rectangleShape); sx++ {
|
for sx := x + 1; sx < len(rectangleShape); sx++ {
|
||||||
if record[sx][y] || !rectangleShape[sx][y] {
|
if !rectangleShape[sx][y] {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
find[2] = true
|
find[2] = true
|
||||||
points = append(points, [2]int{sx + left, y + top})
|
points = append(points, [2]int{sx + left, y + top})
|
||||||
records = append(records, [2]int{sx, y})
|
|
||||||
}
|
}
|
||||||
if !find[2] {
|
if !find[2] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for sy := y - 1; sy >= 0; sy-- {
|
for sy := y - 1; sy >= 0; sy-- {
|
||||||
if record[x][sy] || !rectangleShape[x][sy] {
|
if !rectangleShape[x][sy] {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
find[3] = true
|
find[3] = true
|
||||||
points = append(points, [2]int{x + left, sy + top})
|
points = append(points, [2]int{x + left, sy + top})
|
||||||
records = append(records, [2]int{x, sy})
|
|
||||||
}
|
}
|
||||||
if !find[3] {
|
if !find[3] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for sy := y + 1; sy <= len(rectangleShape[0]); sy++ {
|
for sy := y + 1; sy < len(rectangleShape[0]); sy++ {
|
||||||
if record[x][sy] || !rectangleShape[x][sy] {
|
if !rectangleShape[x][sy] {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
find[4] = true
|
find[4] = true
|
||||||
points = append(points, [2]int{x + left, sy + top})
|
points = append(points, [2]int{x + left, sy + top})
|
||||||
records = append(records, [2]int{x, sy})
|
|
||||||
}
|
}
|
||||||
if !find[4] {
|
if !find[4] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, point := range records {
|
|
||||||
record[point[0]][point[1]] = true
|
|
||||||
}
|
|
||||||
result = append(result, append(points, [2]int{x + left, y + top}))
|
result = append(result, append(points, [2]int{x + left, y + top}))
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
sort.Slice(result, func(i, j int) bool {
|
||||||
|
return len(result[i]) > len(result[j])
|
||||||
|
})
|
||||||
|
|
||||||
|
var notRepeat [][][2]int
|
||||||
|
for _, points := range result {
|
||||||
|
var match = true
|
||||||
|
for _, point := range points {
|
||||||
|
x, y := PositionArrayToXY(point)
|
||||||
|
x = x + (0 - left)
|
||||||
|
y = y + (0 - top)
|
||||||
|
if record[x][y] {
|
||||||
|
match = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
record[x][y] = true
|
||||||
|
}
|
||||||
|
if match {
|
||||||
|
notRepeat = append(notRepeat, points)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return notRepeat
|
||||||
|
}
|
||||||
|
|
||||||
|
// SearchNotRepeatRightAngle 在一组二维坐标中从大到小搜索不重复的直角(L)线
|
||||||
|
func SearchNotRepeatRightAngle(minLength int, xys ...[2]int) (result [][][2]int) {
|
||||||
|
if minLength < 3 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
left, _, top, _ := GetShapeCoverageArea(xys...)
|
||||||
|
rectangleShape := GenerateShape(xys...)
|
||||||
|
record := map[int]map[int]bool{}
|
||||||
|
for x := 0; x < len(rectangleShape); x++ {
|
||||||
|
for y := 0; y < len(rectangleShape[0]); y++ {
|
||||||
|
record[x] = map[int]bool{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, xy := range xys {
|
||||||
|
var points [][2]int
|
||||||
|
var find = map[int]bool{}
|
||||||
|
x, y := PositionArrayToXY(xy)
|
||||||
|
x = x + (0 - left)
|
||||||
|
y = y + (0 - top)
|
||||||
|
// 搜索四个方向
|
||||||
|
for sx := x - 1; sx >= 0; sx-- {
|
||||||
|
if !rectangleShape[sx][y] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
find[1] = true
|
||||||
|
points = append(points, [2]int{sx + left, y + top})
|
||||||
|
}
|
||||||
|
if find[1] {
|
||||||
|
goto up
|
||||||
|
}
|
||||||
|
for sx := x + 1; sx < len(rectangleShape); sx++ {
|
||||||
|
if !rectangleShape[sx][y] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
find[2] = true
|
||||||
|
points = append(points, [2]int{sx + left, y + top})
|
||||||
|
}
|
||||||
|
up:
|
||||||
|
for sy := y - 1; sy >= 0; sy-- {
|
||||||
|
if !rectangleShape[x][sy] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
find[3] = true
|
||||||
|
points = append(points, [2]int{x + left, sy + top})
|
||||||
|
}
|
||||||
|
if find[3] {
|
||||||
|
goto end
|
||||||
|
}
|
||||||
|
// down
|
||||||
|
for sy := y + 1; sy < len(rectangleShape[0]); sy++ {
|
||||||
|
if !rectangleShape[x][sy] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
find[4] = true
|
||||||
|
points = append(points, [2]int{x + left, sy + top})
|
||||||
|
}
|
||||||
|
if !find[4] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
{
|
||||||
|
result = append(result, append(points, [2]int{x + left, y + top}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(result, func(i, j int) bool {
|
||||||
|
return len(result[i]) > len(result[j])
|
||||||
|
})
|
||||||
|
|
||||||
|
var notRepeat [][][2]int
|
||||||
|
for _, points := range result {
|
||||||
|
if len(points) < minLength {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var match = true
|
||||||
|
for _, point := range points {
|
||||||
|
x, y := PositionArrayToXY(point)
|
||||||
|
x = x + (0 - left)
|
||||||
|
y = y + (0 - top)
|
||||||
|
if record[x][y] {
|
||||||
|
match = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
record[x][y] = true
|
||||||
|
}
|
||||||
|
if match {
|
||||||
|
notRepeat = append(notRepeat, points)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return notRepeat
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchNotRepeatFullRectangle 在一组二维坐标中从大到小搜索不重复的填充满的矩形
|
// SearchNotRepeatFullRectangle 在一组二维坐标中从大到小搜索不重复的填充满的矩形
|
||||||
// - 不重复指一个位置被使用后将不会被其他矩形使用
|
// - 不重复指一个位置被使用后将不会被其他矩形使用
|
||||||
// - 返回值表示了匹配的形状的左上角和右下角的点坐标
|
// - 返回值表示了匹配的形状的左上角和右下角的点坐标
|
||||||
func SearchNotRepeatFullRectangle(xys ...[2]int) (result [][2][2]int) {
|
func SearchNotRepeatFullRectangle(minWidth, minHeight int, xys ...[2]int) (result [][2][2]int) {
|
||||||
left, _, top, _ := GetShapeCoverageArea(xys...)
|
left, _, top, _ := GetShapeCoverageArea(xys...)
|
||||||
rectangleShape := GenerateShape(xys...)
|
rectangleShape := GenerateShape(xys...)
|
||||||
record := map[int]map[int]bool{}
|
record := map[int]map[int]bool{}
|
||||||
|
@ -221,7 +330,7 @@ func SearchNotRepeatFullRectangle(xys ...[2]int) (result [][2][2]int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shapes := GetExpressibleRectangleBySize(width, height, 2, 2)
|
shapes := GetExpressibleRectangleBySize(width, height, minWidth, minHeight)
|
||||||
for _, s := range shapes {
|
for _, s := range shapes {
|
||||||
x, y := 0, 0
|
x, y := 0, 0
|
||||||
for {
|
for {
|
||||||
|
@ -284,6 +393,9 @@ func GetExpressibleRectangleBySize(width, height, minWidth, minHeight int) (resu
|
||||||
if width == 0 || height == 0 {
|
if width == 0 || height == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if width < minWidth || height < minHeight {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
width--
|
width--
|
||||||
height--
|
height--
|
||||||
for {
|
for {
|
||||||
|
|
|
@ -16,3 +16,15 @@ func TestGetShapeCoverageArea(t *testing.T) {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetExpressibleRectangleBySize(t *testing.T) {
|
||||||
|
for _, xy := range GetExpressibleRectangleBySize(3, 3, 2, 2) {
|
||||||
|
for y := 0; y < xy[1]+1; y++ {
|
||||||
|
for x := 0; x < xy[0]+1; x++ {
|
||||||
|
fmt.Print("0", " ")
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue