The task for Day 4 is to validate a series of passports by checking that they have valid data on them. For the first part, the passports are simply validated by verifying that they have all of the fields that they should have:

  • byr (Birth Year)
  • iyr (Issue Year)
  • eyr (Expiration Year)
  • hgt (Height)
  • hcl (Hair Color)
  • ecl (Eye Color)
  • pid (Passport ID)
  • cid (Country ID)

For my approach, I first loaded the data from the file (this is a common theme in these), and then went about searching line by line. Here is my code for Part 1:

with open('day4data.txt') as f:
    lines = [line.rstrip() for line in f]

buildline = ''
valid_fields = ['byr','iyr','eyr','hgt','hcl','ecl','pid']
passengers = []
num_fields = len(valid_fields)
#print num_fields
valid_passports=0
num_valid=0

for line in lines:
  if line != '':
    buildline+=' '+line
  else:
    #print buildline
    linearray=buildline.split(' ')
    linearray=linearray[1:]
    for x in linearray:
      #print x[0:3]
      if(x[0:3] in valid_fields):
        num_valid+=1
    #print linearray
    if num_valid == num_fields:
      valid_passports+=1

    #passengers.append(linearray)
    num_valid = 0
    buildline = ''

#print passengers
print valid_passports

Each passport in the file has multiple lines, separated by blank lines. So for each line, it first checks to see if it’s a blank or not. If it’s not a blank, it compiles the line into a single passport line for processing. Once it hits a blank line, it know it has captured all of the data for that particular passport, and processes the data.

The processing is done by splitting the data into an array, then processing through each entry in the array, looking for one of the required fields. It verifies that a passport is valid by checking to see if the number of fields counted is equal to the length of the fields array.

While the array building is sloppy, and probably could have been done by adding the lines directly to an array, instead of a string that’s then split, I am rather proud of a few bits of this code. Comparing the valid field count to the valid fields array means that it would be trivial to add additional valid fields.

Also the check is particularly nice. It would have been easy to do the check using a basic search on each line. The problem is, this could confuse the program if say, “Hair Color” contains invalid data of “byr” (Birthyear). It would think it found the Birthyear field, but it has not. The field is always the first three characters in a valid passport here, so using “if(x[0:3] in valid_fields):” means it always only checks the first 3 characters.

Part 2 added another layer to the validation to make sure the individual fields actually contained properly formatted, valid data. The basic process is the same, it just involved a lot more if statements to check for the various conditions required. My code is below:

with open('day4data.txt') as f:
    lines = [line.rstrip() for line in f]

buildline = ''
valid_fields = ['byr','iyr','eyr','hgt','hcl','ecl','pid']
valid_eyes = ['amb','blu','brn','gry','grn','hzl','oth']
valid_color = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f']
passengers = []
num_fields = len(valid_fields)
#print num_fields
valid_passports=0
num_valid=0
is_valid=0

for line in lines:
  if line != '':
    buildline+=' '+line
  else:
    #print buildline
    linearray=buildline.split(' ')
    linearray=linearray[1:]
    for x in linearray:
      if(x[0:3] == "byr" and len(x[4:]) == 4):
        if 1920<=int(x[4:])<=2002:
          num_valid+=1

      if(x[0:3] == "iyr" and len(x[4:]) == 4):
        if 2010<=int(x[4:])<=2020:
          num_valid+=1

      if(x[0:3] == "eyr" and len(x[4:]) == 4):
        if 2020<=int(x[4:])<=2030:
          num_valid+=1

      if(x[0:3] == "ecl"):
        if x[4:] in valid_eyes:
          num_valid+=1

      if(x[0:3] == "pid") and (len(x[4:]) == 9):
          num_valid+=1

      if(x[0:3] == "hgt" and x[-2:] == 'cm'):
          if 150<=int(x[4:-2]) <= 193:
            num_valid+=1
      if(x[0:3] == "hgt" and x[-2:] == 'in'):
          if 59<=int(x[4:-2]) <= 76:
            num_valid+=1

      if(x[0:3] == 'hcl' and len(x[4:]) == 7):
          #print x[4:]
          #for n in x[5:]:
           # if n not in valid_color:
            #  is_valid=0
          num_valid+=1

    if num_valid == num_fields:
      valid_passports+=1

    #passengers.append(linearray)
    is_valid = 0
    num_valid = 0
    buildline = ''

#print passengers
print valid_passports

Not a lot of fanciness here, but it uses the same basic principle of counting the valid fields up and comparing them to the length. The difference being that if you needed to add a required field, you would also need to add a conditional for that statement.