Example #1
0
def dijkstra(panels):
    source = (0, 0)
    dists = {}
    prevs = {}
    Q = set()
    for p in panels:
        dists[p] = 99999999999
        prevs[p] = None
        Q.add(p)
    dists[source] = 0
    while len(Q) > 0:
        minv = None
        for q in Q:
            if minv == None:
                minv = q
            else:
                if dists[minv] > dists[q]:
                    minv = q
        Q.remove(minv)
        for q in util.adj4(minv):
            if q in Q:
                alt = dists[minv] + 1
                if alt < dists[q]:
                    dists[q] = alt
    return dists
Example #2
0
def min_dist_to_finish(currloc, graph, keylocs, doorlocs, depth, rope):
	if rope != None and rope < 0:
		return None

	if rope != None and key_set_min_dist(keylocs.values(), currloc) > rope:
		return None

	if len(keylocs) == 0:
		return 0

	min_dist = None

	descendants = nx.descendants(graph, currloc)

	# print(zipped)
	for k in keylocs:
		if keylocs[k] in descendants:
		# print(depth)
		# if depth == 0:
		# 	print(min_dist)
			if depth < 18 and min_dist != None:
				print("depth:",depth,"dist:",min_dist)
		# print("locs",keylocs)
			# try:
			path = nx.bidirectional_dijkstra(graph, currloc, keylocs[k])
			pathlen = path[0]
			# pathlen = util.manhattan_dist(currloc, keylocs[k])
			keylocs_val = keylocs[k]
			keylocs.pop(k)
			doorlocs_val = None
			edges_added = []
			if k.upper() in doorlocs:
				free_pos = doorlocs[k.upper()]
				for loc in util.adj4(free_pos):
					if loc in graph.nodes and not loc in doorlocs.values():
						edges_added.append((free_pos, loc))
				graph.add_edges_from(edges_added, weight=1)
				doorlocs_val = doorlocs[k.upper()]
				doorlocs.pop(k.upper())
			ropetogive = None
			if min_dist == None:
				if rope != None:
					ropetogive = rope - pathlen
			else:
				ropetogive = min_dist - pathlen
			res = min_dist_to_finish(keylocs_val, graph, keylocs, doorlocs, depth + 1, ropetogive)
			if res != None:
				new_min_dist = pathlen + res
				if min_dist == None or new_min_dist < min_dist:
					min_dist = new_min_dist
			keylocs[k] = keylocs_val
			if doorlocs_val != None:
				for e in edges_added:
					graph.remove_edges_from(edges_added)
				doorlocs[k.upper()] = doorlocs_val
			# except nx.NetworkXNoPath:
			# 	print("fail")
			# 	continue
	return min_dist
Example #3
0
def get_input_seq(panels, loc):
    dest = None
    prev = None
    for key in panels:
        if panels[key][0] != 1:
            for loc2 in util.adj4(key):
                if not loc2 in panels:
                    dest = loc2
                    prev = key
                    break
        if dest != None:
            break
    if dest == None:
        return None, None
    rel = get_dir(prev, dest)
    seq = list(reversed([get_back(x) for x in panels[loc][1]
                         ])) + panels[prev][1] + [get_dir(prev, dest)]
    return seq, panels[prev][1] + [get_dir(prev, dest)]
Example #4
0
            if c == "@":
                currloc = key
            elif c.islower():
                keylocs[c] = key
            else:
                assert c.isupper()
                doorlocs[c] = key
        G.add_node(key)


def invalid(c):
    return c.isupper()


for node in G.nodes:
    for node2 in util.adj4(node):
        if node2 in G.nodes:
            G.add_edge(node, node2, weight=1)

key_map = get_key_map(G, keylocs)

for node in G.nodes:
    for node2 in util.adj4(node):
        if node2 in G.nodes and (invalid(locs[node]) or invalid(locs[node2])):
            if (node, node2) in G.edges:
                G.remove_edge(node, node2)

# print(currloc)
# print(G.nodes)
# print(G.edges)
Example #5
0
filtered_panels = {}
oxygen_loc = None
for loc in panels:
    if panels[loc][0] != 1:
        filtered_panels[loc] = panels[loc][0]
    if panels[loc][0] == 2:
        oxygen_loc = loc
util.print_at_loc((1, 42), "Part 1")
util.print_at_loc((1, 43), dijkstra(filtered_panels)[oxygen_loc])
util.print_at_loc((1, 44), "Part 2")
oxygen = set()
oxygen.add(oxygen_loc)
no_oxygen = set()
for p in filtered_panels:
    no_oxygen.add(p)
no_oxygen.remove(oxygen_loc)

mins = 0
while len(no_oxygen) > 0:
    possible_new = set()
    for o in oxygen:
        for n in util.adj4(o):
            possible_new.add(n)
    actual_new = no_oxygen.intersection(possible_new)
    for o in actual_new:
        no_oxygen.remove(o)
        oxygen.add(o)
    mins += 1
util.print_at_loc((1, 45), mins)
Example #6
0
import networkx as nx

# Fun puzzle! I'm getting a lot more comfortable with networkx. Pretty
# much all of my bugs today were with off-by-one errors or typos, so 
# it went pretty smoothly.

fn = "./in.txt"
l = util.filetorawlist(fn)
G = nx.Graph()
for r in range(len(l)):
	for c in range(len(l[r])):
		if l[r][c] == ".":
			G.add_node((r, c))

for node in G.nodes:
	for node2 in util.adj4(node):
		if node2 in G.nodes:
			G.add_edge(node, node2)

inner_portals = {}
outer_portals = {}
for r in range(2, len(l) - 2):
	for c in range(2, len(l[r]) - 2):
		if l[r][c] == ".":
			portal_text = None
			if l[r][c - 1].isupper() and l[r][c - 2].isupper():
				portal_text = l[r][c - 2] + l[r][c - 1]
			elif l[r][c + 1].isupper() and l[r][c + 2].isupper():
				portal_text = l[r][c + 1] + l[r][c + 2]
			elif l[r - 1][c].isupper() and l[r - 2][c].isupper():
				portal_text = l[r - 2][c] + l[r - 1][c]
# second part of tuple is list of [completed, backtrack dir]
panels = {(0, 0): (0, [False, None])}
util.clear_terminal()
while not panels[loc][1][0] or panels[loc][1][1] != None:
    # add in this line to watch the logic of the maze construction
    time.sleep(maze_tic_speed)
    old_loc = loc
    new_panel = None
    if panels[loc][1][0]:
        # backtrack
        _, = c.calc([panels[loc][1][1].value])
        loc = get_move(loc, panels[loc][1][1])
    else:
        # explore
        next_place = None
        for new_place in util.adj4(loc):
            if not new_place in panels:
                next_place = new_place
                break
        if next_place == None:
            panels[loc][1][0] = True
        else:
            step = get_dir(loc, next_place)
            out, = c.calc([step.value])
            if out == 0:
                panels[next_place] = (1, [True, get_back(step)])
                new_panel = (next_place, "#")
            else:
                loc = next_place
                panels[loc] = (0, [False, get_back(step)]) if out == 1 else (
                    2, [False, get_back(step)])
Example #8
0
while True:
    val = comp.calc()
    if val == None:
        break
    if val == 10:
        r += 1
        c = 0
    else:
        char = str(chr(val))
        a[(c, r)] = char
        c += 1

tot = 0
for k in a:
    intersection = True
    for adj in util.adj4(k):
        if not adj in a:
            intersection = False
            break
        if a[adj] == ".":
            intersection = False
            break
    if intersection:
        tot += k[0] * k[1]

print("Part 1")
print(tot)
print("Part 2")

A = "L,12,L,12,R,12"
B = "L,8,L,8,R,12,L,8,L,8"