@@ -1,6 +1,6 @@
|
||||
use crate::utils;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use crate::utils;
|
||||
|
||||
pub fn task1() {
|
||||
let input = utils::read_file("input/day02.txt");
|
||||
@@ -83,7 +83,7 @@ pub fn task2_linear() {
|
||||
// has that prefix.
|
||||
let mut root = Node::default();
|
||||
for id in input.lines() {
|
||||
add_id_to_tree(&mut root, &id);
|
||||
add_id_to_tree(&mut root, id);
|
||||
}
|
||||
|
||||
// find a match..
|
||||
@@ -92,11 +92,11 @@ pub fn task2_linear() {
|
||||
}
|
||||
|
||||
fn find_some_match(node: &Node) -> Option<String> {
|
||||
if let Some(result) = check_children_for_match(&node) {
|
||||
return Some(result);
|
||||
if let Some(result) = check_children_for_match(node) {
|
||||
Some(result)
|
||||
} else {
|
||||
for child in node.outgoing.values() {
|
||||
if let Some(result) = find_some_match(&child) {
|
||||
if let Some(result) = find_some_match(child) {
|
||||
return Some(result);
|
||||
}
|
||||
}
|
||||
@@ -113,14 +113,14 @@ fn find_some_match(node: &Node) -> Option<String> {
|
||||
/// suffixes that appear more than once in a child node. Then we look at
|
||||
/// all possible suffixes from all child nodes. If one suffix appears exactly
|
||||
/// twice, we have a match.
|
||||
fn check_children_for_match<'a>(node: &Node<'a>) -> Option<String> {
|
||||
fn check_children_for_match(node: &Node<'_>) -> Option<String> {
|
||||
let edges: Vec<_> = node.outgoing.keys().collect();
|
||||
// create a set of candidate suffixes for each edge
|
||||
let suffix_candidates: HashMap<char, HashSet<&str>> = edges
|
||||
.iter()
|
||||
.map(|c| {
|
||||
let mut suffix_count = HashMap::<&str, HashSet<&str>>::new();
|
||||
let ref ids = node.outgoing.get(&c).unwrap().same_prefix;
|
||||
let ids = &node.outgoing.get(c).unwrap().same_prefix;
|
||||
for id in ids {
|
||||
suffix_count
|
||||
.entry(&id[node.depth + 1..])
|
||||
@@ -136,7 +136,8 @@ fn check_children_for_match<'a>(node: &Node<'a>) -> Option<String> {
|
||||
.map(|(suffix, _)| *suffix)
|
||||
.collect(),
|
||||
)
|
||||
}).collect();
|
||||
})
|
||||
.collect();
|
||||
// go over all suffixes and count their occurences. If # = 2, match!
|
||||
let mut suffix_counter: HashMap<&str, usize> = HashMap::new();
|
||||
for suffix_set in suffix_candidates.values() {
|
||||
@@ -144,15 +145,10 @@ fn check_children_for_match<'a>(node: &Node<'a>) -> Option<String> {
|
||||
*suffix_counter.entry(suffix).or_insert(0) += 1;
|
||||
}
|
||||
}
|
||||
if let Some(suffix) =
|
||||
suffix_counter
|
||||
.iter()
|
||||
.find_map(|(suffix, count)| if *count == 2 { Some(suffix) } else { None })
|
||||
{
|
||||
Some(format!("{}{}", node.prefix, &suffix))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
.map(|suffix| format!("{}{}", node.prefix, &suffix))
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
@@ -165,12 +161,12 @@ struct Node<'a> {
|
||||
|
||||
fn add_id_to_tree<'a>(root: &mut Node<'a>, id: &'a str) {
|
||||
let mut current = root;
|
||||
current.same_prefix.insert(&id);
|
||||
current.same_prefix.insert(id);
|
||||
for (i, c) in id.chars().enumerate() {
|
||||
{
|
||||
let mut next = current.outgoing.entry(c).or_insert(Node::default());
|
||||
next.depth = i + 1;
|
||||
next.same_prefix.insert(&id);
|
||||
next.same_prefix.insert(id);
|
||||
next.prefix = &id[..=i];
|
||||
}
|
||||
current = { current }.outgoing.get_mut(&c).unwrap();
|
||||
|
||||
@@ -16,7 +16,7 @@ pub fn task1() {
|
||||
.lines()
|
||||
.map(|line| {
|
||||
// #12 @ 590,968: 25x14
|
||||
let m = re.captures(&line).unwrap();
|
||||
let m = re.captures(line).unwrap();
|
||||
let id: u32 = m.get(1).unwrap().as_str().parse().unwrap();
|
||||
let left: u32 = m.get(2).unwrap().as_str().parse().unwrap();
|
||||
let top: u32 = m.get(3).unwrap().as_str().parse().unwrap();
|
||||
@@ -28,7 +28,7 @@ pub fn task1() {
|
||||
|mut map, (id, left, top, width, height)| {
|
||||
for x in left..left + width {
|
||||
for y in top..top + height {
|
||||
if let None = map.get(&(x, y)) {
|
||||
if map.get(&(x, y)).is_none() {
|
||||
map.insert((x, y), Use::Single(id));
|
||||
} else {
|
||||
map.insert((x, y), Use::Multi);
|
||||
@@ -53,7 +53,7 @@ pub fn task2() {
|
||||
let claims: Vec<_> = input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let m = re.captures(&line).unwrap();
|
||||
let m = re.captures(line).unwrap();
|
||||
let id: u32 = m.get(1).unwrap().as_str().parse().unwrap();
|
||||
let left: u32 = m.get(2).unwrap().as_str().parse().unwrap();
|
||||
let top: u32 = m.get(3).unwrap().as_str().parse().unwrap();
|
||||
@@ -67,7 +67,7 @@ pub fn task2() {
|
||||
|mut map, (id, left, top, width, height)| {
|
||||
for x in *left..*left + *width {
|
||||
for y in *top..*top + *height {
|
||||
if let None = map.get(&(x, y)) {
|
||||
if map.get(&(x, y)).is_none() {
|
||||
map.insert((x, y), Use::Single(*id));
|
||||
} else {
|
||||
map.insert((x, y), Use::Multi);
|
||||
|
||||
@@ -29,7 +29,7 @@ pub fn task1() {
|
||||
} else if line.contains("wakes up") {
|
||||
Activity::Awakens
|
||||
} else {
|
||||
let number: u32 = line.split(' ').find(|part| part.starts_with("#")).unwrap()[1..]
|
||||
let number: u32 = line.split(' ').find(|part| part.starts_with('#')).unwrap()[1..]
|
||||
.parse()
|
||||
.unwrap();
|
||||
Activity::Starts(number)
|
||||
@@ -45,7 +45,7 @@ pub fn task1() {
|
||||
let minute = Duration::minutes(1);
|
||||
for (time, activity) in input.into_iter() {
|
||||
// for all minutes since last time slot fill arrays
|
||||
let mut iter_time = last_time.clone();
|
||||
let mut iter_time = last_time;
|
||||
while iter_time < time {
|
||||
if current_state == State::Asleep && iter_time.hour() == 0 {
|
||||
sleep_map.entry(current_id).or_insert([0; 60])[iter_time.minute() as usize] += 1;
|
||||
@@ -98,7 +98,7 @@ pub fn task2() {
|
||||
} else if line.contains("wakes up") {
|
||||
Activity::Awakens
|
||||
} else {
|
||||
let number: u32 = line.split(' ').find(|part| part.starts_with("#")).unwrap()[1..]
|
||||
let number: u32 = line.split(' ').find(|part| part.starts_with('#')).unwrap()[1..]
|
||||
.parse()
|
||||
.unwrap();
|
||||
Activity::Starts(number)
|
||||
@@ -114,7 +114,7 @@ pub fn task2() {
|
||||
let minute = Duration::minutes(1);
|
||||
for (time, activity) in input.into_iter() {
|
||||
// for all minutes since last time slot fill arrays
|
||||
let mut iter_time = last_time.clone();
|
||||
let mut iter_time = last_time;
|
||||
while iter_time < time {
|
||||
if current_state == State::Asleep && iter_time.hour() == 0 {
|
||||
sleep_map.entry(current_id).or_insert([0; 60])[iter_time.minute() as usize] += 1;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::cmp::Ordering::{Equal, Greater, Less};
|
||||
|
||||
use crate::utils;
|
||||
|
||||
pub fn task1() {
|
||||
@@ -12,7 +14,8 @@ pub fn task1() {
|
||||
split.next().unwrap().parse().unwrap(),
|
||||
split.next().unwrap().parse().unwrap(),
|
||||
)
|
||||
}).collect();
|
||||
})
|
||||
.collect();
|
||||
|
||||
let max_x = coordinates.iter().max_by_key(|it| it.0).unwrap().0;
|
||||
let max_y = coordinates.iter().max_by_key(|it| it.1).unwrap().1;
|
||||
@@ -26,22 +29,17 @@ pub fn task1() {
|
||||
area.push(vec);
|
||||
}
|
||||
|
||||
for (_, (a, b)) in coordinates.iter().enumerate() {
|
||||
for x in 0..area.len() {
|
||||
for y in 0..area[x].len() {
|
||||
for (a, b) in coordinates.iter() {
|
||||
for (x, col) in area.iter_mut().enumerate() {
|
||||
for (y, cell) in col.iter_mut().enumerate() {
|
||||
let d = (i32::abs(*a as i32 - x as i32) + i32::abs(*b as i32 - y as i32)) as u16;
|
||||
area[x][y] = match area[x][y] {
|
||||
*cell = match *cell {
|
||||
None => Single(d, (*a, *b)),
|
||||
Single(dd, (aa, bb)) => {
|
||||
if dd < d {
|
||||
Single(dd, (aa, bb))
|
||||
} else if dd > d {
|
||||
Single(d, (*a, *b))
|
||||
} else {
|
||||
// equal
|
||||
Multi(d)
|
||||
}
|
||||
}
|
||||
Single(dd, (aa, bb)) => match dd.cmp(&d) {
|
||||
Less => Single(dd, (aa, bb)),
|
||||
Equal => Single(d, (*a, *b)),
|
||||
Greater => Multi(d),
|
||||
},
|
||||
Multi(dd) => {
|
||||
if d < dd {
|
||||
Single(d, (*a, *b))
|
||||
@@ -60,18 +58,15 @@ pub fn task1() {
|
||||
.map(|(_, (a, b))| {
|
||||
let count = area
|
||||
.iter()
|
||||
.flat_map(|v| v)
|
||||
.flatten()
|
||||
.filter(|entry| {
|
||||
if let Single(_, (x, y)) = entry {
|
||||
if a == x && b == y {
|
||||
true
|
||||
a == x && b == y
|
||||
} else {
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}).count();
|
||||
})
|
||||
.count();
|
||||
let infinite = area[0].iter().any(|bla| bla.belongs_to_point(*a, *b))
|
||||
|| area[area.len() - 1]
|
||||
.iter()
|
||||
@@ -82,7 +77,8 @@ pub fn task1() {
|
||||
.any(|line| line[line.len() - 1].belongs_to_point(*a, *b));
|
||||
// println!("{} has size {} (infinite: {:?})", i, count, infinite);
|
||||
(count, infinite)
|
||||
}).collect::<Vec<_>>();
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
println!(
|
||||
"Overall occupation: {} of {}",
|
||||
@@ -127,7 +123,8 @@ pub fn task2() {
|
||||
split.next().unwrap().parse().unwrap(),
|
||||
split.next().unwrap().parse().unwrap(),
|
||||
)
|
||||
}).collect();
|
||||
})
|
||||
.collect();
|
||||
|
||||
let max_x = coordinates.iter().max_by_key(|it| it.0).unwrap().0;
|
||||
let max_y = coordinates.iter().max_by_key(|it| it.1).unwrap().1;
|
||||
@@ -141,10 +138,13 @@ pub fn task2() {
|
||||
.map(|(a, b)| {
|
||||
(i32::abs(*a as i32 - x as i32) + i32::abs(*b as i32 - y as i32))
|
||||
as usize
|
||||
}).sum::<usize>()
|
||||
}).filter(|it| *it < 10000)
|
||||
})
|
||||
.sum::<usize>()
|
||||
})
|
||||
.filter(|it| *it < 10000)
|
||||
.count()
|
||||
}).sum();
|
||||
})
|
||||
.sum();
|
||||
|
||||
println!("Part 2: {}", result);
|
||||
}
|
||||
|
||||
@@ -18,13 +18,12 @@ pub fn task1() {
|
||||
|
||||
let mut open: HashSet<char> = tasks
|
||||
.iter()
|
||||
.filter(|task| !depends_on.contains_key(task))
|
||||
.map(|c| *c)
|
||||
.filter(|task| !depends_on.contains_key(task)).copied()
|
||||
.collect();
|
||||
|
||||
let mut result = String::new();
|
||||
while open.len() > 0 {
|
||||
let next = open.iter().min().unwrap().clone();
|
||||
while !open.is_empty() {
|
||||
let next = *open.iter().min().unwrap();
|
||||
open.remove(&next);
|
||||
result.push(next);
|
||||
let newly_open: HashSet<char> = depends_on
|
||||
@@ -32,7 +31,7 @@ pub fn task1() {
|
||||
.filter(|(_task, deps)| deps.iter().all(|dep| result.chars().any(|c| c == *dep)))
|
||||
.map(|(task, _)| *task)
|
||||
.collect();
|
||||
open = open.union(&newly_open).map(|c| *c).collect();
|
||||
open = open.union(&newly_open).copied().collect();
|
||||
for c in newly_open {
|
||||
depends_on.remove(&c);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::utils;
|
||||
|
||||
pub fn both() {
|
||||
let input: Vec<usize> = utils::read_file("input/day08.txt")
|
||||
.split(" ")
|
||||
.split(' ')
|
||||
.map(|x| x.parse().unwrap())
|
||||
.collect();
|
||||
|
||||
@@ -23,13 +23,13 @@ impl Node {
|
||||
let num_meta: usize = input[1];
|
||||
let mut children = Vec::new();
|
||||
while num_children > 0 {
|
||||
let (node, rest) = Node::extract_from(&rest_input);
|
||||
let (node, rest) = Node::extract_from(rest_input);
|
||||
children.push(node);
|
||||
rest_input = rest;
|
||||
num_children -= 1;
|
||||
}
|
||||
|
||||
let metadata = rest_input[..num_meta].iter().map(|x| *x).collect();
|
||||
let metadata = rest_input[..num_meta].to_vec();
|
||||
(Node { metadata, children }, &rest_input[num_meta..])
|
||||
}
|
||||
|
||||
@@ -39,14 +39,14 @@ impl Node {
|
||||
.children
|
||||
.iter()
|
||||
.map(|child| {
|
||||
let s: usize = child.metadata_sum().clone();
|
||||
let s: usize = child.metadata_sum();
|
||||
s
|
||||
})
|
||||
.sum::<usize>()
|
||||
}
|
||||
|
||||
fn task2(&self) -> usize {
|
||||
if self.children.len() > 0 {
|
||||
if !self.children.is_empty() {
|
||||
self.metadata
|
||||
.iter()
|
||||
.map(|meta| match self.children.get(*meta - 1) {
|
||||
|
||||
@@ -30,7 +30,7 @@ pub fn task1() {
|
||||
let mut time = 0;
|
||||
loop {
|
||||
time += 1;
|
||||
let new_lights = lights.iter().map(|light| light.move_copy()).collect();
|
||||
let new_lights: Vec<Light> = lights.iter().map(|light| light.move_copy()).collect();
|
||||
// print_lights(&new_lights);
|
||||
let new_area = get_area(&new_lights);
|
||||
// println!("Area: {} ", new_area);
|
||||
@@ -45,7 +45,7 @@ pub fn task1() {
|
||||
print_lights(&lights);
|
||||
}
|
||||
|
||||
fn get_area(lights: &Vec<Light>) -> usize {
|
||||
fn get_area(lights: &[Light]) -> usize {
|
||||
let xmin = lights.iter().map(|it| it.x).min().unwrap();
|
||||
let xmax = lights.iter().map(|it| it.x).max().unwrap();
|
||||
let ymin = lights.iter().map(|it| it.y).min().unwrap();
|
||||
@@ -53,7 +53,7 @@ fn get_area(lights: &Vec<Light>) -> usize {
|
||||
(xmax - xmin) as usize * (ymax - ymin) as usize
|
||||
}
|
||||
|
||||
fn print_lights(lights: &Vec<Light>) {
|
||||
fn print_lights(lights: &[Light]) {
|
||||
let xmin = lights.iter().map(|it| it.x).min().unwrap();
|
||||
let xmax = lights.iter().map(|it| it.x).max().unwrap();
|
||||
let ymin = lights.iter().map(|it| it.y).min().unwrap();
|
||||
@@ -64,14 +64,12 @@ fn print_lights(lights: &Vec<Light>) {
|
||||
let mut screen: Vec<Vec<u8>> = Vec::with_capacity(height as usize);
|
||||
for _ in 0..=height {
|
||||
let mut chars = Vec::with_capacity(width as usize);
|
||||
for _ in 0..=width {
|
||||
chars.push('.' as u8);
|
||||
}
|
||||
chars.resize(width as usize + 1, b'.');
|
||||
screen.push(chars);
|
||||
}
|
||||
lights
|
||||
.iter()
|
||||
.for_each(|light| screen[(light.y - ymin) as usize][(light.x - xmin) as usize] = '#' as u8);
|
||||
.for_each(|light| screen[(light.y - ymin) as usize][(light.x - xmin) as usize] = b'#');
|
||||
for line in screen.iter() {
|
||||
println!("{}", String::from_utf8(line.clone()).unwrap());
|
||||
}
|
||||
|
||||
@@ -56,9 +56,9 @@ pub fn task2_fast() {
|
||||
let serial = 6392;
|
||||
|
||||
let mut cache: Vec<Vec<i32>> = Vec::with_capacity(301);
|
||||
for x in 0 as usize..=300 {
|
||||
for x in 0_usize..=300 {
|
||||
let mut v: Vec<i32> = Vec::with_capacity(301);
|
||||
for y in 0 as usize..=300 {
|
||||
for y in 0_usize..=300 {
|
||||
if x == 0 || y == 0 {
|
||||
v.push(0);
|
||||
} else {
|
||||
@@ -72,10 +72,10 @@ pub fn task2_fast() {
|
||||
}
|
||||
let values = &cache;
|
||||
|
||||
for x in 0 as usize..=300 {
|
||||
for y in 0 as usize..=300 {
|
||||
for x in 0_usize..=300 {
|
||||
for y in 0_usize..=300 {
|
||||
if x != 0 && y != 0 {
|
||||
let cached = area_sum(&values, x, y, 1);
|
||||
let cached = area_sum(values, x, y, 1);
|
||||
let calc = fuel_level(x as i32, y as i32, serial);
|
||||
//println!("{},{}: {} ({})", x, y, values[x][y], calc);
|
||||
assert_eq!(calc, cached);
|
||||
@@ -87,7 +87,7 @@ pub fn task2_fast() {
|
||||
.map(|square_size| {
|
||||
let result = (1..=301 - square_size)
|
||||
.flat_map(|x: usize| (1..=301 - square_size).map(move |y: usize| (x, y)))
|
||||
.map(|(x, y)| (x, y, area_sum(&values, x, y, square_size)))
|
||||
.map(|(x, y)| (x, y, area_sum(values, x, y, square_size)))
|
||||
.max_by_key(|(_, _, value)| *value)
|
||||
.unwrap();
|
||||
(result.0, result.1, result.2, square_size)
|
||||
@@ -96,7 +96,7 @@ pub fn task2_fast() {
|
||||
println!("{:?}", result);
|
||||
}
|
||||
|
||||
fn area_sum(values: &Vec<Vec<i32>>, x: usize, y: usize, length: usize) -> i32 {
|
||||
fn area_sum(values: &[Vec<i32>], x: usize, y: usize, length: usize) -> i32 {
|
||||
values[x + length - 1][y + length - 1] + values[x - 1][y - 1]
|
||||
- values[x - 1][y + length - 1]
|
||||
- values[x + length - 1][y - 1]
|
||||
@@ -108,7 +108,7 @@ fn fuel_level(x: i32, y: i32, serial: i32) -> i32 {
|
||||
power += serial;
|
||||
power *= rack_id;
|
||||
power = power / 100 % 10;
|
||||
power = power - 5;
|
||||
power -= 5;
|
||||
power
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ pub fn task1() {
|
||||
|
||||
input.next();
|
||||
for line in input {
|
||||
let key = line.split(" => ").nth(0).unwrap();
|
||||
let key = line.split(" => ").next().unwrap();
|
||||
transformations.insert(key.to_string(), line.chars().last().unwrap());
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ fn read_input() -> (Vec<Vec<char>>, Vec<Cart>) {
|
||||
for (x, c) in line.chars().enumerate() {
|
||||
if tiles.contains(&c) {
|
||||
map[x][y] = c;
|
||||
} else {
|
||||
if c != ' ' {
|
||||
} else if c != ' ' {
|
||||
map[x][y] = match c {
|
||||
'>' => '-',
|
||||
'<' => '-',
|
||||
@@ -43,7 +42,6 @@ fn read_input() -> (Vec<Vec<char>>, Vec<Cart>) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(map, carts)
|
||||
}
|
||||
@@ -57,7 +55,7 @@ struct Cart {
|
||||
active: bool,
|
||||
}
|
||||
|
||||
fn perform_round(map: &Vec<Vec<char>>, carts: &mut Vec<Cart>) {
|
||||
fn perform_round(map: &[Vec<char>], carts: &mut Vec<Cart>) {
|
||||
carts.sort_unstable_by(|a, b| {
|
||||
if a.y == b.y {
|
||||
a.x.cmp(&b.x)
|
||||
|
||||
@@ -19,7 +19,7 @@ pub fn task1() {
|
||||
println!("Final full round was {}", round);
|
||||
println!(
|
||||
"Result: {}",
|
||||
game.units.iter().map(|it| it.health).sum::<i32>() * round as i32
|
||||
game.units.iter().map(|it| it.health).sum::<i32>() * round
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ pub fn task2() {
|
||||
}
|
||||
println!(
|
||||
"Result: {}",
|
||||
game.units.iter().map(|it| it.health).sum::<i32>() * round as i32
|
||||
game.units.iter().map(|it| it.health).sum::<i32>() * round
|
||||
);
|
||||
}
|
||||
println!("Searching stopped with lowest win {:?}", lowest_win); // 7169 too low
|
||||
@@ -158,7 +158,7 @@ impl Game {
|
||||
from: Position,
|
||||
target_type: WarriorType,
|
||||
) -> Option<Position> {
|
||||
let mut map = Map::from_game(&self, from);
|
||||
let mut map = Map::from_game(self, from);
|
||||
|
||||
for unit in self.units.iter() {
|
||||
if unit.warrior_type == target_type {
|
||||
@@ -199,13 +199,8 @@ impl Game {
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
let map = Map::from_game(&self, from);
|
||||
if let Some(path) = map.shortest_path(from, to) {
|
||||
// println!("{:?}", path);
|
||||
Some(*path.get(1).unwrap_or(&from))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let map = Map::from_game(self, from);
|
||||
map.shortest_path(from, to).map(|path| *path.get(1).unwrap_or(&from))
|
||||
}
|
||||
|
||||
/// Returns true if a full round was played, false if the round aborted because all
|
||||
@@ -284,7 +279,7 @@ impl Game {
|
||||
}
|
||||
curr += 1;
|
||||
}
|
||||
return true;
|
||||
true
|
||||
}
|
||||
|
||||
fn from_input(input: &Vec<&str>, goblin_attack: i32, elve_attack: i32) -> Self {
|
||||
@@ -354,7 +349,7 @@ impl Display for Game {
|
||||
}
|
||||
}
|
||||
f.write_str(&line)?;
|
||||
f.write_str(&"\n")?;
|
||||
f.write_str("\n")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -387,7 +382,7 @@ impl Display for Map {
|
||||
});
|
||||
}
|
||||
f.write_str(&line)?;
|
||||
f.write_str(&"\n")?;
|
||||
f.write_str("\n")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -411,7 +406,7 @@ impl Map {
|
||||
}
|
||||
fields[clear.0][clear.1] = MapTile::Empty;
|
||||
Map {
|
||||
fields: fields,
|
||||
fields,
|
||||
width: game.width,
|
||||
height: game.height,
|
||||
}
|
||||
@@ -487,10 +482,6 @@ impl Map {
|
||||
}
|
||||
|
||||
candidates.sort_unstable();
|
||||
if let Some(x) = candidates.first() {
|
||||
Some(*x)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
candidates.first().copied()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ pub fn task1() {
|
||||
let input = &input[1..];
|
||||
let mut map: HashMap<Point, Tile> = HashMap::new();
|
||||
add_default_neighbors_for_room(&mut map, Point(0, 0));
|
||||
parse_input(&mut map, &input, Point(0, 0));
|
||||
parse_input(&mut map, input, Point(0, 0));
|
||||
|
||||
// print_map(&map);
|
||||
|
||||
@@ -33,14 +33,14 @@ fn parse_input(map: &mut HashMap<Point, Tile>, input: &str, position: Point) ->
|
||||
}
|
||||
let mut position = position;
|
||||
let mut input = input;
|
||||
let mut iterator = input.chars();
|
||||
while let Some(c) = iterator.next() {
|
||||
let iterator = input.chars();
|
||||
for c in iterator {
|
||||
match c {
|
||||
'(' => {
|
||||
let (parts, rest) = split_parts(&input);
|
||||
let (parts, rest) = split_parts(input);
|
||||
let mut middle_points: HashSet<Point> = HashSet::new();
|
||||
for part in parts {
|
||||
if part.len() > 0 {
|
||||
if !part.is_empty() {
|
||||
for x in parse_input(map, part, position) {
|
||||
middle_points.insert(x);
|
||||
}
|
||||
@@ -48,7 +48,7 @@ fn parse_input(map: &mut HashMap<Point, Tile>, input: &str, position: Point) ->
|
||||
}
|
||||
let mut end_points: HashSet<Point> = HashSet::new();
|
||||
for point in middle_points {
|
||||
if rest.len() > 0 {
|
||||
if !rest.is_empty() {
|
||||
for x in parse_input(map, rest, point) {
|
||||
end_points.insert(x);
|
||||
}
|
||||
@@ -122,7 +122,7 @@ fn split_parts(input: &str) -> (Vec<&str>, &str) {
|
||||
}
|
||||
}
|
||||
let closing_index =
|
||||
closing_index.expect(&format!("No matching closing parenthesis in {}", input));
|
||||
closing_index.unwrap_or_else(|| panic!("No matching closing parenthesis in {}", input));
|
||||
(parts, &input[closing_index + 1..])
|
||||
}
|
||||
|
||||
@@ -132,9 +132,7 @@ fn add_default_neighbors_for_room(map: &mut HashMap<Point, Tile>, position: Poin
|
||||
map.insert(p, Wall);
|
||||
}
|
||||
for p in position.neighbors() {
|
||||
if !map.contains_key(&p) {
|
||||
map.insert(p, Unknown);
|
||||
}
|
||||
map.entry(p).or_insert(Unknown);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ impl Cave {
|
||||
|
||||
fn erosion_index(&mut self, x: usize, y: usize) -> usize {
|
||||
if let Some(value) = self.map.get(&(x, y)) {
|
||||
return *value;
|
||||
*value
|
||||
} else {
|
||||
let geo_index = match (x, y) {
|
||||
(0, 0) => 0,
|
||||
@@ -71,7 +71,7 @@ impl Cave {
|
||||
};
|
||||
let erosion_index = (geo_index + self.depth) % 20183;
|
||||
self.map.insert((x, y), erosion_index);
|
||||
return erosion_index;
|
||||
erosion_index
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ impl Cave {
|
||||
if self.equipment_allowed_for_region(node.0, node.1, node.2) {
|
||||
result.push(Edge {
|
||||
cost: 1,
|
||||
node: node,
|
||||
node,
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
@@ -80,7 +80,7 @@ pub fn task2() {
|
||||
} else {
|
||||
for child in cube.children() {
|
||||
heap.push(Candidate {
|
||||
count: bots.iter().filter(|bot| child.intersects(&bot)).count(),
|
||||
count: bots.iter().filter(|bot| child.intersects(bot)).count(),
|
||||
cube: child,
|
||||
})
|
||||
}
|
||||
@@ -96,7 +96,7 @@ pub fn task2() {
|
||||
let best = candidate_points
|
||||
.iter()
|
||||
.filter(|(_, count)| *count == best_candidate_count)
|
||||
.min_by_key(|(point, _)| origin.distance(&point));
|
||||
.min_by_key(|(point, _)| origin.distance(point));
|
||||
|
||||
println!("{:?}", best);
|
||||
if let Some((best, _)) = best {
|
||||
@@ -136,7 +136,7 @@ impl Bot {
|
||||
}
|
||||
|
||||
fn dist(&self, p: &Point) -> isize {
|
||||
self.center.distance(&p)
|
||||
self.center.distance(p)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::cmp::Reverse;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub fn task1() {
|
||||
let input = "Immune System:
|
||||
let _input = "Immune System:
|
||||
17 units each with 5390 hit points (weak to radiation, bludgeoning) with an attack that does 4507 fire damage at initiative 2
|
||||
989 units each with 1274 hit points (immune to fire; weak to bludgeoning, slashing) with an attack that does 25 slashing damage at initiative 3
|
||||
|
||||
@@ -41,7 +41,7 @@ Infection:
|
||||
|
||||
println!(
|
||||
"Standing units after the game: {}",
|
||||
game.groups.iter().map(|(_, it)| it.units).sum::<i64>()
|
||||
game.groups.values().map(|it| it.units).sum::<i64>()
|
||||
);
|
||||
|
||||
// 21107 too high
|
||||
@@ -79,7 +79,7 @@ impl Game {
|
||||
fn round(&mut self) {
|
||||
let mut target: HashMap<usize, usize> = HashMap::new();
|
||||
// lock targets ordered by effective power
|
||||
let mut all_by_power: Vec<&Group> = self.groups.iter().map(|(_, it)| it).collect();
|
||||
let mut all_by_power: Vec<&Group> = self.groups.values().collect();
|
||||
all_by_power.sort_unstable_by_key(|a| Reverse((a.effective_power(), a.initiative)));
|
||||
// for group in all_by_power.iter() {
|
||||
// println!(
|
||||
@@ -93,8 +93,7 @@ impl Game {
|
||||
for group in all_by_power.iter() {
|
||||
if let Some(t) = self
|
||||
.groups
|
||||
.iter()
|
||||
.map(|(_, it)| it)
|
||||
.values()
|
||||
.filter(|it| it.team != group.team)
|
||||
.filter(|it| !target.values().any(|t| *t == it.id))
|
||||
// .filter(|it| group.compute_attack_damage_to(&it) >= it.hp_each)
|
||||
@@ -108,13 +107,13 @@ impl Game {
|
||||
// })
|
||||
.max_by_key(|it| {
|
||||
(
|
||||
group.compute_attack_damage_to(&it),
|
||||
group.compute_attack_damage_to(it),
|
||||
it.effective_power(),
|
||||
it.initiative,
|
||||
)
|
||||
})
|
||||
{
|
||||
if group.compute_attack_damage_to(&t) <= 0 {
|
||||
if group.compute_attack_damage_to(t) <= 0 {
|
||||
println!(
|
||||
"Didn't find a target where {:?} can deal positive damage.",
|
||||
group
|
||||
@@ -127,8 +126,7 @@ impl Game {
|
||||
}
|
||||
|
||||
// attack ordered by initiative
|
||||
let mut all_ids_by_initiative: Vec<usize> =
|
||||
self.groups.iter().map(|(_, it)| it.id).collect();
|
||||
let mut all_ids_by_initiative: Vec<usize> = self.groups.values().map(|it| it.id).collect();
|
||||
all_ids_by_initiative.sort_unstable_by_key(|id| Reverse(self.groups[id].initiative));
|
||||
|
||||
for active_id in all_ids_by_initiative {
|
||||
@@ -139,7 +137,7 @@ impl Game {
|
||||
}
|
||||
if let Some(enemy_id) = target.get(&active_id) {
|
||||
let enemy = &self.groups[enemy_id];
|
||||
let damage: i64 = self.groups[&active_id].compute_attack_damage_to(&enemy);
|
||||
let damage: i64 = self.groups[&active_id].compute_attack_damage_to(enemy);
|
||||
let dying_units = damage / enemy.hp_each;
|
||||
if let Some(enemy) = self.groups.get_mut(enemy_id) {
|
||||
enemy.units -= dying_units;
|
||||
@@ -157,7 +155,7 @@ impl Game {
|
||||
}
|
||||
|
||||
fn is_over(&self) -> bool {
|
||||
self.groups.len() == 0
|
||||
self.groups.is_empty()
|
||||
|| self.groups.iter().all(|(_, it)| it.team == Team::Infection)
|
||||
|| self
|
||||
.groups
|
||||
@@ -199,10 +197,10 @@ impl Group {
|
||||
let mut weaknesses: Vec<String> = Vec::new();
|
||||
let mut immunities: Vec<String> = Vec::new();
|
||||
for part in m[3].split("; ") {
|
||||
if part.starts_with("weak to ") {
|
||||
weaknesses = part[8..].split(", ").map(|it| it.to_string()).collect();
|
||||
} else if part.starts_with("immune to ") {
|
||||
immunities = part[10..].split(", ").map(|it| it.to_string()).collect();
|
||||
if let Some(stripped) = part.strip_prefix("weak to ") {
|
||||
weaknesses = stripped.split(", ").map(|it| it.to_string()).collect();
|
||||
} else if let Some(stripped) = part.strip_prefix("immune to ") {
|
||||
immunities = stripped.split(", ").map(|it| it.to_string()).collect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
|
||||
pub fn read_file(path: &str) -> String {
|
||||
let mut f = File::open(path).expect(&format!("file '{}' not found", path));
|
||||
let mut f = File::open(path).unwrap_or_else(|_| panic!("file '{}' not found", path));
|
||||
|
||||
let mut contents = String::new();
|
||||
f.read_to_string(&mut contents)
|
||||
|
||||
Reference in New Issue
Block a user