prettify and lint optimization
This commit is contained in:
@@ -1,20 +1,21 @@
|
||||
def parse_file(file_path):
|
||||
"""Parse the input file to extract instructions and the node map."""
|
||||
try:
|
||||
with open(file_path, 'r') as file:
|
||||
with open(file_path, "r") as file:
|
||||
lines = file.readlines()
|
||||
|
||||
instructions = lines[0].strip()
|
||||
node_map = {}
|
||||
for line in lines[2:]:
|
||||
node, neighbors = line.strip().split(' = ')
|
||||
node_map[node] = tuple(neighbors[1:-1].split(', '))
|
||||
node, neighbors = line.strip().split(" = ")
|
||||
node_map[node] = tuple(neighbors[1:-1].split(", "))
|
||||
|
||||
return instructions, node_map
|
||||
except Exception as e:
|
||||
print(f"Error parsing file {file_path}: {e}")
|
||||
raise
|
||||
|
||||
|
||||
def find_repeating_unit(sequence):
|
||||
"""Find the repeating unit in a sequence."""
|
||||
for i in range(1, len(sequence) + 1):
|
||||
@@ -23,7 +24,8 @@ def find_repeating_unit(sequence):
|
||||
return unit
|
||||
return sequence
|
||||
|
||||
def navigate_network(instructions, node_map, start_node='AAA', end_node='ZZZ'):
|
||||
|
||||
def navigate_network(instructions, node_map, start_node="AAA", end_node="ZZZ"):
|
||||
"""Navigate the network based on the instructions and return the number of steps."""
|
||||
current_node = start_node
|
||||
steps = 0
|
||||
@@ -33,28 +35,34 @@ def navigate_network(instructions, node_map, start_node='AAA', end_node='ZZZ'):
|
||||
|
||||
while current_node != end_node:
|
||||
if (current_node, instruction_index) in visited:
|
||||
print(f"Loop detected at {current_node} with instruction index {instruction_index}")
|
||||
print(
|
||||
f"Loop detected at {current_node} with instruction index {instruction_index}"
|
||||
)
|
||||
return -1 # Indicates a loop without reaching the end node
|
||||
|
||||
visited.add((current_node, instruction_index))
|
||||
direction = instructions[instruction_index % len(instructions)]
|
||||
current_node = node_map[current_node][0 if direction == 'L' else 1]
|
||||
current_node = node_map[current_node][0 if direction == "L" else 1]
|
||||
instruction_index += 1
|
||||
steps += 1
|
||||
|
||||
return steps
|
||||
|
||||
|
||||
def run_test():
|
||||
"""Run the test with the provided file path."""
|
||||
try:
|
||||
expected_result = 6
|
||||
instructions, node_map = parse_file("../test.txt")
|
||||
result = navigate_network(instructions, node_map)
|
||||
assert result == expected_result, f"Test failed, expected {expected_result} but got {result}"
|
||||
assert (
|
||||
result == expected_result
|
||||
), f"Test failed, expected {expected_result} but got {result}"
|
||||
print(f"Test passed with {result} steps.")
|
||||
except AssertionError as error:
|
||||
print(error)
|
||||
|
||||
|
||||
def main():
|
||||
print("Start Tests")
|
||||
run_test()
|
||||
@@ -70,5 +78,6 @@ def main():
|
||||
except Exception as e:
|
||||
print(f"Error during main execution: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
import sys
|
||||
from math import gcd
|
||||
|
||||
|
||||
def parse_file(file_path):
|
||||
print(f"Parsing file: {file_path}")
|
||||
with open(file_path, 'r') as file:
|
||||
with open(file_path, "r") as file:
|
||||
D = file.read().strip()
|
||||
steps, rule = D.split('\n\n')
|
||||
GO = {'L': {}, 'R': {}}
|
||||
for line in rule.split('\n'):
|
||||
st, lr = line.split('=')
|
||||
left, right = lr.split(',')
|
||||
GO['L'][st.strip()] = left.strip()[1:].strip()
|
||||
GO['R'][st.strip()] = right[:-1].strip()
|
||||
return [0 if char == 'L' else 1 for char in steps], GO
|
||||
steps, rule = D.split("\n\n")
|
||||
GO = {"L": {}, "R": {}}
|
||||
for line in rule.split("\n"):
|
||||
st, lr = line.split("=")
|
||||
left, right = lr.split(",")
|
||||
GO["L"][st.strip()] = left.strip()[1:].strip()
|
||||
GO["R"][st.strip()] = right[:-1].strip()
|
||||
return [0 if char == "L" else 1 for char in steps], GO
|
||||
|
||||
|
||||
def lcm(xs):
|
||||
ans = 1
|
||||
@@ -20,16 +21,17 @@ def lcm(xs):
|
||||
ans = (x * ans) // gcd(x, ans)
|
||||
return ans
|
||||
|
||||
|
||||
def navigate_network_simultaneously(steps, GO):
|
||||
print("Starting navigation of network.")
|
||||
POS = [s for s in GO['L'] if s.endswith('A')]
|
||||
POS = [s for s in GO["L"] if s.endswith("A")]
|
||||
T = {}
|
||||
t = 0
|
||||
while True:
|
||||
NP = []
|
||||
for i, p in enumerate(POS):
|
||||
p = GO['L' if steps[t % len(steps)] == 0 else 'R'][p]
|
||||
if p.endswith('Z'):
|
||||
p = GO["L" if steps[t % len(steps)] == 0 else "R"][p]
|
||||
if p.endswith("Z"):
|
||||
T[i] = t + 1
|
||||
if len(T) == len(POS):
|
||||
print(f"All paths reached 'Z' nodes at step {t + 1}.")
|
||||
@@ -40,19 +42,24 @@ def navigate_network_simultaneously(steps, GO):
|
||||
print(f"Step {t}: Current nodes - {POS}")
|
||||
assert False
|
||||
|
||||
|
||||
def run_test():
|
||||
print("Running test...")
|
||||
expected_result = 6
|
||||
steps, GO = parse_file("../test2.txt")
|
||||
result = navigate_network_simultaneously(steps, GO)
|
||||
assert result == expected_result, f"Test failed, expected {expected_result} but got {result}"
|
||||
assert (
|
||||
result == expected_result
|
||||
), f"Test failed, expected {expected_result} but got {result}"
|
||||
print(f"Test passed with {result} steps.")
|
||||
|
||||
|
||||
def main():
|
||||
run_test()
|
||||
steps, GO = parse_file("../input.txt")
|
||||
result = navigate_network_simultaneously(steps, GO)
|
||||
print(f"All paths reached 'Z' nodes simultaneously in {result} steps.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use std::fs;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
// Type alias to simplify the complex type
|
||||
type StepsRules = (Vec<u8>, HashMap<String, (String, String)>);
|
||||
|
||||
fn gcd(a: u64, b: u64) -> u64 {
|
||||
if b == 0 {
|
||||
a
|
||||
@@ -14,10 +17,12 @@ fn lcm(a: u64, b: u64) -> u64 {
|
||||
a / gcd(a, b) * b
|
||||
}
|
||||
|
||||
fn parse_file(file_path: &Path) -> Result<(Vec<u8>, HashMap<String, (String, String)>), String> {
|
||||
fn parse_file(file_path: &Path) -> Result<StepsRules, String> {
|
||||
let data = fs::read_to_string(file_path).map_err(|e| e.to_string())?;
|
||||
let mut sections = data.trim().split("\n\n");
|
||||
let steps = sections.next().unwrap()
|
||||
let steps = sections
|
||||
.next()
|
||||
.unwrap()
|
||||
.chars()
|
||||
.map(|c| if c == 'L' { 0 } else { 1 })
|
||||
.collect();
|
||||
@@ -27,7 +32,9 @@ fn parse_file(file_path: &Path) -> Result<(Vec<u8>, HashMap<String, (String, Str
|
||||
for line in rules_section.lines() {
|
||||
let mut parts = line.split('=').map(str::trim);
|
||||
let state = parts.next().unwrap().to_string();
|
||||
let directions = parts.next().unwrap()
|
||||
let directions = parts
|
||||
.next()
|
||||
.unwrap()
|
||||
.split(',')
|
||||
.map(str::trim)
|
||||
.map(|s| s.trim_matches(|c: char| c == '(' || c == ')').to_string())
|
||||
@@ -40,20 +47,25 @@ fn parse_file(file_path: &Path) -> Result<(Vec<u8>, HashMap<String, (String, Str
|
||||
}
|
||||
|
||||
fn navigate_network_simultaneously(steps: &[u8], rules: &HashMap<String, (String, String)>) -> u64 {
|
||||
let start_nodes: Vec<String> = rules.keys()
|
||||
.filter(|k| k.ends_with('A'))
|
||||
.cloned()
|
||||
.collect();
|
||||
let start_nodes: Vec<String> = rules.keys().filter(|k| k.ends_with('A')).cloned().collect();
|
||||
let mut current_nodes = start_nodes.clone();
|
||||
let mut step_count = 0;
|
||||
let mut time_to_z = HashMap::new();
|
||||
|
||||
while time_to_z.len() < start_nodes.len() {
|
||||
for (i, node) in current_nodes.iter_mut().enumerate() {
|
||||
let direction = if steps[step_count % steps.len()] == 0 { 'L' } else { 'R' };
|
||||
let next_node = if direction == 'L' { &rules[node].0 } else { &rules[node].1 };
|
||||
let direction = if steps[step_count % steps.len()] == 0 {
|
||||
'L'
|
||||
} else {
|
||||
'R'
|
||||
};
|
||||
let next_node = if direction == 'L' {
|
||||
&rules[node].0
|
||||
} else {
|
||||
&rules[node].1
|
||||
};
|
||||
*node = next_node.clone();
|
||||
|
||||
|
||||
if next_node.ends_with('Z') && !time_to_z.contains_key(&i) {
|
||||
time_to_z.insert(i, step_count + 1);
|
||||
}
|
||||
@@ -70,9 +82,9 @@ fn navigate_network_simultaneously(steps: &[u8], rules: &HashMap<String, (String
|
||||
time_to_z.values().fold(1, |acc, &val| lcm(acc, val as u64))
|
||||
}
|
||||
|
||||
fn run_test(test_file: &Path) {
|
||||
fn run_test(test_path: &Path) {
|
||||
println!("Running test...");
|
||||
let (steps, rules) = parse_file(test_file).expect("Failed to parse test file");
|
||||
let (steps, rules) = parse_file(test_path).expect("Failed to parse test file");
|
||||
let result = navigate_network_simultaneously(&steps, &rules);
|
||||
assert_eq!(result, 6, "Test failed: expected 6, got {}", result);
|
||||
println!("Test passed with {} steps.", result);
|
||||
@@ -80,10 +92,13 @@ fn run_test(test_file: &Path) {
|
||||
|
||||
fn main() {
|
||||
let test_path = Path::new("../test.txt");
|
||||
run_test(&test_path);
|
||||
run_test(test_path); // Removed needless borrow
|
||||
|
||||
let input_path = Path::new("../input.txt");
|
||||
let (steps, rules) = parse_file(&input_path).expect("Failed to parse input file");
|
||||
let result = navigate_network_simultaneously(&steps, &rules);
|
||||
println!("All paths reached 'Z' nodes simultaneously in {} steps.", result);
|
||||
let (steps, rules) = parse_file(input_path).expect("Failed to parse input file"); // Removed needless borrow
|
||||
let result = navigate_network_simultaneously(&steps, &rules); // Calculate result for input file
|
||||
println!(
|
||||
"All paths reached 'Z' nodes simultaneously in {} steps.",
|
||||
result
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as path from 'path';
|
||||
|
||||
function gcd(a: number, b: number): number {
|
||||
while (b !== 0) {
|
||||
let t = b;
|
||||
const t = b;
|
||||
b = a % b;
|
||||
a = t;
|
||||
}
|
||||
@@ -33,7 +33,7 @@ function parseFile(filePath: string): { steps: number[], rules: { [key: string]:
|
||||
function navigateNetworkSimultaneously(steps: number[], rules: { [key: string]: { [key: string]: string } }): number {
|
||||
console.log("Starting navigation of network.");
|
||||
const startNodes = Object.keys(rules['L']).filter((node: string) => node.endsWith('A'));
|
||||
let currentNodes = startNodes;
|
||||
const currentNodes = startNodes;
|
||||
let stepCount = 0;
|
||||
const timeToZ: { [key: number]: number } = {};
|
||||
|
||||
@@ -74,8 +74,8 @@ function main(): void {
|
||||
const { steps, rules } = parseFile(inputPath);
|
||||
const result = navigateNetworkSimultaneously(steps, rules);
|
||||
console.log(`All paths reached 'Z' nodes simultaneously in ${result} steps.`);
|
||||
} catch (error: any) {
|
||||
console.error(`Error: ${error.message}`);
|
||||
} catch (error) {
|
||||
console.error(`Error: ${(error as Error).message}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user