123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280 |
- package main
- import (
- "bufio"
- "fmt"
- "log"
- "os"
- "regexp"
- "strconv"
- "strings"
- )
- func checkByr(line string) int {
- if strings.Contains(line, "byr:") {
- re := regexp.MustCompile(`byr:(\d{4})`)
- result := re.FindStringSubmatch(line)
- if len(result) != 2 {
- return 0
- }
- byrString := result[1]
- if byrString == "" {
- return 0
- }
- byr, err := strconv.ParseInt(byrString, 10, 32)
- if err != nil {
- return 0
- }
- if byr >= 1920 && byr <= 2002 {
- return 1
- }
- }
- return 0
- }
- func checkIyr(line string) int {
- if strings.Contains(line, "iyr:") {
- re := regexp.MustCompile(`iyr:(\d{4})`)
- result := re.FindStringSubmatch(line)
- if len(result) != 2 {
- return 0
- }
- iyrString := result[1]
- if iyrString == "" {
- return 0
- }
- iyr, err := strconv.ParseInt(iyrString, 10, 32)
- if err != nil {
- return 0
- }
- if iyr >= 2010 && iyr <= 2020 {
- return 1
- }
- }
- return 0
- }
- func checkEyr(line string) int {
- if strings.Contains(line, "eyr:") {
- re := regexp.MustCompile(`eyr:(\d{4})`)
- result := re.FindStringSubmatch(line)
- if len(result) != 2 {
- return 0
- }
- eyrString := result[1]
- if eyrString == "" {
- return 0
- }
- eyr, err := strconv.ParseInt(eyrString, 10, 32)
- if err != nil {
- return 0
- }
- if eyr >= 2020 && eyr <= 2030 {
- return 1
- }
- }
- return 0
- }
- func checkHgt(line string) int {
- if strings.Contains(line, "hgt:") {
- re := regexp.MustCompile(`hgt:(\d+)(\w{2})`)
- result := re.FindStringSubmatch(line)
- if len(result) != 3 {
- return 0
- }
- hgtString := result[1]
- if hgtString == "" {
- return 0
- }
- tp := result[2]
- if tp == "" {
- return 0
- }
- hgt, err := strconv.ParseInt(hgtString, 10, 32)
- if err != nil {
- return 0
- }
- switch tp {
- case "cm":
- if hgt >= 150 && hgt <= 193 {
- return 1
- }
- case "in":
- if hgt >= 59 && hgt <= 76 {
- return 1
- }
- }
- }
- return 0
- }
- func checkHcl(line string) int {
- if strings.Contains(line, "hcl:#") {
- re := regexp.MustCompile(`hcl:#([0-9a-f]{6})`)
- result := re.FindStringSubmatch(line)
- if len(result) != 2 {
- return 0
- }
- hcl := result[1]
- if hcl != "" {
- return 1
- }
- }
- return 0
- }
- var eyeColors = []string{"amb", "blu", "brn", "gry", "grn", "hzl", "oth"}
- func checkEcl(line string) int {
- if strings.Contains(line, "ecl:") {
- re := regexp.MustCompile(`ecl:(\w{3})`)
- result := re.FindStringSubmatch(line)
- if len(result) != 2 {
- return 0
- }
- ecl := result[1]
- if ecl == "" {
- return 0
- }
- for _, color := range eyeColors {
- if color == ecl {
- return 1
- }
- }
- }
- return 0
- }
- func checkPid(line string) int {
- if strings.Contains(line, "pid:") {
- re := regexp.MustCompile(`pid:(\d+)`)
- result := re.FindStringSubmatch(line)
- if len(result) != 2 {
- return 0
- }
- pid := result[1]
- if pid == "" {
- return 0
- }
- if len(pid) != 9 {
- return 0
- }
- _, err := strconv.ParseInt(pid, 10, 32)
- if err == nil {
- return 1
- }
- }
- return 0
- }
- func getChecks() map[string]func(string) int {
- toCheck := make(map[string]func(string) int)
- toCheck["byr:"] = checkByr
- toCheck["iyr:"] = checkIyr
- toCheck["eyr:"] = checkEyr
- toCheck["hgt:"] = checkHgt
- toCheck["hcl:"] = checkHcl
- toCheck["ecl:"] = checkEcl
- toCheck["pid:"] = checkPid
- return toCheck
- }
- func performCheck(line string, name string, check func(string) int) (int, int) {
- check1 := 0
- check2 := 0
- if strings.Contains(line, name) {
- check1 = 1
- check2 = check(line)
- }
- return check1, check2
- }
- func checkLine(line string, toCheck map[string]func(string) int) (int, int) {
- checks1 := 0
- checks2 := 0
- for name, check := range toCheck {
- check1, check2 := performCheck(line, name, check)
- checks1 += check1
- checks2 += check2
- }
- return checks1, checks2
- }
- func countChecks(line string, toCheck map[string]func(string) int, valid1 *int, valid2 *int) {
- check1, check2 := checkLine(line, toCheck)
- if check1 == 7 {
- *valid1++
- }
- if check2 == 7 {
- *valid2++
- }
- }
- func main() {
- if len(os.Args) < 2 {
- log.Fatal("You need to specify a file!")
- }
- file, err := os.Open(os.Args[1])
- if err != nil {
- log.Fatalf("failed to open")
- }
- var (
- valid1, valid2 int
- text string
- )
- toCheck := getChecks()
- scanner := bufio.NewScanner(file)
- for scanner.Scan() {
- line := scanner.Text()
- if line == "" {
- countChecks(text, toCheck, &valid1, &valid2)
- text = ""
- continue
- }
- text += line + " "
- }
- if err := scanner.Err(); err != nil {
- log.Println(err)
- }
- countChecks(text, toCheck, &valid1, &valid2)
- fmt.Println("Part1: ", valid1)
- fmt.Println("Part2: ", valid2)
- }
|