Skip to content

Commit 65aecaa

Browse files
committed
②⓪⓪ Rust puzzles 🍾
1 parent e99597a commit 65aecaa

File tree

5 files changed

+206
-5
lines changed

5 files changed

+206
-5
lines changed

2021/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# http://adventofcode.com/2021
22
[workspace]
33
members = ["day*"]
4-
exclude = ["day16", "day18"]
4+
exclude = ["day18"]
55
resolver = "2"

2021/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
![AoC2021](https://img.shields.io/badge/Advent_of_Code-2021-8A2BE2)
44
![Stars: 50](https://img.shields.io/badge/Stars-50⭐-blue)
5-
![Rust: 23](https://img.shields.io/badge/Rust-23-cyan?logo=Rust)
5+
![Rust: 24](https://img.shields.io/badge/Rust-24-cyan?logo=Rust)
66
![Python: 12](https://img.shields.io/badge/Python-12-cyan?logo=Python)
77

88
## 2021 ([Calendar](https://adventofcode.com/2021)) ([Solutions](../2021/)) : 50⭐
@@ -24,7 +24,7 @@ Puzzle | Stars
2424
[Day 13: Transparent Origami](https://adventofcode.com/2021/day/13) | ⭐⭐ | [![Rust](../scripts/assets/rust.png)](../2021/day13/day13.rs) [![Python](../scripts/assets/python.png)](../2021/day13/day13.py)
2525
[Day 14: Extended Polymerization](https://adventofcode.com/2021/day/14) | ⭐⭐ | [![Rust](../scripts/assets/rust.png)](../2021/day14/day14.rs)
2626
[Day 15: Chiton](https://adventofcode.com/2021/day/15) | ⭐⭐ | [![Rust](../scripts/assets/rust.png)](../2021/day15/day15.rs)
27-
[Day 16: Packet Decoder](https://adventofcode.com/2021/day/16) | ⭐⭐ | [![Python](../scripts/assets/python.png)](../2021/day16/day16.py)
27+
[Day 16: Packet Decoder](https://adventofcode.com/2021/day/16) | ⭐⭐ | [![Rust](../scripts/assets/rust.png)](../2021/day16/day16.rs) [![Python](../scripts/assets/python.png)](../2021/day16/day16.py)
2828
[Day 17: Trick Shot](https://adventofcode.com/2021/day/17) | ⭐⭐ | [![Rust](../scripts/assets/rust.png)](../2021/day17/day17.rs)
2929
[Day 18: Snailfish](https://adventofcode.com/2021/day/18) | ⭐⭐ | [![Python](../scripts/assets/python.png)](../2021/day18/day18.py)
3030
[Day 19: Beacon Scanner](https://adventofcode.com/2021/day/19) | ⭐⭐ | [![Rust](../scripts/assets/rust.png)](../2021/day19/day19.rs)

2021/day16/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "day16"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
aoc = { path = "../../aoc" }
8+
9+
[[bin]]
10+
name = "day16"
11+
path = "day16.rs"

2021/day16/day16.rs

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
//! [Day 16: Packet Decoder](https://adventofcode.com/2021/day/16)
2+
3+
fn int_value(bits: &str) -> u32 {
4+
bits.chars()
5+
.map_while(|c| c.to_digit(2))
6+
.fold(0, |acc, d| (acc << 1) + d)
7+
}
8+
9+
fn read_packet(packet: &str, mut offset: usize, sum_of_versions: &mut u32) -> (usize, u64) {
10+
assert!(offset < packet.len());
11+
12+
let version = int_value(&packet[offset..offset + 3]);
13+
let type_id = int_value(&packet[offset + 3..offset + 6]);
14+
offset += 6;
15+
16+
// compute part 1 answer
17+
*sum_of_versions += version;
18+
19+
//
20+
if type_id == 4 {
21+
let mut literal_value = 0;
22+
loop {
23+
let last = &packet[offset..=offset];
24+
let nibble = int_value(&packet[offset + 1..offset + 5]);
25+
literal_value = (literal_value * 16) + u64::from(nibble);
26+
offset += 5;
27+
if offset > packet.len() || last == "0" {
28+
return (offset, literal_value);
29+
}
30+
}
31+
}
32+
33+
// subpackets
34+
let mut values = Vec::new();
35+
36+
// length of subpackets
37+
let length_id = int_value(&packet[offset..=offset]);
38+
offset += 1;
39+
40+
if length_id == 0 {
41+
//
42+
let length = int_value(&packet[offset..offset + 15]);
43+
offset += 15;
44+
45+
let end_offset: usize = offset + usize::try_from(length).unwrap();
46+
47+
while length != 0 && offset < end_offset {
48+
let (new_offset, value) = read_packet(packet, offset, sum_of_versions);
49+
values.push(value);
50+
offset = new_offset;
51+
}
52+
} else {
53+
let mut count = int_value(&packet[offset..offset + 11]);
54+
offset += 11;
55+
56+
while count > 0 && offset < packet.len() {
57+
let (new_offset, value) = read_packet(packet, offset, sum_of_versions);
58+
values.push(value);
59+
count -= 1;
60+
offset = new_offset;
61+
}
62+
};
63+
64+
let computed = match type_id {
65+
0 => values.iter().sum(),
66+
1 => values.iter().product(),
67+
2 => *values.iter().min().unwrap(),
68+
3 => *values.iter().max().unwrap(),
69+
5 => u64::from(values[0] > values[1]),
70+
6 => u64::from(values[0] < values[1]),
71+
7 => u64::from(values[0] == values[1]),
72+
_ => panic!(),
73+
};
74+
75+
(offset, computed)
76+
}
77+
78+
struct Puzzle {
79+
part1: u32,
80+
part2: u64,
81+
}
82+
83+
impl Puzzle {
84+
/// Get the puzzle input.
85+
fn solve_from_file(path: &str) -> Self {
86+
let data = std::fs::read_to_string(path).unwrap_or_else(|_| {
87+
eprintln!("cannot read input file {path}");
88+
std::process::exit(1);
89+
});
90+
91+
Self::solve(&data)
92+
}
93+
94+
fn solve(data: &str) -> Self {
95+
let bin_data = data
96+
.chars()
97+
.map_while(|c| c.to_digit(16))
98+
.map(|d| match d {
99+
0 => "0000",
100+
1 => "0001",
101+
2 => "0010",
102+
3 => "0011",
103+
4 => "0100",
104+
5 => "0101",
105+
6 => "0110",
106+
7 => "0111",
107+
8 => "1000",
108+
9 => "1001",
109+
10 => "1010",
110+
11 => "1011",
111+
12 => "1100",
112+
13 => "1101",
113+
14 => "1110",
114+
15 => "1111",
115+
_ => panic!(),
116+
})
117+
.collect::<Vec<_>>()
118+
.join("");
119+
120+
let mut part1 = 0;
121+
let (_, part2) = read_packet(&bin_data, 0, &mut part1);
122+
123+
Self { part1, part2 }
124+
}
125+
}
126+
127+
fn main() {
128+
let args = aoc::parse_args();
129+
let puzzle = Puzzle::solve_from_file(args.path.as_str());
130+
println!("{}", puzzle.part1);
131+
println!("{}", puzzle.part2);
132+
}
133+
134+
/// Test from puzzle input
135+
#[cfg(test)]
136+
mod test {
137+
use super::*;
138+
139+
#[test]
140+
fn test_bin() {
141+
assert_eq!(int_value("a"), 0);
142+
assert_eq!(int_value("0"), 0);
143+
assert_eq!(int_value("01"), 1);
144+
assert_eq!(int_value("11"), 3);
145+
assert_eq!(int_value("10000"), 16);
146+
assert_eq!(int_value("10101010101010101010101010101010"), 0xAAAAAAAA);
147+
}
148+
149+
#[test]
150+
fn test_part1() {
151+
let puzzle = Puzzle::solve("8A004A801A8002F478");
152+
assert_eq!(puzzle.part1, 16);
153+
154+
let puzzle = Puzzle::solve("620080001611562C8802118E34");
155+
assert_eq!(puzzle.part1, 12);
156+
157+
let puzzle = Puzzle::solve("C0015000016115A2E0802F182340");
158+
assert_eq!(puzzle.part1, 23);
159+
160+
let puzzle = Puzzle::solve("A0016C880162017C3686B18A3D4780");
161+
assert_eq!(puzzle.part1, 31);
162+
}
163+
164+
#[test]
165+
fn test_part2() {
166+
let puzzle = Puzzle::solve("C200B40A82");
167+
assert_eq!(puzzle.part2, 3);
168+
169+
let puzzle = Puzzle::solve("04005AC33890");
170+
assert_eq!(puzzle.part2, 54);
171+
172+
let puzzle = Puzzle::solve("880086C3E88112");
173+
assert_eq!(puzzle.part2, 7);
174+
175+
let puzzle = Puzzle::solve("CE00C43D881120");
176+
assert_eq!(puzzle.part2, 9);
177+
178+
let puzzle = Puzzle::solve("D8005AC2A8F0");
179+
assert_eq!(puzzle.part2, 1);
180+
181+
let puzzle = Puzzle::solve("F600BC2D8F");
182+
assert_eq!(puzzle.part2, 0);
183+
184+
let puzzle = Puzzle::solve("9C005AC2F8F0");
185+
assert_eq!(puzzle.part2, 0);
186+
187+
let puzzle = Puzzle::solve("9C0141080250320F1802104A08");
188+
assert_eq!(puzzle.part2, 1);
189+
}
190+
}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# [Advent of Code](https://adventofcode.com) in Rust 🦀
22

33
![Stars: 494](https://img.shields.io/badge/Stars-494⭐-blue)
4-
![Rust: 199](https://img.shields.io/badge/Rust-199-cyan?logo=Rust)
4+
![Rust: 200](https://img.shields.io/badge/Rust-200-cyan?logo=Rust)
55
![Python: 121](https://img.shields.io/badge/Python-121-cyan?logo=Python)
66

77
Solutions of [Advent of Code](https://adventofcode.com/) in [Rust](https://www.rust-lang.org), and sometimes in [Python](https://www.python.org/) and other languages.
@@ -42,7 +42,7 @@ Calendar | Solutions | Stars | Rust | Python | 🎄
4242
[Advent of Code 2024](https://adventofcode.com/2024) | [Solutions](2024/README.md) | 44⭐ | 22 | 8 | 3
4343
[Advent of Code 2023](https://adventofcode.com/2023) | [Solutions](2023/README.md) | 50⭐ | 25 | 11 | 1
4444
[Advent of Code 2022](https://adventofcode.com/2022) | [Solutions](2022/README.md) | 50⭐ | 24 | 18 |
45-
[Advent of Code 2021](https://adventofcode.com/2021) | [Solutions](2021/README.md) | 50⭐ | 23 | 12 |
45+
[Advent of Code 2021](https://adventofcode.com/2021) | [Solutions](2021/README.md) | 50⭐ | 24 | 12 |
4646
[Advent of Code 2020](https://adventofcode.com/2020) | [Solutions](2020/README.md) | 50⭐ | 7 | 23 |
4747
[Advent of Code 2019](https://adventofcode.com/2019) | [Solutions](2019/README.md) | 50⭐ | 8 | 23 | 2
4848
[Advent of Code 2018](https://adventofcode.com/2018) | [Solutions](2018/README.md) | 50⭐ | 25 | 4 | 1

0 commit comments

Comments
 (0)