more successes.

This commit is contained in:
2025-09-19 10:40:28 -04:00
parent 7c3186abcf
commit af075edb24
25 changed files with 3425 additions and 145 deletions
+45 -30
View File
@@ -43,37 +43,52 @@ struct Location {
fn main() {
let mut current_position = Location { x: 1, y: 1 };
// let directions = read_data("2016_02_data.txt");
let directions = "ULL\nRRDDD\nLURDL\nUUUUUD";
for next_direction in directions.chars() {
match next_direction {
'R' => {
if current_position.x < 3 {
current_position.x += 1;
let directions = read_data("2016_02_data.txt");
//let directions = "ULL\nRRDDD\nLURDL\nUUUUUD";
for line_of_directions in directions.lines() {
println!("Processing directions of {line_of_directions} starting at {}x{}", current_position.x, current_position.y);
for current_direction in line_of_directions.chars() {
// print!(" [{current_direction}] ");
match current_direction {
'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");
}
}
},
'L' => {
if current_position.x > 0 {
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"); }
_ => { unreachable!("invalid direction.") }
}
// println!("Ending line at {}x{}", current_position.x, current_position.y);
//
}
println!("CELL = {}", (current_position.x + 1) + (current_position.y * 3));
}
println!("Ending at {}x{}", current_position.x, current_position.y);
}
// 2445 is wrong.
// 3775 is wrong.
// 84452
+3
View File
@@ -9,6 +9,7 @@ struct EncryptedRoom {
fn main() {
let binding = read_data("2016_04_data.txt");
let inputs = binding.lines();
for line in inputs {
@@ -40,6 +41,8 @@ fn main() {
println!("HASH: {hash:?}");
// now find the 5 most frequently occurring characters in alphabetical order
// once we have the new value, compare it to the checksum
for (k, v) in hash {
}
}
}
+66 -42
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;
fn has_abba(input: &str) -> bool {
let chars: Vec<char> = input.chars().collect();
@@ -31,24 +13,29 @@ fn has_abba(input: &str) -> bool {
false
}
fn extract_hypernet(input: &str) -> (String, String) {
let mut payload = String::new();
let mut real_balance = String::from(input);
while real_balance.contains('[') {
let (prefix, balance) = real_balance.split_once('[').unwrap();
let (tmp, t_balance) = balance.split_once(']').unwrap();
payload = format!("{}{}", payload, tmp.to_string());
real_balance = format!("{}{}", prefix, t_balance);
// extract the text between the '[' and ']' characters
/// Split the address into supernet (outside brackets) and hypernet (inside brackets) parts.
fn split_address(input: &str) -> (Vec<String>, Vec<String>) {
let mut supernets = Vec::new();
let mut hypernets = Vec::new();
let mut rest = input;
while let Some((prefix, balance)) = rest.split_once('[') {
let (inside, suffix) = balance.split_once(']').unwrap();
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 {
let abba = has_abba(address);
let noabba = !has_abba(hypernet);
println!("[{address}] ABBA: {abba} [{hypernet}] NOABBA: {noabba}");
abba && noabba
fn has_tls(supernets: &[String], hypernets: &[String]) -> bool {
let has_outside = supernets.iter().any(|s| has_abba(s));
let has_inside = hypernets.iter().any(|h| has_abba(h));
has_outside && !has_inside
}
fn main() {
@@ -57,27 +44,64 @@ fn main() {
("abba[mnop]qrst", true),
("abcd[bddb]xyyx", 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 {
println!("------------------Testing [[{input}]]");
let (address, hypernet) = extract_hypernet(input);
println!("[[{input}]] = ADD: {address} HN: {hypernet}");
assert_eq!(has_tls(address.as_str(), hypernet.as_str()), expected)
let (supernets, hypernets) = split_address(input);
println!(
"[[{input}]] = SUPERNETS: {:?} HYPERNETS: {:?}",
supernets, hypernets
);
assert_eq!(has_tls(&supernets, &hypernets), expected)
}
let binding = read_data("2016_07_data.txt");
let lines = binding.lines();
for line in lines {
let (address, hypernet) = extract_hypernet(line);
println!("Processing ||||{line}|||| -> {}/{}", address, hypernet);
if has_tls(address.as_str(), hypernet.as_str()) {
let (supernets, hypernets) = split_address(line);
if has_tls(&supernets, &hypernets) {
num_good += 1;
}
}
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.
+25 -5
View File
@@ -1,5 +1,5 @@
const SCREEN_COLS: usize = 50;
const SCREEN_ROWS: usize = 6;
const SCREEN_COLS: usize = 8;
const SCREEN_ROWS: usize = 3;
const SCREEN_SIZE: usize = SCREEN_COLS * SCREEN_ROWS;
#[derive(Debug, Copy, Clone)]
@@ -9,20 +9,31 @@ enum Actions {
RotateColumn(u32, u32)
}
struct World {
width: u32,
height: u32,
memory: Box<[bool]>
}
impl Actions {
// rotate a column 1 time.
fn rotate_column(&self, column_index: u32, target: &mut [bool; SCREEN_SIZE]) {
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;
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.
fn rotate_row(&self, row_index: u32, target: &mut [bool; SCREEN_SIZE]) {
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}");
}
}
@@ -95,6 +106,13 @@ fn dump_screen(to_display: &[bool; SCREEN_SIZE]) {
fn main() {
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![
"rect 3x2",
"rotate column x=1 by 1",
@@ -109,3 +127,5 @@ fn main() {
dump_screen(&screen_space);
}
}
+58 -2
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
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
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.
View File