Skip to content

Commit

Permalink
day 18 py
Browse files Browse the repository at this point in the history
  • Loading branch information
RongkunWang committed Dec 18, 2023
1 parent 28916b1 commit 00d851c
Show file tree
Hide file tree
Showing 5 changed files with 281 additions and 30 deletions.
14 changes: 14 additions & 0 deletions inputs/18_example.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
R 6 (#70c710)
D 5 (#0dc571)
L 2 (#5713f0)
D 2 (#d2c081)
R 2 (#59c680)
D 2 (#411b91)
L 5 (#8ceee2)
U 2 (#caa173)
L 1 (#1b58a2)
U 2 (#caa171)
R 2 (#7807d2)
U 3 (#a77fa3)
L 2 (#015232)
U 2 (#7a21e3)
2 changes: 2 additions & 0 deletions solutions/18_example.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
62
952408144115
32 changes: 2 additions & 30 deletions src/python/10_rk.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3
import sys
import collections
import util

"""
assuming there is loop
Expand Down Expand Up @@ -150,37 +151,8 @@ def sol1(IN):
continue
m[IN[1][0]][IN[1][1]] = c

ninside = util.calculate_inside(l_loop, m)

ninside = 0
for x, line in enumerate(l_loop):
boundary_start = ""
inside = False
# print(line)
for y, boundary in enumerate(line):
if boundary:
t = m[x][y]
# print(t)
if t == "|":
# print("flip")
inside = not inside
elif boundary_start == "":
# print("start with ", t)
# this can't be '-'
boundary_start = t
elif t != "-":
# skip over -
# print("end in", t)
# print(f"{boundary_start}{t}")
if f"{boundary_start}{t}" in ["FJ", "L7"]:
# print("flip")
# flip only in those cases
inside = not inside
boundary_start = ""
elif inside:
# print(x,y)
ninside += 1

pass

# print(l_loop)
# # initialize outtermost boundary first
Expand Down
174 changes: 174 additions & 0 deletions src/python/18_rk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
#!/usr/bin/env python3
import sys
import util
import math

def parse():
l = []
with open(sys.argv[1], 'r') as infile:
for line in infile:
line = line.strip()
di, step, color = line.split()
color = color[2:-1]
l.append((di, int(step), color))
return l

def decode(color):
return int(color[:5], 16), util.diDecode[int(color[5])]


def getSign(prev_di, di):
if prev_di == "R" and di == "D" or prev_di == "U" and di == "L":
return "7"
elif prev_di == "R" and di == "U" or prev_di == "D" and di == "L":
return "J"
elif prev_di == "L" and di == "D" or prev_di == "U" and di == "R":
return "F"
elif prev_di == "L" and di == "U" or prev_di == "D" and di == "R":
return "L"

def sol(l, sol1 = True):
maxr, maxc = -math.inf, -math.inf
minr, minc = math.inf, math.inf
output = 0
pos = (0, 0)
for di, s, color in l:
if not sol1:
s, di = decode(color)
pos = util.tuple_add(pos, util.tuple_mul(util.direction_map[di], s))
output += s
maxr = max(maxr, pos[0])
maxc = max(maxc, pos[1])
minr = min(minr, pos[0])
minc = min(minc, pos[1])
assert pos == (0, 0)

nr = int(maxr-minr+1)
nc = int(maxc-minc+1)

# a projection of (minr, minc) --> (0, 0)

pos = (-minr, -minc)

l_loop = util.matrix([[0 for j in range(nc)] for i in range(nr)])
m = util.matrix([["." for j in range(nc)] for i in range(nr)])
# print(l_loop, m, sep="\n")


# sort out the starting point first
prev_di = ""
for di, s, color in l:
if not sol1:
s, di = decode(color)
if prev_di != "":
m[pos] = getSign(prev_di, di)
for i in range(s):
pos = util.tuple_add(pos, util.direction_map[di])
l_loop[pos] = 1

if di == "D" or di == "U":
m[pos] = "|"
elif di == "L" or di == "R":
m[pos] = "-"

pass
prev_di = di
pass
m[pos] = getSign(l[-1][0], l[0][0])
# print(pos, m[pos])

# print(l_loop, m, sep="\n")

output += util.calculate_inside(l_loop, m)
return output

def sol2(l, sol2=True):
maxr, maxc = -math.inf, -math.inf
minr, minc = math.inf, math.inf
l_boundary = {0:{}}
output = 0
pos = (0, 0)
first_di = None
prev_di = None
for di, s, color in l:
if sol2:
s, di = decode(color)
if not first_di:
first_di = di

# correct the turning point
if prev_di != "":
l_boundary[pos[0]][pos[1]] = getSign(prev_di, di)

prev_di = di
if di == "U" or di == "D":
for i in range(s):
pos = util.tuple_add(pos, util.direction_map[di])
if pos[0] in l_boundary:
l_boundary[pos[0]][pos[1]] = "|"
else:
l_boundary[pos[0]] = {pos[1]:"|"}
else:
pos = util.tuple_add(pos, util.tuple_mul(util.direction_map[di], s))
pass

output += s
maxr = max(maxr, pos[0])
maxc = max(maxc, pos[1])
minr = min(minr, pos[0])
minc = min(minc, pos[1])
pass
assert pos == (0, 0)

l_boundary[0][0] = getSign(prev_di, first_di)
# print(l_boundary)
# print(l_boundary[0][0])

inside = False
s_prevline = 0
l_prevline = None
for r in range(minr, maxr+1):
lb = sorted([(i, j) for i, j in l_boundary[r].items()], key = lambda x:x[0])
# print(lb)
if l_prevline == lb:
output += s_prevline
continue
s_prevline = 0
l_prevline = lb

ib = 0
l_group = []
inside = False
true_next = False
prev_type_bound = None
prev_pos = None
for ib in range(len(lb)-1):
p1, s1 = lb[ib]
p2, s2 = lb[ib+1]
dist = p2-p1-1

if s1+s2 in ["F7", "LJ"]:
true_next = False
continue
elif s1 == "|" or true_next:
true_next = False
inside = not inside
elif s1+s2 in ["FJ", "L7"]:
true_next = True
continue

if inside:
s_prevline += dist
output += s_prevline
# print(output, s_prevline)
return output

def main():
l = parse()
# print(l)
# print(sol(l))
print(sol2(l, False))
print(sol2(l))
pass

main()
89 changes: 89 additions & 0 deletions src/python/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
class matrix:
def __init__(self, l):
self._l = [[e for e in il] for il in l]

def dim(self):
return len(self._l), len(self._l[0])

def __iter__(self):
for x in self._l:
yield x


def __getitem__(self, tup):
if type(tup) == type((0,0)):
return self._l[tup[0]][tup[1]]
else:
return self._l[tup]

def __setitem__(self, tup, val):
self._l[tup[0]][tup[1]] = val

def __str__(self):
s = ""
for l in self:
for e in l:
s += str(e)
s += "\n"
return s

def tuple_add(a, b):
return (a[0]+b[0], a[1]+b[1])

def tuple_mul(a, b):
return (a[0]*b, a[1]*b)

diDecode = [
"R", "D", "L", "U"
]

direction_map = {
"r":(0, 1),
"d":(1, 0),
"l":(0, -1),
"u":(-1, 0),

"R":(0, 1),
"D":(1, 0),
"L":(0, -1),
"U":(-1, 0),
}


# day 10
def calculate_inside(l_loop, m):
"""
l_loop is the matrix where 1 is boundary, 0 is anything else
m is the whole matrix (list of list/str), but only boundary part will be accessed
"""
ninside = 0
for x, line in enumerate(l_loop):
boundary_start = ""
inside = False
# print(line)
for y, boundary in enumerate(line):
if boundary:
t = m[x][y]
# print(t)
if t == "|":
# print("flip")
inside = not inside
elif boundary_start == "":
# print("start with ", t)
# this can't be '-'
boundary_start = t
elif t != "-":
# skip over -
# print("end in", t)
# print(f"{boundary_start}{t}")
if f"{boundary_start}{t}" in ["FJ", "L7"]:
# print("flip")
# flip only in those cases
inside = not inside
boundary_start = ""
elif inside:
# print(x,y)
ninside += 1

pass
return ninside

0 comments on commit 00d851c

Please sign in to comment.