112 lines
2.1 KiB
Go
112 lines
2.1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
|
)
|
|
|
|
func main() {
|
|
inp := h.StdinToStringSlice()
|
|
part1(inp)
|
|
fmt.Println()
|
|
part2(inp)
|
|
}
|
|
|
|
func part1(inp []string) {
|
|
var ret int
|
|
fresh, ing := parseDB(inp)
|
|
for i := range ing {
|
|
for j := range fresh {
|
|
if fresh[j].Contains(ing[i]) {
|
|
ret++
|
|
break
|
|
}
|
|
}
|
|
}
|
|
fmt.Println("# Part 1")
|
|
fmt.Println(ret)
|
|
}
|
|
|
|
func part2(inp []string) {
|
|
fresh, _ := parseDB(inp)
|
|
for {
|
|
var toDel []*Range
|
|
for i := 0; i < len(fresh)-1; i++ {
|
|
for j := i + 1; j < len(fresh); j++ {
|
|
if fresh[i].Overlaps(fresh[j]) {
|
|
fresh[i].Merge(fresh[j])
|
|
toDel = append(toDel, fresh[j])
|
|
}
|
|
}
|
|
if len(toDel) > 0 {
|
|
break
|
|
}
|
|
}
|
|
if len(toDel) == 0 {
|
|
break
|
|
}
|
|
for i := range toDel {
|
|
for j := 0; j < len(fresh); j++ {
|
|
if fresh[j] == toDel[i] {
|
|
fresh = append(fresh[:j], fresh[j+1:]...)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// At this point, all ranges in 'fresh' should be non-overlapping
|
|
var ret int
|
|
for i := range fresh {
|
|
ret += fresh[i].Size()
|
|
}
|
|
fmt.Println("# Part 2")
|
|
fmt.Println(ret)
|
|
}
|
|
|
|
type Range struct {
|
|
beg, end int
|
|
}
|
|
|
|
func NewRange(inp string) *Range {
|
|
r := Range{}
|
|
fmt.Sscanf(inp, "%d-%d", &r.beg, &r.end)
|
|
return &r
|
|
}
|
|
func (r *Range) Contains(i int) bool { return r.beg <= i && i <= r.end }
|
|
func (r *Range) Overlaps(r2 *Range) bool {
|
|
return r.Contains(r2.beg) || r.Contains(r2.end) || r2.Contains(r.beg) || r2.Contains(r.end)
|
|
}
|
|
func (r *Range) Merge(r2 *Range) {
|
|
if !r.Overlaps(r2) {
|
|
fmt.Println("Panic! Tried to merge non-overlapping ranges")
|
|
os.Exit(1)
|
|
}
|
|
r.beg = h.Min(r.beg, r2.beg)
|
|
r.end = h.Max(r.end, r2.end)
|
|
}
|
|
func (r *Range) Size() int { return (r.end - r.beg) + 1 }
|
|
func (r Range) String() string { return fmt.Sprintf("%d to %d", r.beg, r.end) }
|
|
|
|
func parseDB(inp []string) ([]*Range, []int) {
|
|
var retRng []*Range
|
|
var retInt []int
|
|
inRanges := true
|
|
for i := range inp {
|
|
if inp[i] == "" {
|
|
inRanges = false
|
|
continue
|
|
}
|
|
if inRanges {
|
|
retRng = append(retRng, NewRange(inp[i]))
|
|
continue
|
|
}
|
|
var ri int
|
|
fmt.Sscanf(inp[i], "%d", &ri)
|
|
retInt = append(retInt, ri)
|
|
}
|
|
return retRng, retInt
|
|
}
|