Categories
Programming What I’m Up To

My solution to Advent of Code 2020’s Day 6 challenge, in Python

Welcome to another installment in my Advent of Code 2020 series, where I present my solutions to this year’s Advent of Code challenges!

In this installment, I share my Python solution to Day 6 of Advent of Code, titled Custom Customs.

Spoiler alert!

Please be warned: If you want to try solving the challenge on your own and without any help, stop reading now! The remainder of this post will be all about my solution to both parts of the Day 6 challenge.

The Day 6 challenge, part one

The challenge

Here’s the text from part one of the challenge:

As your flight approaches the regional airport where you’ll switch to a much larger plane, customs declaration forms are distributed to the passengers.

The form asks a series of 26 yes-or-no questions marked a through z. All you need to do is identify the questions for which anyone in your group answers “yes”. Since your group is just you, this doesn’t take very long.

However, the person sitting next to you seems to be experiencing a language barrier and asks if you can help. For each of the people in their group, you write down the questions for which they answer “yes”, one per line. For example:

In this group, there are 6 questions to which anyone answered “yes”: abcxy, and z. (Duplicate answers to the same question don’t count extra; each question counts at most once.)

Another group asks for your help, then another, and eventually you’ve collected answers from every group on the plane (your puzzle input). Each group’s answers are separated by a blank line, and within each group, each person’s answers are on a single line. For example:

This list represents answers from five groups:

  • The first group contains one person who answered “yes” to 3 questions: ab, and c.
  • The second group contains three people; combined, they answered “yes” to 3 questions: ab, and c.
  • The third group contains two people; combined, they answered “yes” to 3 questions: ab, and c.
  • The fourth group contains four people; combined, they answered “yes” to only 1 question, a.
  • The last group contains one person who answered “yes” to only 1 question, b.

In this example, the sum of these counts is 3 + 3 + 3 + 1 + 1 = 11.

For each group, count the number of questions to which anyone answered “yes”. What is the sum of those counts?

Importing the data

Every Advent of Code participant gets their own set of data. I copied my data and went through my usual process of bringing it into a Jupyter Notebook running a Python kernel.

This involves pasting it into a triple-quoted string and assigning it to the variable raw_input, and then splitting it using two newline characters in a row as a delimiter, producing a list named split_input:

Each item in the split_input list represents the collected answers for a group. If a group has more than one person in it, a newline character separates each person’s answers.

In the sample of split_input shown below:

  • The first line shows the answers for the first group, which is made up of two people.
  • The fifth line shows the answers for the fifth group, which is made up of five people. All of them answered yes to only one question: Question v.

Finally, I split each item in split_items, using the newline character as the separator:

The result was a list that I named groups, where:

  • Each item in groups represents a group of passengers
  • Each group is a list, where each item in the list represents the answers for one passenger in that group.

Here’s a sample of groups:

With the input data massaged into something that could easily be processed in Python, it was time to get to work.

Strategy

The goal was to get the total of all the “yes” answers for all the groups, keeping in mind that if any person in the group answers “yes” to a given question, the group is considered to have answered “yes” to that question.

Consider a group of three people. If:

  • the first person in the group answered “yes” to questions a, b, and c,
  • the second person in the group answered “yes” to questions d, e, and f,
  • and the third person in the group answered “yes” to questions g, h, and i…

…the the group is considered to have answered yes to questions a though i.

To put it mathematically, a group’s answers was the union of the answers of everyone in the group.

With that in mind, I wrote this function:

This function takes advantage of the fact that while Python’s union() is a set method, it can take one or more non-set arguments, as long as it can convert the arguments into a set.

For example, this code:

results in this set:

I rearranged the set so that its items would appear in alphabetical order so that it would be easier to read. This is fine, because with sets, there is no order.

Now that I had count_union_group_answers(), I could apply it to groups

…and get the answer for part one: 6504.

The Day 6 challenge, part two

The challenge

Here’s the text of part two:

As you finish the last group’s customs declaration, you notice that you misread one word in the instructions:

You don’t need to identify the questions to which anyone answered “yes”; you need to identify the questions to which everyone answered “yes”!

Using the same example as above:

This list represents answers from five groups:

  • In the first group, everyone (all 1 person) answered “yes” to 3 questions: ab, and c.
  • In the second group, there is no question to which everyone answered “yes”.
  • In the third group, everyone answered yes to only 1 question, a. Since some people did not answer “yes” to b or c, they don’t count.
  • In the fourth group, everyone answered yes to only 1 question, a.
  • In the fifth group, everyone (all 1 person) answered “yes” to 1 question, b.

In this example, the sum of these counts is 3 + 0 + 1 + 1 + 1 = 6.

For each group, count the number of questions to which everyone answered “yes”. What is the sum of those counts?

Strategy

This time, the goal was to get the total of all the “yes” answers for all the groups, keeping in mind that the group is only considered to have answered “yes” to a given question if every person in the group answered “yes” to that question.

Consider a group of three people. If:

  • the first person in the group answered “yes” to questions a, b, and c,
  • the second person in the group answered “yes” to questions a, e, and f,
  • and the third person in the group answered “yes” to questions a, h, and i…

…the the group is considered to have answered yes to question a, and nothing else.

To put it mathematically, a group’s answers was the intersection of the answers of everyone in the group.

All I had to do was tweak the count_union_group_answers() function from part one to find the intersection of group members’ answers…

…and then apply count_intersection_group_answers() to groups

This gave me the answer for part two: 3351.

Recommended reading

Solutions for other days in Advent of Code 2020

Categories
Security Tampa Bay What I’m Up To

The Undercroft and their cybersecurity course, UC Baseline

Photo: The Undercroft sign, featuring the Undercroft’s “mascot” — a stag standing upright in a suit, leaning jauntily against an umbrella, walking stick-style.One of the silver linings of my job evaporating due to the pandemic is that I suddenly had a lot of free time to try some new things. The best of those new things by far was my five weeks in The Undercroft’s inaugural UC Baseline cybersecurity course.

What is The Undercroft?

The Undercroft was recently featured in the Tampa Magazine article, The Latest on Tampa’s Tech Scene. Here’s the relevant excerpt:

Over the past year, a number of notable out-of-state tech companies have chosen to open offices in or relocate to Tampa. Last December, Tampa beat out other up-and-coming tech hubs like Denver and Atlanta as the new home of Boston-based Drift, a marketing technology platform. Information technology training franchiser New Horizons moved its headquarters from Pennsylvania to Tampa in January. And that same month, D.C.-based technology company TheIncLab expanded to Ybor City. TheIncLab opened an “Artificial Intelligence Experience Lab” in The Undercroft, a cybersecurity incubator that launched last summer with the hopes of turning the historic Ybor into a tech industry hotspot.

“At The Undercroft, we’re focusing on the supply side of cybersecurity,” says CEO Adam Sheffield. “How do we support more talent in this community and more people who have passion for the field?”

Initially conceived as a co-working type space where startups and members could connect, The Undercroft launched a training program, UC Baseline, in response to layoffs during the coronavirus shutdown. The UC Baseline program is designed to help educate people moving into the cybersecurity workforce or transitioning from traditional IT roles. Ten participants have signed up for the six-week program that offers courses in networking, software, and hardware, according to Sheffield Incubators and accelerators are behind much of Tampa’s recent tech growth, as nonprofits like the Tampa Bay Wave and Embarc Collective offer resources and networking opportunities for local startups, including two recent programs that focus on boosting the  representation of women and diversity in the tech industry.

To describe The Undercroft as Tampa Bay’s security guild and cybersecurity coworking space is fair, but that description doesn’t capture the spirit of the place.

A better way to paint the picture would be to call it the 21st-century cybersecurity counterpart of coffeehouses in 17th- and 18th-century England. Like those coffeehouses of old, The Undercroft is a place in a beautiful old building that functions as the home for the (often boisterous) exchange of ideas, the advancement of specialized fields of knowledge, a little deal-making, and if you pay attention, a great place to learn.

(Thankfully, The Undercroft departs from those old coffeehouses in one important way: Women are welcome in The Undercroft.)

How I ended up in UC Baseline

Back in mid-July, I’d heard about scholarships for The Undercoft’s then-upcoming cybersecurity class. I posted an article about it, which ended with this quip:

(I’ll admit it: Although I’m not likely to qualify, I applied.)

I applied, and to my surprise, I qualified, which meant that I was in this classroom a couple of weeks later:

What I did in UC Baseline

And thus began five intense weeks, which comprised the following…

Hardware 101 — Gain a thorough understanding about the devices on which all our software runs and through which all our information flows:

Networking 101 — Learn how our systems are connected and the ways in which they communicate through these connections:

Tap to view at full size.

Linux 101 — Covers the foundations of security in Linux environments, the OS on which the internet runs:

Tap to view at full size.

Windows 101 — Here’s a big challenge — learn the foundations of security for Windows environments:

Tap to view at full size.

Information Security 101 — Covers everything from core IT concepts, to cybersecurity principles, methods, and practices:

Tap to view my set of links from Infosec Week at UC Baseline.

Python 101 — If you’re doing security, you should have some coding skills to automate your work and build tooling, and Python’s an excellent language for that task:

Tap to view at full size.

 

This is not for someone who’s casually curious about cybersecurity. It’s a lot of work. As I wrote midway through the course:

If you take The Undercroft’s five-week cybersecurity course, UC Baseline, you will have to absorb a lot of material.

After one particular day, I felt like the cat in this video:

The course was taught by a team of instructors who work in the security industry when they’re not teaching. They’re also a personable bunch, and all of them went above and beyond in their efforts to ensure that we students were getting the most out of our classes.

The course ended with a career fair featuring presenters and recruiters from local and national cybersecurity organizations…

and then a Capture the Flag competition and socially-distanced barbecue:

The payoff

Did it pay off to devote 5 weeks, 5 days a week, 8 hours a day, to attend UC Baseline? I think it did.

I’m really a programmer and developer evangelist by training and experience. There’s a tendency in both these lines of work to think of security as an afterthought. Attending UC Baseline, learning from actual security professionals, getting my hands on the actual hardware and software used by the pros, and even just being in The Undercroft helped me refine my security mindset.

That in turn helped me bring my A-game when it was time to apply for a job at Auth0 and then go through their rigorous interview process (which I wrote about here).

I’m not alone — 8 out of 10 of the inaugural UC Baseline class got work around a month or so after completing the program.

My thanks to the instructors for the excellent courses:  , Koby Bryan , Michael Dorsey , George Bilbrey , Jon B , Zoran Jovic, as well as my fellow students, who made the classes more enjoyable: Hawley , Danielle True ,  , Melissa Bloomer , Alyssa Kennedy , Nicolas Claude , Ryan Butler, and Anthony Davis!

And of course, special thanks to Team Undercroft, for making such a special place — the Tampa tech scene just wouldn’t be same without you: Joy Randels, Adam Sheffield, and Chris Machowski!

Another UC Baseline in 2021!

If UC Baseline sounds interesting to you, and if you think you’re up to the challenge, there’s another one taking place in early 2021. Visit the UC Baseline page to find out more!

Find out more

Categories
Programming What I’m Up To

My solution to Advent of Code 2020’s Day 5 challenge, in Python

Welcome to another installment in my Advent of Code 2020 series, where I present my solutions to this year’s Advent of Code challenges!

In this installment, I share my Python solution to Day 5 of Advent of Code, titled Binary Boarding.

Spoiler alert!

Please be warned: If you want to try solving the challenge on your own and without any help, stop reading now! The remainder of this post will be all about my solution to both parts of the Day 5 challenge.

The Day 5 challenge, part one

The challenge

Here’s the text from part one of the challenge:

You board your plane only to discover a new problem: you dropped your boarding pass! You aren’t sure which seat is yours, and all of the flight attendants are busy with the flood of people that suddenly made it through passport control.

You write a quick program to use your phone’s camera to scan all of the nearby boarding passes (your puzzle input); perhaps you can find your seat through process of elimination.

Instead of zones or groups, this airline uses binary space partitioning to seat people. A seat might be specified like FBFBBFFRLR, where F means “front”, B means “back”, L means “left”, and R means “right”.

The first 7 characters will either be F or B; these specify exactly one of the 128 rows on the plane (numbered 0 through 127). Each letter tells you which half of a region the given seat is in. Start with the whole list of rows; the first letter indicates whether the seat is in the front (0 through 63) or the back (64 through 127). The next letter indicates which half of that region the seat is in, and so on until you’re left with exactly one row.

For example, consider just the first seven characters of FBFBBFFRLR:

  • Start by considering the whole range, rows 0 through 127.
  • F means to take the lower half, keeping rows 0 through 63.
  • B means to take the upper half, keeping rows 32 through 63.
  • F means to take the lower half, keeping rows 32 through 47.
  • B means to take the upper half, keeping rows 40 through 47.
  • B keeps rows 44 through 47.
  • F keeps rows 44 through 45.
  • The final F keeps the lower of the two, row 44.

The last three characters will be either L or R; these specify exactly one of the 8 columns of seats on the plane (numbered 0 through 7). The same process as above proceeds again, this time with only three steps. L means to keep the lower half, while R means to keep the upper half.

For example, consider just the last 3 characters of FBFBBFFRLR:

  • Start by considering the whole range, columns 0 through 7.
  • R means to take the upper half, keeping columns 4 through 7.
  • L means to take the lower half, keeping columns 4 through 5.
  • The final R keeps the upper of the two, column 5.

So, decoding FBFBBFFRLR reveals that it is the seat at row 44, column 5.

Every seat also has a unique seat ID: multiply the row by 8, then add the column. In this example, the seat has ID 44 * 8 + 5 = 357.

Here are some other boarding passes:

  • BFFFBBFRRR: row 70, column 7, seat ID 567.
  • FFFBBBFRRR: row 14, column 7, seat ID 119.
  • BBFFBBFRLL: row 102, column 4, seat ID 820.

As a sanity check, look through your list of boarding passes. What is the highest seat ID on a boarding pass?

Importing the data

Every Advent of Code participant gets their own set of data. I copied my data and went through my usual process of bringing it into Python. This involves pasting it into a triple-quoted string and assigning it to the variable raw_input, and then splitting it using the newline character as a delimiter, producing a list named split_input:

Strategy

They dropped a hint in the title of the challenge: Binary Boarding.

They dropped a hint by saying the airlines seats people using binary space partitioning instead of zones.

They dropped a hint when they said that the row numbers range from 0 to 127, and that a seven-character sequence determined your row. Only two characters could be used in that sequence, F and B.

(Additional hint for those of you who didn’t study binary numbers: The numbers 0 through 127 can be represented using seven bits.)

They dropped a hint when they said that the seat numbers (which they called column numbers) range from 0 to 7, and that a three-character sequence determined your seat. Only two characters could be used in that sequence, L and R.

(Additional hint for those of you who didn’t study binary numbers: The numbers 0 through 7 can be represented using three bits.)

The “FB” and “LR” sequences are just binary numbers in disguise.

Solving this challenge involves:

  • Converting the “FB” and “LR” strings into binary strings.
  • Converting those binary strings into decimal numbers.
  • Doing the math on those numbers to get the seat IDs.

Converting the “FB” and “LR” strings into binary strings and converting those binary strings into decimal numbers

For each “FB” string, I wanted to convert the Fs to 0s and Bs to 1s. In order to do this, I used Python’s string.maketrans() method to build a character translation table and its string.translate() method to make the translation using that table.

The result was this function:

The first line in the function uses string.maketrans() to define a translation table. string.maketrans() takes two arguments:

  1. The characters to be translated.
  2. The corresponding resulting characters.

In this case, I only want F to be translated into 0 and B to be translated into 1. All other characters translated using this table will remain unchanged.

The second line does the actual translating, using the translation table as its guide.

With the function defined, I could then use it to create a list of all the rows, expressed as binary strings:

This line of code creates a new list, binary_rows, by taking the first seven characters of each line of input data — the “FB” string — and converting it to binary.

Here’s a sample of the result:

The next step was to convert binary_rows into a list of its numeric equivalents:

This line of code, creates a new list, decimal_rows, by converting each binary string into its decimal numeric equivalent. It does this by using the int() function to convert strings to integers, and the extra argument specifies that value represented in the string is in base 2, a.k.a. binary.

Here’s a sample of the result:

It was time to do the same thing with the “LR” strings. This was pretty much the same operation as with the “FB” strings.

First, an LR-to-01 converter:

Then, a list comprehension to use that converter:

This line of code creates a new list, binary_columns, by taking the last three characters of each line of input data — the “LR” string — and converting it to binary.

Finally, convert these numbers into decimal:

I now had two lists that I could use to do the math:

  • decimal_rows: The “FB” sequences, converted into decimal numbers.
  • decimal_columns: The “LR” sequences, converted into decimal numbers.

Doing the math to get the seat IDs

As stated in the problem definition, the ID for any given seat is (its row number * 8) + (its seat number). I needed to build a list of seat IDs using decimal_rows and decimal_columns.

Here’s the code I used to do it:

The first line uses zip() to take two lists to make a single list filled with tuples. Each tuple has an item from the first list and a corresponding item from the second list. Here’s an example of zip() in action:

The second line uses the newly-created decimal_rows_and_columns as a basis for creating a new list of seat IDs.

Once the seat_ids list was created, it was a matter of using the max() function to get the highest ID value, which was the solution for part one. In my case, the value was 883.

The Day 5 challenge, part two

The challenge

Here’s the text of part two:

Ding! The “fasten seat belt” signs have turned on. Time to find your seat.

It’s a completely full flight, so your seat should be the only missing boarding pass in your list. However, there’s a catch: some of the seats at the very front and back of the plane don’t exist on this aircraft, so they’ll be missing from your list as well.

Your seat wasn’t at the very front or back, though; the seats with IDs +1 and -1 from yours will be in your list.

What is the ID of your seat?

Strategy

It’s a full flight, so my seat should be the only one missing from the list. I could find this seat by doing the following:

  • Sorting the seats in ascending order.
  • Iterating through the seats, while keeping an eye out for a “gap”. That gap is my seat.

Solution

Here’s the code I used to solve part two:

It creates a list of sorted seat IDs, which it then loops through. While looping through it, it checks to see if the ID of the seat immediately after the current one is 2 higher than the current ID. If it is, we’ve found the gap, and the ID of my seat is the ID of the current seat plus one.

In my case, the seat ID was 532. I entered that value and solved part two.

Categories
Current Events Tampa Bay

What’s happening in the Tampa Bay tech/entrepreneur/nerd scene (Week of Monday, December 7, 2020)

Once again, here’s the weekly list of events for events for Tampa Bay techies, entrepreneurs, and nerds. Every week, on GlobalNerdy.com and on the mailing list, I scour the announcements for events that are interesting to or useful for those of you who are building the future here in “The Other Bay Area, on The Other West Coast”.

This list covers events from Monday, December 7 through Sunday, December 13, 2020.

Events — especially virtual, online ones — can pop up at the last minute. I add them to the list as I find out about them. Come back and check this article from time to time, as you might find a new listing that wasn’t there before!

This week’s events

Monday, December 7

Tuesday, December 8

Wednesday, December 9

Thursday, December 10

Friday, December 11

Saturday, December 12

Sunday, December 13

Do you have any events or announcements that you’d like to see on this list?

Let me know at joey@joeydevilla.com!

Join the mailing list!

If you’d like to get this list in your email inbox every week, enter your email address below. You’ll only be emailed once a week, and the email will contain this list, plus links to any interesting news, upcoming events, and tech articles.

Join the Tampa Bay Tech Events list and always be informed of what’s coming up in Tampa Bay!


Categories
Programming What I’m Up To

My solution to Advent of Code 2020’s Day 4 challenge, in Python

Welcome to another installment in my Advent of Code 2020 series, where I present my solutions to this year’s Advent of Code challenges!

In this installment, I share my Python solution to Day 4 of Advent of Code, a.k.a. “The Toboggan Puzzle”.

Spoiler alert!

Please be warned: If you want to try solving the challenge on your own and without any help, stop reading now! The remainder of this post will be all about my solution to both parts of the Day 4 challenge.

The Day 4 challenge, part one

The challenge

Here’s the text from part one of the challenge:

You arrive at the airport only to realize that you grabbed your North Pole Credentials instead of your passport. While these documents are extremely similar, North Pole Credentials aren’t issued by a country and therefore aren’t actually valid documentation for travel in most of the world.

It seems like you’re not the only one having problems, though; a very long line has formed for the automatic passport scanners, and the delay could upset your travel itinerary.

Due to some questionable network security, you realize you might be able to solve both of these problems at the same time.

The automatic passport scanners are slow because they’re having trouble detecting which passports have all required 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)

Passport data is validated in batch files (your puzzle input). Each passport is represented as a sequence of key:value pairs separated by spaces or newlines. Passports are separated by blank lines.

Here is an example batch file containing four passports:

The first passport is valid – all eight fields are present. The second passport is invalid – it is missing hgt (the Height field).

The third passport is interesting; the only missing field is cid, so it looks like data from North Pole Credentials, not a passport at all! Surely, nobody would mind if you made the system temporarily ignore missing cid fields. Treat this “passport” as valid.

The fourth passport is missing two fields, cid and byr. Missing cid is fine, but missing any other field is not, so this passport is invalid.

According to the above rules, your improved system would report 2 valid passports.

Count the number of valid passports – those that have all required fields. Treat cid as optional. In your batch file, how many passports are valid?

Importing the data

Every Advent of Code participant gets their own set of data. I copied my data and went through my usual process of bringing it into Python. This involves pasting it into a triple-quoted string and assigning it to the variable raw_input.