Partial solution for 10.1. We've got grouping, but still need sorting and some printing cleanup.
This commit is contained in:
parent
06a0886b67
commit
e47b6c4a45
6 changed files with 328 additions and 0 deletions
114
2018/internal/day10/groups.go
Normal file
114
2018/internal/day10/groups.go
Normal file
|
@ -0,0 +1,114 @@
|
|||
package day10
|
||||
|
||||
// GroupPoints creates groups of points, then sorts them and returns the sorted list
|
||||
// A 'group' is a series of points that are adjacent to each other.
|
||||
// If this function finds any non-adjacent points, it returns nil.
|
||||
func GroupPoints(points []*Point) [][]*Point {
|
||||
// this seems a bit weird, but it's mapping points that just contain an x,y value to
|
||||
// the actual point objects with velocity information.
|
||||
pointMap := make(map[int]map[int]*Point)
|
||||
for _, p := range points {
|
||||
if pointMap[p.X] == nil {
|
||||
pointMap[p.X] = make(map[int]*Point)
|
||||
}
|
||||
pointMap[p.X][p.Y] = p
|
||||
}
|
||||
|
||||
// If any point is not adjacent to at least one other, we are not done moving.
|
||||
for _, p := range points {
|
||||
if !adjacencyInMap(pointMap, p) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// now, for each point, check for presence in existing groups,
|
||||
// then check the map for adjacencies
|
||||
// This could be more efficient, but the readability of the range
|
||||
// is desirable.
|
||||
groups := [][]*Point{}
|
||||
for _, p := range points {
|
||||
if checkGroups(groups, p) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find and place all adjacent points.
|
||||
group := buildGroup(pointMap, []*Point{}, p)
|
||||
groups = append(groups, group)
|
||||
}
|
||||
|
||||
// TODO: sort the groups
|
||||
|
||||
return groups
|
||||
}
|
||||
|
||||
// returns true if point is already a member of one of groups
|
||||
func checkGroups(groups [][]*Point, point *Point) bool {
|
||||
for _, group := range groups {
|
||||
if checkGroup(group, point) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func checkGroup(group []*Point, point *Point) bool {
|
||||
for _, member := range group {
|
||||
if point == member {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func arePointsAdjacent(p1, p2 *Point) bool {
|
||||
return (p1.X == p2.X-1 || p1.X == p2.X+1 || p1.X == p2.X) &&
|
||||
(p1.Y == p2.Y-1 || p1.Y == p2.Y+1 || p1.Y == p2.Y)
|
||||
}
|
||||
|
||||
func adjacencyInMap(pMap map[int]map[int]*Point, p *Point) bool {
|
||||
return (pMap[p.X-1] != nil && pMap[p.X-1][p.Y] != nil) ||
|
||||
(pMap[p.X+1] != nil && pMap[p.X+1][p.Y] != nil) ||
|
||||
pMap[p.X][p.Y-1] != nil || pMap[p.X][p.Y+1] != nil
|
||||
}
|
||||
|
||||
// recursively walk all adjacent points, adding them to the group.
|
||||
func buildGroup(pMap map[int]map[int]*Point, group []*Point, p *Point) []*Point {
|
||||
// this both prevents duplicates and prevents infinite recursion
|
||||
if checkGroup(group, p) {
|
||||
return group
|
||||
}
|
||||
|
||||
group = append(group, p)
|
||||
|
||||
// look in each of 8 directions, if a point is found, recurse
|
||||
if pMap[p.X-1] != nil {
|
||||
if pMap[p.X-1][p.Y] != nil {
|
||||
group = buildGroup(pMap, group, pMap[p.X-1][p.Y])
|
||||
}
|
||||
if pMap[p.X-1][p.Y-1] != nil {
|
||||
group = buildGroup(pMap, group, pMap[p.X-1][p.Y-1])
|
||||
}
|
||||
if pMap[p.X-1][p.Y+1] != nil {
|
||||
group = buildGroup(pMap, group, pMap[p.X-1][p.Y+1])
|
||||
}
|
||||
}
|
||||
if pMap[p.X+1] != nil {
|
||||
if pMap[p.X+1][p.Y] != nil {
|
||||
group = buildGroup(pMap, group, pMap[p.X+1][p.Y])
|
||||
}
|
||||
if pMap[p.X+1][p.Y-1] != nil {
|
||||
group = buildGroup(pMap, group, pMap[p.X+1][p.Y-1])
|
||||
}
|
||||
if pMap[p.X+1][p.Y+1] != nil {
|
||||
group = buildGroup(pMap, group, pMap[p.X+1][p.Y+1])
|
||||
}
|
||||
}
|
||||
if pMap[p.X][p.Y-1] != nil {
|
||||
group = buildGroup(pMap, group, pMap[p.X][p.Y-1])
|
||||
}
|
||||
if pMap[p.X][p.Y+1] != nil {
|
||||
group = buildGroup(pMap, group, pMap[p.X][p.Y+1])
|
||||
}
|
||||
|
||||
return group
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue