Skip to content

Commit a0bc943

Browse files
committed
d18p1
1 parent 30a5931 commit a0bc943

File tree

4 files changed

+226
-1
lines changed

4 files changed

+226
-1
lines changed

Cargo.lock

Lines changed: 46 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ edition = "2021"
88
[dependencies]
99
aocf = "0.1.21"
1010
colored = "2.1.0"
11+
hex_color = "3.0.0"
1112
mut-binary-heap = "0.1.0"
1213
regex = "1.10.2"
1314
serde_json = "1.0.120"

src/day18.rs

Lines changed: 173 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,175 @@
1+
use std::{
2+
cmp::{max, min},
3+
iter::once,
4+
};
5+
6+
use colored::{Colorize, CustomColor};
7+
use grid::*;
8+
use hex_color::HexColor;
9+
10+
mod grid;
11+
mod macros;
12+
13+
type Int = i32;
14+
15+
#[derive(Debug)]
16+
struct Point {
17+
point: grid::Point,
18+
terrain: Terrain,
19+
}
20+
21+
impl Point {
22+
fn new(p: grid::Point, c: String) -> Point {
23+
Point {
24+
point: p,
25+
terrain: Terrain::Trench(c),
26+
}
27+
}
28+
}
29+
30+
#[derive(Debug, Clone)]
31+
enum Terrain {
32+
Ground,
33+
Trench(String),
34+
}
35+
36+
impl Terrain {
37+
fn to_string(&self) -> String {
38+
use Terrain::*;
39+
match self {
40+
Ground => ".".to_string(),
41+
Trench(color) => {
42+
let c = HexColor::parse(&color).unwrap();
43+
"#".custom_color(CustomColor::new(c.r, c.g, c.b))
44+
.to_string()
45+
}
46+
}
47+
}
48+
}
49+
50+
#[derive(Debug)]
51+
struct Polygon {
52+
points: Vec<Point>,
53+
}
54+
55+
impl Polygon {
56+
fn new() -> Polygon {
57+
Polygon { points: Vec::new() }
58+
}
59+
60+
fn translate(mut self, x: Int, y: Int) -> Polygon {
61+
Polygon {
62+
points: self
63+
.points
64+
.iter()
65+
.map(|p| Point {
66+
point: p.point.translate(x, y),
67+
terrain: p.terrain.clone(),
68+
})
69+
.collect(),
70+
}
71+
}
72+
73+
fn translate_to_px_py(self) -> Polygon {
74+
let mut min_x = Int::MAX;
75+
let mut min_y = Int::MAX;
76+
for p in &self.points {
77+
min_x = min(min_x, p.point.x);
78+
min_y = min(min_y, p.point.y);
79+
}
80+
self.translate(-min_x, -min_y)
81+
}
82+
83+
fn print(&self) {
84+
let mut max_x = 0;
85+
let mut max_y = 0;
86+
for p in &self.points {
87+
max_x = max(max_x, p.point.x);
88+
max_y = max(max_y, p.point.y);
89+
}
90+
for y in 0..=max_y {
91+
for x in 0..=max_x {
92+
if let Some(p) = self
93+
.points
94+
.iter()
95+
.find(|p| p.point.x == x && p.point.y == y)
96+
{
97+
print!("{}", p.terrain.to_string());
98+
} else {
99+
print!("{}", Terrain::Ground.to_string())
100+
}
101+
}
102+
println!();
103+
}
104+
}
105+
106+
fn calc_area(&self) -> Int {
107+
//Shoelace formule to calculate area of polygon
108+
if self.points.is_empty() {
109+
0
110+
} else {
111+
let b = self.points.len() as Int;
112+
let points: Vec<_> = self.points.iter().chain(once(&self.points[0])).collect();
113+
let mut area = 0;
114+
for i in 0..self.points.len() {
115+
let (p_0, p_1) = (points[i].point, points[i + 1].point);
116+
area += p_0.x * p_1.y - p_1.x * p_0.y;
117+
}
118+
area = (area / 2).abs();
119+
// A = i + b/2 - 1
120+
// i = A-b/2+1
121+
// Filled polygon = i + b
122+
b + area - b / 2 + 1
123+
}
124+
}
125+
}
126+
1127
fn main() {
2-
println!("Hello, World! from src/day18.rs!");
128+
println!("Hello, World! from src/day18.rs!");
129+
// Part 1 - Example
130+
let dig_plan = vec_of_strings![
131+
"R 6 (#70c710)",
132+
"D 5 (#0dc571)",
133+
"L 2 (#5713f0)",
134+
"D 2 (#d2c081)",
135+
"R 2 (#59c680)",
136+
"D 2 (#411b91)",
137+
"L 5 (#8ceee2)",
138+
"U 2 (#caa173)",
139+
"L 1 (#1b58a2)",
140+
"U 2 (#caa171)",
141+
"R 2 (#7807d2)",
142+
"U 3 (#a77fa3)",
143+
"L 2 (#015232)",
144+
"U 2 (#7a21e3)",
145+
];
146+
let mut polygon: Polygon = Polygon::new();
147+
let mut p = grid::Point::new(0, 0);
148+
for op in dig_plan {
149+
let (d, l, c) = {
150+
let mut i = op.split_whitespace();
151+
(
152+
i.next().unwrap(),
153+
i.next().unwrap().parse::<Int>().unwrap(),
154+
i.next().unwrap(),
155+
)
156+
};
157+
let c = &c[1..c.len() - 1].to_string();
158+
let direction = match d {
159+
"R" => East,
160+
"D" => South,
161+
"U" => North,
162+
"L" => West,
163+
_ => panic!("Invalid direction: '{}'", d),
164+
};
165+
for i in 0..l {
166+
polygon.points.push(Point::new(p, c.clone()));
167+
p = p.move_to(&direction);
168+
}
169+
}
170+
dbg!(&polygon);
171+
polygon = polygon.translate_to_px_py();
172+
polygon.print();
173+
let a = polygon.calc_area();
174+
test!(62, a);
3175
}

src/grid.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,10 @@ impl Point {
222222
};
223223
self
224224
}
225+
226+
pub fn translate(mut self, x: Int, y: Int) -> Point {
227+
self.x += x;
228+
self.y += y;
229+
self
230+
}
225231
}

0 commit comments

Comments
 (0)