package main import ( "encoding/hex" "fmt" "strconv" "strings" h "git.bullercodeworks.com/brian/adventofcode/helpers" ) func main() { inp := h.StdinToStringSlice() var passports []*Passport var p *Passport p, inp = GetFirstPassport(inp) for p != nil { passports = append(passports, p) p, inp = GetFirstPassport(inp) } var valid int for _, t := range passports { if t.IsValid() { valid++ } } fmt.Printf("%d Valid Passports\n", valid) } type Passport struct { BirthYear string IssueYear string Expiration string Height string HairColor string EyeColor string PassportID string CountryID string } func GetFirstPassport(input []string) (*Passport, []string) { ret := Passport{} var k int for k = range input { if strings.TrimSpace(input[k]) == "" { break } pts := strings.Split(input[k], " ") for pk := range pts { keyval := strings.Split(pts[pk], ":") if len(keyval) == 2 { switch keyval[0] { case "byr": ret.BirthYear = keyval[1] case "iyr": ret.IssueYear = keyval[1] case "eyr": ret.Expiration = keyval[1] case "hgt": ret.Height = keyval[1] case "hcl": ret.HairColor = keyval[1] case "ecl": ret.EyeColor = keyval[1] case "pid": ret.PassportID = keyval[1] case "cid": ret.CountryID = keyval[1] } } } } if k == 0 { return nil, []string{} } return &ret, input[k+1:] } func (p *Passport) ValidBirthYear() bool { wrk, err := strconv.Atoi(p.BirthYear) return err == nil && wrk >= 1920 && wrk <= 2002 } func (p *Passport) ValidIssueYear() bool { wrk, err := strconv.Atoi(p.IssueYear) return err == nil && wrk >= 2010 && wrk <= 2020 } func (p *Passport) ValidExpiration() bool { wrk, err := strconv.Atoi(p.Expiration) return err == nil && wrk >= 2020 && wrk <= 2030 } func (p *Passport) ValidHeight() bool { if strings.Contains(p.Height, "in") { wrk, err := strconv.Atoi(strings.TrimSuffix(p.Height, "in")) return err == nil && wrk >= 59 && wrk <= 76 } else if strings.Contains(p.Height, "cm") { wrk, err := strconv.Atoi(strings.TrimSuffix(p.Height, "cm")) return err == nil && wrk >= 150 && wrk <= 193 } return false } func (p *Passport) ValidHairColor() bool { if !strings.HasPrefix(p.HairColor, "#") { return false } _, err := hex.DecodeString(p.HairColor[1:]) return err == nil } func (p *Passport) ValidEyeColor() bool { return p.EyeColor == "amb" || p.EyeColor == "blu" || p.EyeColor == "brn" || p.EyeColor == "gry" || p.EyeColor == "grn" || p.EyeColor == "hzl" || p.EyeColor == "oth" } func (p *Passport) ValidPassportID() bool { _, err := strconv.Atoi(p.PassportID) return err == nil && len(p.PassportID) == 9 } func (p *Passport) IsValid() bool { return p.ValidBirthYear() && p.ValidIssueYear() && p.ValidExpiration() && p.ValidHeight() && p.ValidHairColor() && p.ValidEyeColor() && p.ValidPassportID() }