Compare commits
2 Commits
8157a9bf7e
...
476f34e2b4
| Author | SHA1 | Date | |
|---|---|---|---|
| 476f34e2b4 | |||
| 9c5d12c6b0 |
54
src/day06.rs
54
src/day06.rs
@@ -14,9 +14,18 @@ type RiddleResult = usize;
|
|||||||
type Point = (i32, i32);
|
type Point = (i32, i32);
|
||||||
|
|
||||||
fn part1(input: &str) -> RiddleResult {
|
fn part1(input: &str) -> RiddleResult {
|
||||||
let (m, mut pos, _) = parse(input);
|
let (m, pos) = parse(input);
|
||||||
|
|
||||||
let mut dir = '^';
|
let dir = '^';
|
||||||
|
let visited = get_visited(&m, pos, dir);
|
||||||
|
visited.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_visited(
|
||||||
|
m: &HashMap<(i32, i32), char>,
|
||||||
|
mut pos: (i32, i32),
|
||||||
|
mut dir: char,
|
||||||
|
) -> HashSet<(i32, i32)> {
|
||||||
let mut visited = HashSet::new();
|
let mut visited = HashSet::new();
|
||||||
while m.contains_key(&pos) {
|
while m.contains_key(&pos) {
|
||||||
let (x, y) = pos;
|
let (x, y) = pos;
|
||||||
@@ -40,27 +49,22 @@ fn part1(input: &str) -> RiddleResult {
|
|||||||
pos = next;
|
pos = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
visited.len()
|
visited
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part2(input: &str) -> RiddleResult {
|
fn part2(input: &str) -> RiddleResult {
|
||||||
let (m, pos, opens) = parse(input);
|
let (m, pos) = parse(input);
|
||||||
|
|
||||||
let dir = '^';
|
let dir = '^';
|
||||||
opens
|
get_visited(&m, pos, dir)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|open| {
|
.filter(|open| is_loop(&m, *open, pos, dir))
|
||||||
let mut m = m.clone();
|
|
||||||
m.insert(*open, '#');
|
|
||||||
is_loop(m, pos, dir)
|
|
||||||
})
|
|
||||||
.count()
|
.count()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(input: &str) -> (HashMap<Point, char>, Point, HashSet<Point>) {
|
fn parse(input: &str) -> (HashMap<Point, char>, Point) {
|
||||||
let mut m = HashMap::new();
|
let mut m = HashMap::new();
|
||||||
let mut pos = None;
|
let mut pos = None;
|
||||||
let mut opens = HashSet::new();
|
|
||||||
input.lines().enumerate().for_each(|(y, line)| {
|
input.lines().enumerate().for_each(|(y, line)| {
|
||||||
line.char_indices().for_each(|(x, c)| {
|
line.char_indices().for_each(|(x, c)| {
|
||||||
let x = x as i32;
|
let x = x as i32;
|
||||||
@@ -71,22 +75,16 @@ fn parse(input: &str) -> (HashMap<Point, char>, Point, HashSet<Point>) {
|
|||||||
} else {
|
} else {
|
||||||
m.insert((x, y), c);
|
m.insert((x, y), c);
|
||||||
}
|
}
|
||||||
if c == '.' {
|
|
||||||
opens.insert((x, y));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
(m, pos.unwrap(), opens)
|
(m, pos.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_loop(m: HashMap<Point, char>, mut pos: Point, mut dir: char) -> bool {
|
fn is_loop(m: &HashMap<Point, char>, block: Point, mut pos: Point, mut dir: char) -> bool {
|
||||||
let mut visited = HashSet::new();
|
let mut visited = HashSet::new();
|
||||||
while m.contains_key(&pos) {
|
loop {
|
||||||
let (x, y) = pos;
|
let (x, y) = pos;
|
||||||
if visited.contains(&(pos, dir)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
visited.insert((pos, dir));
|
|
||||||
let next = match dir {
|
let next = match dir {
|
||||||
'^' => (x, y - 1),
|
'^' => (x, y - 1),
|
||||||
'v' => (x, y + 1),
|
'v' => (x, y + 1),
|
||||||
@@ -94,7 +92,16 @@ fn is_loop(m: HashMap<Point, char>, mut pos: Point, mut dir: char) -> bool {
|
|||||||
'>' => (x + 1, y),
|
'>' => (x + 1, y),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
if let Some('#') = m.get(&next) {
|
let next_tile = m.get(&next);
|
||||||
|
if None == next_tile {
|
||||||
|
return false;
|
||||||
|
} else if next == block || Some(&'#') == next_tile {
|
||||||
|
// we only check for loops on a collision to speed things up
|
||||||
|
if visited.contains(&(pos, dir)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
visited.insert((pos, dir));
|
||||||
|
|
||||||
dir = match dir {
|
dir = match dir {
|
||||||
'^' => '>',
|
'^' => '>',
|
||||||
'v' => '<',
|
'v' => '<',
|
||||||
@@ -106,7 +113,6 @@ fn is_loop(m: HashMap<Point, char>, mut pos: Point, mut dir: char) -> bool {
|
|||||||
pos = next;
|
pos = next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
Reference in New Issue
Block a user