Advertisement
Guest User

Advent of Code 2020 Day 4

a guest
Dec 5th, 2020
211
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 6.11 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "encoding/json"
  5.     "fmt"
  6.     "io/ioutil"
  7.     "log"
  8.     "os"
  9.     "strconv"
  10.     "strings"
  11.     "time"
  12. )
  13.  
  14. type config struct {
  15.     Passports []passport
  16. }
  17.  
  18. type passport struct {
  19.     Byr string //`json:"byr"` // birth year
  20.     Iyr string //`json:"iyr"` // issue year
  21.     Eyr string //`json:"eyr"` // expiration year
  22.     Hgt string //`json:"hgt"` // height
  23.     Hcl string //`json:"hcl"` // hair color
  24.     Ecl string //`json:"ecl"` // eye color
  25.     Pid string //`json:"pid"` // passport id
  26.     Cid string //`json:"cid"` // country id
  27. }
  28.  
  29. func parse() config {
  30.     f, err := os.Open("input.txt")
  31.     if err != nil {
  32.         log.Println(err)
  33.     }
  34.     defer func() {
  35.         err = f.Close()
  36.         if err != nil {
  37.             log.Println(err)
  38.         }
  39.     }()
  40.  
  41.     fb, err := ioutil.ReadAll(f)
  42.     if err != nil {
  43.         log.Println(err)
  44.     }
  45.  
  46.     var jb []byte
  47.     for i := range fb {
  48.         switch {
  49.         case i == 0: // beginning
  50.             header := []byte("{\"passports\":[{\"")
  51.             for hb := range header {
  52.                 jb = append(jb, header[hb])
  53.             }
  54.             jb = append(jb, fb[i])
  55.         case fb[i] == 58: // :
  56.             colon := []byte("\":\"")
  57.             for cb := range colon {
  58.                 jb = append(jb, colon[cb])
  59.             }
  60.         case fb[i] == 32: // space
  61.             space := []byte("\",\"")
  62.             for sb := range space {
  63.                 jb = append(jb, space[sb])
  64.             }
  65.         case fb[i] == 10: // newline
  66.             if fb[i-1] != 10 {
  67.                 newline := []byte("\",\"") // treat like space
  68.                 for nb := range newline {
  69.                     jb = append(jb, newline[nb])
  70.                 }
  71.             } else {
  72.                 // divider
  73.                 jb = jb[:len(jb)-2]
  74.                 divider := []byte("},{\"")
  75.                 for db := range divider {
  76.                     jb = append(jb, divider[db])
  77.                 }
  78.             }
  79.         default:
  80.             jb = append(jb, fb[i])
  81.         }
  82.     }
  83.  
  84.     jb = jb[:len(jb)-2]
  85.     footer := []byte("}]}")
  86.     for ftb := range footer {
  87.         jb = append(jb, footer[ftb])
  88.     }
  89.  
  90.     var batch config
  91.  
  92.     err = json.Unmarshal(jb, &batch)
  93.     if err != nil {
  94.         log.Println(err.Error())
  95.     }
  96.  
  97.     return batch
  98.  
  99. }
  100.  
  101. func byr(done chan bool, d string) {
  102.     birth_year, err := strconv.Atoi(d)
  103.     if err != nil {
  104.         log.Println(err)
  105.     }
  106.     switch {
  107.     case birth_year >= 1920 && birth_year <= 2002:
  108.         done <- true
  109.         return
  110.     default:
  111.         done <- false
  112.         return
  113.     }
  114. }
  115.  
  116. func ecl(done chan bool, d string) {
  117.     switch d {
  118.     case "amb":
  119.         done <- true
  120.         return
  121.     case "blu":
  122.         done <- true
  123.         return
  124.     case "brn":
  125.         done <- true
  126.         return
  127.     case "gry":
  128.         done <- true
  129.         return
  130.     case "grn":
  131.         done <- true
  132.         return
  133.     case "hzl":
  134.         done <- true
  135.         return
  136.     case "oth":
  137.         done <- true
  138.         return
  139.     default:
  140.         done <- false
  141.         return
  142.     }
  143. }
  144.  
  145. func pid(done chan bool, d string) {
  146.     passport_id := []byte(d)
  147.     switch len(passport_id) {
  148.     case 9:
  149.         done <- true
  150.         return
  151.     default:
  152.         done <- false
  153.         return
  154.     }
  155. }
  156.  
  157. func iyr(done chan bool, d string) {
  158.     issue_year, err := strconv.Atoi(d)
  159.     if err != nil {
  160.         log.Println(err)
  161.     }
  162.     switch {
  163.     case issue_year >= 2010 && issue_year <= 2020:
  164.         done <- true
  165.         return
  166.     default:
  167.         done <- false
  168.         return
  169.     }
  170. }
  171.  
  172. func eyr(done chan bool, d string) {
  173.     expiration_year, err := strconv.Atoi(d)
  174.     if err != nil {
  175.         log.Println(err)
  176.     }
  177.     switch {
  178.     case expiration_year >= 2020 && expiration_year <= 2030:
  179.         done <- true
  180.         return
  181.     default:
  182.         done <- false
  183.         return
  184.     }
  185. }
  186.  
  187. func hcl(done chan bool, d string) { // # + 6*char (0-9),(a-f) TODO: read about octal
  188.     hair_color := []byte(d)
  189.     switch len(hair_color) {
  190.     case 7: // check
  191.         switch hair_color[0] {
  192.         case 35: // #, check
  193.             for i := 1; i < len(hair_color); i++ {
  194.                 switch hair_color[i] {
  195.                 case 060: // 0
  196.                     break
  197.                 case 061: // 1
  198.                     break
  199.                 case 062: // 2
  200.                     break
  201.                 case 063: // 3
  202.                     break
  203.                 case 064: // 4
  204.                     break
  205.                 case 065: // 5
  206.                     break
  207.                 case 066: // 6
  208.                     break
  209.                 case 067: // 7
  210.                     break
  211.                 case 070: // 8
  212.                     break
  213.                 case 071: // 9
  214.                     break
  215.                 case 97: // a
  216.                     break
  217.                 case 98: // b
  218.                     break
  219.                 case 99: // c
  220.                     break
  221.                 case 100: // d
  222.                     break
  223.                 case 101: // e
  224.                     break
  225.                 case 102: // f
  226.                     break
  227.                 default:
  228.                     done <- false
  229.                     return
  230.                 }
  231.             }
  232.             done <- true
  233.             return
  234.         default:
  235.             done <- false
  236.             return
  237.         }
  238.     default:
  239.         done <- false
  240.         return
  241.     }
  242. }
  243.  
  244. func hgt(done chan bool, d string) {
  245.     _, err := strconv.Atoi(d)
  246.     if err != nil {
  247.         switch {
  248.         case strings.Contains(d, "cm"):
  249.             height := strings.Split(d, "")
  250.             height = height[:len(height)-2]
  251.             height_value, err := strconv.Atoi(strings.Join(height, ""))
  252.             if err != nil {
  253.                 done <- false
  254.                 return
  255.             }
  256.             switch {
  257.             case height_value >= 150 && height_value <= 193:
  258.                 done <- true
  259.                 return
  260.             default:
  261.                 done <- false
  262.                 return
  263.             }
  264.         case strings.Contains(d, "in"):
  265.             height := strings.Split(d, "")
  266.             height = height[:len(height)-2]
  267.             height_value, err := strconv.Atoi(strings.Join(height, ""))
  268.             if err != nil {
  269.                 done <- false
  270.                 return
  271.             }
  272.             switch {
  273.             case height_value >= 59 && height_value <= 76:
  274.                 done <- true
  275.                 return
  276.             default:
  277.                 done <- false
  278.                 return
  279.             }
  280.         default:
  281.             done <- false
  282.             return
  283.         }
  284.     }
  285.     done <- false
  286.     return
  287. }
  288.  
  289. func is_valid(p passport) bool {
  290.  
  291.     done := make(chan bool, 7)
  292.     go byr(done, p.Byr)
  293.  
  294.     go ecl(done, p.Ecl)
  295.  
  296.     go pid(done, p.Pid)
  297.  
  298.     go iyr(done, p.Iyr)
  299.  
  300.     go eyr(done, p.Eyr)
  301.  
  302.     go hcl(done, p.Hcl)
  303.  
  304.     go hgt(done, p.Hgt)
  305.  
  306.     i := 0
  307.     for i != 7 { // TODO: research later... write small program
  308.         switch <-done {
  309.         case false:
  310.             return false
  311.         case true:
  312.             i++
  313.         }
  314.     }
  315.     return true
  316. }
  317.  
  318. func main() {
  319.     t := time.Now()
  320.     batch := parse()
  321.     var valid int
  322.     var not_valid int
  323.     for i := range batch.Passports {
  324.         switch {
  325.         case batch.Passports[i].Byr == "":
  326.             break
  327.         case batch.Passports[i].Ecl == "":
  328.             break
  329.         case batch.Passports[i].Pid == "":
  330.             break
  331.         case batch.Passports[i].Iyr == "":
  332.             break
  333.         case batch.Passports[i].Eyr == "":
  334.             break
  335.         case batch.Passports[i].Hcl == "":
  336.             break
  337.         case batch.Passports[i].Hgt == "":
  338.             break
  339.         default:
  340.             if is_valid(batch.Passports[i]) {
  341.                 valid++
  342.             } else {
  343.                 not_valid++
  344.             }
  345.         }
  346.     }
  347.     d := time.Since(t)
  348.     fmt.Printf("valid: %v not valid: %v total: %v/%v time: %v", valid, not_valid, valid+not_valid, len(batch.Passports), d.Nanoseconds())
  349. }
  350.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement