solve Day18 in Rust
This commit is contained in:
parent
65424cea56
commit
bfea3d7501
@ -1,7 +1,7 @@
|
|||||||
def parse_instructions(file_path):
|
def parse_instructions(file_path):
|
||||||
"""Parse instructions from the given file."""
|
"""Parse instructions from the given file."""
|
||||||
try:
|
try:
|
||||||
with open(file_path, 'r') as file:
|
with open(file_path, "r") as file:
|
||||||
instructions = [line.strip().split() for line in file.readlines()]
|
instructions = [line.strip().split() for line in file.readlines()]
|
||||||
print(f"Parsed {len(instructions)} instructions from {file_path}")
|
print(f"Parsed {len(instructions)} instructions from {file_path}")
|
||||||
return instructions
|
return instructions
|
||||||
@ -9,9 +9,10 @@ def parse_instructions(file_path):
|
|||||||
print(f"Error reading file {file_path}: {e}")
|
print(f"Error reading file {file_path}: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def apply_instruction(grid, position, direction, steps):
|
def apply_instruction(grid, position, direction, steps):
|
||||||
"""Apply a single instruction to the grid and update the position."""
|
"""Apply a single instruction to the grid and update the position."""
|
||||||
deltas = {'U': (0, -1), 'D': (0, 1), 'L': (-1, 0), 'R': (1, 0)}
|
deltas = {"U": (0, -1), "D": (0, 1), "L": (-1, 0), "R": (1, 0)}
|
||||||
dx, dy = deltas[direction]
|
dx, dy = deltas[direction]
|
||||||
for _ in range(steps):
|
for _ in range(steps):
|
||||||
position = (position[0] + dx, position[1] + dy)
|
position = (position[0] + dx, position[1] + dy)
|
||||||
@ -19,6 +20,7 @@ def apply_instruction(grid, position, direction, steps):
|
|||||||
# print(f"Moved {direction} to {position}")
|
# print(f"Moved {direction} to {position}")
|
||||||
return position
|
return position
|
||||||
|
|
||||||
|
|
||||||
def create_path(instructions):
|
def create_path(instructions):
|
||||||
"""Create the path based on the instructions."""
|
"""Create the path based on the instructions."""
|
||||||
grid = set()
|
grid = set()
|
||||||
@ -32,26 +34,34 @@ def create_path(instructions):
|
|||||||
|
|
||||||
return grid
|
return grid
|
||||||
|
|
||||||
|
|
||||||
def flood_fill(grid, bounds):
|
def flood_fill(grid, bounds):
|
||||||
"""Perform flood-fill to find cells outside the path."""
|
"""Perform flood-fill to find cells outside the path."""
|
||||||
filled = set()
|
filled = set()
|
||||||
to_fill = [(bounds[0], y) for y in range(bounds[2], bounds[3] + 1)] \
|
to_fill = (
|
||||||
+ [(bounds[1], y) for y in range(bounds[2], bounds[3] + 1)] \
|
[(bounds[0], y) for y in range(bounds[2], bounds[3] + 1)]
|
||||||
+ [(x, bounds[2]) for x in range(bounds[0], bounds[1] + 1)] \
|
+ [(bounds[1], y) for y in range(bounds[2], bounds[3] + 1)]
|
||||||
|
+ [(x, bounds[2]) for x in range(bounds[0], bounds[1] + 1)]
|
||||||
+ [(x, bounds[3]) for x in range(bounds[0], bounds[1] + 1)]
|
+ [(x, bounds[3]) for x in range(bounds[0], bounds[1] + 1)]
|
||||||
|
)
|
||||||
|
|
||||||
while to_fill:
|
while to_fill:
|
||||||
x, y = to_fill.pop()
|
x, y = to_fill.pop()
|
||||||
if (x, y) in filled or (x, y) in grid:
|
if (x, y) in filled or (x, y) in grid:
|
||||||
continue
|
continue
|
||||||
filled.add((x, y))
|
filled.add((x, y))
|
||||||
if x > bounds[0]: to_fill.append((x - 1, y))
|
if x > bounds[0]:
|
||||||
if x < bounds[1]: to_fill.append((x + 1, y))
|
to_fill.append((x - 1, y))
|
||||||
if y > bounds[2]: to_fill.append((x, y - 1))
|
if x < bounds[1]:
|
||||||
if y < bounds[3]: to_fill.append((x, y + 1))
|
to_fill.append((x + 1, y))
|
||||||
|
if y > bounds[2]:
|
||||||
|
to_fill.append((x, y - 1))
|
||||||
|
if y < bounds[3]:
|
||||||
|
to_fill.append((x, y + 1))
|
||||||
|
|
||||||
return filled
|
return filled
|
||||||
|
|
||||||
|
|
||||||
def calculate_area(grid):
|
def calculate_area(grid):
|
||||||
"""Calculate the area inside the loop."""
|
"""Calculate the area inside the loop."""
|
||||||
min_x = min(grid, key=lambda x: x[0])[0]
|
min_x = min(grid, key=lambda x: x[0])[0]
|
||||||
@ -66,6 +76,7 @@ def calculate_area(grid):
|
|||||||
|
|
||||||
return inside_area
|
return inside_area
|
||||||
|
|
||||||
|
|
||||||
def run_test(test_file):
|
def run_test(test_file):
|
||||||
"""Run the algorithm with test input."""
|
"""Run the algorithm with test input."""
|
||||||
try:
|
try:
|
||||||
@ -79,6 +90,7 @@ def run_test(test_file):
|
|||||||
print(f"Assertion Error: {e}")
|
print(f"Assertion Error: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main function to run the puzzle solution."""
|
"""Main function to run the puzzle solution."""
|
||||||
test_file = "../test.txt"
|
test_file = "../test.txt"
|
||||||
@ -97,5 +109,6 @@ def main():
|
|||||||
else:
|
else:
|
||||||
print("Test failed. Halting execution.")
|
print("Test failed. Halting execution.")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
@ -1,7 +1,7 @@
|
|||||||
def parse_instructions(file_path):
|
def parse_instructions(file_path):
|
||||||
"""Parse instructions from the given file."""
|
"""Parse instructions from the given file."""
|
||||||
try:
|
try:
|
||||||
with open(file_path, 'r') as file:
|
with open(file_path, "r") as file:
|
||||||
lines = file.read().splitlines()
|
lines = file.read().splitlines()
|
||||||
print(f"Parsed {len(lines)} instructions from {file_path}")
|
print(f"Parsed {len(lines)} instructions from {file_path}")
|
||||||
return lines
|
return lines
|
||||||
@ -9,6 +9,7 @@ def parse_instructions(file_path):
|
|||||||
print(f"Error reading file {file_path}: {e}")
|
print(f"Error reading file {file_path}: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def calculate_area(lines):
|
def calculate_area(lines):
|
||||||
"""Calculate the area inside the loop defined by the instructions."""
|
"""Calculate the area inside the loop defined by the instructions."""
|
||||||
DIRECTIONS = [(0, 1), (1, 0), (0, -1), (-1, 0)]
|
DIRECTIONS = [(0, 1), (1, 0), (0, -1), (-1, 0)]
|
||||||
@ -24,18 +25,29 @@ def calculate_area(lines):
|
|||||||
row, column = points[-1]
|
row, column = points[-1]
|
||||||
points.append((row + dr * steps, column + dc * steps))
|
points.append((row + dr * steps, column + dc * steps))
|
||||||
|
|
||||||
area = abs(
|
area = (
|
||||||
sum(x1 * y2 - x2 * y1 for (x1, y1), (x2, y2) in zip(points, points[1:] + points[:1]))
|
abs(
|
||||||
) // 2 + boundary // 2 + 1
|
sum(
|
||||||
|
x1 * y2 - x2 * y1
|
||||||
|
for (x1, y1), (x2, y2) in zip(points, points[1:] + points[:1])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
// 2
|
||||||
|
+ boundary // 2
|
||||||
|
+ 1
|
||||||
|
)
|
||||||
|
|
||||||
return area
|
return area
|
||||||
|
|
||||||
|
|
||||||
def run_test(test_file, expected_result):
|
def run_test(test_file, expected_result):
|
||||||
"""Run the algorithm with test input and compare with the expected result."""
|
"""Run the algorithm with test input and compare with the expected result."""
|
||||||
try:
|
try:
|
||||||
lines = parse_instructions(test_file)
|
lines = parse_instructions(test_file)
|
||||||
calculated_area = calculate_area(lines)
|
calculated_area = calculate_area(lines)
|
||||||
assert calculated_area == expected_result, f"Test failed, expected {expected_result}, got {calculated_area}"
|
assert (
|
||||||
|
calculated_area == expected_result
|
||||||
|
), f"Test failed, expected {expected_result}, got {calculated_area}"
|
||||||
print(f"Test passed, area: {calculated_area}")
|
print(f"Test passed, area: {calculated_area}")
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
print(e)
|
print(e)
|
||||||
@ -44,11 +56,14 @@ def run_test(test_file, expected_result):
|
|||||||
print(f"Error during test execution: {e}")
|
print(f"Error during test execution: {e}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main function to run the puzzle solution."""
|
"""Main function to run the puzzle solution."""
|
||||||
test_file = "../test.txt"
|
test_file = "../test.txt"
|
||||||
input_file = "../input.txt"
|
input_file = "../input.txt"
|
||||||
expected_test_area = 952408144115 # Replace with the correct expected area for the test
|
expected_test_area = (
|
||||||
|
952408144115 # Replace with the correct expected area for the test
|
||||||
|
)
|
||||||
|
|
||||||
# Run test
|
# Run test
|
||||||
try:
|
try:
|
||||||
@ -61,5 +76,6 @@ def main():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Execution halted due to error: {e}")
|
print(f"Execution halted due to error: {e}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
8
Day18/rust/Cargo.toml
Normal file
8
Day18/rust/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "rust"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
73
Day18/rust/src/main.rs
Normal file
73
Day18/rust/src/main.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
use std::fs::File;
|
||||||
|
use std::io::{self, BufRead};
|
||||||
|
|
||||||
|
fn parse_instructions(file_path: &str) -> io::Result<Vec<String>> {
|
||||||
|
let file = File::open(file_path)?;
|
||||||
|
let lines = io::BufReader::new(file).lines();
|
||||||
|
let instructions: Vec<String> = lines.collect::<Result<_, _>>()?;
|
||||||
|
println!(
|
||||||
|
"Parsed {} instructions from {}",
|
||||||
|
instructions.len(),
|
||||||
|
file_path
|
||||||
|
);
|
||||||
|
Ok(instructions)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate_area(lines: &Vec<String>) -> i64 {
|
||||||
|
let directions: Vec<(i64, i64)> = vec![(0, 1), (1, 0), (0, -1), (-1, 0)];
|
||||||
|
let mut points: Vec<(i64, i64)> = vec![(0, 0)];
|
||||||
|
let mut boundary = 0;
|
||||||
|
|
||||||
|
for line in lines {
|
||||||
|
if line.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(color) = line.split(' ').last() {
|
||||||
|
let instructions = &color[2..color.len() - 1];
|
||||||
|
let direction_index =
|
||||||
|
i64::from_str_radix(&instructions[instructions.len() - 1..], 16).unwrap();
|
||||||
|
let (dr, dc) = directions[direction_index as usize];
|
||||||
|
let steps = i64::from_str_radix(&instructions[..instructions.len() - 1], 16).unwrap();
|
||||||
|
boundary += steps;
|
||||||
|
let (row, column) = points.last().unwrap();
|
||||||
|
points.push((row + dr * steps, column + dc * steps));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut area = 0;
|
||||||
|
for i in 0..points.len() {
|
||||||
|
let (x1, y1) = points[i];
|
||||||
|
let (x2, y2) = points[(i + 1) % points.len()];
|
||||||
|
area += x1 * y2 - x2 * y1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(area.abs() / 2) + (boundary / 2) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_test(test_file: &str, expected_result: i64) -> io::Result<()> {
|
||||||
|
let lines = parse_instructions(test_file)?;
|
||||||
|
let calculated_area = calculate_area(&lines);
|
||||||
|
assert_eq!(calculated_area, expected_result, "Test failed");
|
||||||
|
println!("Test passed, area: {}", calculated_area);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let test_file = "../test.txt";
|
||||||
|
let input_file = "../input.txt";
|
||||||
|
let expected_test_area: i64 = 952408144115; // Replace with the correct expected area for the test
|
||||||
|
|
||||||
|
if let Err(e) = run_test(test_file, expected_test_area) {
|
||||||
|
eprintln!("Execution halted due to error: {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match parse_instructions(input_file) {
|
||||||
|
Ok(lines) => {
|
||||||
|
let area = calculate_area(&lines);
|
||||||
|
println!("Puzzle result (area): {}", area);
|
||||||
|
}
|
||||||
|
Err(e) => eprintln!("Execution halted due to error: {}", e),
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@ function parseInstructions(filePath: string): string[] {
|
|||||||
|
|
||||||
function calculateArea(lines: string[]): number {
|
function calculateArea(lines: string[]): number {
|
||||||
const DIRECTIONS: [number, number][] = [[0, 1], [1, 0], [0, -1], [-1, 0]];
|
const DIRECTIONS: [number, number][] = [[0, 1], [1, 0], [0, -1], [-1, 0]];
|
||||||
let points: [number, number][] = [[0, 0]];
|
const points: [number, number][] = [[0, 0]];
|
||||||
let boundary: number = 0;
|
let boundary: number = 0;
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
|
Loading…
Reference in New Issue
Block a user