Move to have day be 2 digit always
[advent-of-code-2020.git] / day04 / count_valid_passports_2.py
diff --git a/day04/count_valid_passports_2.py b/day04/count_valid_passports_2.py
new file mode 100644 (file)
index 0000000..e8a0d34
--- /dev/null
@@ -0,0 +1,109 @@
+#!/usr/bin/python3
+
+REQUIRED_FIELDS=(('byr', "Birth Year"),('iyr', "Issue Year"),('eyr', "Expiration Year"),('hgt', "Height"),('hcl', "Hair Colour"),('ecl', "Eye Colour"),('pid',"Passport ID"))
+OPTIONAL_FIELDS=(('cid', "Country ID"))
+VALID_EYE_COLOURS=('amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth')
+
+def check_passport(passport_data):
+    print(passport_data)
+    for field in REQUIRED_FIELDS:
+        if field[0] not in passport_data:
+            return False
+        # check the field data
+        if field[0] == 'byr':
+            if not check_year(passport_data[field[0]], 1920, 2002):
+                return False
+        elif field[0] == 'iyr':
+            if not check_year(passport_data[field[0]], 2010, 2020):
+                return False
+        elif field[0] == 'eyr':
+            if not check_year(passport_data[field[0]], 2020, 2030):
+                return False
+        elif field[0] == 'hgt':
+            if not check_height(passport_data[field[0]]):
+                return False
+        elif field[0] == 'hcl':
+            if not check_hair_colour(passport_data[field[0]]):
+                return False
+        elif field[0] == 'ecl':
+            if not passport_data[field[0]] in VALID_EYE_COLOURS:
+                return False
+        elif field[0] == 'pid':
+            if not check_pid(passport_data[field[0]]):
+                return False
+    return True
+
+def check_year(data, min_year, max_year):
+    try:
+        year = int(data)
+        if year >= min_year and year <= max_year:
+            return True
+        return False
+    except:
+        return False
+
+def check_height(data):
+    try:
+        unit = data[-2:]
+        value = int(data[:-2])
+
+        if unit == "cm":
+            if value >= 150 and value <= 193:
+                return True
+        elif unit == "in":
+            if value >= 59 and value <= 76:
+                return True
+        return False
+    except:
+        return False
+
+def check_hair_colour(data):
+    if data[0] != "#":
+        return False
+    if len(data) != 7:
+        return False
+    if data != data.lower():
+        return False
+    try:
+        value = int(data[1:], 16)
+        return True
+    except:
+        return False
+    return False
+
+def check_pid(data):
+    # first check that the string length is correct
+    if len(data) != 9:
+        return False
+
+    # now check that it's a number
+    try:
+        int(data, 10)
+        return True
+    except:
+        return False
+
+def main():
+    new_passport=False
+    passport_data=dict()
+    valid_passports=0
+    for line in open("input.txt"):
+        if new_passport:
+            if check_passport(passport_data):
+                valid_passports += 1
+            passport_data.clear()
+        line=line.rstrip()
+        if line == '':
+            new_passport=True
+            continue
+        new_passport=False
+        parts=line.split(" ")
+        for part in parts:
+            (key, value) = part.split(":")
+            passport_data[key] = value
+    if not new_passport:
+        if check_passport(passport_data):
+            valid_passports += 1
+    print("Found", valid_passports, "valid passports")
+
+main()