AOC Day 3 2021

This is part of a greater series about solving advent of code with spreadsheets.

Foreword

There was a lot of repetitive work in this challenge. Easy enough in sheets but not easy on readers. Particularly on the number of bits …

Part One

As always, read the problem text first. In summary, the input is a list of binary numbers (of the same length). The goal is to find, for each binary place, the most and least common values.

The number gamma uses the common bits. The number epsilon uses the least common bits.

Finally, multiply gamma by epsilon.

Solving Part One

Input parsing is boring and repetitive. Skip!0

(0) For the curious. SPLIT uses non-empty separators. Instead use MID.

Data is ready as the following columns.

DATA BIT 0 B2 (e.g 1) ...
BIT 1 C2 (e.g 0) ...
2 D2 (e.g 1) ...

Each individual gamma bit is calculated like the following.

GAMMA BIT 0 H2 = ROUND(AVERAGE(B2:B))
BIT 1 I2 = ROUND(AVERAGE(C2:C))
2 J2 = repeat ↓

All those bits become a number like this.

GAMMA H4 = BIN2DEC(CONCATENATE(H2:J2))
EPSILON I4 = (2^4 - 1) - H4
OUTPUT J4 = H4 * I4

How Part One Works

Most of the cleverness is with binary.

AVERAGE

First, why is the AVERAGE rounded the most common value?

A is the count of 1s. Z is the count of 0s.

The average equals …

Case by case analysis shows …1

(1) Sometimes it’s worth proving a program. Sometimes I roll with faulty assumptions and it works out.

We ignore the particular case that A = Z. The author didn’t provide guidance on ties. And in fact no inputs need tie-breaking.

BIN2DEC Limitations

The function BIN2DEC converts binary to decimal. It is particular about input …

(2) The fact that it’s a signed number might surprise you. It surprised me! I had no idea until I wrote this article.

The second condition is a problem. The demo uses 3 bits, but the challenge input uses 12.

The solution is to convert to decimal in pieces.

Epsilon From Gamma

This solution uses trickery to calculate epsilon. A single cell flips the bits of gamma. When 0 and 1 are the only options this works to get the less common value.

To flip bits in binary use subtraction. This subtraction is converted into decimal.

  11111  →   (2^6 - 1)
- gamma     -    gamma
-------     ----------

Part Two

Part two requires much more effort.

In summary the objective is still to get two bitstrings

Instead of building these however, the twist is that they’re already in the input.

Each desired number requires multiple passes and filters on the input.

In an extreme attempt to be concise, only the solution for oxygen will be shown. The solution for carbon requires only sign switches and replacing some 1s with 0s.

(3) Has there ever been a more frustrating expression?

For oxygen

The final output is the multiplication of oxygen and carbon of course.

Solving Part Two

The same data table is used with slightly different coordinates. This change is necessary for a new row later. Additionally, the column the bits come from is included.

DATA A1 ...
DATA BIT 0 B4 (e.g 1) ...
BIT 1 C4 (e.g 0) ...
2 D4 (e.g 1) ...

For each bit there is a column …

1 MORE COMMON GC BIT pass
G1 =
SUM(B4:B)
>=COUNT(B4:B)/2
G2 = IF(G1,1,0) 1 G4 =
B4=G$2
rep →
H1 =
SUMIF(G4:G,"=TRUE",C4:C)
>=COUNTIF(G4:G,"=TRUE")/2
repeat ↓ 2 H4 =
AND(B4,C3=H$2)
rep →
repeat ↓ repeat ↓ rep ↓ repeat ↓ rep ↘

Finally, there is a cell finding what binary number passes the most checks.

PASSES L4 = COUNTIF(G4:I4,"=TRUE")
OXYGEN STR M4 =
INDEX(A4:A,
MATCH(MAX(L4:L),L4:L,0))

Converting that oxygen binary number to decimal is left out.

How Part Two Works

SUM >= COUNT/2

Comparing SUM(B4:B) to COUNT(B3:B)/2 is a slight re-working of AVERAGE in part 14. SUM becomes SUMIF on the second pass to prevent summing across rows already filtered out.

(4) I use SUMIF and COUNTIF to control tie-breaking behavior (necessary for carbon).

Why not FILTER

The FILTER function5 could power alternative solutions. This function takes a range and returns a range matching a criteria.

(5) FILTER doesn’t work like COUNTIF. There’s no string “criteria”. Instead it takes in a range of boolean values.

Here’s a sample. The list starts at 3 values: 1, 5, and 10.

DATA A2 = 1 5 10
> 4 B2 = A2>4 => FALSE TRUE TRUE
FILTER > 4 C2 = FILTER(A2:A, B2:B) => 5 10
< 6 D2 = C2 < 6 => TRUE FALSE
FILTER < 6 E2 = FILTER(C2:C, D2:D) => 5

Ultimately, FILTER wasn’t the right fit.

The Famous Duo INDEX and MATCH

In the spreadsheet world there might not be a better duo than INDEX and MATCH.

Combined they allow you to look up cells by a different column6. For programming folk if you were writing a SQL statement to SELECT one row …

(6) Excel users get this in one function: XLOOKUP.

Unpacking this formula M4 = INDEX(A4:A, MATCH(MAX(L4:L), L4:L, 0))

You may be interested in the previous or next day's solution.