day8 part 2 work in progress, still not working
This commit is contained in:
parent
3d1582f685
commit
7b73d8402a
@ -39,9 +39,13 @@ class Node:
|
|||||||
|
|
||||||
def is_A_node(self):
|
def is_A_node(self):
|
||||||
return self.value[2] == 'A'
|
return self.value[2] == 'A'
|
||||||
|
|
||||||
def is_Z_node(self):
|
def is_Z_node(self):
|
||||||
return self.value[2] == 'Z'
|
return self.value[2] == 'Z'
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.value} = ({self.left}, {self.right})"
|
||||||
|
|
||||||
|
|
||||||
def parse(input_file:str) -> Tuple[str, List[Node]]:
|
def parse(input_file:str) -> Tuple[str, List[Node]]:
|
||||||
the_list = []
|
the_list = []
|
||||||
|
@ -1,37 +1,24 @@
|
|||||||
#!/usr/bin/env python3.11
|
#!/usr/bin/env python3.11
|
||||||
from typing import List, Tuple
|
from typing import List
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from datetime import datetime, timedelta
|
||||||
from threading import current_thread
|
|
||||||
from data import Node, parse
|
from data import Node, parse
|
||||||
|
|
||||||
def count_steps_XXA_to_XXZ(node: Node, directions:str, node_list: List[Node]) -> int:
|
def count_steps_XXA_to_XXZ(directions:str, node_list: List[Node]) -> int:
|
||||||
print(f"thread {current_thread().name} counting from {node}")
|
current_nodes = list(filter(lambda node: node.is_A_node(), node_list))
|
||||||
if not node.is_A_node():
|
|
||||||
raise Exception("node must be a XXA node")
|
|
||||||
count = 0
|
count = 0
|
||||||
current_node = node
|
start_time = datetime.now()
|
||||||
while not current_node.is_Z_node():
|
while not all(map(lambda n: n.is_Z_node(), current_nodes)):
|
||||||
current_node = current_node.move_left(node_list) if directions[count % len(directions)] == 'L' else current_node.move_right(node_list)
|
if directions[count % len(directions)] == 'L':
|
||||||
|
current_nodes = list(map(lambda n: n.move_left(node_list), current_nodes))
|
||||||
|
else:
|
||||||
|
current_nodes = list(map(lambda n: n.move_right(node_list), current_nodes))
|
||||||
|
if start_time + timedelta(minutes=1) <= datetime.now():
|
||||||
|
str_nodes = [node.__str__() for node in current_nodes]
|
||||||
|
print(f"count: {count} / {str_nodes}")
|
||||||
|
start_time = datetime.now()
|
||||||
count += 1
|
count += 1
|
||||||
print(f"thread {current_thread().name} as counted {count} steps to {current_node}")
|
|
||||||
return count
|
return count
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
directions, node_list = parse('input.txt')
|
directions, node_list = parse('input.txt')
|
||||||
print("solving all nodes")
|
print(count_steps_XXA_to_XXZ(directions, node_list))
|
||||||
solved_node_list = map(lambda node: node.resolve_left_right_nodes(node_list), node_list)
|
|
||||||
#print(node_list)
|
|
||||||
print("all_nodes_solved")
|
|
||||||
xxA_nodes = list(filter(lambda node: node.is_A_node(), solved_node_list))
|
|
||||||
print(xxA_nodes)
|
|
||||||
results = []
|
|
||||||
#Parallel version
|
|
||||||
#with ThreadPoolExecutor(max_workers=10) as executor:
|
|
||||||
# print("starting ThreadPool")
|
|
||||||
# for xxA_node in xxA_nodes:
|
|
||||||
# results.append(executor.submit(count_steps_XXA_to_XXZ, xxA_node, directions, solved_node_list))
|
|
||||||
#results = map(lambda exec: exec.result(), results)
|
|
||||||
results = [count_steps_XXA_to_XXZ(xxA_node, directions, solved_node_list) for xxA_node in xxA_nodes]
|
|
||||||
print(results)
|
|
||||||
print(sum(results))
|
|
||||||
|
|
||||||
|
25
day8/part2_cycles.py
Executable file
25
day8/part2_cycles.py
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#!/usr/bin/env python3.11
|
||||||
|
from typing import List
|
||||||
|
import math
|
||||||
|
from data import Node, parse
|
||||||
|
|
||||||
|
def find_cycle(start_node, directions, node_list) -> List[Node]:
|
||||||
|
node_cycle = []
|
||||||
|
idx = 0
|
||||||
|
current_node = (start_node, idx)
|
||||||
|
while current_node not in node_cycle and not current_node[0].is_Z_node() :
|
||||||
|
node_cycle.append(current_node)
|
||||||
|
idx += 1
|
||||||
|
if directions[(idx - 1) % len(directions)] == 'L':
|
||||||
|
current_node = (current_node[0].move_left(node_list), idx % len(directions))
|
||||||
|
else:
|
||||||
|
current_node = (current_node[0].move_right(node_list), idx % len(directions))
|
||||||
|
node_cycle.append(current_node)
|
||||||
|
return [node for node,_ in node_cycle]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
directions, node_list = parse('input.txt')
|
||||||
|
xxA_nodes = list(filter(lambda node: node.is_A_node(), node_list))
|
||||||
|
cycles = list(map(len,map(lambda node: find_cycle(node, directions, node_list), xxA_nodes)))
|
||||||
|
print(cycles)
|
||||||
|
print(math.lcm(*cycles))
|
28
day8/part2_parallel.py
Executable file
28
day8/part2_parallel.py
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env python3.11
|
||||||
|
from typing import List
|
||||||
|
import concurrent.futures
|
||||||
|
from data import Node, parse
|
||||||
|
|
||||||
|
#It is inefficient, more time in sys than in User...
|
||||||
|
|
||||||
|
def movement(current_node: Node, direction: str, node_list: List[Node]) -> Node:
|
||||||
|
if direction == 'L':
|
||||||
|
return current_node.move_left(node_list)
|
||||||
|
else:
|
||||||
|
return current_node.move_right(node_list)
|
||||||
|
|
||||||
|
def count_steps_XXA_to_XXZ(directions:str, node_list: List[Node]) -> int:
|
||||||
|
current_nodes = list(filter(lambda node: node.is_A_node(), node_list))
|
||||||
|
count = 0
|
||||||
|
while not all(map(lambda n: n.is_Z_node(), current_nodes)):
|
||||||
|
with concurrent.futures.ThreadPoolExecutor(max_workers=8) as executor:
|
||||||
|
futures = []
|
||||||
|
direction = directions[count % len(directions)]
|
||||||
|
futures = [executor.submit(movement, node, direction, node_list) for node in current_nodes]
|
||||||
|
current_nodes = [exec.result() for exec in concurrent.futures.as_completed(futures)]
|
||||||
|
count += 1
|
||||||
|
return count
|
||||||
|
if __name__ == '__main__':
|
||||||
|
directions, node_list = parse('input.txt')
|
||||||
|
print(count_steps_XXA_to_XXZ(directions, node_list))
|
||||||
|
|
34
day8/vis.py
Normal file
34
day8/vis.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
from typing import List, Optional
|
||||||
|
|
||||||
|
import networkx as nx
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
from data import parse, Node
|
||||||
|
|
||||||
|
destinations, node_list = parse("input.txt")
|
||||||
|
|
||||||
|
starting_nodes = []
|
||||||
|
for node in node_list:
|
||||||
|
if node.is_A_node():
|
||||||
|
starting_nodes.append(node)
|
||||||
|
|
||||||
|
|
||||||
|
def add_node(node: Node, known_nodes: List[str], graph: nx.Graph, node_list:List[Node], predecessor: Optional[str] = None):
|
||||||
|
if node.value not in known_nodes:
|
||||||
|
known_nodes.append(node.value)
|
||||||
|
add_node(node.move_left(node_list), known_nodes, graph, node_list, predecessor=node.value)
|
||||||
|
graph.add_node(node.value)
|
||||||
|
if predecessor is not None:
|
||||||
|
graph.add_edge(predecessor, node.value)
|
||||||
|
add_node(node.move_right(node_list), known_nodes, graph, node_list, predecessor=node.value)
|
||||||
|
|
||||||
|
subplot_num=121
|
||||||
|
for node in starting_nodes:
|
||||||
|
current_node = node
|
||||||
|
known_nodes = []
|
||||||
|
G = nx.DiGraph()
|
||||||
|
add_node(node, known_nodes, G, node_list)
|
||||||
|
plt.subplot(subplot_num)
|
||||||
|
nx.draw(G)
|
||||||
|
subplot_num += 1
|
||||||
|
plt.show()
|
Loading…
x
Reference in New Issue
Block a user