21
loading...
This website collects cookies to deliver better user experience
1
or 0
to be able to efficiently slice the matrix while doing calculations.lines = np.loadtxt("day_3.txt", "U")
bits = int(len(lines[0]))
array(['011010010110', '101110100110', '011011011110', '100011010001',
'011011100111', '011000100101', '101101011001', '010001001001',
'100010110111', '001110110101', '100111011001',
view
of the data, which will give us a single large array containing one character per entry, and we also cast it to int
type:lines.view('U1').astype(int)
array([0, 1, 1, ..., 1, 1, 0])
reshape
it. The final import code is:lines = np.loadtxt("day_3.txt", "U")
bits = int(len(lines[0]))
data = lines.view('U1').astype(int).reshape(lines.shape[0], bits)
[0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0]
into a number like 1602
. There are several ways of doing it, the way I've chosen is to multiply the array by another array that is made up of powers of 2: [..., 32, 16, 8, 4, 2, 1]
. So I will pre-calculate pow2
early on in the code:pow2 = 1<<np.arange(bits)[::-1]
int()
function to convert it. int
has base-conversion abilities:bin2dec = lambda x: int("".join(map(str,x.astype(int))),2)
bin2dec = lambda x: np.packbits(np.pad(x,[32-bits, 0])).view('>u4')
pow2
method, precalculating it, and doing pow2.dot(x)
any time I want to convert x
to a number.0
or 1
in each column and comparing them to see which one is more. Since numpy can directly tell us all the elements that have a given value, and it can also do this per axis.1
in every bit position is:ones = (data == 1).sum(axis=0)
array([483, 487, 485, 467, 513, 509, 492, 532, 508, 497, 490, 506])
pow2
which was precalculated earlier.ones = (data == 1).sum(axis=0)
zeros = (data == 0).sum(axis=0)
result = pow2.dot(ones > zeros) * pow2.dot(ones < zeros)
for
loop:for idx in range(bits):
column = data[:, idx]
1
than 0
by taking the sum of the column, and seeing if that number is greater than half the size of the column:column.sum()*2 >= column.size
True
if the 1
s are more common than the 0
s. Since we need to then collect all the entries that match this value, we can do:column == (column.sum()*2 >= column.size)
True
or False
depending on whether the value in column is the same as the majority value or not.data
matrix, and discard the rest, by using this array as the subscript when accessing the data matrix:data[column == (column.sum()*2 >= column.size)]
data
gets to 1 rowfor idx in range(bits):
column = data[:, idx]
data = data[column == (column.sum()*2 >= column.size)]
if len(data) == 1:
break
a = b = data
for idx in range(bits):
acol = a[:, idx]
bcol = b[:, idx]
a = a[acol == (acol.sum()*2 >= acol.size)] if len(a) > 1 else a
b = b[bcol == (bcol.sum()*2 < bcol.size)] if len(b) > 1 else b
result = pow2.dot(a[0] == 1) * pow2.dot(b[0] == 1)
import numpy as np
lines = np.loadtxt("day_3.txt", "U")
bits = int(len(lines[0]))
data = lines.view('U1').astype(int).reshape(lines.shape[0], bits)
pow2 = 1 << np.arange(bits)[::-1]
ones = (data == 1).sum(axis=0)
zeros = (data == 0).sum(axis=0)
result = pow2.dot(ones > zeros) * pow2.dot(ones < zeros)
print("Part 1 result:", result)
a = b = data
for idx in range(bits):
acol = a[:, idx]
bcol = b[:, idx]
a = a[acol == (acol.sum()*2 >= acol.size)] if len(a) > 1 else a
b = b[bcol == (bcol.sum()*2 < bcol.size)] if len(b) > 1 else b
result = pow2.dot(a[0]) * pow2.dot(b[0])
print("Part 2 result:", result)