days 7-10

master
george 2 years ago
parent 474ad0a248
commit db450943a0

16
day07/Cargo.lock generated

@ -0,0 +1,16 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day07"
version = "0.1.0"
dependencies = [
"rustc-hash",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"

@ -0,0 +1,9 @@
[package]
name = "day07"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rustc-hash = "1.1.0"

@ -0,0 +1,134 @@
use rustc_hash::FxHashMap;
use std::path::Path;
const TOTAL_SPACE: usize = 70_000_000;
const REQUIRED_SPACE: usize = 30_000_000;
fn main() {
let s = std::fs::read_to_string("/dev/stdin").unwrap();
let mut commands = s.split("$ ");
commands.next(); // chuck out first empty string
let mut pwd: Option<String> = None;
let mut file_tree: FxHashMap<String, Vec<(String, Option<usize>)>> = FxHashMap::default();
let mut dir_totals: FxHashMap<String, usize> = FxHashMap::default();
for command in commands {
let lines = command.lines().collect::<Vec<&str>>();
let cmd = lines.first().unwrap();
let args = cmd.split(' ').collect::<Vec<&str>>();
let cmd = args.first().unwrap();
let args = args.get(1..).unwrap();
match *cmd {
"cd" => cd(&mut pwd, args),
"ls" => ls(
&pwd,
lines.get(1..).unwrap(),
&mut file_tree,
&mut dir_totals,
),
invalid => panic!("unexpected command: {:?}", invalid),
}
}
for directory in file_tree.iter() {
let mut total = 0;
let dir_str = Path::new(&directory.0);
if dir_str.file_name().is_some()
&& dir_totals.contains_key(&dir_str.to_str().unwrap().to_string())
{
continue;
}
for item in directory.1.iter() {
if let Some(file_size) = item.1 {
total += file_size;
}
}
dir_totals.insert(directory.0.to_string(), total);
}
let mut dirs = file_tree.iter().collect::<Vec<_>>();
dirs.sort_by(|a, b| {
b.0.split('/')
.count()
.cmp(&a.0.split('/').count())
.then(b.0.len().cmp(&a.0.len()))
});
for dir in dirs.iter() {
for sub_dir in dir.1.iter().filter(|dir| dir.1.is_none()) {
let balls = (dir.0.to_owned() + &sub_dir.0.replace("dir ", "/")).replace("//", "/");
dir_totals.insert(
dir.0.to_owned(),
*dir_totals.get(&dir.0.to_owned()).unwrap() + *dir_totals.get(&balls).unwrap(),
);
}
}
let sum = dir_totals
.iter()
.filter(|dir| dir.1 < &100000)
.fold(0, |total, dir| total + dir.1);
let free_space = TOTAL_SPACE - dir_totals.get("/").unwrap();
let minimum_required = REQUIRED_SPACE - free_space;
let mut deletable: Vec<(&String, &usize)> = dir_totals
.iter()
.filter(|dir| dir.1 >= &minimum_required)
.collect();
deletable.sort_by(|a, b| a.1.cmp(b.1));
println!("P1: {} P2: {}", sum, deletable.first().unwrap().1);
}
fn cd(pwd: &mut Option<String>, args: &[&str]) {
let path_str = String::new();
let path = pwd.as_ref().unwrap_or(&path_str);
let dir = args.first().expect("cd requries an arg").to_string();
if dir == ".." {
let mut split_path = path.split('/').collect::<Vec<&str>>();
split_path.pop();
if split_path.len() == 1 {
split_path.push("");
}
*pwd = Some(split_path.join("/"));
} else if !path.is_empty() && path != "/" {
*pwd = Some(path.to_owned() + "/" + &dir);
} else {
*pwd = Some(path.to_owned() + &dir);
}
}
fn ls(
pwd: &Option<String>,
lines: &[&str],
file_tree: &mut FxHashMap<String, Vec<(String, Option<usize>)>>,
dir_totals: &mut FxHashMap<String, usize>,
) {
let mut contents: Vec<(String, Option<usize>)> = Vec::new();
let mut contains_dirs = false; // if no inner dirs, work out total here
for line in lines {
if line.starts_with("dir ") {
contents.push((line.to_string(), None));
contains_dirs = true;
continue;
}
let file_data = line.split_once(' ').unwrap();
let (file_size, file_name) = (
file_data.0.parse::<usize>().unwrap(),
file_data.1.to_string(),
);
contents.push((file_name, Some(file_size)));
}
if !contains_dirs {
let mut total = 0;
for (_, size) in contents.iter() {
total += size.unwrap();
}
dir_totals.insert(pwd.as_ref().unwrap().to_string(), total);
}
file_tree.insert(pwd.as_ref().unwrap().to_string(), contents);
}

16
day09/Cargo.lock generated

@ -0,0 +1,16 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day09"
version = "0.1.0"
dependencies = [
"rustc-hash",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"

@ -0,0 +1,9 @@
[package]
name = "day09"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rustc-hash = "1.1.0"

@ -0,0 +1,73 @@
use rustc_hash::FxHashSet;
use std::cmp::Ordering;
use std::io::{self, BufRead};
fn main() {
let lines = io::stdin().lock().lines().map(|l| l.unwrap());
let mut head = (0, 0);
let mut knots: Vec<(isize, isize)> = vec![(0, 0); 9];
let mut visited_p1: FxHashSet<(isize, isize)> = FxHashSet::default();
let mut visited_p2: FxHashSet<(isize, isize)> = FxHashSet::default();
visited_p1.insert((0, 0));
visited_p2.insert((0, 0));
for line in lines {
let (dir, len) = line.split_once(' ').unwrap();
let position = (dir, len.parse::<isize>().unwrap());
let mut current;
for _ in 0..position.1 {
step_head(&mut head, position.0);
current = head;
for i in 0..9 {
let knot = knots.get_mut(i).unwrap();
follow(i, current, knot, &mut visited_p1, &mut visited_p2);
current = *knot;
}
}
}
println!("P1: {}, P2: {}", visited_p1.len(), visited_p2.len());
}
fn step_head(head: &mut (isize, isize), dir: &str) {
match dir {
"L" => head.1 -= 1,
"R" => head.1 += 1,
"U" => head.0 -= 1,
"D" => head.0 += 1,
invalid => panic!("invalid direction '{}'", invalid),
}
}
fn follow(
idx: usize,
head: (isize, isize),
tail: &mut (isize, isize),
visited_p1: &mut FxHashSet<(isize, isize)>,
visited_p2: &mut FxHashSet<(isize, isize)>,
) {
let diffx = (tail.0 - head.0).abs();
let diffy = (tail.1 - head.1).abs();
if (diffx == 1 || diffx == 0) && (diffy == 1 || diffy == 0) {
return;
}
match tail.0.cmp(&head.0) {
Ordering::Greater => tail.0 -= 1,
Ordering::Less => tail.0 += 1,
_ => (),
}
match tail.1.cmp(&head.1) {
Ordering::Greater => tail.1 -= 1,
Ordering::Less => tail.1 += 1,
_ => (),
}
if idx == 0 {
visited_p1.insert(*tail);
}
if idx == 8 {
visited_p2.insert(*tail);
}
}

7
day10/Cargo.lock generated

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day10"
version = "0.1.0"

@ -0,0 +1,8 @@
[package]
name = "day10"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

@ -0,0 +1,83 @@
use std::collections::VecDeque;
use std::io::{self, BufRead, Write};
#[derive(Debug)]
struct Operation {
opcode: String,
arg: Option<isize>,
cycles: usize,
}
const SIGNAL_TICK_COUNT: usize = 220;
const DRAW_CRT: usize = 240;
fn main() {
let lines = io::stdin().lock().lines().map(|l| l.unwrap());
let mut program: Vec<Operation> = vec![];
let mut queue: VecDeque<&Operation> = VecDeque::new();
for line in lines {
let cmd = line.split(' ').collect::<Vec<&str>>();
let op = cmd.first().unwrap();
let mut arg: Option<isize> = None;
if let Some(num) = cmd.get(1) {
arg = Some(num.parse::<isize>().unwrap());
}
let cycles = match op {
&"noop" => 1,
&"addx" => 2,
invalid => panic!("invalid opcode {}", invalid),
};
program.push(Operation {
opcode: op.to_string(),
arg,
cycles,
});
}
// init counters, program and queue
let mut x = 1;
let mut current_op = program.first().unwrap();
let mut cycles_remaining_for_current = current_op.cycles;
let mut signal_sum = 0;
let mut screen = [[false; 40]; 6];
for (screen_idx, i) in (1..DRAW_CRT + 1).enumerate() {
if cycles_remaining_for_current == 0 {
if current_op.opcode == "addx" {
x += current_op.arg.unwrap();
}
current_op = queue.pop_front().unwrap();
cycles_remaining_for_current = current_op.cycles;
}
let cmd = program.get(i % program.len()).unwrap();
queue.push_back(cmd);
cycles_remaining_for_current -= 1;
match i {
20 | 60 | 100 | 140 | 180 | 220 => signal_sum += x * i as isize,
_ => (),
}
let (scrx, scry): (usize, usize) = (screen_idx / 40, screen_idx % 40);
screen[scrx][scry] = x == screen_idx as isize % 40
|| x - 1 == screen_idx as isize % 40
|| x + 1 == screen_idx as isize % 40;
if i == SIGNAL_TICK_COUNT {
println!("{}", signal_sum);
}
}
draw_screen(&screen);
}
fn draw_screen(screen: &[[bool; 40]; 6]) {
let mut lock = io::stdout().lock();
for y in 0..6 {
for x in 0..40 {
write!(lock, "{}", if screen[y][x] { "#" } else { "." }).unwrap()
}
writeln!(lock).unwrap();
}
}
Loading…
Cancel
Save