aoc-2020/d02/main.go

111 lines
2.2 KiB
Go

package main
import (
"bufio"
"fmt"
"log"
"os"
"regexp"
"strconv"
"strings"
)
func proccessLines(path string, f func(string) (stop bool, err error)) error {
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
stop, err := f(scanner.Text())
if stop || err != nil {
return err
}
}
if err := scanner.Err(); err != nil {
return err
}
return nil
}
var matcher = regexp.MustCompile(`([0-9]+)-([0-9]+) ([a-zA-Z]): ([a-zA-Z]+)`)
func part1() {
totalValid := 0
err := proccessLines("input.txt", func(line string) (stop bool, err error) {
results := matcher.FindStringSubmatch(line)
if results == nil {
err = fmt.Errorf("invalid line %s", line)
return
}
minCount, err := strconv.Atoi(results[1])
if err != nil {
return
}
maxCount, err := strconv.Atoi(results[2])
if err != nil {
return
}
letter := results[3]
password := results[4]
// fmt.Printf("Make sure %s is in %s between %d and %d times\n", letter, password, minCount, maxCount)
// Validate
count := strings.Count(password, letter)
if minCount <= count && count <= maxCount {
totalValid++
}
return
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total valid %d\n", totalValid)
}
func part2() {
totalValid := 0
err := proccessLines("input.txt", func(line string) (stop bool, err error) {
results := matcher.FindStringSubmatch(line)
if results == nil {
err = fmt.Errorf("invalid line %s", line)
return
}
pos1, err := strconv.Atoi(results[1])
if err != nil {
return
}
pos2, err := strconv.Atoi(results[2])
if err != nil {
return
}
// 1 vs 0 indexed
pos1--
pos2--
letter := results[3]
password := results[4]
// fmt.Printf("Make sure %s is in %s between %d and %d times\n", letter, password, minCount, maxCount)
// Validate
if pos1 >= len(password) || pos2 >= len(password) {
return
}
letter1 := string(password[pos1])
letter2 := string(password[pos2])
if (letter == letter1 || letter == letter2) && letter1 != letter2 {
totalValid++
}
return
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total valid %d\n", totalValid)
}
func main() {
part1()
part2()
}