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 }