Compare commits
5 Commits
9fe58d5490
...
fd47622c68
Author | SHA1 | Date |
---|---|---|
|
fd47622c68 | |
|
e2b0a51104 | |
|
72f4207e0f | |
|
586ea78d86 | |
|
612bd4313f |
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "part1"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -0,0 +1,92 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
fn parse_graph(string: &str) -> Vec<Vec<u64>> {
|
||||||
|
let mut n = 0;
|
||||||
|
let mut node_to_index: HashMap<String, usize> = HashMap::new();
|
||||||
|
for item in string.lines() {
|
||||||
|
let mut parts = item.split(" ");
|
||||||
|
let city_from = parts.next().unwrap();
|
||||||
|
parts.next();
|
||||||
|
let city_to = parts.next().unwrap();
|
||||||
|
if !node_to_index.contains_key(city_from) {
|
||||||
|
node_to_index.insert(city_from.to_string().clone(), n);
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
if !node_to_index.contains_key(city_to) {
|
||||||
|
node_to_index.insert(city_to.to_string().clone(), n);
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut graph: Vec<Vec<u64>> = vec![vec![0; n]; n];
|
||||||
|
for item in string.lines() {
|
||||||
|
let mut parts = item.split(" ");
|
||||||
|
let city_from = parts.next().unwrap();
|
||||||
|
parts.next();
|
||||||
|
let city_to = parts.next().unwrap();
|
||||||
|
parts.next();
|
||||||
|
let distance = parts.next().unwrap();
|
||||||
|
let distance: u64 = distance.parse().unwrap();
|
||||||
|
let u = *node_to_index.get(city_from).unwrap();
|
||||||
|
let v = *node_to_index.get(city_to).unwrap();
|
||||||
|
graph[u][v] = distance;
|
||||||
|
graph[v][u] = distance;
|
||||||
|
}
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_permutations(n: usize) -> Vec<Vec<usize>> {
|
||||||
|
let mut c: Vec<usize> = vec![0; n];
|
||||||
|
let mut permutations: Vec<Vec<usize>> = Vec::new();
|
||||||
|
let mut permutation: Vec<usize> = Vec::new();
|
||||||
|
for i in 0..n {
|
||||||
|
permutation.push(i);
|
||||||
|
}
|
||||||
|
permutations.push(permutation.clone());
|
||||||
|
|
||||||
|
let mut i = 1;
|
||||||
|
while i < n {
|
||||||
|
if c[i] < i {
|
||||||
|
if i % 2 == 0 {
|
||||||
|
let tmp = permutation[0];
|
||||||
|
permutation[0] = permutation[i];
|
||||||
|
permutation[i] = tmp;
|
||||||
|
} else {
|
||||||
|
let tmp = permutation[c[i]];
|
||||||
|
permutation[c[i]] = permutation[i];
|
||||||
|
permutation[i] = tmp;
|
||||||
|
}
|
||||||
|
permutations.push(permutation.clone());
|
||||||
|
c[i] += 1;
|
||||||
|
i = 1;
|
||||||
|
} else {
|
||||||
|
c[i] = 0;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
permutations
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shortest_distance_brute_force(graph: &Vec<Vec<u64>>) -> u64 {
|
||||||
|
let mut min_distance: u64 = u64::MAX;
|
||||||
|
for permutation in all_permutations(graph.len()) {
|
||||||
|
let mut distance = 0;
|
||||||
|
for i in 0..(graph.len() - 1) {
|
||||||
|
let u = permutation[i];
|
||||||
|
let v = permutation[i+1];
|
||||||
|
let d = graph[u][v];
|
||||||
|
distance += d;
|
||||||
|
}
|
||||||
|
if distance < min_distance {
|
||||||
|
min_distance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
min_distance
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
let string = std::io::read_to_string(std::io::stdin()).unwrap();
|
||||||
|
let graph = parse_graph(&string);
|
||||||
|
let min_distance = shortest_distance_brute_force(&graph);
|
||||||
|
println!("{}", min_distance);
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "part1"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -0,0 +1,92 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
fn parse_graph(string: &str) -> Vec<Vec<u64>> {
|
||||||
|
let mut n = 0;
|
||||||
|
let mut node_to_index: HashMap<String, usize> = HashMap::new();
|
||||||
|
for item in string.lines() {
|
||||||
|
let mut parts = item.split(" ");
|
||||||
|
let city_from = parts.next().unwrap();
|
||||||
|
parts.next();
|
||||||
|
let city_to = parts.next().unwrap();
|
||||||
|
if !node_to_index.contains_key(city_from) {
|
||||||
|
node_to_index.insert(city_from.to_string().clone(), n);
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
if !node_to_index.contains_key(city_to) {
|
||||||
|
node_to_index.insert(city_to.to_string().clone(), n);
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut graph: Vec<Vec<u64>> = vec![vec![0; n]; n];
|
||||||
|
for item in string.lines() {
|
||||||
|
let mut parts = item.split(" ");
|
||||||
|
let city_from = parts.next().unwrap();
|
||||||
|
parts.next();
|
||||||
|
let city_to = parts.next().unwrap();
|
||||||
|
parts.next();
|
||||||
|
let distance = parts.next().unwrap();
|
||||||
|
let distance: u64 = distance.parse().unwrap();
|
||||||
|
let u = *node_to_index.get(city_from).unwrap();
|
||||||
|
let v = *node_to_index.get(city_to).unwrap();
|
||||||
|
graph[u][v] = distance;
|
||||||
|
graph[v][u] = distance;
|
||||||
|
}
|
||||||
|
return graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_permutations(n: usize) -> Vec<Vec<usize>> {
|
||||||
|
let mut c: Vec<usize> = vec![0; n];
|
||||||
|
let mut permutations: Vec<Vec<usize>> = Vec::new();
|
||||||
|
let mut permutation: Vec<usize> = Vec::new();
|
||||||
|
for i in 0..n {
|
||||||
|
permutation.push(i);
|
||||||
|
}
|
||||||
|
permutations.push(permutation.clone());
|
||||||
|
|
||||||
|
let mut i = 1;
|
||||||
|
while i < n {
|
||||||
|
if c[i] < i {
|
||||||
|
if i % 2 == 0 {
|
||||||
|
let tmp = permutation[0];
|
||||||
|
permutation[0] = permutation[i];
|
||||||
|
permutation[i] = tmp;
|
||||||
|
} else {
|
||||||
|
let tmp = permutation[c[i]];
|
||||||
|
permutation[c[i]] = permutation[i];
|
||||||
|
permutation[i] = tmp;
|
||||||
|
}
|
||||||
|
permutations.push(permutation.clone());
|
||||||
|
c[i] += 1;
|
||||||
|
i = 1;
|
||||||
|
} else {
|
||||||
|
c[i] = 0;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
permutations
|
||||||
|
}
|
||||||
|
|
||||||
|
fn longest_distance_brute_force(graph: &Vec<Vec<u64>>) -> u64 {
|
||||||
|
let mut max_distance: u64 = 0;
|
||||||
|
for permutation in all_permutations(graph.len()) {
|
||||||
|
let mut distance = 0;
|
||||||
|
for i in 0..(graph.len() - 1) {
|
||||||
|
let u = permutation[i];
|
||||||
|
let v = permutation[i+1];
|
||||||
|
let d = graph[u][v];
|
||||||
|
distance += d;
|
||||||
|
}
|
||||||
|
if distance > max_distance {
|
||||||
|
max_distance = distance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
max_distance
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
let string = std::io::read_to_string(std::io::stdin()).unwrap();
|
||||||
|
let graph = parse_graph(&string);
|
||||||
|
let max_distance = longest_distance_brute_force(&graph);
|
||||||
|
println!("{}", max_distance);
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "part1"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -0,0 +1,73 @@
|
||||||
|
use std::u64;
|
||||||
|
|
||||||
|
|
||||||
|
fn is_increasing(levels: &Vec<u64>) -> bool {
|
||||||
|
let mut current = 0;
|
||||||
|
for item in levels {
|
||||||
|
if *item < current {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
current = *item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_decreasing(levels: &Vec<u64>) -> bool {
|
||||||
|
let mut current = u64::MAX;
|
||||||
|
for item in levels {
|
||||||
|
if *item > current {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
current = *item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_monotonous(levels: &Vec<u64>) -> bool {
|
||||||
|
return is_increasing(levels) || is_decreasing(levels);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_safe(levels: &Vec<u64>) -> bool {
|
||||||
|
if !is_monotonous(levels) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for i in 0..(levels.len() - 1) {
|
||||||
|
let j = i+1;
|
||||||
|
let a = levels[i];
|
||||||
|
let b = levels[j];
|
||||||
|
let diff = (a as i64 - b as i64).abs() as u64;
|
||||||
|
if diff < 1 || diff > 3 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_safe_but_one(levels: &Vec<u64>) -> bool {
|
||||||
|
if is_safe(levels) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for i in 0..(levels.len()) {
|
||||||
|
let mut levels_but_one = levels.clone();
|
||||||
|
levels_but_one.remove(i);
|
||||||
|
if is_safe(&levels_but_one) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
let mut count = 0;
|
||||||
|
for line in std::io::stdin().lines() {
|
||||||
|
let line = line.unwrap();
|
||||||
|
let levels: Vec<u64> = line.split(" ").map(|x| x.parse::<u64>().unwrap()).collect();
|
||||||
|
if is_safe_but_one(&levels) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("{}", count);
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "day05"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -0,0 +1,161 @@
|
||||||
|
use std::{cmp::Ordering, collections::{BTreeSet, HashMap}};
|
||||||
|
|
||||||
|
fn filter_orderings(orderings: &Vec<(u64, u64)>, update: &Vec<u64>) -> Vec<(u64, u64)> {
|
||||||
|
let mut new_orderings: Vec<(u64, u64)> = Vec::new();
|
||||||
|
for item in orderings {
|
||||||
|
if update.contains(&item.0) && update.contains(&item.1) {
|
||||||
|
new_orderings.push(*item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_orderings
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_incoming(v: usize, graph: &Vec<Vec<bool>>) -> bool {
|
||||||
|
for u in 0..graph.len() {
|
||||||
|
if graph[u][v] {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_edge(graph: &Vec<Vec<bool>>) -> bool {
|
||||||
|
for i in 0..graph.len() {
|
||||||
|
for j in 0..graph[i].len() {
|
||||||
|
if graph[i][j] {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn topological_sorting(graph: &Vec<Vec<bool>>) -> Vec<usize> {
|
||||||
|
let mut graph = graph.clone();
|
||||||
|
let mut l: Vec<usize> = Vec::new();
|
||||||
|
let mut s: BTreeSet<usize> = BTreeSet::new();
|
||||||
|
// Extract the set of nodes with no incoming edge
|
||||||
|
for v in 0..graph.len() {
|
||||||
|
if !has_incoming(v, &graph) {
|
||||||
|
s.insert(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while !s.is_empty() {
|
||||||
|
let u: usize = s.pop_first().unwrap();
|
||||||
|
l.push(u);
|
||||||
|
for v in 0..graph.len() {
|
||||||
|
if graph[u][v] {
|
||||||
|
graph[u][v] = false;
|
||||||
|
if !has_incoming(v, &graph) {
|
||||||
|
s.insert(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if has_edge(&graph) {
|
||||||
|
panic!("Graph has at least one cycle");
|
||||||
|
}
|
||||||
|
l
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_correct(update: &Vec<u64>, ordering: &Vec<u64>) -> bool {
|
||||||
|
|
||||||
|
for i in 0..(update.len() - 1) {
|
||||||
|
let u = update[i];
|
||||||
|
let ordering_i = ordering.iter().position(|&e| e == u).unwrap();
|
||||||
|
for j in (i+1)..update.len() {
|
||||||
|
let v = update[j];
|
||||||
|
let ordering_j = ordering.iter().position(|&e| e == v).unwrap();
|
||||||
|
if ordering_i > ordering_j {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_graph(ordering: &Vec<(u64, u64)>) -> (Vec<Vec<bool>>, HashMap<usize, u64>) {
|
||||||
|
let mut n: usize = 0;
|
||||||
|
let mut vertex_to_number: HashMap<usize, u64> = HashMap::new();
|
||||||
|
let mut number_to_vertex: HashMap<u64, usize> = HashMap::new();
|
||||||
|
for order in ordering {
|
||||||
|
let u = order.0;
|
||||||
|
let v = order.1;
|
||||||
|
if !number_to_vertex.contains_key(&u) {
|
||||||
|
number_to_vertex.insert(u, n);
|
||||||
|
vertex_to_number.insert(n, u);
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
if !number_to_vertex.contains_key(&v) {
|
||||||
|
number_to_vertex.insert(v, n);
|
||||||
|
vertex_to_number.insert(n, v);
|
||||||
|
n += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut graph: Vec<Vec<bool>> = vec![vec![false; n]; n];
|
||||||
|
for order in ordering {
|
||||||
|
let u = *number_to_vertex.get(&order.0).unwrap();
|
||||||
|
let v = *number_to_vertex.get(&order.1).unwrap();
|
||||||
|
graph[u][v] = true;
|
||||||
|
}
|
||||||
|
(graph, vertex_to_number)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_middle(array: &Vec<u64>) -> u64 {
|
||||||
|
let index = array.len() / 2;
|
||||||
|
array[index]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_ordering(a: u64, b: u64, order: &Vec<u64>) -> Ordering {
|
||||||
|
let i = order.iter().position(|&e| e == a);
|
||||||
|
let j = order.iter().position(|&e| e == b);
|
||||||
|
return i.cmp(&j);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
let mut sum_ordered: u64 = 0;
|
||||||
|
let mut sum_unordered: u64 = 0;
|
||||||
|
let mut orderings: Vec<(u64, u64)> = Vec::new();
|
||||||
|
let mut updates: Vec<Vec<u64>> = Vec::new();
|
||||||
|
let mut part = 0;
|
||||||
|
for line in std::io::stdin().lines() {
|
||||||
|
let line = line.unwrap();
|
||||||
|
if line == "" {
|
||||||
|
part += 1;
|
||||||
|
} else if part == 0 {
|
||||||
|
let mut parts = line.split("|");
|
||||||
|
let ordering_first = parts.next().unwrap();
|
||||||
|
let ordering_second = parts.next().unwrap();
|
||||||
|
let ordering_first: u64 = ordering_first.parse().unwrap();
|
||||||
|
let ordering_second: u64 = ordering_second.parse().unwrap();
|
||||||
|
let ordering = (ordering_first, ordering_second);
|
||||||
|
orderings.push(ordering);
|
||||||
|
} else if part == 1 {
|
||||||
|
let parts = line.split(",");
|
||||||
|
let update = parts.map(|num| num.parse::<u64>().unwrap()).collect();
|
||||||
|
updates.push(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for update in updates {
|
||||||
|
let update_orderings = filter_orderings(&orderings, &update);
|
||||||
|
let (graph, vertex_to_number) = parse_graph(&update_orderings);
|
||||||
|
let topological_sort = topological_sorting(&graph);
|
||||||
|
let sorted_num = topological_sort
|
||||||
|
.iter()
|
||||||
|
.map(|v| *vertex_to_number.get(v).unwrap())
|
||||||
|
.collect();
|
||||||
|
if is_correct(&update, &sorted_num) {
|
||||||
|
let middle = get_middle(&update);
|
||||||
|
sum_ordered += middle;
|
||||||
|
} else {
|
||||||
|
let mut update_sorted = update.clone();
|
||||||
|
update_sorted.sort_by(|a, b| compare_ordering(*a, *b, &sorted_num));
|
||||||
|
let middle = get_middle(&update_sorted);
|
||||||
|
sum_unordered += middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("{}", sum_ordered);
|
||||||
|
println!("{}", sum_unordered);
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "day06"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -0,0 +1,106 @@
|
||||||
|
|
||||||
|
struct Guardian {
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
dx: isize,
|
||||||
|
dy: isize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Guardian {
|
||||||
|
pub fn new(x: usize, y: usize) -> Self {
|
||||||
|
let dx = 0;
|
||||||
|
let dy = -1;
|
||||||
|
Guardian{ x, y, dx, dy }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rotate90(self: &mut Self) {
|
||||||
|
if self.dx == 1 && self.dy == 0 {
|
||||||
|
self.dx = 0;
|
||||||
|
self.dy = 1;
|
||||||
|
} else if self.dx == 0 && self.dy == 1 {
|
||||||
|
self.dx = -1;
|
||||||
|
self.dy = 0;
|
||||||
|
} else if self.dx == -1 && self.dy == 0 {
|
||||||
|
self.dx = 0;
|
||||||
|
self.dy = -1;
|
||||||
|
} else if self.dx == 0 && self.dy == -1 {
|
||||||
|
self.dx = 1;
|
||||||
|
self.dy = 0;
|
||||||
|
} else {
|
||||||
|
panic!("Cannot rotate this orientation.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn forward(self: &mut Self) {
|
||||||
|
self.x = (self.x as isize + self.dx) as usize;
|
||||||
|
self.y = (self.y as isize + self.dy) as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn front(self: &mut Self) -> (isize, isize) {
|
||||||
|
(self.x as isize + self.dx, self.y as isize + self.dy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn guardian_coverage(obstacles: &Vec<Vec<bool>>, guard: &mut Guardian) -> Vec<Vec<bool>> {
|
||||||
|
let mut covered: Vec<Vec<bool>> = vec![vec![false; obstacles[0].len()]; obstacles.len()];
|
||||||
|
covered[guard.y][guard.x] = true;
|
||||||
|
let bound_x = obstacles[0].len() as isize;
|
||||||
|
let bound_y = obstacles.len() as isize;
|
||||||
|
loop {
|
||||||
|
let (x, y) = guard.front();
|
||||||
|
if x < 0 || y < 0 || x >= bound_x || y >= bound_y {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
let x = x as usize;
|
||||||
|
let y = y as usize;
|
||||||
|
if obstacles[y][x] {
|
||||||
|
guard.rotate90();
|
||||||
|
} else {
|
||||||
|
covered[y][x] = true;
|
||||||
|
guard.forward();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
covered
|
||||||
|
}
|
||||||
|
|
||||||
|
fn number_of_true(grid: &Vec<Vec<bool>>) -> u64 {
|
||||||
|
let mut count = 0;
|
||||||
|
for row in grid {
|
||||||
|
for item in row {
|
||||||
|
if *item {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()>{
|
||||||
|
let mut obstacles: Vec<Vec<bool>> = Vec::new();
|
||||||
|
let mut guard: Guardian = Guardian::new(0, 0);
|
||||||
|
let mut y: usize = 0;
|
||||||
|
for line in std::io::stdin().lines() {
|
||||||
|
let line: String = line.unwrap();
|
||||||
|
let mut obstacles_row: Vec<bool> = Vec::new();
|
||||||
|
let mut x: usize = 0;
|
||||||
|
for letter in line.chars() {
|
||||||
|
if letter == '^' {
|
||||||
|
guard = Guardian::new(x, y);
|
||||||
|
obstacles_row.push(false);
|
||||||
|
} else if letter == '#' {
|
||||||
|
obstacles_row.push(true);
|
||||||
|
} else {
|
||||||
|
obstacles_row.push(false);
|
||||||
|
}
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
obstacles.push(obstacles_row);
|
||||||
|
y += 1;
|
||||||
|
}
|
||||||
|
let coverage = guardian_coverage(&obstacles, &mut guard);
|
||||||
|
let covered = number_of_true(&coverage);
|
||||||
|
println!("{}", covered);
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
[package]
|
||||||
|
name = "day06"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
|
@ -0,0 +1,115 @@
|
||||||
|
use std::collections::BTreeSet;
|
||||||
|
|
||||||
|
|
||||||
|
struct Guardian {
|
||||||
|
x: usize,
|
||||||
|
y: usize,
|
||||||
|
dx: isize,
|
||||||
|
dy: isize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Guardian {
|
||||||
|
pub fn new(x: usize, y: usize) -> Self {
|
||||||
|
let dx = 0;
|
||||||
|
let dy = -1;
|
||||||
|
Guardian{ x, y, dx, dy }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rotate90(self: &mut Self) {
|
||||||
|
if self.dx == 1 && self.dy == 0 {
|
||||||
|
self.dx = 0;
|
||||||
|
self.dy = 1;
|
||||||
|
} else if self.dx == 0 && self.dy == 1 {
|
||||||
|
self.dx = -1;
|
||||||
|
self.dy = 0;
|
||||||
|
} else if self.dx == -1 && self.dy == 0 {
|
||||||
|
self.dx = 0;
|
||||||
|
self.dy = -1;
|
||||||
|
} else if self.dx == 0 && self.dy == -1 {
|
||||||
|
self.dx = 1;
|
||||||
|
self.dy = 0;
|
||||||
|
} else {
|
||||||
|
panic!("Cannot rotate this orientation.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn forward(self: &mut Self) {
|
||||||
|
self.x = (self.x as isize + self.dx) as usize;
|
||||||
|
self.y = (self.y as isize + self.dy) as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn front(self: &mut Self) -> (isize, isize) {
|
||||||
|
(self.x as isize + self.dx, self.y as isize + self.dy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn is_stuck_in_loop(obstacles: &Vec<Vec<bool>>, x: usize, y: usize, supplement_obstacle_x: usize, supplement_obstacle_y: usize) -> bool {
|
||||||
|
let mut visited: BTreeSet<(usize, usize, isize, isize)> = BTreeSet::new();
|
||||||
|
let bound_x = obstacles[0].len() as isize;
|
||||||
|
let bound_y = obstacles.len() as isize;
|
||||||
|
let mut guard: Guardian = Guardian::new(x, y);
|
||||||
|
loop {
|
||||||
|
if visited.contains(&(guard.x, guard.y, guard.dx, guard.dy)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
visited.insert((guard.x, guard.y, guard.dx, guard.dy));
|
||||||
|
}
|
||||||
|
let (x, y) = guard.front();
|
||||||
|
if x < 0 || y < 0 || x >= bound_x || y >= bound_y {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
let x = x as usize;
|
||||||
|
let y = y as usize;
|
||||||
|
if obstacles[y][x] || supplement_obstacle_x == x && supplement_obstacle_y == y {
|
||||||
|
guard.rotate90();
|
||||||
|
} else {
|
||||||
|
guard.forward();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fn find_loops(guard: Guardian, obstacles: &Vec<Vec<bool>>) -> u64 {
|
||||||
|
let mut count: u64 = 0;
|
||||||
|
for i in 0..obstacles.len() {
|
||||||
|
for j in 0..obstacles.len() {
|
||||||
|
if !obstacles[i][j] {
|
||||||
|
if is_stuck_in_loop(obstacles, guard.x, guard.y, j, i) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
count
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()>{
|
||||||
|
let mut obstacles: Vec<Vec<bool>> = Vec::new();
|
||||||
|
let mut guard: Guardian = Guardian::new(0, 0);
|
||||||
|
let mut y: usize = 0;
|
||||||
|
for line in std::io::stdin().lines() {
|
||||||
|
let line: String = line.unwrap();
|
||||||
|
let mut obstacles_row: Vec<bool> = Vec::new();
|
||||||
|
let mut x: usize = 0;
|
||||||
|
for letter in line.chars() {
|
||||||
|
if letter == '^' {
|
||||||
|
guard = Guardian::new(x, y);
|
||||||
|
obstacles_row.push(false);
|
||||||
|
} else if letter == '#' {
|
||||||
|
obstacles_row.push(true);
|
||||||
|
} else {
|
||||||
|
obstacles_row.push(false);
|
||||||
|
}
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
obstacles.push(obstacles_row);
|
||||||
|
y += 1;
|
||||||
|
}
|
||||||
|
let loops: u64 = find_loops(guard, &obstacles);
|
||||||
|
println!("{}", loops);
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue