package main import ( "bufio" "errors" "fmt" "os" "strconv" "strings" ) type freshRange struct { start, end int } func (r *freshRange) contains(c int) bool { return c >= r.start && c <= r.end } func (r *freshRange) nInRange() int { return (r.end - r.start) + 1 } func check(err error) { if err != nil { panic(err) } } func getRanges(scanner *bufio.Scanner) (ranges []freshRange, err error) { ranges = make([]freshRange, 0, 5) for scanner.Scan() { text := scanner.Text() if text == "" { return ranges, nil } startEnd := strings.Split(text, "-") if len(startEnd) != 2 { return nil, errors.New("Fresh range does not contain exactly two numbers") } start, err := strconv.Atoi(startEnd[0]) if err != nil { return nil, err } end, err := strconv.Atoi(startEnd[1]) if err != nil { return nil, err } ranges = append(ranges, freshRange{start, end}) } return nil, errors.New("No empty line in file to delimit fresh ranges") } func main() { file, err := os.Open("five.txt") check(err) defer file.Close() scanner := bufio.NewScanner(file) ranges, err := getRanges(scanner) check(err) authRanges := make([]freshRange, 1, len(ranges)) authRanges[0] = ranges[0] RANGE: for _, r := range ranges { for _, authR := range authRanges { if authR.contains(r.start) { if r.end > authR.end { authR.end = r.end } continue RANGE } if authR.contains(r.end) { if r.start < authR.start { authR.start = r.start } continue RANGE } } authRanges = append(authRanges, r) } potentialNFresh := 0 for _, r := range authRanges { potentialNFresh += r.nInRange() } fmt.Printf("N raw %d and consolidated %d. %d potential fresh ingredients.\n", len(ranges), len(authRanges), potentialNFresh) }