• Skip to main content
  • Skip to primary sidebar
BMA

BeMyAficionado

Inspire Affection

Advent Of Code 2020 – Day 4 – Passport Processing

December 12, 2020 by varunshrivastava Leave a Comment

I just love the way Eric Wastl links the story.

This time it’s about passport processing.

Do visit the link to read the story and understand the task better. But at a high-level, you need to understand this – there are two types of documents:

  • North Pole Credentials
  • Passport

The passport scanner machine is slow and facing some problem detecting which passport have all the fields. The expected fields are as follows:

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

The format of the passport is represented as:

  • sequence of the key:val pair separated by space or newline.
  • Passports are separated by blank lines.

Below is the example batch file containing four passports:

ecl:gry pid:860033327 eyr:2020 hcl:#fffffd byr:1937 iyr:2017 cid:147 hgt:183cm

iyr:2013 ecl:amb cid:350 eyr:2023 pid:028048884 hcl:#cfa07d byr:1929

hcl:#ae17e1 iyr:2013 eyr:2024 ecl:brn pid:760753108 byr:1931 hgt:179cm

hcl:#cfa07d eyr:2025 pid:166559648 iyr:2011 ecl:brn hgt:59in

Table of Contents

  • Part 1 – Scan and Verify that the given passport contains all the required fields
      • Step – 1
      • Step – 2
      • Step – 3
  • Part – 2 – Strict Field Validation

Part 1 – Scan and Verify that the given passport contains all the required fields

While scanning the passport we have to look for the presence of all the credentials. However, there is one optional field cid. Except cid all the other fields are mandatory.

So, we have to read the batch file, scan all the passports and identify how many of those passports are valid (contains all the mandatory fields).

The first thing that we have to do is to parse the given file and fetch the required information.

Perhaps this is the most important step in this problem. So, how can we parse the file in a way that will help us to quickly solve the problem.

Here’s an idea.

When you look at the test file, what do you see?

Well, the information related to the single passport is spread across multiple lines. But one thing that separates one passport from the other is the empty line. Or specifically whenever we encounter \n\n twice in a row. I’ll use this information to separate out the different passports in the batch file.

Once I have the each passport details in its own line then I can simply replace the \n with an empty space ' '. This will give me all the information in one line.

After I have the data in the above format then by splitting them by ' ' will give us the key and value of the passport and then further splitting each keyval by : will give us their value.

I’ll stop with the explanation now and write some code.

Step – 1

f = open("../inputs/day4.txt")
all_lines = f.read().strip()
lines = all_lines.split("\n\n")

Step – 2

Iterate over each line and parse the key and value

for line in lines:
    line = line.strip().replace("\n", " ")

    details = {}
    for keyval in line.split(" "):
        key,val = keyval.split(":")[0], keyval.split(":")[1]
        details[key] = val

Step – 3

Verify the required field and increment the counter.

def is_valid(details):
    mandatory_fields = ("byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid")
    for field in mandatory_fields:
        if field not in details:
            return False
    
    return True

f = open("../inputs/day4.txt")
all_lines = f.read().strip()
lines = all_lines.split("\n\n")

count = 0
for line in lines:
    line = line.strip().replace("\n", " ")

    details = {}
    for keyval in line.split(" "):
        key,val = keyval.split(":")[0], keyval.split(":")[1]
        details[key] = val
    
    if is_valid(details):
        count += 1

print(count)

Let’s run the above code with our actual input.

Great!!! it works. With this we have completed our part of the problem. Let’s checkout the part two.

Part – 2 – Strict Field Validation

In addition to the previous condition, more rules have been introduced. Now each field has to be strictly validated as per the requirement. Following are the added rules:

  • byr (Birth Year) – four digits; at least 1920 and at most 2002.
  • iyr (Issue Year) – four digits; at least 2010 and at most 2020.
  • eyr (Expiration Year) – four digits; at least 2020 and at most 2030.
  • hgt (Height) – a number followed by either cm or in:
    • If cm, the number must be at least 150 and at most 193.
    • If in, the number must be at least 59 and at most 76.
  • hcl (Hair Color) – a # followed by exactly six characters 0–9 or a–f.
  • ecl (Eye Color) – exactly one of: amb blu brn gry grn hzl oth.
  • pid (Passport ID) – a nine-digit number, including leading zeroes.
  • cid (Country ID) – ignored, missing or not.

Looking at different types of validation, I can broadly categorize the validators as:

  • Range Validator
  • Color Validator
  • Number Validator
  • Height Validator

Just by looking at the problem, I’m tending towards the use of lambda to make the code more clean to the eyes. This problem can be done gracefully in by following object oriented style and strategic design pattern but that’s an overkill for this problem; also I’m not in the mood to create classes today. So, lambda will serve us well in this scenario.

I will choose Python to work with this problem.

I will start by creating different validators. You can see them below:

def height_validator(val = ""):
    if not val[0:-2].isnumeric():
        return False

    if val[-2:] == "cm":
        return range_validator(val[:-2], 150, 193)
    
    if val[-2:]  == "in":
        return range_validator(val[:-2], 59, 76)

    return False

def range_validator(val, low, high):
    number = int(val)
    if low <= number <= high:
        return True

def color_validator(val):
    if val[0] != '#':
        return False
    
    if len(val) != 7:
        return False

    flag = True
    for index in range(1, len(val)):
        if not ('0' <= val[index] <= '9' or 'a' <= val[index] <= 'f'):
            flag = False
            break

    return flag

def number_validator(val = ""):
    return val.isdigit()

Each validator validates what is asked for.

Now all we have to do is associate these validators with the is_valid method to get the correct output.

This is where the lambdas are helpful. You see we are going to perform a similar validation on all the fields, so instead of creating a different condition for a different field, we can map the respective field validator at the time of the initialization.

This can be done via lambdas.

Then all that will be left to do is to call that lambda on that field to validate it. Simple.

Let me show you how it’s done in the code:

def is_valid(details):
    mandatory_fields = {
        "byr": lambda val: range_validator(val, 1920, 2002), 
        "iyr": lambda val: range_validator(val, 2010, 2020), 
        "eyr": lambda val: range_validator(val, 2020, 2030), 
        "hgt": lambda val: height_validator(val), 
        "hcl": lambda val: color_validator(val), 
        "ecl": lambda val: val in ("amb", "blu", "brn", "gry", "grn", "hzl", "oth"), 
        "pid": lambda val: len(val) == 9 and val.isdigit(),
        "cid": lambda val: True
    }

    for field in mandatory_fields:
        if field == "cid": continue
        if field not in details:
            return False
    
    for field in details:
        if not mandatory_fields[field](details[field]):
            return False
    
    return True

In the above code, we have associated a lambda function with the field at the time of initialization. In fact, it would be more efficient if we move the initialization part outside of the function.

As you can see in the code below. This is much more optimized because now it doesn’t have to create the dictionary every time the is_valid function is called.

mandatory_fields = {
    "byr": lambda val: range_validator(val, 1920, 2002), 
    "iyr": lambda val: range_validator(val, 2010, 2020), 
    "eyr": lambda val: range_validator(val, 2020, 2030), 
    "hgt": lambda val: height_validator(val), 
    "hcl": lambda val: color_validator(val), 
    "ecl": lambda val: val in ("amb", "blu", "brn", "gry", "grn", "hzl", "oth"), 
    "pid": lambda val: len(val) == 9 and val.isdigit(),
    "cid": lambda val: True
}

def is_valid(details):

    for field in mandatory_fields:
        if field == "cid": continue
        if field not in details:
            return False
    
    for field in details:
        if not mandatory_fields[field](details[field]):
            return False
    
    return True

Great!!! I think the code is ready to be tested with the actual input.

Awesome!!! Getting the correct result for the given problem.

I hope you liked this question. And if you are enjoying it then don’t forget to subscribe to this blog. There’s a lot more to come. And don’t forget to comment your thoughts below.

Related

Filed Under: Programming Tagged With: aoc-2020, day-4, problem-solving, programming, python

Primary Sidebar

Subscribe to Blog via Email

Do you enjoy the content? Feel free to leave your email with me to receive new content straight to your inbox. I'm an engineer, you can trust me :)

Join 874 other subscribers

Latest Podcasts

Recent Posts

  • Is The Cosmos a Vast Computation?
  • Building Semantic Search for E-commerce Using Product Embeddings and OpenSearch
  • Leader Election with ZooKeeper: Simplifying Distributed Systems Management
  • AWS Serverless Event Driven Data Ingestion from Multiple and Diverse Sources
  • A Step-by-Step Guide to Deploy a Static Website with CloudFront and S3 Using CDK Behind A Custom Domain

Recent Comments

  • Varun Shrivastava on Deploy Lambda Function and API Gateway With Terraform
  • Vaibhav Shrivastava on Deploy Lambda Function and API Gateway With Terraform
  • Varun Shrivastava on Should Girls Wear Short Clothes?
  • D on Should Girls Wear Short Clothes?
  • disqus_X5PikVsRAg on Basic Calculator Leetcode Problem Using Object-Oriented Programming In Java

Categories

  • Blogging
  • Cooking
  • Fashion
  • Finance & Money
  • Programming
  • Reviews
  • Software Quality Assurance
  • Technology
  • Travelling
  • Tutorials
  • Web Hosting
  • Wordpress N SEO

Archives

  • November 2024
  • September 2024
  • July 2024
  • April 2024
  • February 2024
  • November 2023
  • June 2023
  • May 2023
  • April 2023
  • August 2022
  • May 2022
  • April 2022
  • February 2022
  • January 2022
  • November 2021
  • September 2021
  • August 2021
  • June 2021
  • May 2021
  • April 2021
  • February 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • April 2020
  • February 2020
  • December 2019
  • November 2019
  • October 2019
  • August 2019
  • July 2019
  • June 2019
  • May 2019
  • April 2019
  • March 2019
  • January 2019
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • March 2018
  • February 2018
  • January 2018
  • December 2017
  • November 2017
  • October 2017
  • September 2017
  • August 2017
  • July 2017
  • June 2017
  • May 2017
  • April 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016
  • August 2016
  • July 2016
  • June 2016
  • May 2016

Tags

Affordable Hosting (4) algorithms (4) amazon (3) aoc-2020 (7) believe in yourself (4) best (4) database (4) earn money blogging (5) education (4) elementary sorting algorithms (4) experience (3) fashion (4) finance (6) Financial Freedom (7) food (7) friends (3) goals (5) google (5) india (10) indian cuisine (5) indian education system (4) java (16) life (16) life changing (4) love (4) make money (3) microservices (9) motivation (4) oops (4) podcast (6) poor education system (4) principles of microservices (5) problem-solving (7) programmer (5) programming (28) python (5) reality (3) seo (6) spring (3) success (10) success factor (4) technology (4) top 5 (7) typescript (3) wordpress (7)

Copyright © 2025 · Be My Aficionado · WordPress · Log in

Go to mobile version