package main import "core:math" import "core:slice" import "core:strconv" import "core:strings" import "core:bytes" import "core:fmt" import "core:os" import "../util" map_batch :: proc(batch: []string) -> map[string]string { batch_map := make(map[string]string) for line in batch { parts := strings.split(line, " ") for part in parts { entry := strings.split(part, ":") batch_map[entry[0]] = entry[1] } } return batch_map } EXPECTED_FIELDS :: []string{ "byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid", } part_1 :: proc(lines: []string) { result := 0 batches := make([dynamic]map[string]string) batch: []string batch_idx := 0 for line, idx in lines { if len(line) == 0 { batch := lines[batch_idx:idx] append(&batches, map_batch(batch)) batch_idx = idx + 1 } } batch_loop: for batch in batches { for field in EXPECTED_FIELDS { _, ok := batch[field] if !ok do continue batch_loop } result += 1 } fmt.printfln("Part 1: %d", result) } part_2 :: proc(lines: []string) { result := 0 batches := make([dynamic]map[string]string) batch: []string batch_idx := 0 for line, idx in lines { if len(line) == 0 { batch := lines[batch_idx:idx] append(&batches, map_batch(batch)) batch_idx = idx + 1 } } batch_loop: for batch in batches { for field in EXPECTED_FIELDS { val, ok := batch[field] if !ok do continue batch_loop switch field { case "byr": if len(val) != 4 do continue batch_loop year, ok := strconv.parse_int(val); assert(ok) if year < 1920 || year > 2002 do continue batch_loop case "iyr": if len(val) != 4 do continue batch_loop year, ok := strconv.parse_int(val); assert(ok) if year < 2010 || year > 2020 do continue batch_loop case "eyr": if len(val) != 4 do continue batch_loop year, ok := strconv.parse_int(val); assert(ok) if year < 2020 || year > 2030 do continue batch_loop case "hgt": if len(val) < 3 do continue batch_loop unit := val[len(val)-2:] length, ok := strconv.parse_int(val[:len(val)-2]); assert(ok) switch unit { case "cm": if length < 150 || length > 193 do continue batch_loop case "in": if length < 59 || length > 76 do continue batch_loop case: continue batch_loop } case "hcl": if len(val) != 7 do continue batch_loop if val[0] != '#' do continue batch_loop for letter in val[1:] { switch letter { case '0'..='9': continue case 'a'..='f': continue case: continue batch_loop } } case "ecl": EXPECTED_COLORS :: []string{ "amb", "blu", "brn", "gry", "grn", "hzl", "oth", } if !slice.contains(EXPECTED_COLORS, val) do continue batch_loop case "pid": if len(val) != 9 do continue batch_loop for letter in val { switch letter { case '0'..='9': continue case: continue batch_loop } } } } result += 1 } fmt.printfln("Part 2: %d", result) } main :: proc() { context.allocator = context.temp_allocator defer free_all(context.temp_allocator) INPUT :: #load("input.txt", string) lines := strings.split(INPUT, "\n") lines = lines[:len(lines)-1] part_1(lines) part_2(lines) }