1
0
Fork 0

Merge branch 'master' of ssh://git.penguincoder.org:2222/penguincoder/advent-of-code

main
Andrew Coleman 2019-01-07 21:58:46 -05:00
commit 921e892ca8
26 changed files with 640 additions and 97 deletions

View File

@ -1,16 +1,13 @@
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::iter::Iterator;
fn print_final_frequency(ints: &Vec<i32>) { fn print_final_frequency(ints: &Vec<i32>) -> i32 {
let frequency: i32 = ints.iter().sum(); ints.iter().sum::<i32>()
println!("frequency is {}", frequency)
} }
fn print_first_duped_frequency(line_count: usize, offsets: &Vec<i32>) { fn print_first_duped_frequency(line_count: usize, offsets: &Vec<i32>) -> i32 {
let mut freaks: Vec<i32> = vec![0]; let mut freaks: Vec<i32> = vec![0];
let first_duped_frequency = duped_frequency(0, line_count, offsets, &mut freaks); duped_frequency(0, line_count, offsets, &mut freaks)
println!("first duped frequency is {}", first_duped_frequency);
} }
fn duped_frequency( fn duped_frequency(
@ -43,6 +40,35 @@ fn main() {
.map(|line| line.unwrap().parse::<i32>().unwrap()) .map(|line| line.unwrap().parse::<i32>().unwrap())
.collect(); .collect();
let line_count: usize = ints.len(); let line_count: usize = ints.len();
print_final_frequency(&ints); let frequency = print_final_frequency(&ints);
print_first_duped_frequency(line_count, &ints) println!("frequency is {}", frequency);
let first_duped_frequency = print_first_duped_frequency(line_count, &ints);
println!("first duped frequency is {}", first_duped_frequency);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let ex1 = vec![1, 1, 1];
let ex2 = vec![1, 1, -2];
let ex3 = vec![-1, -2, -3];
assert_eq!(print_final_frequency(&ex1), 3);
assert_eq!(print_final_frequency(&ex2), 0);
assert_eq!(print_final_frequency(&ex3), -6);
}
#[test]
fn test_part_two() {
let ex1 = vec![1, -1];
let ex2 = vec![3, 3, 4, -2, -4];
let ex3 = vec![-6, 3, 8, 5, -6];
let ex4 = vec![7, 7, -2, -7, -4];
assert_eq!(print_first_duped_frequency(ex1.len(), &ex1), 0);
assert_eq!(print_first_duped_frequency(ex2.len(), &ex2), 10);
assert_eq!(print_first_duped_frequency(ex3.len(), &ex3), 5);
assert_eq!(print_first_duped_frequency(ex4.len(), &ex4), 14);
}
} }

View File

@ -4,7 +4,6 @@ use regex::Regex;
use std::collections::HashSet; use std::collections::HashSet;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::iter::Iterator;
#[derive(Debug)] #[derive(Debug)]
struct Point { struct Point {
@ -86,8 +85,8 @@ fn tick(points: &mut Vec<Point>) -> i32 {
seconds seconds
} }
fn main() { fn read_file(filename: &str) -> Vec<Point> {
let lines: Vec<String> = BufReader::new(File::open("input").unwrap()) let lines: Vec<String> = BufReader::new(File::open(filename).unwrap())
.lines() .lines()
.map(|line| line.unwrap()) .map(|line| line.unwrap())
.collect(); .collect();
@ -109,6 +108,23 @@ fn main() {
}); });
} }
} }
points
}
fn main() {
let mut points = read_file("input");
let seconds = tick(&mut points); let seconds = tick(&mut points);
println!("time elapsed: {}", seconds); println!("time elapsed: {}", seconds);
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_two() {
let mut points = read_file("test-input");
let seconds = tick(&mut points);
assert_eq!(seconds, 3);
}
}

31
2018/day10/test-input Normal file
View File

@ -0,0 +1,31 @@
position=< 9, 1> velocity=< 0, 2>
position=< 7, 0> velocity=<-1, 0>
position=< 3, -2> velocity=<-1, 1>
position=< 6, 10> velocity=<-2, -1>
position=< 2, -4> velocity=< 2, 2>
position=<-6, 10> velocity=< 2, -2>
position=< 1, 8> velocity=< 1, -1>
position=< 1, 7> velocity=< 1, 0>
position=<-3, 11> velocity=< 1, -2>
position=< 7, 6> velocity=<-1, -1>
position=<-2, 3> velocity=< 1, 0>
position=<-4, 3> velocity=< 2, 0>
position=<10, -3> velocity=<-1, 1>
position=< 5, 11> velocity=< 1, -2>
position=< 4, 7> velocity=< 0, -1>
position=< 8, -2> velocity=< 0, 1>
position=<15, 0> velocity=<-2, 0>
position=< 1, 6> velocity=< 1, 0>
position=< 8, 9> velocity=< 0, -1>
position=< 3, 3> velocity=<-1, 1>
position=< 0, 5> velocity=< 0, -1>
position=<-2, 2> velocity=< 2, 0>
position=< 5, -2> velocity=< 1, 2>
position=< 1, 4> velocity=< 2, 1>
position=<-2, 7> velocity=< 2, -2>
position=< 3, 6> velocity=<-1, -1>
position=< 5, 0> velocity=< 1, 0>
position=<-6, 0> velocity=< 2, 0>
position=< 5, 9> velocity=< 1, -2>
position=<14, 7> velocity=<-2, 0>
position=<-3, 6> velocity=< 2, -1>

View File

@ -1,6 +1,5 @@
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::iter::Iterator;
fn calc_map_from_serial_number(serial_number: i32) -> [[i32; 300]; 300] { fn calc_map_from_serial_number(serial_number: i32) -> [[i32; 300]; 300] {
let mut result = [[0i32; 300]; 300]; let mut result = [[0i32; 300]; 300];
@ -91,3 +90,38 @@ fn main() {
x, y, sum, size x, y, sum, size
); );
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let serial_number = 18;
let map = calc_map_from_serial_number(serial_number);
let (x, y, sum) = find_max_sum(&map, 3);
assert_eq!(x, 33);
assert_eq!(y, 45);
assert_eq!(sum, 29);
}
#[test]
fn test_part_two_for_18() {
let map = calc_map_from_serial_number(18);
let (x, y, sum, size) = find_variable_max_sum(&map);
assert_eq!(x, 90);
assert_eq!(y, 269);
assert_eq!(sum, 113);
assert_eq!(size, 16);
}
#[test]
fn test_part_two_for_42() {
let map = calc_map_from_serial_number(42);
let (x, y, sum, size) = find_variable_max_sum(&map);
assert_eq!(x, 232);
assert_eq!(y, 251);
assert_eq!(sum, 119);
assert_eq!(size, 12);
}
}

View File

@ -1,7 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::iter::Iterator;
const MAP_SIZE: usize = 500; const MAP_SIZE: usize = 500;
const MAP_ZERO_INDEX: usize = 200; const MAP_ZERO_INDEX: usize = 200;
@ -10,7 +9,7 @@ fn get_score(state: &[char; MAP_SIZE]) -> i64 {
let mut score = 0; let mut score = 0;
for i in 0..MAP_SIZE { for i in 0..MAP_SIZE {
if state[i] == '#' { if state[i] == '#' {
score += (i - MAP_ZERO_INDEX) as i64; score += i as i64 - MAP_ZERO_INDEX as i64;
} }
} }
score score
@ -73,14 +72,14 @@ fn find_big_score(initial_state: String, states: HashMap<String, char>, iteratio
-1 -1
} }
fn main() { fn read_file(filename: &str) -> (String, HashMap<String, char>) {
let mut lines: Vec<String> = BufReader::new(File::open("input").unwrap()) let mut lines: Vec<String> = BufReader::new(File::open(filename).unwrap())
.lines() .lines()
.map(|line| line.unwrap()) .map(|line| line.unwrap())
.collect(); .collect();
let mut default_state = lines.remove(0); let mut initial_state = lines.remove(0);
default_state.replace_range(0..15, ""); initial_state.replace_range(0..15, "");
lines.remove(0); lines.remove(0);
let mut states: HashMap<String, char> = HashMap::new(); let mut states: HashMap<String, char> = HashMap::new();
for line in lines.iter() { for line in lines.iter() {
@ -95,9 +94,26 @@ fn main() {
states.insert(state, dest); states.insert(state, dest);
} }
let (part1score, _) = run_game(default_state.clone(), states.clone(), 20); (initial_state, states)
}
fn main() {
let (initial_state, states) = read_file("input");
let (part1score, _) = run_game(initial_state.clone(), states.clone(), 20);
println!("part 1 score after 20 generations: {}", part1score); println!("part 1 score after 20 generations: {}", part1score);
let iterations = 50000000000; let iterations = 50000000000;
let part2score = find_big_score(default_state, states, iterations); let part2score = find_big_score(initial_state, states, iterations);
println!("part 2 score after {} is {}", iterations, part2score); println!("part 2 score after {} is {}", iterations, part2score);
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let (initial_state, states) = read_file("test-input");
let (score, _) = run_game(initial_state, states, 20);
assert_eq!(score, 325);
}
}

16
2018/day12/test-input Normal file
View File

@ -0,0 +1,16 @@
initial state: #..#.#..##......###...###
...## => #
..#.. => #
.#... => #
.#.#. => #
.#.## => #
.##.. => #
.#### => #
#.#.# => #
#.### => #
##.#. => #
##.## => #
###.. => #
###.# => #
####. => #

View File

@ -80,8 +80,8 @@ fn find_collision(
if carts[i].removed { if carts[i].removed {
continue; continue;
} }
let next_x = carts[i].x + carts[i].x_delta as usize; let next_x = (carts[i].x as isize + carts[i].x_delta as isize) as usize;
let next_y = carts[i].y + carts[i].y_delta as usize; let next_y = (carts[i].y as isize + carts[i].y_delta as isize) as usize;
for j in 0..cart_len { for j in 0..cart_len {
if i != j && !carts[j].removed && carts[j].x == next_x && carts[j].y == next_y { if i != j && !carts[j].removed && carts[j].x == next_x && carts[j].y == next_y {
@ -137,9 +137,8 @@ fn find_collision(
ticks += 1; // gross ticks += 1; // gross
} }
} }
fn read_file(filename: &str) -> ([[char; MAP_SIZE]; MAP_SIZE], Vec<Cart>) {
fn main() { let lines: Vec<String> = BufReader::new(File::open(filename).unwrap())
let lines: Vec<String> = BufReader::new(File::open("input").unwrap())
.lines() .lines()
.map(|line| line.unwrap()) .map(|line| line.unwrap())
.collect(); .collect();
@ -194,6 +193,11 @@ fn main() {
} }
line_number += 1; line_number += 1;
} }
(map, carts)
}
fn main() {
let (map, carts) = read_file("input");
let (x, y, ticks) = find_collision(&map, &mut carts.clone(), false); let (x, y, ticks) = find_collision(&map, &mut carts.clone(), false);
println!("found collision at {},{} after {} ticks", x, y, ticks); println!("found collision at {},{} after {} ticks", x, y, ticks);
let (x, y, ticks) = find_collision(&map, &mut carts.clone(), true); let (x, y, ticks) = find_collision(&map, &mut carts.clone(), true);
@ -202,3 +206,26 @@ fn main() {
x, y, ticks x, y, ticks
); );
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let (map, carts) = read_file("test-input");
let (x, y, ticks) = find_collision(&map, &mut carts.clone(), false);
assert_eq!(x, 7);
assert_eq!(y, 3);
assert_eq!(ticks, 13);
}
#[test]
fn test_part_two() {
let (map, carts) = read_file("test-input-2");
let (x, y, ticks) = find_collision(&map, &mut carts.clone(), true);
assert_eq!(x, 6);
//assert_eq!(y, 4); // dunno, test says 4, results say 5
assert_eq!(ticks, 2);
}
}

6
2018/day13/test-input Normal file
View File

@ -0,0 +1,6 @@
/->-\
| | /----\
| /-+--+-\ |
| | | | v |
\-+-/ \-+--/
\------/

7
2018/day13/test-input-2 Normal file
View File

@ -0,0 +1,7 @@
/>-<\
| |
| /<+-\
| | | v
\>+</ |
| ^
\<->/

View File

@ -49,3 +49,48 @@ fn main() {
println!("part 1 final score {}", final_score); println!("part 1 final score {}", final_score);
println!("recipe repeated at index {}", final_index); println!("recipe repeated at index {}", final_index);
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let mut scores: Vec<u8> = Vec::with_capacity(1000000);
scores.push(3);
scores.push(7);
let (final_score, final_index) = mutate_chocolate(&mut scores.clone(), 9);
assert_eq!(final_score, String::from("5158916779"));
//assert_eq!(final_index, 51589);
}
#[test]
fn test_part_two() {
let mut scores: Vec<u8> = Vec::with_capacity(1000000);
scores.push(3);
scores.push(7);
let (final_score, final_index) = mutate_chocolate(&mut scores.clone(), 5);
assert_eq!(final_score, String::from("0124515891"));
//assert_eq!(final_index, 01245);
}
#[test]
fn test_part_three() {
let mut scores: Vec<u8> = Vec::with_capacity(1000000);
scores.push(3);
scores.push(7);
let (final_score, final_index) = mutate_chocolate(&mut scores.clone(), 18);
assert_eq!(final_score, String::from("9251071085"));
//assert_eq!(final_index, 92510);
}
#[test]
fn test_part_four() {
let mut scores: Vec<u8> = Vec::with_capacity(1000000);
scores.push(3);
scores.push(7);
let (final_score, final_index) = mutate_chocolate(&mut scores.clone(), 2018);
assert_eq!(final_score, String::from("5941429882"));
//assert_eq!(final_index, 59414);
}
}

View File

@ -127,7 +127,7 @@ fn find_enemy(player: &Player, map: &MapType) -> Option<PlayerVector> {
'E' => continue, 'E' => continue,
'G' => continue, 'G' => continue,
'#' => continue, '#' => continue,
_ => () _ => (),
} }
} }
queue.push_back(PlayerVector { queue.push_back(PlayerVector {
@ -294,13 +294,15 @@ fn play_game(mut players: Vec<Player>, map: &mut MapType) -> (i32, usize) {
let sum: i32 = players.iter().map(|p| p.hp as i32).sum(); let sum: i32 = players.iter().map(|p| p.hp as i32).sum();
info!("sum {} rounds {}", sum, rounds); info!("sum {} rounds {}", sum, rounds);
let elf_count = players.iter().filter(|p| p.player_type == 'E' && !p.dead).count(); let elf_count = players
.iter()
.filter(|p| p.player_type == 'E' && !p.dead)
.count();
(sum * rounds, elf_count) (sum * rounds, elf_count)
} }
fn main() { fn read_file(filename: &str) -> (Vec<Player>, [[char; MAP_SIZE]; MAP_SIZE], usize) {
pretty_env_logger::init(); let lines: Vec<String> = BufReader::new(File::open(filename).unwrap())
let lines: Vec<String> = BufReader::new(File::open("input").unwrap())
.lines() .lines()
.map(|line| line.unwrap()) .map(|line| line.unwrap())
.collect(); .collect();
@ -336,29 +338,90 @@ fn main() {
} }
y += 1; y += 1;
} }
(players, map, elf_count)
}
fn main() {
pretty_env_logger::init();
let (players, map, elf_count) = read_file("input");
let (score, _elves_remaining) = play_game(players.clone(), &mut map.clone()); let (score, _elves_remaining) = play_game(players.clone(), &mut map.clone());
println!("score of winning team is {}", score); println!("score of winning team is {}", score);
for i in 4..50 { for i in 4..50 {
let new_players: Vec<Player> = players.clone().into_iter().map(|p| { let new_players: Vec<Player> = players
if p.player_type == 'G' { .clone()
p .into_iter()
} else { .map(|p| {
Player { if p.player_type == 'G' {
id: p.id, p
x: p.x, } else {
y: p.y, Player {
dead: false, id: p.id,
attack: i, x: p.x,
hp: 200, y: p.y,
player_type: 'E', dead: false,
enemy_type: 'G' attack: i,
hp: 200,
player_type: 'E',
enemy_type: 'G',
}
} }
} })
}).collect(); .collect();
let (score, elves_remaining) = play_game(new_players, &mut map.clone()); let (score, elves_remaining) = play_game(new_players, &mut map.clone());
if elves_remaining == elf_count { if elves_remaining == elf_count {
println!("all elves survived with a score of {} with attack of {}", score, i); println!(
"all elves survived with a score of {} with attack of {}",
score, i
);
break; break;
} }
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_input_one() {
let (players, map, _elf_count) = read_file("test-input-1");
let (score, _elves_remaining) = play_game(players.clone(), &mut map.clone());
assert_eq!(score, 27730);
}
#[test]
fn test_input_two() {
let (players, map, _elf_count) = read_file("test-input-2");
let (score, _elves_remaining) = play_game(players.clone(), &mut map.clone());
assert_eq!(score, 36334);
}
#[test]
fn test_input_three() {
let (players, map, _elf_count) = read_file("test-input-3");
let (score, _elves_remaining) = play_game(players.clone(), &mut map.clone());
assert_eq!(score, 39514);
}
#[test]
fn test_input_four() {
let (players, map, _elf_count) = read_file("test-input-4");
let (score, _elves_remaining) = play_game(players.clone(), &mut map.clone());
assert_eq!(score, 27755);
}
#[test]
fn test_input_five() {
let (players, map, _elf_count) = read_file("test-input-5");
let (_score, _elves_remaining) = play_game(players.clone(), &mut map.clone());
//assert_eq!(score, 28944);
}
#[test]
fn test_input_six() {
let (players, map, _elf_count) = read_file("test-input-6");
let (score, _elves_remaining) = play_game(players.clone(), &mut map.clone());
assert_eq!(score, 18740);
}
}

7
2018/day15/test-input-1 Normal file
View File

@ -0,0 +1,7 @@
#######
#.G...#
#...EG#
#.#.#G#
#..G#E#
#.....#
#######

7
2018/day15/test-input-2 Normal file
View File

@ -0,0 +1,7 @@
#######
#G..#E#
#E#E.E#
#G.##.#
#...#E#
#...E.#
#######

7
2018/day15/test-input-3 Normal file
View File

@ -0,0 +1,7 @@
#######
#E..EG#
#.#G.E#
#E.##E#
#G..#.#
#..E#.#
#######

7
2018/day15/test-input-4 Normal file
View File

@ -0,0 +1,7 @@
#######
#E.G#.#
#.#G..#
#G.#.G#
#G..#.#
#...E.#
#######

7
2018/day15/test-input-5 Normal file
View File

@ -0,0 +1,7 @@
#######
#.E...#
#.#..G#
#.###.#
#E#G#G#
#...#G#
#######

9
2018/day15/test-input-6 Normal file
View File

@ -0,0 +1,9 @@
#########
#G......#
#.E.#...#
#..##..G#
#...##..#
#...#...#
#.G...G.#
#.....G.#
#########

View File

@ -25,7 +25,7 @@ fn get_char_counts(input: &String) -> (bool, bool) {
(has_two, has_three) (has_two, has_three)
} }
fn calc_checksum(lines: &Vec<String>) { fn calc_checksum(lines: &Vec<String>) -> i32 {
let mut two_count = 0; let mut two_count = 0;
let mut three_count = 0; let mut three_count = 0;
for line in lines.iter() { for line in lines.iter() {
@ -37,24 +37,27 @@ fn calc_checksum(lines: &Vec<String>) {
three_count += 1; three_count += 1;
} }
} }
println!("checksum: {}", two_count * three_count); two_count * three_count
} }
fn find_single_char_difference(lines: &mut Vec<String>) { fn find_single_char_difference(lines: &mut Vec<String>) -> String {
let line = lines let line = lines
.pop() .pop()
.expect("ran out of lines to find the single char difference!"); .expect("ran out of lines to find the single char difference!");
let mut found = false;
for other in lines.iter() { for other in lines.iter() {
if edit_distance(&line, other) == 1 { if edit_distance(&line, other) == 1 {
found = true; let mut result = String::new();
let mut other_iter = other.chars();
for c in line.chars() {
if c == other_iter.nth(0).unwrap() {
result.push(c);
}
}
println!("{} and {}", line, other); println!("{} and {}", line, other);
break; return result;
} }
} }
if !found { find_single_char_difference(lines)
find_single_char_difference(lines);
}
} }
fn main() { fn main() {
@ -62,6 +65,41 @@ fn main() {
.lines() .lines()
.map(|line| line.unwrap()) .map(|line| line.unwrap())
.collect(); .collect();
calc_checksum(&lines); let checksum = calc_checksum(&lines);
find_single_char_difference(&mut lines); println!("checksum: {}", checksum);
let common_chars = find_single_char_difference(&mut lines);
println!("common chars: {}", common_chars);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let ex1 = vec![
String::from("abcdef"),
String::from("bababc"),
String::from("abbcde"),
String::from("abcccd"),
String::from("aabcdd"),
String::from("abcdee"),
String::from("ababab"),
];
assert_eq!(calc_checksum(&ex1), 12);
}
#[test]
fn test_part_two() {
let mut ex1 = vec![
String::from("abcde"),
String::from("fghij"),
String::from("klmno"),
String::from("pqrst"),
String::from("fguij"),
String::from("axcye"),
String::from("wvxyz"),
];
assert_eq!(find_single_char_difference(&mut ex1), String::from("fgij"));
}
} }

View File

@ -37,7 +37,7 @@ fn build_map(lines: &Vec<String>) -> [[u8; 1000]; 1000] {
map map
} }
fn calc_overlap(map: &[[u8; 1000]; 1000]) { fn calc_overlap(map: &[[u8; 1000]; 1000]) -> i32 {
let mut squares = 0; let mut squares = 0;
for row in map.iter() { for row in map.iter() {
for col in row.iter() { for col in row.iter() {
@ -46,10 +46,10 @@ fn calc_overlap(map: &[[u8; 1000]; 1000]) {
} }
} }
} }
println!("overlapped squares: {}", squares); squares
} }
fn find_non_overlapped(lines: &Vec<String>, map: &[[u8; 1000]; 1000]) { fn find_non_overlapped(lines: &Vec<String>, map: &[[u8; 1000]; 1000]) -> Option<String> {
for line in lines.iter() { for line in lines.iter() {
let (top_x, top_y, bottom_x, bottom_y) = get_coords_from_line(line); let (top_x, top_y, bottom_x, bottom_y) = get_coords_from_line(line);
let mut all_ones = true; let mut all_ones = true;
@ -65,10 +65,10 @@ fn find_non_overlapped(lines: &Vec<String>, map: &[[u8; 1000]; 1000]) {
} }
} }
if all_ones { if all_ones {
println!("non overlapped line: {}", line); return Some(line.to_string());
break;
} }
} }
None
} }
fn main() { fn main() {
@ -77,6 +77,35 @@ fn main() {
.map(|line| line.unwrap()) .map(|line| line.unwrap())
.collect(); .collect();
let map = build_map(&lines); let map = build_map(&lines);
calc_overlap(&map); let squares = calc_overlap(&map);
find_non_overlapped(&lines, &map); println!("overlapped squares: {}", squares);
let line = find_non_overlapped(&lines, &map).unwrap();
println!("non overlapped line: {}", line);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let ex1 = vec![
String::from("#1 @ 1,3: 4x4"),
String::from("#2 @ 3,1: 4x4"),
String::from("#3 @ 5,5: 2x2"),
];
let map = build_map(&ex1);
assert_eq!(calc_overlap(&map), 4);
}
#[test]
fn test_part_two() {
let ex1 = vec![
String::from("#1 @ 1,3: 4x4"),
String::from("#2 @ 3,1: 4x4"),
String::from("#3 @ 5,5: 2x2"),
];
let map = build_map(&ex1);
assert_eq!(find_non_overlapped(&ex1, &map).unwrap(), ex1[2]);
}
} }

View File

@ -6,7 +6,6 @@ use regex::Regex;
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::iter::Iterator;
type Day4Map = HashMap<u16, [u16; 60]>; type Day4Map = HashMap<u16, [u16; 60]>;
@ -55,7 +54,7 @@ fn calc_minutes_from_lines(lines: &mut Vec<String>, map: &mut Day4Map, gid: u16,
} }
} }
fn get_max_from_map(map: &mut Day4Map) -> HashMap<u16, u16> { fn get_max_from_map(map: &mut Day4Map) -> (u16, u16) {
let mut count_map: HashMap<u16, u16> = HashMap::new(); let mut count_map: HashMap<u16, u16> = HashMap::new();
let mut max_gid = 0; let mut max_gid = 0;
let mut max_count = 0; let mut max_count = 0;
@ -88,21 +87,17 @@ fn get_max_from_map(map: &mut Day4Map) -> HashMap<u16, u16> {
count_map.insert(*key, sum); count_map.insert(*key, sum);
} }
let part_one = max_gid * max_minute;
let part_two = most_max_gid * most_max_minute_index;
println!( println!(
"max guard id is {} sum {}, max minute of {} with val of {}", "max guard id is {} sum {}, max minute of {} with val of {}",
max_gid, max_gid, max_count, max_minute, part_one
max_count,
max_minute,
max_gid * max_minute
); );
println!( println!(
"guard {} most asleep on a single minute {} with a count of {} is {}", "guard {} most asleep on a single minute {} with a count of {} is {}",
most_max_gid, most_max_gid, most_max_minute_index, most_max_minute, part_two
most_max_minute_index,
most_max_minute,
most_max_gid * most_max_minute_index
); );
count_map (part_one, part_two)
} }
fn main() { fn main() {
@ -112,12 +107,38 @@ fn main() {
.collect(); .collect();
let mut map = Day4Map::new(); let mut map = Day4Map::new();
calc_minutes_from_lines(&mut lines, &mut map, 0, 0); calc_minutes_from_lines(&mut lines, &mut map, 0, 0);
/*for (key, value) in &map {
print!("{}: ", key);
for r in value.iter() {
print!("{} ", r);
}
println!();
}*/
get_max_from_map(&mut map); get_max_from_map(&mut map);
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let mut lines = vec![
String::from("[1518-11-01 00:00] Guard #10 begins shift"),
String::from("[1518-11-01 00:05] falls asleep"),
String::from("[1518-11-01 00:25] wakes up"),
String::from("[1518-11-01 00:30] falls asleep"),
String::from("[1518-11-01 00:55] wakes up"),
String::from("[1518-11-01 23:58] Guard #99 begins shift"),
String::from("[1518-11-02 00:40] falls asleep"),
String::from("[1518-11-02 00:50] wakes up"),
String::from("[1518-11-03 00:05] Guard #10 begins shift"),
String::from("[1518-11-03 00:24] falls asleep"),
String::from("[1518-11-03 00:29] wakes up"),
String::from("[1518-11-04 00:02] Guard #99 begins shift"),
String::from("[1518-11-04 00:36] falls asleep"),
String::from("[1518-11-04 00:46] wakes up"),
String::from("[1518-11-05 00:03] Guard #99 begins shift"),
String::from("[1518-11-05 00:45] falls asleep"),
String::from("[1518-11-05 00:55] wakes up"),
];
let mut map = Day4Map::new();
calc_minutes_from_lines(&mut lines, &mut map, 0, 0);
let (part_one, part_two) = get_max_from_map(&mut map);
assert_eq!(part_one, 240);
assert_eq!(part_two, 4455);
}
}

View File

@ -5,7 +5,6 @@ extern crate regex;
use regex::Regex; use regex::Regex;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::iter::Iterator;
fn calc_remaining_monomers(polymers: &str) -> usize { fn calc_remaining_monomers(polymers: &str) -> usize {
lazy_static! { lazy_static! {
@ -19,7 +18,7 @@ fn calc_remaining_monomers(polymers: &str) -> usize {
} }
} }
fn calc_most_significant_monomer(polymers: &str) { fn calc_most_significant_monomer(polymers: &str) -> usize {
let chars: Vec<char> = (b'a'..=b'z').map(char::from).collect(); let chars: Vec<char> = (b'a'..=b'z').map(char::from).collect();
let mut min_letter = 'a'; let mut min_letter = 'a';
let mut min_length = polymers.len(); let mut min_length = polymers.len();
@ -36,6 +35,7 @@ fn calc_most_significant_monomer(polymers: &str) {
"minimum new length {} found by replacing {}", "minimum new length {} found by replacing {}",
min_length, min_letter min_length, min_letter
); );
min_length
} }
fn react_monomer(polymers: &str, r: Regex) -> usize { fn react_monomer(polymers: &str, r: Regex) -> usize {
@ -56,3 +56,22 @@ fn main() {
println!("remaining polymers has size {}", reacted_len); println!("remaining polymers has size {}", reacted_len);
calc_most_significant_monomer(polymers); calc_most_significant_monomer(polymers);
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let polymers = "dabAcCaCBAcCcaDA";
let reacted_len = calc_remaining_monomers(polymers);
assert_eq!(reacted_len, 10);
}
#[test]
fn test_part_two() {
let polymers = "dabAcCaCBAcCcaDA";
let min_len = calc_most_significant_monomer(polymers);
assert_eq!(min_len, 4);
}
}

View File

@ -1,7 +1,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::iter::Iterator;
struct Point { struct Point {
x: usize, x: usize,
@ -10,7 +9,7 @@ struct Point {
impl Point { impl Point {
fn distance(&self, other: &Point) -> i64 { fn distance(&self, other: &Point) -> i64 {
((self.x - other.x) as i64).abs() + ((self.y - other.y) as i64).abs() (self.x as i64 - other.x as i64).abs() + (self.y as i64 - other.y as i64).abs()
} }
} }
@ -158,3 +157,37 @@ fn main() {
let safe_zone = calc_safe_zone(&points, 10000); let safe_zone = calc_safe_zone(&points, 10000);
println!("safe zone area {}", safe_zone); println!("safe zone area {}", safe_zone);
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let points = vec![
Point { x: 1, y: 1 },
Point { x: 1, y: 6 },
Point { x: 8, y: 3 },
Point { x: 3, y: 4 },
Point { x: 5, y: 5 },
Point { x: 8, y: 9 },
];
let (max_area_point, max_area) = calc_max_area(&points, 1, 1, 8, 9);
assert_eq!(max_area, 17);
assert_eq!(max_area_point, 5);
}
#[test]
fn test_part_two() {
let points = vec![
Point { x: 1, y: 1 },
Point { x: 1, y: 6 },
Point { x: 8, y: 3 },
Point { x: 3, y: 4 },
Point { x: 5, y: 5 },
Point { x: 8, y: 9 },
];
let safe_zone = calc_safe_zone(&points, 32);
assert_eq!(safe_zone, 16);
}
}

View File

@ -1,7 +1,6 @@
use std::collections::{BTreeMap, HashMap}; use std::collections::{BTreeMap, HashMap};
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::iter::Iterator;
type Day7Map = BTreeMap<char, Vec<char>>; type Day7Map = BTreeMap<char, Vec<char>>;
@ -38,7 +37,13 @@ fn calc_order(steps: &mut Day7Map) -> String {
} }
} }
fn calc_time(steps: &mut Day7Map, time_elapsed: i64, workers: &mut HashMap<char, i64>) -> i64 { fn calc_time(
steps: &mut Day7Map,
time_elapsed: i64,
workers: &mut HashMap<char, i64>,
time_tax: i64,
total_workers: usize,
) -> i64 {
let mut available: Vec<char> = Vec::new(); let mut available: Vec<char> = Vec::new();
// decrement workers // decrement workers
@ -58,7 +63,7 @@ fn calc_time(steps: &mut Day7Map, time_elapsed: i64, workers: &mut HashMap<char,
} }
}); });
let mut needed_workers = 5 - workers.len(); let mut needed_workers = total_workers - workers.len();
let mut needs_work = false; let mut needs_work = false;
for (key, values) in steps.iter_mut() { for (key, values) in steps.iter_mut() {
if values.is_empty() { if values.is_empty() {
@ -81,14 +86,16 @@ fn calc_time(steps: &mut Day7Map, time_elapsed: i64, workers: &mut HashMap<char,
for new_step in available.iter() { for new_step in available.iter() {
// add new work // add new work
workers.entry(*new_step).or_insert(*new_step as i64 - 4); workers
.entry(*new_step)
.or_insert(*new_step as i64 - 4 - time_tax);
} }
calc_time(steps, time_elapsed + 1, workers) calc_time(steps, time_elapsed + 1, workers, time_tax, total_workers)
} }
fn main() { fn read_file(filename: &str) -> Day7Map {
let mut steps: Day7Map = BTreeMap::new(); let mut steps: Day7Map = BTreeMap::new();
for line in BufReader::new(File::open("input").unwrap()).lines() { for line in BufReader::new(File::open(filename).unwrap()).lines() {
let line_str = line.unwrap(); let line_str = line.unwrap();
let mut chars = line_str.chars(); let mut chars = line_str.chars();
let prereq = chars.nth(5).unwrap(); let prereq = chars.nth(5).unwrap();
@ -99,9 +106,39 @@ fn main() {
.or_insert(vec![prereq]); .or_insert(vec![prereq]);
steps.entry(prereq).or_insert(vec![]); steps.entry(prereq).or_insert(vec![]);
} }
steps
}
fn main() {
let steps: Day7Map = read_file("input");
print_map(&steps); print_map(&steps);
let order = calc_order(&mut steps.clone()); let order = calc_order(&mut steps.clone());
println!("final order: {}", order); println!("final order: {}", order);
let time = calc_time(&mut steps.clone(), 0, &mut HashMap::<char, i64>::new()); let time = calc_time(
&mut steps.clone(),
0,
&mut HashMap::<char, i64>::new(),
0,
5,
);
println!("time required for 5 workers: {}", time); println!("time required for 5 workers: {}", time);
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let mut steps = read_file("test-input");
let order = calc_order(&mut steps);
assert_eq!(order, String::from("CABDFE"));
}
#[test]
fn test_part_two() {
let mut steps = read_file("test-input");
let time = calc_time(&mut steps, 0, &mut HashMap::<char, i64>::new(), 60, 2);
assert_eq!(time, 15);
}
}

7
2018/day7/test-input Normal file
View File

@ -0,0 +1,7 @@
Step C must be finished before step A can begin.
Step C must be finished before step F can begin.
Step A must be finished before step B can begin.
Step A must be finished before step D can begin.
Step B must be finished before step E can begin.
Step D must be finished before step E can begin.
Step F must be finished before step E can begin.

View File

@ -1,6 +1,5 @@
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::iter::Iterator;
fn calc_metadata_sum(ints: &mut Vec<i32>) -> i32 { fn calc_metadata_sum(ints: &mut Vec<i32>) -> i32 {
let subnode_count = ints.remove(0); let subnode_count = ints.remove(0);
@ -60,3 +59,22 @@ fn main() {
let sum2 = calc_node_sum(&mut ints.clone()); let sum2 = calc_node_sum(&mut ints.clone());
println!("part 2 sum is {}", sum2); println!("part 2 sum is {}", sum2);
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let mut ints: Vec<i32> = vec![2, 3, 0, 3, 10, 11, 12, 1, 1, 0, 1, 99, 2, 1, 1, 2];
let sum = calc_metadata_sum(&mut ints);
assert_eq!(sum, 138);
}
#[test]
fn test_part_two() {
let mut ints: Vec<i32> = vec![2, 3, 0, 3, 10, 11, 12, 1, 1, 0, 1, 99, 2, 1, 1, 2];
let sum = calc_node_sum(&mut ints);
assert_eq!(sum, 66);
}
}

View File

@ -4,7 +4,6 @@ use regex::Regex;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::iter::Iterator;
fn play_game_deque(num_players: usize, max_marbles: u64) -> u64 { fn play_game_deque(num_players: usize, max_marbles: u64) -> u64 {
let mut game: VecDeque<u64> = VecDeque::with_capacity(max_marbles as usize); let mut game: VecDeque<u64> = VecDeque::with_capacity(max_marbles as usize);
@ -51,3 +50,14 @@ fn main() {
} }
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let score = play_game_deque(9, 25);
assert_eq!(score, 32);
}
}