Skip to content

Commit eaf554d

Browse files
committed
2018 day 7
1 parent c3f67d1 commit eaf554d

File tree

5 files changed

+106
-5
lines changed

5 files changed

+106
-5
lines changed

crates/aoc/src/cli/mode/default.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ pub fn main(args: &Arguments) -> Result<(), Box<dyn Error>> {
1515

1616
// FIXME support 80 character wide output (without time?)
1717
println!(
18-
"Puzzle │ Part 1 │ Part 2 │ Time "
18+
"Puzzle │ Part 1 │ Part 2 │ Time "
1919
);
2020
println!(
21-
"────────┼──────────────────────┼────────────────────────────────────────┼───────────"
21+
"────────┼────────────────────────────┼────────────────────────────────────────┼───────────"
2222
);
2323
let mut total = Duration::default();
2424
for (year, day, f) in puzzles {
@@ -33,7 +33,7 @@ pub fn main(args: &Arguments) -> Result<(), Box<dyn Error>> {
3333

3434
// Hack to treat "🎄" as two characters wide
3535
// ("🎄" is 1 wide in Unicode 8 but 2 wide in Unicode 9+)
36-
let part1_width = if part1 == "🎄" { 19 } else { 20 };
36+
let part1_width = if part1 == "🎄" { 25 } else { 26 };
3737
let part2_width = if part2 == "🎄" { 37 } else { 38 };
3838

3939
println!(
@@ -43,10 +43,10 @@ pub fn main(args: &Arguments) -> Result<(), Box<dyn Error>> {
4343
}
4444

4545
println!(
46-
"────────┼──────────────────────┼────────────────────────────────────────┼───────────"
46+
"────────┼────────────────────────────┼────────────────────────────────────────┼───────────"
4747
);
4848
println!(
49-
" │ {}",
49+
" │ {}",
5050
format_duration(total),
5151
);
5252

crates/utils/src/bit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ impl<T: UnsignedInteger> BitIterator<T> {
5252
impl<T: UnsignedInteger> Iterator for BitIterator<T> {
5353
type Item = (u32, T);
5454

55+
#[inline]
5556
fn next(&mut self) -> Option<Self::Item> {
5657
if self.n == T::ZERO {
5758
None
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Step C must be finished before step A can begin.
2+
Step C must be finished before step F can begin.
3+
Step A must be finished before step B can begin.
4+
Step A must be finished before step D can begin.
5+
Step B must be finished before step E can begin.
6+
Step D must be finished before step E can begin.
7+
Step F must be finished before step E can begin.

crates/year2018/src/day07.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
use utils::bit::BitIterator;
2+
use utils::prelude::*;
3+
4+
/// Scheduling steps with dependencies.
5+
#[derive(Clone, Debug)]
6+
pub struct Day07 {
7+
steps: u32,
8+
requirements: [u32; 26],
9+
workers: usize,
10+
base_duration: u32,
11+
}
12+
13+
impl Day07 {
14+
pub fn new(input: &str, input_type: InputType) -> Result<Self, InputError> {
15+
let step = parser::byte_range(b'A'..=b'Z').map(|x| x - b'A');
16+
17+
let mut steps = 0u32;
18+
let mut requirements = [0u32; 26];
19+
for item in step
20+
.with_prefix("Step ")
21+
.with_suffix(" must be finished before step ")
22+
.then(step.with_suffix(" can begin."))
23+
.with_suffix(parser::eol())
24+
.parse_iterator(input)
25+
{
26+
let (first, second) = item?;
27+
steps |= (1 << first) | (1 << second);
28+
requirements[second as usize] |= 1 << first;
29+
}
30+
31+
Ok(Self {
32+
steps,
33+
requirements,
34+
workers: match input_type {
35+
InputType::Example => 2,
36+
InputType::Real => 5,
37+
},
38+
base_duration: match input_type {
39+
InputType::Example => 1,
40+
InputType::Real => 61,
41+
},
42+
})
43+
}
44+
45+
#[must_use]
46+
pub fn part1(&self) -> String {
47+
let mut sequence = String::with_capacity(26);
48+
let mut todo = self.steps;
49+
while todo != 0 {
50+
let (s, bit) = BitIterator::ones(todo)
51+
.find(|&(r, _)| self.requirements[r as usize] & todo == 0)
52+
.expect("no valid sequence");
53+
todo &= !bit;
54+
sequence.push((b'A' + s as u8) as char);
55+
}
56+
sequence
57+
}
58+
59+
#[must_use]
60+
pub fn part2(&self) -> u32 {
61+
let mut pending = self.steps;
62+
let mut incomplete = self.steps;
63+
let mut second = 0;
64+
let mut in_progress = Vec::with_capacity(self.workers);
65+
66+
while incomplete != 0 {
67+
for (s, bit) in BitIterator::ones(pending)
68+
.filter(|&(s, _)| self.requirements[s as usize] & incomplete == 0)
69+
.take(self.workers - in_progress.len())
70+
{
71+
pending &= !bit;
72+
in_progress.push((second + self.base_duration + s, bit));
73+
}
74+
75+
(second, _) = *in_progress.iter().min().expect("no valid sequence");
76+
in_progress.retain(|&(completed_at, bit)| {
77+
if completed_at == second {
78+
incomplete &= !bit;
79+
false
80+
} else {
81+
true
82+
}
83+
});
84+
}
85+
86+
second
87+
}
88+
}
89+
90+
examples!(Day07 -> (&'static str, u32) [
91+
{file: "day07_example0.txt", part1: "CABDFE", part2: 15},
92+
]);

crates/year2018/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ utils::year!(2018 => year2018, ${
88
4 => day04::Day04,
99
5 => day05::Day05,
1010
6 => day06::Day06,
11+
7 => day07::Day07,
1112
});

0 commit comments

Comments
 (0)