more successes.

This commit is contained in:
Trevor Merritt 2025-09-19 10:40:28 -04:00
parent 7c3186abcf
commit af075edb24
25 changed files with 3425 additions and 145 deletions

View File

@ -23,63 +23,60 @@ fn identify_wires(input: &str) -> Vec<String> {
working working
} }
fn parse_instruction(input: &str) -> Option<Actions> { fn parse_instruction(input: &str) -> Actions {
let parts : Vec<_> = input.split_whitespace().collect(); let parts : Vec<_> = input.split_whitespace().collect();
match parts.len() { match parts.len() {
3 => { 3 => {
Some(Actions::Connection { a: parts[0].to_string(), z: parts[2].to_string() }) Actions::Connection { a: parts[0].to_string(), z: parts[2].to_string() }
}, },
4 => { 4 => {
// NOT // NOT
match parts[0] { match parts[0] {
"NOT" => { "NOT" => {
Some(Actions::NOT { a: parts[1].to_string(), z: parts[3].to_string()} ) }, Actions::NOT { a: parts[1].to_string(), z: parts[3].to_string()} },
_ => { _ => {
println!("UNHANDLED 4 PART -> {input}"); unreachable!("UNHANDLED 4 PART -> {input}");
Some(Actions::Connection { a: "__".to_string(), z: "__".to_string() })
} }
} }
} }
5 => { 5 => {
match parts[1] { match parts[1] {
"RSHIFT" => { "RSHIFT" => {
Some(Actions::RSHIFT { Actions::RSHIFT {
a: parts[0].to_string(), a: parts[0].to_string(),
d: parts[2].parse::<u32>().unwrap(), d: parts[2].parse::<u32>().unwrap(),
z: parts[4].to_string(), z: parts[4].to_string(),
}) }
}, },
"LSHIFT" => { "LSHIFT" => {
Some(Actions::LSHIFT { Actions::LSHIFT {
a: parts[0].to_string(), a: parts[0].to_string(),
d: parts[2].parse::<u32>().unwrap(), d: parts[2].parse::<u32>().unwrap(),
z: parts[4].to_string() z: parts[4].to_string()
}) }
}, },
"AND" => { "AND" => {
Some(Actions::AND { Actions::AND {
a: parts[0].to_string(), a: parts[0].to_string(),
b: parts[2].to_string(), b: parts[2].to_string(),
z: parts[4].to_string(), z: parts[4].to_string(),
}) }
}, },
"OR" => { "OR" => {
Some(Actions::OR { Actions::OR {
a: parts[0].to_string(), a: parts[0].to_string(),
b: parts[2].to_string(), b: parts[2].to_string(),
z: parts[4].to_string(), z: parts[4].to_string(),
}) }
}, },
_ => { _ => {
println!("UNHANDLED 5 PART -> {input}"); unreachable!("UNHANDLED 5 PART -> {input}");
None
} }
} }
}, },
_ => { _ => {
println!("Unhandled {} part -> {input}", parts.len()); unreachable!("Unhandled {} part -> {input}", parts.len());
None
} }
} }
} }
@ -92,8 +89,6 @@ fn main() {
for line in lines { for line in lines {
let parsed = parse_instruction(line); let parsed = parse_instruction(line);
if parsed.is_some() { println!("PARSED [[{line}]] into [[{parsed:?}]]");
println!("PARSED [[{line}]] into [[{parsed:?}]]");
}
} }
} }

View File

@ -5,11 +5,11 @@ use core::read_data;
enum Expr { enum Expr {
Value(u16), Value(u16),
Wire(String), Wire(String),
Not(Box<Expr>),
And(Box<Expr>, Box<Expr>), And(Box<Expr>, Box<Expr>),
Or(Box<Expr>, Box<Expr>), Or(Box<Expr>, Box<Expr>),
LShift(Box<Expr>, u8), LShift(Box<Expr>, u8),
RShift(Box<Expr>, u8), RShift(Box<Expr>, u8),
Not(Box<Expr>),
} }
fn parse_expr(token: &str) -> Expr { fn parse_expr(token: &str) -> Expr {

View File

@ -1,55 +1,51 @@
use core::read_data; use std::fs;
fn parsed_string(input: &str) -> String { fn parsed_string(input: &str) -> String {
let mut output = String::new(); let mut output = String::new();
let mut chars = input.chars().peekable();
while let Some(char) = chars.next() { // Skip the surrounding quotes
match char { let mut chars = input[1..input.len() - 1].chars().peekable();
'\\' => {
match chars.next() { while let Some(ch) = chars.next() {
Some('n') => output.push('\n'), match ch {
Some('t') => output.push('\t'), '\\' => match chars.next() {
Some('\\') => output.push('\\'), Some('\\') => output.push('\\'),
Some('"') => output.push('"'), Some('"') => output.push('"'),
Some('x') => { Some('n') => output.push('\n'),
let hi = chars.next().unwrap(); Some('t') => output.push('\t'),
let lo = chars.next().unwrap(); Some('x') => {
let value = u8::from_str_radix(&format!("{hi}{lo}"), 16).unwrap(); // Must be exactly two hex digits
output.push(value as char) let hi = chars.next().expect("Incomplete \\x escape");
} let lo = chars.next().expect("Incomplete \\x escape");
Some(other) => output.push(other), let hex = format!("{hi}{lo}");
None => {} let value = u8::from_str_radix(&hex, 16)
.expect("Invalid hex escape in input");
output.push(value as char);
} }
} Some(other) => panic!("Invalid escape: \\{other}"),
'"' => {} None => panic!("Dangling backslash"),
_ => output.push(char) },
_ => output.push(ch),
} }
} }
output output
} }
use core::read_data;
fn main() { fn main() {
let mut char_count = 0; // Read your puzzle input file
let mut mem_count = 0; let input = read_data("2015_08_data.txt");
let binding = read_data("2015_08_data.txt"); let mut raw_total = 0;
let lines = binding.lines(); let mut mem_total = 0;
let binding = vec![
r#""""#,
r#""abc""#,
r#""aaa\"aaa""#,
r#"\x27"#
].join("\n");
let lines = binding.lines();
for line in lines { for line in input.lines() {
let raw_size = line.len(); let raw_len = line.len();
let parsed = parsed_string(line).len(); let mem_len = parsed_string(line).len();
println!("||{line}|| -> raw: {raw_size} parsed: {parsed}"); raw_total += raw_len;
char_count += parsed; mem_total += mem_len;
mem_count += raw_size;
} }
println!("{} - {} = {}", char_count, mem_count, 0);
println!("{}", mem_count - char_count); println!("Part 1: {} - {} = {}", raw_total, mem_total, raw_total - mem_total);
} }

View File

@ -1,3 +1,19 @@
fn next_password(input: &str) -> Vec<char> {
// increment the last character.
let mut work: Vec<_> = input.clone().chars().collect();
let wlen = input.len();
print!("[[{work:?}]] ");
if work[wlen - 1] == 'z' {
} else {
work[wlen - 1] = (work[wlen - 1] as u8 + 1) as char;
}
println!(" became {work:?}");
work
}
fn includes_straight(input: &str) -> bool { fn includes_straight(input: &str) -> bool {
true true
} }
@ -19,8 +35,10 @@ fn includes_pair(input: &str) -> bool {
false false
} }
fn find_next_password(input: &str) -> String {} fn find_next_password(input: &str) -> String {
let next_password = next_password(input).join("");
next_password
}
fn main() { fn main() {
let params = vec![ let params = vec![

View File

@ -43,37 +43,52 @@ struct Location {
fn main() { fn main() {
let mut current_position = Location { x: 1, y: 1 }; let mut current_position = Location { x: 1, y: 1 };
// let directions = read_data("2016_02_data.txt"); let directions = read_data("2016_02_data.txt");
let directions = "ULL\nRRDDD\nLURDL\nUUUUUD"; //let directions = "ULL\nRRDDD\nLURDL\nUUUUUD";
for line_of_directions in directions.lines() {
for next_direction in directions.chars() { println!("Processing directions of {line_of_directions} starting at {}x{}", current_position.x, current_position.y);
match next_direction { for current_direction in line_of_directions.chars() {
'R' => { // print!(" [{current_direction}] ");
if current_position.x < 3 { match current_direction {
current_position.x += 1; 'U' => {
if current_position.y > 0 {
current_position.y -= 1;
//println!("Moving up.")
} else {
//println!("At Edge");
}
},
'D' => {
if current_position.y < 2 {
current_position.y += 1;
//println!("Moving down.");
} else {
//println!("At Edge");
}
},
'L' => {
if current_position.x > 0 {
current_position.x -= 1;
//println!("Moving left.");
} else {
//println!("At Edge");
}
},
'R' => {
if current_position.x < 2 {
current_position.x += 1;
//println!("Moving right.");
} else {
//println!("At Edge");
}
} }
}, _ => { unreachable!("invalid direction.") }
'L' => { }
if current_position.x > 0 { // println!("Ending line at {}x{}", current_position.x, current_position.y);
current_position.x -= 1; //
}
},
'U' => {
if current_position.y < 3 {
current_position.y += 1;
}
},
'D' => {
if current_position.y > 0 {
current_position.y -= 1;
}
},
'\n' => {
println!("At {current_position:?}");
7 },
_ => { unreachable!("Invalid direction"); }
} }
println!("CELL = {}", (current_position.x + 1) + (current_position.y * 3));
} }
println!("Ending at {}x{}", current_position.x, current_position.y);
} }
// 2445 is wrong. // 84452
// 3775 is wrong.

View File

@ -9,6 +9,7 @@ struct EncryptedRoom {
fn main() { fn main() {
let binding = read_data("2016_04_data.txt"); let binding = read_data("2016_04_data.txt");
let inputs = binding.lines(); let inputs = binding.lines();
for line in inputs { for line in inputs {
@ -40,6 +41,8 @@ fn main() {
println!("HASH: {hash:?}"); println!("HASH: {hash:?}");
// now find the 5 most frequently occurring characters in alphabetical order // now find the 5 most frequently occurring characters in alphabetical order
// once we have the new value, compare it to the checksum // once we have the new value, compare it to the checksum
for (k, v) in hash {
}
} }
} }

View File

@ -1,23 +1,5 @@
// While snooping around the local network of EBHQ, you compile a list of IP addresses (they're
// IPv7, of course; IPv6 is much too limited). You'd like to figure out which IPs support TLS
// (transport-layer snooping).
//
// An IP supports TLS if it has an Autonomous Bridge Bypass Annotation, or ABBA. An ABBA is any
// four-character sequence which consists of a pair of two different characters followed by the
// reverse of that pair, such as xyyx or abba. However, the IP also must not have an ABBA within
// any hypernet sequences, which are contained by square brackets.
//
// For example:
//
// abba[mnop]qrst supports TLS (abba outside square brackets).
// abcd[bddb]xyyx does not support TLS (bddb is within square brackets, even though xyyx is outside
// square brackets).
// aaaa[qwer]tyui does not support TLS (aaaa is invalid; the interior characters must be different).
// ioxxoj[asdfgh]zxcvbn supports TLS (oxxo is outside square brackets, even though it's within a
// larger string).
// How many IPs in your puzzle input support TLS?
use core::read_data; use core::read_data;
fn has_abba(input: &str) -> bool { fn has_abba(input: &str) -> bool {
let chars: Vec<char> = input.chars().collect(); let chars: Vec<char> = input.chars().collect();
@ -31,24 +13,29 @@ fn has_abba(input: &str) -> bool {
false false
} }
fn extract_hypernet(input: &str) -> (String, String) { /// Split the address into supernet (outside brackets) and hypernet (inside brackets) parts.
let mut payload = String::new(); fn split_address(input: &str) -> (Vec<String>, Vec<String>) {
let mut real_balance = String::from(input); let mut supernets = Vec::new();
while real_balance.contains('[') { let mut hypernets = Vec::new();
let (prefix, balance) = real_balance.split_once('[').unwrap(); let mut rest = input;
let (tmp, t_balance) = balance.split_once(']').unwrap();
payload = format!("{}{}", payload, tmp.to_string()); while let Some((prefix, balance)) = rest.split_once('[') {
real_balance = format!("{}{}", prefix, t_balance); let (inside, suffix) = balance.split_once(']').unwrap();
// extract the text between the '[' and ']' characters supernets.push(prefix.to_string());
hypernets.push(inside.to_string());
rest = suffix;
} }
(real_balance, payload.to_string()) if !rest.is_empty() {
supernets.push(rest.to_string());
}
(supernets, hypernets)
} }
fn has_tls(address: &str, hypernet: &str) -> bool { fn has_tls(supernets: &[String], hypernets: &[String]) -> bool {
let abba = has_abba(address); let has_outside = supernets.iter().any(|s| has_abba(s));
let noabba = !has_abba(hypernet); let has_inside = hypernets.iter().any(|h| has_abba(h));
println!("[{address}] ABBA: {abba} [{hypernet}] NOABBA: {noabba}"); has_outside && !has_inside
abba && noabba
} }
fn main() { fn main() {
@ -57,27 +44,64 @@ fn main() {
("abba[mnop]qrst", true), ("abba[mnop]qrst", true),
("abcd[bddb]xyyx", false), ("abcd[bddb]xyyx", false),
("aaaa[qwer]tyui", false), ("aaaa[qwer]tyui", false),
("ioxxoj[asdfgh]zxcvbn", true) ("ioxxoj[asdfgh]zxcvbn", true),
("aaa[qwer]abba", true), // tricky case: should be valid
]; ];
for (input, expected) in params { for (input, expected) in params {
println!("------------------Testing [[{input}]]"); println!("------------------Testing [[{input}]]");
let (address, hypernet) = extract_hypernet(input); let (supernets, hypernets) = split_address(input);
println!("[[{input}]] = ADD: {address} HN: {hypernet}"); println!(
assert_eq!(has_tls(address.as_str(), hypernet.as_str()), expected) "[[{input}]] = SUPERNETS: {:?} HYPERNETS: {:?}",
supernets, hypernets
);
assert_eq!(has_tls(&supernets, &hypernets), expected)
} }
let binding = read_data("2016_07_data.txt"); let binding = read_data("2016_07_data.txt");
let lines = binding.lines(); let lines = binding.lines();
for line in lines { for line in lines {
let (address, hypernet) = extract_hypernet(line); let (supernets, hypernets) = split_address(line);
println!("Processing ||||{line}|||| -> {}/{}", address, hypernet); if has_tls(&supernets, &hypernets) {
if has_tls(address.as_str(), hypernet.as_str()) {
num_good += 1; num_good += 1;
} }
} }
println!("Found {num_good} good addresses."); println!("Found {num_good} good addresses.");
} }
#[cfg(test)]
mod test {
use crate::{has_abba, split_address, has_tls};
// 132 too high #[test]
fn abba_tests() {
let params = vec![
("abba", true),
("aabb", false),
("ioxxoj", true),
("aaaa", false),
];
for (input, result) in params {
assert_eq!(has_abba(input), result, "failed on {input}");
}
}
#[test]
fn split_and_tls_tests() {
let cases = vec![
("abba[mnop]qrst", true),
("abcd[bddb]xyyx", false),
("aaaa[qwer]tyui", false),
("ioxxoj[asdfgh]zxcvbn", true),
("aaa[qwer]abba", true), // confirms split works
];
for (input, expected) in cases {
let (sup, hyp) = split_address(input);
assert_eq!(has_tls(&sup, &hyp), expected, "failed on {input}");
}
}
}
// 118 with ChatGPT to explain how merging the hypernet sections cause problems.

View File

@ -1,5 +1,5 @@
const SCREEN_COLS: usize = 50; const SCREEN_COLS: usize = 8;
const SCREEN_ROWS: usize = 6; const SCREEN_ROWS: usize = 3;
const SCREEN_SIZE: usize = SCREEN_COLS * SCREEN_ROWS; const SCREEN_SIZE: usize = SCREEN_COLS * SCREEN_ROWS;
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -9,20 +9,31 @@ enum Actions {
RotateColumn(u32, u32) RotateColumn(u32, u32)
} }
struct World {
width: u32,
height: u32,
memory: Box<[bool]>
}
impl Actions { impl Actions {
// rotate a column 1 time. // rotate a column 1 time.
fn rotate_column(&self, column_index: u32, target: &mut [bool; SCREEN_SIZE]) { fn rotate_column(&self, column_index: u32, target: &mut [bool; SCREEN_SIZE]) {
let first_value = target[column_index as usize]; let first_value = target[column_index as usize];
for index in (SCREEN_COLS..0).rev() { let mut last_value = false;
for index in (0..SCREEN_COLS).rev() {
let offset = index as u32 * SCREEN_COLS as u32 + column_index; let offset = index as u32 * SCREEN_COLS as u32 + column_index;
println!("index = {index} offset = {offset}"); let next_offset = offset + SCREEN_COLS as u32;
println!("index: {} offset: {} next_offset: {}",
index, offset, next_offset);
last_value = target[offset as usize];
target[offset as usize] = last_value;
} }
} }
// rotate a row 1 time. // rotate a row 1 time.
fn rotate_row(&self, row_index: u32, target: &mut [bool; SCREEN_SIZE]) { fn rotate_row(&self, row_index: u32, target: &mut [bool; SCREEN_SIZE]) {
for index in (SCREEN_ROWS..0).rev() { for index in (SCREEN_ROWS..0).rev() {
let offset = index as u32 * SCREEN_COLS as u32 + index; let offset = index as u32 * SCREEN_COLS as u32 + index as u32;
println!("index = {index} offset = {offset}"); println!("index = {index} offset = {offset}");
} }
} }
@ -95,6 +106,13 @@ fn dump_screen(to_display: &[bool; SCREEN_SIZE]) {
fn main() { fn main() {
let mut screen_space:[bool; SCREEN_SIZE] = [false; SCREEN_SIZE]; let mut screen_space:[bool; SCREEN_SIZE] = [false; SCREEN_SIZE];
let mut world = World {
width: 8,
height: 3,
memory: Box::new([false; 8*3]),
};
let directions = vec![ let directions = vec![
"rect 3x2", "rect 3x2",
"rotate column x=1 by 1", "rotate column x=1 by 1",
@ -109,3 +127,5 @@ fn main() {
dump_screen(&screen_space); dump_screen(&screen_space);
} }
} }

View File

@ -1,3 +1,59 @@
fn main() { use std::ptr::hash;
use core::read_data;
/// Calculate the decompressed length of a string.
/// If `recursive` is true, markers are expanded recursively (Part 2).
/// If `recursive` is false, markers are expanded only once (Part 1).
fn decompressed_len(input: &str, recursive: bool) -> usize {
let mut total = 0;
let mut i = 0;
let binding = input.to_ascii_uppercase();
let bytes = binding.as_bytes();
while i < bytes.len() {
if bytes[i] == b'(' {
// find end of marker
let end = input[i..].find(')').unwrap() + i;
let marker = &input[i + 1..end];
let (a, b) = marker.split_once('x').unwrap();
let a: usize = a.parse().unwrap();
let b: usize = b.parse().unwrap();
i = end + 1;
let segment = &input[i..i + a];
let seg_len = if recursive {
decompressed_len(segment, true)
} else {
segment.len()
};
total += seg_len * b;
i += a;
} else {
total += 1;
i += 1;
}
}
total
} }
fn main() {
let puzzle_input = read_data("2016_09_data.txt");
let params = vec![
("ADVENT", 6),
("A(1x5)BC", 7),
("(3x3)XYZ", 9),
("A(2x2)BCD(2x2)EFG", 11),
("(6x1)(1x3)A", 6),
("X(8x2)(3x3)ABCY", 18),
(puzzle_input.as_str(), 100)
];
for (input, size) in params {
let decompressed_size = decompressed_len(input, false);
println!("Tested {} char string for expanded size of {} -> Calculated {}", input.len(), size, decompressed_size);
}
}
// 138735 ChatGPT held my hand through this as parsing text is not my strong point.

54
2016/src/bin/2016_15a.rs Normal file
View File

@ -0,0 +1,54 @@
use core::read_data;
struct Disc {
pub id: u32,
pub num_slots: u32,
pub current_slot: u32,
}
fn parse_disc(input: &str) -> Disc {
// Example line:
// "Disc #1 has 5 positions; at time=0, it is at position 4."
let parts: Vec<&str> = input
.trim_end_matches('.')
.split_whitespace()
.collect();
let id = parts[1][1..].parse::<u32>().unwrap(); // "#1" → "1"
let num_slots = parts[3].parse::<u32>().unwrap(); // "5"
let current_slot = parts[11].parse::<u32>().unwrap(); // "4"
Disc { id, num_slots, current_slot }
}
fn holes_line_up(discs: &Vec<Disc>, time: u32) -> bool {
for disc in discs {
// Puzzle logic: capsule reaches disc `id` at time + id
if (disc.current_slot + time + disc.id) % disc.num_slots != 0 {
return false;
}
}
true
}
fn main() {
let binding = read_data("2016_15_data.txt");
let inputs = binding.lines();
let mut discs = vec![];
for line in inputs {
let new_disc = parse_disc(line);
discs.push(new_disc);
}
println!("Discs loaded. Searching for the correct release time...");
let mut time = 0;
while !holes_line_up(&discs, time) {
time += 1;
}
println!("Capsule falls through at time {time}.");
}
// 317371

57
2016/src/bin/2016_15b.rs Normal file
View File

@ -0,0 +1,57 @@
use core::read_data;
struct Disc {
pub id: u32,
pub num_slots: u32,
pub current_slot: u32,
}
fn parse_disc(input: &str) -> Disc {
// Example line:
// "Disc #1 has 5 positions; at time=0, it is at position 4."
let parts: Vec<&str> = input
.trim_end_matches('.')
.split_whitespace()
.collect();
let id = parts[1][1..].parse::<u32>().unwrap(); // "#1" → "1"
let num_slots = parts[3].parse::<u32>().unwrap(); // "5"
let current_slot = parts[11].parse::<u32>().unwrap(); // "4"
Disc { id, num_slots, current_slot }
}
fn holes_line_up(discs: &Vec<Disc>, time: u32) -> bool {
for disc in discs {
// Puzzle logic: capsule reaches disc `id` at time + id
if (disc.current_slot + time + disc.id) % disc.num_slots != 0 {
return false;
}
}
true
}
fn main() {
let binding = read_data("2016_15_data.txt");
let inputs = binding.lines();
let mut discs = vec![];
for line in inputs {
let new_disc = parse_disc(line);
discs.push(new_disc);
}
println!("Discs loaded. Searching for the correct release time...");
discs.push(Disc { id: 7, num_slots: 11, current_slot: 0 });
let mut time = 0;
while !holes_line_up(&discs, time) {
time += 1;
}
println!("Capsule falls through at time {time}.");
}
// 2080951 help from ChatGPT to understand
// that each disc ticks 1/time unit, but they dont all tick at that second,
// they cascade.

0
2016/src/bin/2016_17a.rs Normal file
View File

View File

@ -5,3 +5,4 @@ edition = "2024"
[dependencies] [dependencies]
core = { path = "../core" } core = { path = "../core" }
chrono = "0.4"

View File

@ -32,3 +32,4 @@ fn main() {
} }
println!("Found {num_good} good boxes? / Checksum {}", num_two * num_three); println!("Found {num_good} good boxes? / Checksum {}", num_two * num_three);
} }
// Checksum 5434

111
2018/src/bin/2018_03a.rs Normal file
View File

@ -0,0 +1,111 @@
use core::read_data;
pub const WORLD_WIDTH: u32 = 1000;
pub const WORLD_HEIGHT: u32 = 1000;
pub const WORLD_SIZE: u32 = WORLD_WIDTH * WORLD_HEIGHT;
#[derive(Debug)]
struct Point {
pub x: u32,
pub y: u32
}
#[derive(Debug)]
struct Region {
pub elf: u32,
pub start: Point,
pub end: Point,
pub size: Point
}
impl Region {
fn new_with_size(start: Point, size: Point) -> Region {
Region {
elf: 0,
end: Point { x: start.x + size.x, y: start.y + size.y },
start,
size
}
}
// fn new_with_end(start: Point, end: Point) -> Region {
//
// }
}
fn apply_region(to_claim: &Region, world: &mut [u32; WORLD_SIZE as usize]) {
println!("Claiming from {}x{} to {}x{}",
to_claim.start.x,
to_claim.start.y,
to_claim.end.x,
to_claim.end.y
);
for y in to_claim.start.y..to_claim.end.y {
for x in to_claim.start.x..to_claim.end.x {
let offset = y * WORLD_WIDTH + x;
world[offset as usize] += 1;
}
}
}
/// convert a single line of input into a region claim.
fn line_to_region(input: &str) -> Region {
// [[#<elf> @ <start.x, start.y>: <width.x, width.y>
let (elf, balance) = input.split_once("@").unwrap();
let (_, elf_id) = elf.split_once('#').unwrap();
let (start_point, size_point) = balance.split_once(": ").unwrap();
let (start_x, start_y) = start_point.trim().split_once(',').unwrap();
let (size_x, size_y) =size_point.trim().split_once('x').unwrap();
let start = Point {
x: start_x.parse().unwrap(),
y: start_y.parse().unwrap()
};
let size = Point {
x: size_x.parse().unwrap(),
y: size_y.parse().unwrap()
};
let end = Point {
x: start.x + size.x,
y: start.y + size.y,
};
println!("ELF: [[{elf_id}]] START_POINT: [[{start_x}x{start_y}]] SIZE: [[{size_x}x{size_y}]] END: [[{}x{}]]",
end.x, end.y
);
let mut working = Region {
elf: elf_id.trim().parse().unwrap(),
start,
end,
size,
};
println!("Decoded [[{input}]] to [[{working:?}]]");
working
}
fn main() {
let binding = read_data("2018_03_data.txt");
let lines = binding.lines();
let mut world = [0x00u32; WORLD_SIZE as usize];
for line in lines {
apply_region(
&line_to_region(
line
), &mut world
);
}
// now count the areas with a value >=2
let mut num_multiclaimed = 0;
for offset in 0..WORLD_SIZE {
if world[offset as usize] >= 2 {
num_multiclaimed += 1;
}
}
println!("There are {num_multiclaimed} multi-claimed squares.");
}
// 120419 too high

89
2018/src/bin/2018_04a.rs Normal file
View File

@ -0,0 +1,89 @@
use std::collections::HashMap;
use chrono::{NaiveDateTime, Timelike};
use core::read_data;
use crate::WorkEvent::*;
#[derive(Debug)]
enum WorkEvent {
// [1518-09-07 00:00] Guard #2383 begins shift
StartShift(u32),
// [1518-08-20 00:17] falls asleep
FallAsleep,
// [1518-05-09 00:58] wakes up
WakeUp
}
fn parse_line(input: &str) -> (WorkEvent, NaiveDateTime) {
let (mut date, balance) = input.split_once("] ").unwrap();
let mut event = FallAsleep;
if balance.contains('#') {
let (_, guard_id_plus_junk) = balance.split_once("#").unwrap();
let (guard_id, _) = guard_id_plus_junk.split_once(" ").unwrap();
event = StartShift(guard_id.parse().unwrap());
} else {
if !balance.contains("falls") {
event = WakeUp
}
}
let parsed = NaiveDateTime::parse_from_str(date.strip_prefix('[').unwrap(), "%Y-%m-%d %H:%M").unwrap();
(event, parsed)
}
fn main() {
let binding = read_data("2018_04_data.txt");
let lines = binding.lines();
let mut worklog = HashMap::new();
for line in lines {
// println!("-- LINE = __{line}__ --");
let (event, when) = parse_line(line);
worklog.insert(when, event);
// println!("--");
}
println!("Loaded {} work events. Sorting...", worklog.len());
let mut items: Vec<_> = worklog.iter().collect();
items.sort_by(|a, b| a.0.cmp(& b.0));
let mut sleeping_guard = 0;
let mut sleep_time = NaiveDateTime::default();
let mut working_guard = 0;
let mut guard_sleep_log = HashMap::new();
let mut minute_sleep_log: HashMap<u32, HashMap<i32, i32>> = HashMap::new();
for index in 0..=60 {
minute_sleep_log.insert(index, HashMap::new());
}
for (k, v) in items {
println!("K: {k} V: {v:?}");
match v {
StartShift(guard_id) => {
working_guard = *guard_id;
// println!("Guard {guard_id} started at {k:?}");
}
FallAsleep => {
// println!("Guard {working_guard} is now sleeping at {k:?}");
sleeping_guard = working_guard;
sleep_time = *k;
}
WakeUp => {
let sleep_duration = k.signed_duration_since(sleep_time);
// println!("Guard {sleeping_guard} is now waking up at {k:?}, was sleeping for {} minutes.", sleep_duration.num_minutes());
*guard_sleep_log.entry(sleeping_guard).or_insert(0) += sleep_duration.num_minutes();
sleeping_guard = 0;
// println!("Sleep from {} to {} for {}", sleep_time.minute(), k.minute(), working_guard);
for minute in sleep_time.minute()..=k.minute() {
println!("Marking sleep at {minute} for {working_guard}");
minute_sleep_log.entry(minute).or_insert(HashMap::from((working_guard, 1)));
println!("MSL has {} entries.", minute_sleep_log.len());
}
}
}
// println!("--");
}
println!("Guard Sleep Log:");
println!("{guard_sleep_log:?}");
}

26
2018/src/bin/2018_05a.rs Normal file
View File

@ -0,0 +1,26 @@
fn process(input: &str) -> (String, u32) {
let num_changes = 0;
let mut peekables = input.chars().peekable();
while let Some(current_char) = peekables.next() {
println!("Checking {current_char} and {}", peekables.next().unwrap());
}
(String::new(), num_changes)
}
fn process_recursively(input: &str) -> String {
let mut working_str = input;
println!("RECURSIVE START: {}", input.len());
let mut need_again = true;
while need_again {
let (working, last_count) = process(working_str);
if last_count > 0 { need_again = true; }
let w2 = working.clone();
working_str = w2.as_str();
}
"dabCBAcaDA".to_string()
}
fn main() {
assert_eq!(process_recursively("dabAcCaCBAcCcaDA"), "dabCBAcaDA");
}

289
Cargo.lock generated
View File

@ -11,6 +11,15 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "aoc2015" name = "aoc2015"
version = "0.1.0" version = "0.1.0"
@ -38,6 +47,7 @@ dependencies = [
name = "aoc2018" name = "aoc2018"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"chrono",
"core", "core",
] ]
@ -84,6 +94,12 @@ dependencies = [
"regex", "regex",
] ]
[[package]]
name = "autocfg"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.10.4" version = "0.10.4"
@ -93,16 +109,51 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "bumpalo"
version = "3.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
[[package]]
name = "cc"
version = "1.2.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54"
dependencies = [
"find-msvc-tools",
"shlex",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.3" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "chrono"
version = "0.4.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
dependencies = [
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-link 0.2.0",
]
[[package]] [[package]]
name = "core" name = "core"
version = "0.1.0" version = "0.1.0"
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]] [[package]]
name = "crypto-common" name = "crypto-common"
version = "0.1.6" version = "0.1.6"
@ -123,6 +174,12 @@ dependencies = [
"crypto-common", "crypto-common",
] ]
[[package]]
name = "find-msvc-tools"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d"
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.7" version = "0.14.7"
@ -133,6 +190,52 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "iana-time-zone"
version = "0.1.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"log",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "js-sys"
version = "0.3.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
[[package]]
name = "log"
version = "0.4.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
[[package]] [[package]]
name = "md-5" name = "md-5"
version = "0.10.6" version = "0.10.6"
@ -149,6 +252,39 @@ version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]]
name = "proc-macro2"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.11.2" version = "1.11.2"
@ -178,14 +314,167 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.18.0" version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "unicode-ident"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.5" version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "wasm-bindgen"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1"
dependencies = [
"unicode-ident",
]
[[package]]
name = "windows-core"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link 0.1.3",
"windows-result",
"windows-strings",
]
[[package]]
name = "windows-implement"
version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.59.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-link"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
[[package]]
name = "windows-link"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
[[package]]
name = "windows-result"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "windows-strings"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
dependencies = [
"windows-link 0.1.3",
]

2
README
View File

@ -1,4 +1,4 @@
Trevors AOC workspace. Trevor's AOC workspace.
This is not for the public. If you aren't Trevor, please go away now. This is not for the public. If you aren't Trevor, please go away now.

1
data/2016_09_data.txt Normal file

File diff suppressed because one or more lines are too long

6
data/2016_15_data.txt Normal file
View File

@ -0,0 +1,6 @@
Disc #1 has 17 positions; at time=0, it is at position 1.
Disc #2 has 7 positions; at time=0, it is at position 0.
Disc #3 has 19 positions; at time=0, it is at position 2.
Disc #4 has 5 positions; at time=0, it is at position 0.
Disc #5 has 3 positions; at time=0, it is at position 0.
Disc #6 has 13 positions; at time=0, it is at position 5.

1407
data/2018_03_data.txt Normal file

File diff suppressed because it is too large Load Diff

1110
data/2018_04_data.txt Normal file

File diff suppressed because it is too large Load Diff

1
data/2018_05_data.txt Normal file

File diff suppressed because one or more lines are too long