more successes.
This commit is contained in:
+45
-30
@@ -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
|
||||
|
||||
@@ -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
@@ -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.
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user