1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
// [nix-shell:~/projects/sandbox/advent]$ cargo run --bin 12
// Compiling advent v0.1.0 (/home/orbekk/projects/sandbox/advent)
// Finished dev [unoptimized + debuginfo] target(s) in 0.40s
// Running `target/debug/12`
// After 10 steps:
// pos=<x= 2, y= 1, z= -3>, vel=<x= -3, y= -2, z= 1>
// pos=<x= 1, y= -8, z= 0>, vel=<x= -1, y= 1, z= 3>
// pos=<x= 3, y= -6, z= 1>, vel=<x= 3, y= 2, z= -3>
// pos=<x= 2, y= 0, z= 4>, vel=<x= 1, y= -1, z= -1>
//
// energy=179
//
// After 1000 steps:
// pos=<x=-26, y= 45, z=-31>, vel=<x= 2, y= 17, z= 6>
// pos=<x= 87, y= 23, z=-12>, vel=<x=-14, y=-13, z= 9>
// pos=<x=-33, y= -2, z=-24>, vel=<x= -2, y=-15, z= -5>
// pos=<x=-20, y=-86, z= 77>, vel=<x= 14, y= 11, z=-10>
//
// energy=14645
use std::fmt;
#[derive(Debug)]
struct Moon {
position: (i64, i64, i64),
velocity: (i64, i64, i64),
}
fn sign(x: i64) -> i64 {
if x < 0 {
-1
} else if x > 0 {
1
} else {
0
}
}
impl Moon {
fn step(&self, moons: &Vec<Moon>) -> Moon {
let (x, y, z) = self.position;
let (mut gx, mut gy, mut gz) = self.velocity;
for moon in moons {
let (ox, oy, oz) = moon.position;
gx += sign(ox - x);
gy += sign(oy - y);
gz += sign(oz - z);
}
let position = (x + gx, y + gy, z + gz);
Moon { position: position, velocity: (gx, gy, gz) }
}
fn energy(&self) -> i64 {
let (x, y, z) = self.position;
let (p, q, r) = self.velocity;
(x.abs() + y.abs() + z.abs()) * (p.abs() + q.abs() + r.abs())
}
}
fn make_moon(x: i64, y: i64, z: i64) -> Moon {
Moon { position: (x, y, z), velocity: (0, 0, 0) }
}
impl fmt::Display for Moon {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let (x, y, z) = self.position;
let (p, q, r) = self.velocity;
write!(f, "pos=<x={:3}, y={:3}, z={:3}>, vel=<x={:3}, y={:3}, z={:3}>",
x, y, z, p, q, r)
}
}
#[derive(Debug)]
struct Moons(Vec<Moon>);
impl Moons {
fn step(&self) -> Moons {
Moons(self.0.iter().map(|m| m.step(&self.0)).collect())
}
fn energy(&self) -> i64 {
self.0.iter().map(|m| m.energy()).sum()
}
}
impl fmt::Display for Moons {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for moon in &self.0 {
moon.fmt(f)?;
write!(f, "\n")?;
}
Ok(())
}
}
fn run_steps(mut m: Moons, steps: i64, debug: bool) {
for i in 0..steps {
if debug {
println!("After {} steps:", i);
println!("{}", m);
}
m = m.step()
}
println!("After {} steps:", steps);
println!("{}", m);
println!("energy={:3}", m.energy())
}
fn main() {
let _ex1 = Moons(vec!(
make_moon(-1, 0, 2),
make_moon(2, -10, -7),
make_moon(4, -8, 8),
make_moon(3, 5, -1),
));
let _ex2 = Moons(vec!(
make_moon(-8, -10, 0),
make_moon(5, 5, 10),
make_moon(2, -7, 3),
make_moon(9, -8, -3),
));
run_steps(_ex1, 10, false);
println!();
run_steps(_ex2, 1000, false);
}
|