lots of stuff ive done.
maybe a status would be good?
This commit is contained in:
+3
-35
@@ -17,25 +17,7 @@
|
||||
// they order?
|
||||
//
|
||||
|
||||
use aoc::read_data;
|
||||
|
||||
fn smallest_of_vec(to_check: &Vec<u32>) -> u32 {
|
||||
let mut working = to_check[0];
|
||||
for current in to_check {
|
||||
if current < &working {
|
||||
working = *current
|
||||
}
|
||||
}
|
||||
working
|
||||
}
|
||||
|
||||
fn sum_of_vec(to_add: &Vec<u32>) -> u32 {
|
||||
let mut working = 0;
|
||||
for current in to_add {
|
||||
working += current
|
||||
}
|
||||
working
|
||||
}
|
||||
use aoc::{read_data, smallest_of_vec, string_to_3u32, sum_of_vec};
|
||||
|
||||
fn calculate_wrapping_needed(length: u32, width: u32, height: u32) -> u32 {
|
||||
let sides = vec![
|
||||
@@ -49,20 +31,6 @@ fn calculate_wrapping_needed(length: u32, width: u32, height: u32) -> u32 {
|
||||
sum_of_vec(&sides) + min_side
|
||||
}
|
||||
|
||||
fn split_str(input: &str) -> Option<(u32, u32, u32)> {
|
||||
let parts: Vec<&str> = input.split('x').collect();
|
||||
if parts.len() == 3 {
|
||||
if let (Ok(a), Ok(b), Ok(c)) = (
|
||||
parts[0].parse::<u32>(),
|
||||
parts[1].parse::<u32>(),
|
||||
parts[2].parse::<u32>(),
|
||||
) {
|
||||
return Some((a, b, c));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Need {} for 2x3x4", calculate_wrapping_needed(2,3,4));
|
||||
println!("Need {} for 1x1x10", calculate_wrapping_needed(1,1,10));
|
||||
@@ -72,11 +40,11 @@ fn main() {
|
||||
let mut working = 0;
|
||||
|
||||
for size in sizes {
|
||||
let (l, w, h) = split_str(size).unwrap();
|
||||
let (l, w, h) = string_to_3u32(size).unwrap();
|
||||
let needed = calculate_wrapping_needed(l, w, h);
|
||||
// println!("Need {} for {}", needed, size);
|
||||
working += needed;
|
||||
}
|
||||
println!("You need {}.", working);
|
||||
}
|
||||
// 1586300.
|
||||
// 1586300
|
||||
+2
-16
@@ -15,7 +15,7 @@
|
||||
// How many total feet of ribbon should they order?
|
||||
//
|
||||
|
||||
use aoc::read_data;
|
||||
use aoc::{read_data, string_to_3u32};
|
||||
|
||||
fn bow_ribbon_length(l: u32, w: u32, h: u32) -> u32 {
|
||||
l * w * h
|
||||
@@ -31,20 +31,6 @@ fn ribbon_for_package(l: u32, w: u32, h: u32) -> u32 {
|
||||
ribbon_for_sides(l, w, h) + bow_ribbon_length(l, w, h)
|
||||
}
|
||||
|
||||
fn split_str(input: &str) -> Option<(u32, u32, u32)> {
|
||||
let parts: Vec<&str> = input.split('x').collect();
|
||||
if parts.len() == 3 {
|
||||
if let (Ok(a), Ok(b), Ok(c)) = (
|
||||
parts[0].parse::<u32>(),
|
||||
parts[1].parse::<u32>(),
|
||||
parts[2].parse::<u32>(),
|
||||
) {
|
||||
return Some((a, b, c));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("Box sized {} requires {}", "2x3x4", ribbon_for_package(2,3,4));
|
||||
println!("Box sized {} requires {}", "1x1x10", ribbon_for_package(1,1,10));
|
||||
@@ -53,7 +39,7 @@ fn main() {
|
||||
let mut total_ribbon = 0;
|
||||
|
||||
for size in sizes {
|
||||
let (l, w, h) = split_str(size).unwrap();
|
||||
let (l, w, h) = string_to_3u32(size).unwrap();
|
||||
let needed = ribbon_for_package(l, w, h);
|
||||
println!("Need {} for {}", needed, size);
|
||||
total_ribbon += needed
|
||||
|
||||
+2
-17
@@ -28,7 +28,6 @@ fn main() {
|
||||
println!("abcdef609043 -> {}", calculate_hash(609043, "abcdef"));
|
||||
println!("pqrstuv1048970 -> {}", calculate_hash(1048970, "pqrstuv"));
|
||||
let mut need5 = true;
|
||||
let mut need6 = true;
|
||||
|
||||
for number in 0..u32::MAX {
|
||||
let hashed = calculate_hash(number, INPUT);
|
||||
@@ -38,22 +37,8 @@ fn main() {
|
||||
if hashed.starts_with("00000") {
|
||||
println!("5 zeros -> {}{} / {}", INPUT, number, hashed);
|
||||
need5 = false;
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if need6 {
|
||||
if hashed.starts_with("000000") {
|
||||
println!("6 zeros -> {}{} / {}", INPUT, number, hashed);
|
||||
need6 = false;
|
||||
}
|
||||
}
|
||||
|
||||
if hashed.starts_with("0000000") {
|
||||
println!("7 zeros -> {}{} / {}", INPUT, number, hashed);
|
||||
} // 318_903_846
|
||||
if number % 100_000 == 0 && !need6 && !need5 {
|
||||
print!(".");
|
||||
stdout().flush().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Now find one that starts with six zeroes.
|
||||
|
||||
|
||||
use std::io::{stdout, Write};
|
||||
use md5::{Digest, Md5};
|
||||
|
||||
const INPUT: &str = "bgvyzdsv";
|
||||
|
||||
fn calculate_hash(input_id: u32, seed: &str) -> String {
|
||||
let to_hash = format!("{}{}", seed, input_id);
|
||||
let as_hash = format!("{:x}", Md5::digest(to_hash.as_bytes()));
|
||||
as_hash
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("abcdef609043 -> {}", calculate_hash(609043, "abcdef"));
|
||||
println!("pqrstuv1048970 -> {}", calculate_hash(1048970, "pqrstuv"));
|
||||
let mut need6 = true;
|
||||
|
||||
for number in 0..u32::MAX {
|
||||
let hashed = calculate_hash(number, INPUT);
|
||||
// are the first 6 characters 0?
|
||||
|
||||
if need6 {
|
||||
if hashed.starts_with("000000") {
|
||||
println!("6 zeros -> {}{} / {}", INPUT, number, hashed);
|
||||
need6 = false;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -20,8 +20,12 @@
|
||||
// ieodomkazucvgmuy is naughty because it has a repeating letter with one between (odo), but no
|
||||
// pair that appears twice.
|
||||
|
||||
|
||||
fn appears_twice_without_overlapping(to_check: &str) -> bool {
|
||||
let mut to_find = vec![];
|
||||
for index in 0..=to_check.len() - 1 {
|
||||
let next_pair = to_check.chars().enumerate();
|
||||
println!("Index {index} = {:?}", next_pair);
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2015_08_data.txt");
|
||||
let lines = binding.lines();
|
||||
let binding = vec![
|
||||
"\"\"",
|
||||
"\"abc\"",
|
||||
"\"abc\\\"abc\"",
|
||||
"\"\\x27\""
|
||||
].join("\n");
|
||||
let lines = binding.lines();
|
||||
|
||||
for line in lines {
|
||||
let mut num_bytes = 0;
|
||||
let mut num_chars = 0;
|
||||
let mut next_char_to_watch = 0;
|
||||
let mut line_chars = line.chars();
|
||||
|
||||
for (current_index, current_char) in line_chars.clone().enumerate() {
|
||||
if current_index > next_char_to_watch {
|
||||
match current_char {
|
||||
'"' => {
|
||||
num_bytes += 1;
|
||||
},
|
||||
'\\' => {
|
||||
println!("Found slash at {current_index}");
|
||||
let x = line_chars.nth(current_index).unwrap();
|
||||
// println!("{}", line_chars.colle
|
||||
}
|
||||
_ => {
|
||||
num_bytes += 1;
|
||||
num_chars += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("[{line}] = B:{num_bytes} C:{num_chars}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// Look-and-say sequences are generated iteratively, using the previous value as input for the next
|
||||
// step. For each step, take the previous value, and replace each run of digits (like 111) with the
|
||||
// number of digits (3) followed by the digit itself (1).
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// 1 becomes 11 (1 copy of digit 1).
|
||||
// 11 becomes 21 (2 copies of digit 1).
|
||||
// 21 becomes 1211 (one 2 followed by one 1).
|
||||
// 1211 becomes 111221 (one 1, one 2, and two 1s).
|
||||
// 111221 becomes 312211 (three 1s, two 2s, and one 1).
|
||||
// Starting with the digits in your puzzle input, apply this process 40 times. What is the length
|
||||
// of the result?
|
||||
//
|
||||
// Your puzzle input is 1113122113.
|
||||
// 1: 311311222113
|
||||
// 2: 13211321322113
|
||||
// 3: 1113122113121113222113
|
||||
// 4: 31131122211311133113322113
|
||||
// 5: 1321132132211331232123222113
|
||||
// 6: ...
|
||||
|
||||
fn num_to_change(input: &str) -> usize {
|
||||
let mut return_value = 0;
|
||||
let mut last_char = '\0';
|
||||
|
||||
for (index, current_char) in input.chars().enumerate() {
|
||||
if index != 0 {
|
||||
if last_char != current_char {
|
||||
return_value = index;
|
||||
break
|
||||
}
|
||||
}
|
||||
last_char = current_char
|
||||
}
|
||||
return_value
|
||||
}
|
||||
|
||||
fn look_and_say(input: &str) -> String {
|
||||
let mut working = String::new();
|
||||
|
||||
|
||||
|
||||
working
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let params = vec![
|
||||
("1", "11"),
|
||||
("11", "21"),
|
||||
("21", "1211"),
|
||||
// ("1211", "111221"),
|
||||
// ("111221", "31221")
|
||||
];
|
||||
|
||||
for (input, output) in params {
|
||||
let result = look_and_say(input);
|
||||
println!("**** {input} processed to {result} expecting {output}");
|
||||
assert_eq!(result, output);
|
||||
}
|
||||
|
||||
// // puzzle time
|
||||
// let mut current_input = "1113122113";
|
||||
// for _ in 0..40 {
|
||||
// let next_input = current_input.clone();
|
||||
// let next_output = look_and_say(next_input);
|
||||
// current_input = next_output.as_str();
|
||||
// }
|
||||
// println!("final -> {current_input}");
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// This year is the Reindeer Olympics! Reindeer can fly at high speeds, but must rest occasionally
|
||||
// to recover their energy. Santa would like to know which of his reindeer is fastest, and so he
|
||||
// has them race.
|
||||
//
|
||||
// Reindeer can only either be flying (always at their top speed) or resting (not moving at all),
|
||||
// and always spend whole seconds in either state.
|
||||
//
|
||||
// For example, suppose you have the following Reindeer:
|
||||
//
|
||||
// Comet can fly 14 km/s for 10 seconds, but then must rest for 127 seconds.
|
||||
// Dancer can fly 16 km/s for 11 seconds, but then must rest for 162 seconds.
|
||||
// After one second, Comet has gone 14 km, while Dancer has gone 16 km. After ten seconds, Comet
|
||||
// has gone 140 km, while Dancer has gone 160 km. On the eleventh second, Comet begins resting
|
||||
// (staying at 140 km), and Dancer continues on for a total distance of 176 km. On the 12th second,
|
||||
// both reindeer are resting. They continue to rest until the 138th second, when Comet flies for
|
||||
// another ten seconds. On the 174th second, Dancer flies for another 11 seconds.
|
||||
//
|
||||
// In this example, after the 1000th second, both reindeer are resting, and Comet is in the lead at
|
||||
// 1120 km (poor Dancer has only gotten 1056 km by that point). So, in this situation, Comet would
|
||||
// win (if the race ended at 1000 seconds).
|
||||
//
|
||||
// Given the descriptions of each reindeer (in your puzzle input), after exactly 2503 seconds, what
|
||||
// distance has the winning reindeer traveled?
|
||||
|
||||
fn tick_world() {
|
||||
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
}
|
||||
+3
-3
@@ -27,6 +27,7 @@
|
||||
//
|
||||
|
||||
use std::{env, fs};
|
||||
use aoc::read_data;
|
||||
use crate::CardinalDirection::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -101,9 +102,8 @@ fn manhattan_distance(directions: &str) -> i32 {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
let directions = fs::read_to_string(format!("{}/data/01_data.txt", env::var("CARGO_MANIFEST_DIR").unwrap())).unwrap();
|
||||
let directions = directions.as_str();
|
||||
let binding = read_data("2016_01_data.txt");
|
||||
let directions = binding.as_str();
|
||||
let parmas: Vec<(&str, i32)> = vec![
|
||||
("R2, L3", 5),
|
||||
("R2, R2, R2", 2),
|
||||
|
||||
+120
-70
@@ -31,97 +31,147 @@ use std::collections::HashMap;
|
||||
use aoc::read_data;
|
||||
use crate::CardinalDirection::*;
|
||||
|
||||
fn manhattan_distance(directions: &str) -> i32 {
|
||||
let mut num_directions = 0;
|
||||
let mut visited_locations: HashMap<String, i32> = HashMap::new();
|
||||
visited_locations.insert("0x0".to_string(), 0);
|
||||
let (mut x_distance, mut y_distance, mut x_move, mut y_move) = (0i32, 0i32, 0i32, 0i32);
|
||||
let mut current_direction = North;
|
||||
for next_direction in directions.split(", ") {
|
||||
let (direction, vector) = next_direction.split_at(1);
|
||||
let distance = vector.parse().unwrap();
|
||||
x_move = 0;
|
||||
y_move = 0;
|
||||
num_directions += 1;
|
||||
|
||||
match (direction, current_direction) {
|
||||
("R", North) => {
|
||||
current_direction = East;
|
||||
x_move = distance;
|
||||
}
|
||||
("R", South) => {
|
||||
current_direction = West;
|
||||
x_move = distance * -1;
|
||||
}
|
||||
("R", East) => {
|
||||
current_direction = South;
|
||||
y_move = distance * -1;
|
||||
}
|
||||
("R", West) => {
|
||||
current_direction = North;
|
||||
y_move = distance;
|
||||
}
|
||||
("L", North) => {
|
||||
current_direction = West;
|
||||
x_move = distance * -1;
|
||||
}
|
||||
("L", South) => {
|
||||
current_direction = East;
|
||||
x_move = distance;
|
||||
}
|
||||
("L", East) => {
|
||||
current_direction = North;
|
||||
y_move = distance;
|
||||
}
|
||||
("L", West) => {
|
||||
current_direction = South;
|
||||
y_move = distance * -1;
|
||||
}
|
||||
_ => {
|
||||
unreachable!("Invalid Direction and Previous Direction");
|
||||
}
|
||||
}
|
||||
|
||||
for _ in 0..=distance {
|
||||
match current_direction {
|
||||
North => y_distance += 1,
|
||||
South => y_distance -= 1,
|
||||
East => x_distance += 1,
|
||||
West => x_distance -= 1
|
||||
}
|
||||
}
|
||||
|
||||
x_distance += x_move;
|
||||
y_distance += y_move;
|
||||
//
|
||||
// // have we been here before?
|
||||
// let new_index = format!("{}x{}", x_distance, y_distance);
|
||||
// for key in visited_locations.keys() {
|
||||
// if *key == new_index {
|
||||
// panic!("********************************MATCH -> {} == {}x{}", key, x_distance, y_distance);
|
||||
// } else {
|
||||
// print!("\tNOT MATCH -> {key} {x_distance}x{y_distance}\n");
|
||||
// }
|
||||
// }
|
||||
// println!("Adding {new_index} to visited list");
|
||||
// visited_locations.insert(new_index, 0);
|
||||
}
|
||||
x_distance.abs() + y_distance.abs()
|
||||
}
|
||||
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum CardinalDirection {
|
||||
North,
|
||||
South,
|
||||
East,
|
||||
West
|
||||
West,
|
||||
}
|
||||
|
||||
fn manhattan_distance(directions: &str) -> i32 {
|
||||
let mut visited_locations: HashMap<String, i32> = HashMap::new();
|
||||
visited_locations.insert("0x0".to_string(), 0);
|
||||
let (mut x_distance, mut y_distance, mut x_move, mut y_move) = (0i32,0i32, 0i32, 0i32);
|
||||
let mut current_direction = North;
|
||||
for next_direction in directions.split(", ") {
|
||||
let (direction, vector) = next_direction.split_at(1);
|
||||
let distance = vector.parse().unwrap();
|
||||
// print!("[{}] At {x_distance}x{y_distance}, FACING {current_direction:?}, TURN {} MOVE {} ::::::", next_direction, direction, distance);
|
||||
fn manhattan_distance_first_repeat(directions: &str) -> i32 {
|
||||
let mut visited: HashSet<(i32, i32)> = HashSet::new();
|
||||
let (mut x, mut y) = (0, 0);
|
||||
let mut facing = CardinalDirection::North;
|
||||
|
||||
x_move = 0; y_move = 0;
|
||||
visited.insert((x, y));
|
||||
|
||||
match direction {
|
||||
"R" => {
|
||||
match current_direction {
|
||||
North => {
|
||||
current_direction = East;
|
||||
x_move = distance;
|
||||
}
|
||||
South => {
|
||||
current_direction = West;
|
||||
x_move = distance * -1 ;
|
||||
}
|
||||
East => {
|
||||
current_direction = South;
|
||||
y_move = distance * -1;
|
||||
}
|
||||
West => {
|
||||
current_direction = North;
|
||||
y_move = distance;
|
||||
}
|
||||
}
|
||||
for instr in directions.split(", ") {
|
||||
let (turn, steps_str) = instr.split_at(1);
|
||||
let steps: i32 = steps_str.parse().unwrap();
|
||||
|
||||
// turn
|
||||
facing = match (facing, turn) {
|
||||
(CardinalDirection::North, "R") => CardinalDirection::East,
|
||||
(CardinalDirection::North, "L") => CardinalDirection::West,
|
||||
(CardinalDirection::South, "R") => CardinalDirection::West,
|
||||
(CardinalDirection::South, "L") => CardinalDirection::East,
|
||||
(CardinalDirection::East, "R") => CardinalDirection::South,
|
||||
(CardinalDirection::East, "L") => CardinalDirection::North,
|
||||
(CardinalDirection::West, "R") => CardinalDirection::North,
|
||||
(CardinalDirection::West, "L") => CardinalDirection::South,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// walk one step at a time
|
||||
for _ in 0..steps {
|
||||
match facing {
|
||||
CardinalDirection::North => y += 1,
|
||||
CardinalDirection::South => y -= 1,
|
||||
CardinalDirection::East => x += 1,
|
||||
CardinalDirection::West => x -= 1,
|
||||
}
|
||||
"L" => {
|
||||
match current_direction {
|
||||
North => {
|
||||
current_direction = West;
|
||||
x_move = distance * -1;
|
||||
}
|
||||
South => {
|
||||
current_direction = East;
|
||||
x_move = distance;
|
||||
}
|
||||
East => {
|
||||
current_direction = North;
|
||||
y_move = distance;
|
||||
}
|
||||
West => {
|
||||
current_direction = South;
|
||||
y_move = distance * -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
println!("INVALID DIRECTION");
|
||||
|
||||
// check repeat
|
||||
if !visited.insert((x, y)) {
|
||||
return x.abs() + y.abs(); // first repeat distance
|
||||
}
|
||||
}
|
||||
x_distance += x_move;
|
||||
y_distance += y_move;
|
||||
|
||||
// have we been here before?
|
||||
let new_index = format!("{}x{}", x_distance, y_distance);
|
||||
for key in visited_locations.keys() {
|
||||
if *key == new_index {
|
||||
panic!("********************************MATCH -> {} == {}x{}", key, x_distance, y_distance);
|
||||
} else {
|
||||
print!("\tNOT MATCH -> {key} {x_distance}x{y_distance}\n");
|
||||
}
|
||||
}
|
||||
println!("Adding {new_index} to visited list");
|
||||
visited_locations.insert(new_index, 0);
|
||||
}
|
||||
x_distance.abs() + y_distance.abs()
|
||||
|
||||
panic!("No repeated location found");
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2016_01_data.txt");
|
||||
// let binding = "R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1";
|
||||
let directions = binding.as_str();
|
||||
let params: Vec<&str> = vec![directions];
|
||||
|
||||
for param in params {
|
||||
println!("Manhattan Distance of {}", manhattan_distance(param));
|
||||
println!("Manhattan Distance of {}", manhattan_distance_first_repeat(param));
|
||||
}
|
||||
}
|
||||
|
||||
// NOT COMPLETED. CANT FIND THE REPEATED LOCATION
|
||||
// 143 -> ChatGPT helped. :(
|
||||
@@ -0,0 +1,79 @@
|
||||
// You arrive at Easter Bunny Headquarters under cover of darkness. However, you left in such a
|
||||
// rush that you forgot to use the bathroom! Fancy office buildings like this one usually have
|
||||
// keypad locks on their bathrooms, so you search the front desk for the code.
|
||||
//
|
||||
// "In order to improve security," the document you find says, "bathroom codes will no longer be
|
||||
// written down. Instead, please memorize and follow the procedure below to access the bathrooms."
|
||||
//
|
||||
// The document goes on to explain that each button to be pressed can be found by starting on the
|
||||
// previous button and moving to adjacent buttons on the keypad: U moves up, D moves down, L moves
|
||||
// left, and R moves right. Each line of instructions corresponds to one button, starting at the
|
||||
// previous button (or, for the first line, the "5" button); press whatever button you're on at the
|
||||
// end of each line. If a move doesn't lead to a button, ignore it.
|
||||
//
|
||||
// You can't hold it much longer, so you decide to figure out the code as you walk to the bathroom.
|
||||
// You picture a keypad like this:
|
||||
//
|
||||
// 1 2 3
|
||||
// 4 5 6
|
||||
// 7 8 9
|
||||
// Suppose your instructions are:
|
||||
//
|
||||
// ULL
|
||||
// RRDDD
|
||||
// LURDL
|
||||
// UUUUD
|
||||
// You start at "5" and move up (to "2"), left (to "1"), and left (you can't, and stay on "1"), so the first button is 1.
|
||||
// Starting from the previous button ("1"), you move right twice (to "3") and then down three times (stopping at "9" after two moves and ignoring the third), ending up with 9.
|
||||
// Continuing from "9", you move left, up, right, down, and left, ending with 8.
|
||||
// Finally, you move up four times (stopping at "2"), then down once, ending with 5.
|
||||
// So, in this example, the bathroom code is 1985.
|
||||
//
|
||||
// Your puzzle input is the instructions from the document you found at the front desk. What is the bathroom code?
|
||||
//
|
||||
|
||||
use aoc::read_data;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Location {
|
||||
pub x: u32,
|
||||
pub y: u32
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
},
|
||||
'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"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
// 2445 is wrong.
|
||||
// 3775 is wrong.
|
||||
@@ -0,0 +1,40 @@
|
||||
// --- Day 3: Squares With Three Sides ---
|
||||
// Now that you can think clearly, you move deeper into the labyrinth of hallways and office
|
||||
// furniture that makes up this part of Easter Bunny HQ. This must be a graphic design department;
|
||||
// the walls are covered in specifications for triangles.
|
||||
//
|
||||
// Or are they?
|
||||
//
|
||||
// The design document gives the side lengths of each triangle it describes, but... 5 10 25? Some
|
||||
// of these aren't triangles. You can't help but mark the impossible ones.
|
||||
//
|
||||
// In a valid triangle, the sum of any two sides must be larger than the remaining side. For
|
||||
// example, the "triangle" given above is impossible, because 5 + 10 is not larger than 25.
|
||||
//
|
||||
|
||||
use aoc::read_data;
|
||||
|
||||
// the total of the sides minus the largest side is greater then the longest side
|
||||
fn possibly_valid_triangle(a: u32, b: u32, c: u32) -> bool {
|
||||
a+b+c - a.max(b).max(c) > a.max(b).max(c)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let binding= read_data("2016_03_data.txt");
|
||||
let possible_triangles = binding.lines();
|
||||
let mut num_valid = 0;
|
||||
|
||||
for current in possible_triangles.clone() {
|
||||
println!("Parsing {current}");
|
||||
let (first, balance) = current.split_at(5);
|
||||
let (second, balance) = balance.split_at(5);
|
||||
let (third, _) = balance.split_at(5);
|
||||
println!("FIRST = [{first}] SECOND = [{second}] THIRD = [{third}]");
|
||||
if possibly_valid_triangle(first.trim().parse().unwrap(), second.trim().parse().unwrap(), third.trim().parse().unwrap()) {
|
||||
num_valid += 1;
|
||||
}
|
||||
}
|
||||
|
||||
println!("Found {num_valid} triangles out of {}", possible_triangles.count());
|
||||
}
|
||||
// 1050
|
||||
@@ -0,0 +1,58 @@
|
||||
use aoc::read_data;
|
||||
|
||||
// the total of the sides minus the largest side is greater then the longest side
|
||||
fn possibly_valid_triangle(a: u32, b: u32, c: u32) -> bool {
|
||||
a+b+c - a.max(b).max(c) > a.max(b).max(c)
|
||||
}
|
||||
|
||||
fn split_at_5_twice(input: &str) -> (u32, u32, u32) {
|
||||
let (a_s, bal) = input.split_at(5);
|
||||
let (b_s, bal) = bal.split_at(5);
|
||||
let c_s = bal.trim();
|
||||
|
||||
let a = a_s.trim().parse().unwrap();
|
||||
let b = b_s.trim().parse().unwrap();
|
||||
let c = c_s.trim().parse().unwrap();
|
||||
(a, b, c)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// read 3 lines...
|
||||
let mut num_valid = 0;
|
||||
let binding = read_data("2016_03_data.txt");
|
||||
let lines = binding.lines();
|
||||
let mut lines_batch: Vec<&str> = vec![];
|
||||
let mut current_batch_numbers = vec![
|
||||
vec![0; 3],
|
||||
vec![0; 3],
|
||||
vec![0; 3]
|
||||
];
|
||||
for line in lines {
|
||||
let (a, b, c) = split_at_5_twice(line);
|
||||
|
||||
let index = lines_batch.len();
|
||||
lines_batch.push(line);
|
||||
current_batch_numbers[0][index] = a;
|
||||
current_batch_numbers[1][index] = b;
|
||||
current_batch_numbers[2][index] = c;
|
||||
|
||||
if lines_batch.len() == 3 {
|
||||
println!("Processing batch...");
|
||||
|
||||
for current_batch_set in current_batch_numbers.clone() {
|
||||
if possibly_valid_triangle(
|
||||
current_batch_set[0],
|
||||
current_batch_set[1],
|
||||
current_batch_set[2],
|
||||
) {
|
||||
num_valid += 1;
|
||||
}
|
||||
}
|
||||
|
||||
lines_batch.clear();
|
||||
}
|
||||
}
|
||||
|
||||
println!("There are {num_valid} valid triangles.");
|
||||
}
|
||||
// 1921
|
||||
@@ -0,0 +1,45 @@
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use aoc::read_data;
|
||||
|
||||
struct EncryptedRoom {
|
||||
encrypted_name: String,
|
||||
sector_id: u32,
|
||||
checksum: String,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2016_04_data.txt");
|
||||
let inputs = binding.lines();
|
||||
|
||||
for line in inputs {
|
||||
let (balance, checksum) = line.split_once('[').unwrap();
|
||||
let (checksum, _) = checksum.split_at(5);
|
||||
let parts = balance.split("-");
|
||||
let num_parts = parts.clone().count();
|
||||
let mut working_enc = String::new();
|
||||
let mut sector_id = 0;
|
||||
|
||||
// walk through the parts to find the sector id
|
||||
for (index, part) in parts.enumerate() {
|
||||
if index < ( num_parts - 1 ) {
|
||||
working_enc += part;
|
||||
} else {
|
||||
sector_id = part.parse::<u32>().unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// count the characters in the string
|
||||
let mut hash: HashMap<char, u32> = HashMap::new();
|
||||
for current_char in working_enc.chars() {
|
||||
hash.entry(current_char).and_modify(|mut x| *x += 1).or_insert(1);
|
||||
}
|
||||
|
||||
// sort the hash into a flipped btreemap
|
||||
println!("[{line}] / ENCRYPTED = [{working_enc}] / Sector ID : [{sector_id}] / checksum [{checksum}]");
|
||||
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
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
use std::io::{stdout, Write};
|
||||
use md5::{Digest, Md5};
|
||||
|
||||
fn main() {
|
||||
let input = "wtnhxymk";
|
||||
let mut password = String::new();
|
||||
|
||||
for index in 2231253..=u32::MAX {
|
||||
let to_hash = format!("{}{}", input, index);
|
||||
let as_hash = format!("{:x}", Md5::digest(to_hash.as_bytes()));
|
||||
if as_hash.starts_with("00000") {
|
||||
// println!("Found hash with {index} -> {as_hash}");
|
||||
let ( sixth,_ ) = as_hash.as_str().split_at(5).1.split_at(1);
|
||||
println!("sixth = {sixth}");
|
||||
// print!(".");
|
||||
stdout().flush().unwrap();
|
||||
password += sixth;
|
||||
if password.len() == 8 {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("\nPassword is [{password}]");
|
||||
}
|
||||
// 2414bc77
|
||||
@@ -0,0 +1,26 @@
|
||||
use std::io::{stdout, Write};
|
||||
use md5::{Digest, Md5};
|
||||
|
||||
fn main() {
|
||||
let input = "wtnhxymk";
|
||||
let mut password = vec![' '; 8];
|
||||
|
||||
for index in 2231253..=u32::MAX {
|
||||
let to_hash = format!("{}{}", input, index);
|
||||
let as_hash = format!("{:x}", Md5::digest(to_hash.as_bytes()));
|
||||
if as_hash.starts_with("00000") {
|
||||
println!("Found hash with {index} -> {as_hash}");
|
||||
let ( sixth,balance ) = as_hash.as_str().split_at(5).1.split_at(1);
|
||||
let ( seventh, _) = balance.split_at(1);
|
||||
stdout().flush().unwrap();
|
||||
let index_for_new_char = sixth.parse::<u32>().unwrap_or(9);
|
||||
if index_for_new_char < 9 && password[index_for_new_char as usize] == ' ' {
|
||||
password[index_for_new_char as usize] = seventh.parse().unwrap();
|
||||
}
|
||||
println!("Index for new char = {index_for_new_char} / Password [{password:?}] / Seventh {seventh}"); // bail out if we have 8 characters
|
||||
|
||||
}
|
||||
}
|
||||
println!("\nPassword is [{password:?}]");
|
||||
}
|
||||
// 437e60fc
|
||||
@@ -0,0 +1,63 @@
|
||||
// Something is jamming your communications with Santa. Fortunately, your signal is only partially
|
||||
// jammed, and protocol in situations like this is to switch to a simple repetition code to get the
|
||||
// message through.
|
||||
//
|
||||
// In this model, the same message is sent repeatedly. You've recorded the repeating message signal
|
||||
// (your puzzle input), but the data seems quite corrupted - almost too badly to recover. Almost.
|
||||
//
|
||||
// All you need to do is figure out which character is most frequent for each position. For example,
|
||||
// suppose you had recorded the following messages:
|
||||
//
|
||||
// eedadn
|
||||
// drvtee
|
||||
// eandsr
|
||||
// raavrd
|
||||
// atevrs
|
||||
// tsrnev
|
||||
// sdttsa
|
||||
// rasrtv
|
||||
// nssdts
|
||||
// ntnada
|
||||
// svetve
|
||||
// tesnvt
|
||||
// vntsnd
|
||||
// vrdear
|
||||
// dvrsen
|
||||
// enarar
|
||||
// The most common character in the first column is e; in the second, a; in the third, s, and so on.
|
||||
// Combining these characters returns the error-corrected message, easter.
|
||||
//
|
||||
// Given the recording in your puzzle input, what is the error-corrected version of the message
|
||||
// being sent?
|
||||
//
|
||||
|
||||
use std::collections::HashMap;
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2016_06_data.txt");
|
||||
let lines = binding.lines();
|
||||
let mut final_string = String::new();
|
||||
|
||||
let mut results = vec![HashMap::<char, u32>::new(); 8];
|
||||
for line in lines {
|
||||
for (index, char) in line.chars().enumerate() {
|
||||
println!("Index {index} -> {char}");
|
||||
results[index].entry(char).and_modify(|x| *x += 1).or_insert(1);
|
||||
}
|
||||
}
|
||||
for results_column in &results {
|
||||
let mut current_max =0 ;
|
||||
let mut current_char = ' ';
|
||||
for (index, (key, value)) in results_column.iter().enumerate() {
|
||||
if current_max < *value {
|
||||
current_max = *value;
|
||||
current_char = *key;
|
||||
}
|
||||
}
|
||||
println!("Character {current_char} with {current_max}");
|
||||
final_string.push(current_char);
|
||||
}
|
||||
println!("Password is {final_string}");
|
||||
}
|
||||
// kjxfwkdh
|
||||
@@ -0,0 +1,46 @@
|
||||
// Of course, that would be the message - if you hadn't agreed to use a modified repetition code
|
||||
// instead.
|
||||
//
|
||||
// In this modified code, the sender instead transmits what looks like random data, but for each
|
||||
// character, the character they actually want to send is slightly less likely than the others.
|
||||
// Even after signal-jamming noise, you can look at the letter distributions in each column and
|
||||
// choose the least common letter to reconstruct the original message.
|
||||
//
|
||||
// In the above example, the least common character in the first column is a; in the second, d,
|
||||
// and so on. Repeating this process for the remaining characters produces the original message,
|
||||
// advent.
|
||||
//
|
||||
// Given the recording in your puzzle input and this new decoding methodology, what is the original
|
||||
// message that Santa is trying to send?
|
||||
//
|
||||
|
||||
use std::collections::HashMap;
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2016_06_data.txt");
|
||||
let lines = binding.lines();
|
||||
let mut final_string = String::new();
|
||||
|
||||
let mut results = vec![HashMap::<char, u32>::new(); 8];
|
||||
for line in lines {
|
||||
for (index, char) in line.chars().enumerate() {
|
||||
println!("Index {index} -> {char}");
|
||||
results[index].entry(char).and_modify(|x| *x += 1).or_insert(1);
|
||||
}
|
||||
}
|
||||
for results_column in &results {
|
||||
let mut current_min = u32::MAX ;
|
||||
let mut current_char = ' ';
|
||||
for (index, (key, value)) in results_column.iter().enumerate() {
|
||||
if current_min > *value {
|
||||
current_min = *value;
|
||||
current_char = *key;
|
||||
}
|
||||
}
|
||||
println!("Character {current_char} with {current_min}");
|
||||
final_string.push(current_char);
|
||||
}
|
||||
println!("Password is {final_string}");
|
||||
}
|
||||
// xrwcsnps
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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?
|
||||
|
||||
fn has_tls(input: &str) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let params = vec![
|
||||
("abba[mnop]qrst", true),
|
||||
("abcd[bddb]xyyx", false),
|
||||
("aaaa[qwer]tyui", false),
|
||||
("ioxxoj[asdfgh]zxcvbn", true)
|
||||
];
|
||||
|
||||
for (input, expected) in params {
|
||||
assert_eq!(has_tls(input), expected)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// The captcha requires you to review a sequence of digits (your puzzle input) and find the sum of all digits that match the next digit in the list. The list is circular, so the digit after the last digit is the first digit in the list.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// 1122 produces a sum of 3 (1 + 2) because the first digit (1) matches the second digit and the third digit (2) matches the fourth digit.
|
||||
// 1111 produces 4 because each digit (all 1) matches the next.
|
||||
// 1234 produces 0 because no digit matches the next.
|
||||
// 91212129 produces 9 because the only digit that matches the next one is the last digit, 9.
|
||||
|
||||
use aoc::read_data;
|
||||
|
||||
fn circular_digit_sum(input: &str) -> u32 {
|
||||
let mut running_total = 0;
|
||||
let mut first_char = ' ';
|
||||
let mut last_char = ' ';
|
||||
let input_length = input.len();
|
||||
for (index, char) in input.chars().enumerate() {
|
||||
if index == 0 {
|
||||
first_char = char;
|
||||
}
|
||||
if index == input_length - 1 {
|
||||
if char == first_char {
|
||||
let num_val = char.to_digit(10).unwrap();
|
||||
running_total += num_val;
|
||||
}
|
||||
}
|
||||
if char == last_char {
|
||||
let num_val = char.to_digit(10).unwrap();
|
||||
running_total += num_val;
|
||||
}
|
||||
last_char = char;
|
||||
}
|
||||
|
||||
running_total
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2017_01_data.txt");
|
||||
let params = vec![
|
||||
("1122", 3),
|
||||
("1111", 4),
|
||||
("1234", 0),
|
||||
("91212129", 9),
|
||||
(&*binding, 1031)
|
||||
];
|
||||
|
||||
for (param, expected) in params {
|
||||
let result = circular_digit_sum(param);
|
||||
print!("Checking if ||{param}|| calculates to ||{expected}|| actual ||{result}||...");
|
||||
assert_eq!(result, expected);
|
||||
println!("success!");
|
||||
}
|
||||
}
|
||||
// 1031
|
||||
@@ -0,0 +1,56 @@
|
||||
// Now, instead of considering the next digit, it wants you to consider the digit halfway around
|
||||
// the circular list. That is, if your list contains 10 items, only include a digit in your sum if
|
||||
// the digit 10/2 = 5 steps forward matches it. Fortunately, your list has an even number of
|
||||
// elements.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// 1212 produces 6: the list contains 4 items, and all four digits match the digit 2 items ahead.
|
||||
// 1221 produces 0, because every comparison is between a 1 and a 2.
|
||||
// 123425 produces 4, because both 2s match each other, but no other digit has a match.
|
||||
// 123123 produces 12.
|
||||
// 12131415 produces 4.
|
||||
|
||||
use aoc::read_data;
|
||||
|
||||
fn halfway_sum_thing(input: &str) -> u32 {
|
||||
let mut running_total = 0;
|
||||
let total_len = input.len();
|
||||
let mut mid_point = total_len / 2;
|
||||
|
||||
for index in 0..=mid_point {
|
||||
let second_index = index + mid_point;
|
||||
let first_char = input.as_bytes()[index];
|
||||
let second_char = input.as_bytes()[index + mid_point];
|
||||
println!("{input} / Comparing {index} and {second_index} of {total_len}");
|
||||
let input_chars: Vec<_> = input.chars().collect();
|
||||
println!("CHARS INPUT = {input_chars:?}");
|
||||
// let second = input.chars().collect()[index + mid_point];
|
||||
if first_char == second_char {
|
||||
println!("match {first_char} == {second_char}");
|
||||
} else {
|
||||
println!("no match");
|
||||
}
|
||||
}
|
||||
|
||||
running_total as u32
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2017_01_data.txt");
|
||||
let params = vec![
|
||||
("1212", 6),
|
||||
("1221", 0),
|
||||
("123425", 4),
|
||||
("123123", 12),
|
||||
("12131415", 4),
|
||||
(&binding, 0)
|
||||
];
|
||||
|
||||
for (input, expected) in params {
|
||||
let result = halfway_sum_thing(input);
|
||||
println!("Input: {input} results in {result} with {expected} expected.");
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
}
|
||||
//
|
||||
@@ -0,0 +1,26 @@
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let mut running_total = 0;
|
||||
let binding = read_data("2017_02_data.txt");
|
||||
let lines = binding.lines();
|
||||
for line in lines {
|
||||
let parts = line.split_whitespace();
|
||||
let mut highest = 0;
|
||||
let mut lowest = i32::MAX;
|
||||
for part in parts {
|
||||
println!("**PART = {part}");
|
||||
let val = part.parse().unwrap();
|
||||
if lowest > val {
|
||||
lowest = val;
|
||||
}
|
||||
if highest < val {
|
||||
highest = val;
|
||||
}
|
||||
}
|
||||
println!("||{line}|| <<<< LINE DONE -> {highest} > {lowest}");
|
||||
running_total += highest - lowest;
|
||||
}
|
||||
println!("Is the total {running_total}?");
|
||||
}
|
||||
// 53460
|
||||
@@ -0,0 +1,35 @@
|
||||
// To ensure security, a valid passphrase must contain no duplicate words.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// aa bb cc dd ee is valid.
|
||||
// aa bb cc dd aa is not valid - the word aa appears more than once.
|
||||
// aa bb cc dd aaa is valid - aa and aaa count as different words.
|
||||
// The system's full passphrase list is available as your puzzle input. How many passphrases are valid?
|
||||
//
|
||||
|
||||
use std::collections::HashMap;
|
||||
use aoc::read_data;
|
||||
|
||||
fn is_valid(input: &str) -> bool {
|
||||
let parts = input.split(' ');
|
||||
let mut working = HashMap::new();
|
||||
|
||||
for part in parts {
|
||||
working.entry(part);
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// let binding = read_data("2017_04_data.txt");
|
||||
let params = vec![
|
||||
("aa bb cc dd ee", true),
|
||||
("aa bb cc dd aa", false),
|
||||
("aa bb cc dd aaa", true)
|
||||
];
|
||||
for (input, expected) in params {
|
||||
let actual = is_valid(input);
|
||||
println!("||{input}|| was expected to be {expected} but was {actual}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Starting with a frequency of zero, what is the resulting frequency after all of the changes in
|
||||
// frequency have been applied?
|
||||
|
||||
use std::collections::HashMap;
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let mut running_total = 0i32;
|
||||
let binding = read_data("2018_01_data.txt");
|
||||
let lines = binding.lines();
|
||||
for line in lines {
|
||||
let (direction, value) = line.split_at(1);
|
||||
let num_val: i32 = value.parse().unwrap();
|
||||
|
||||
println!("Line = {line} -> {direction}||{num_val}");
|
||||
match direction {
|
||||
"-" => {
|
||||
running_total -= num_val;
|
||||
}
|
||||
"+" => {
|
||||
running_total += num_val;
|
||||
}
|
||||
_ => {
|
||||
unreachable!("bad location");
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("Final value = {running_total}");
|
||||
}
|
||||
// 533
|
||||
@@ -0,0 +1,36 @@
|
||||
// do part 1a but figure out the first repeated value
|
||||
|
||||
use std::collections::HashMap;
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let mut visited_locations: HashMap<i32, i32> = HashMap::from([(0, 0)]);
|
||||
// let binding = read_data("2018_01_data.txt");
|
||||
// let lines = binding.lines();
|
||||
let lines = "-6\n+3\n+8\n+5\n-6".to_string();
|
||||
let mut working_value = 0i32;
|
||||
|
||||
for line in lines.lines() {
|
||||
let (direction, velocity) = line.split_at(1);
|
||||
// println!("{line} split to ||{direction}|| and ||{velocity}||");
|
||||
let direction_val : i32 = velocity.parse().unwrap();
|
||||
match direction {
|
||||
"+" => {
|
||||
working_value += direction_val;
|
||||
}
|
||||
"-" => {
|
||||
working_value -= direction_val;
|
||||
}
|
||||
_ => {
|
||||
unreachable!("Invalid direction");
|
||||
}
|
||||
}
|
||||
print!("{working_value}\t");
|
||||
if let Some(found) = visited_locations.get(&working_value) {
|
||||
println!("GET SUCCESS -> {working_value} / {found}");
|
||||
break;
|
||||
}
|
||||
visited_locations.insert(working_value, 0);
|
||||
}
|
||||
}
|
||||
// BROKEN
|
||||
@@ -0,0 +1,20 @@
|
||||
#![feature(int_roundings)]
|
||||
|
||||
use aoc::read_data;
|
||||
|
||||
fn fuel_calc(input: u32) -> u32 {
|
||||
input.div_floor(3).saturating_sub(2)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut working_value = 0;
|
||||
let binding = read_data("2019_01_data.txt");
|
||||
let lines = binding.lines();
|
||||
for line in lines {
|
||||
let number: u32 = line.parse().unwrap();
|
||||
// println!("Line -> {line} - [{number}]");
|
||||
working_value += fuel_calc(number);
|
||||
}
|
||||
println!("Working Value without self-> {working_value}");
|
||||
}
|
||||
// 3228475
|
||||
@@ -0,0 +1,28 @@
|
||||
#![feature(int_roundings)]
|
||||
|
||||
use aoc::read_data;
|
||||
|
||||
fn fuel_calc(input: u32) -> u32 {
|
||||
input.div_floor(3).saturating_sub(2)
|
||||
}
|
||||
|
||||
fn total_fuel(mut mass: u32) -> u32 {
|
||||
let mut total = 0;
|
||||
while mass > 0 {
|
||||
mass = fuel_calc(mass);
|
||||
total += mass;
|
||||
}
|
||||
total
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut working_value = 0;
|
||||
let binding = read_data("2019_01_data.txt");
|
||||
let lines = binding.lines();
|
||||
for line in lines {
|
||||
let number: u32 = line.parse().unwrap();
|
||||
working_value += total_fuel(number);
|
||||
}
|
||||
println!("Working Value without self-> {working_value}");
|
||||
}
|
||||
// 4839845
|
||||
@@ -0,0 +1,9 @@
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let directions = read_data("2019_02_data.txt").split(", ");
|
||||
|
||||
for direction in directions {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
fn is_valid(input: i32) -> bool {
|
||||
let mut has_double = false;
|
||||
let mut last_digit: Option<i32> = None;
|
||||
|
||||
for current_char in input.to_string().chars() {
|
||||
let current_digit = current_char.to_digit(10).unwrap() as i32;
|
||||
|
||||
if let Some(last) = last_digit {
|
||||
if last > current_digit {
|
||||
// Digits decrease → invalid
|
||||
return false;
|
||||
}
|
||||
if last == current_digit {
|
||||
has_double = true;
|
||||
}
|
||||
}
|
||||
|
||||
last_digit = Some(current_digit);
|
||||
}
|
||||
|
||||
has_double
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in 136818..=685979 {
|
||||
print!("START [[{input}]]");
|
||||
if is_valid(input) {
|
||||
println!("Success at {input}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 136888 bad
|
||||
// 145678 bad
|
||||
// 136888
|
||||
@@ -0,0 +1,31 @@
|
||||
fn is_valid(input: i32) -> bool {
|
||||
let mut has_double = false;
|
||||
let mut last_digit: Option<i32> = None;
|
||||
|
||||
for current_char in input.to_string().chars() {
|
||||
let current_digit = current_char.to_digit(10).unwrap() as i32;
|
||||
|
||||
if let Some(last) = last_digit {
|
||||
if last > current_digit {
|
||||
// Digits decrease → invalid
|
||||
return false;
|
||||
}
|
||||
if last == current_digit {
|
||||
has_double = true;
|
||||
}
|
||||
}
|
||||
|
||||
last_digit = Some(current_digit);
|
||||
}
|
||||
|
||||
has_double
|
||||
}
|
||||
|
||||
fn main() {
|
||||
for input in 136818..=685979 {
|
||||
if is_valid(input) {
|
||||
println!("Success at {input}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2020_01_data.txt");
|
||||
let lines = binding.lines();
|
||||
let mut numbers = vec![];
|
||||
let mut left = 0;
|
||||
let mut right = 0;
|
||||
|
||||
for line in lines {
|
||||
numbers.push(line.parse::<u32>().unwrap());
|
||||
}
|
||||
|
||||
for left_number in numbers.clone() {
|
||||
for right_number in numbers.clone() {
|
||||
if left_number + right_number == 2020 {
|
||||
println!("Found {left_number} and {right_number}");
|
||||
println!("Multiplied they are {}", left_number * right_number);
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 972576
|
||||
@@ -0,0 +1,63 @@
|
||||
use aoc::read_data;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ParsedLine {
|
||||
pub min: u32,
|
||||
pub max: u32,
|
||||
pub char: char,
|
||||
pub pass: String,
|
||||
pub raw: String
|
||||
}
|
||||
|
||||
fn is_valid(input: ParsedLine) -> bool {
|
||||
let mut num_char_found = 0;
|
||||
for char in input.pass.chars() {
|
||||
if char == input.char {
|
||||
num_char_found += 1;
|
||||
}
|
||||
}
|
||||
|
||||
println!("||{}|| Found CHAR {} REPEATED {num_char_found} TIMES", input.raw, input.char);
|
||||
|
||||
num_char_found <= input.max && num_char_found >= input.min
|
||||
}
|
||||
|
||||
fn parse_string_to_parts(input: &str) -> ParsedLine {
|
||||
let (both_ranges, balance) = input.split_once(" ").unwrap();
|
||||
let (low_count, high_count) = both_ranges.split_once('-').unwrap();
|
||||
let (find_char, balance) = balance.split_once(':').unwrap();
|
||||
|
||||
ParsedLine {
|
||||
min: low_count.parse().unwrap(),
|
||||
max: high_count.parse().unwrap(),
|
||||
char: find_char.chars().next().unwrap(),
|
||||
pass: balance.to_string(),
|
||||
raw: input.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
let mut num_valid = 0;
|
||||
let params = vec![
|
||||
("1-3 a: abcde", true),
|
||||
("1-3 b: cdefg", false),
|
||||
("2-9 c: ccccccccc", true)
|
||||
];
|
||||
|
||||
let binding = read_data("2020_02_data.txt");
|
||||
let lines = binding.lines();
|
||||
|
||||
for input in lines {
|
||||
let parsed = parse_string_to_parts(input);
|
||||
let result = is_valid(parsed.clone());
|
||||
// println!("Testing [{input}] and RESULT [{result}]");
|
||||
// assert_eq!(is_valid(parsed), output);
|
||||
if result {
|
||||
num_valid += 1;
|
||||
}
|
||||
}
|
||||
println!("Found {num_valid} valid passwords.");
|
||||
}
|
||||
// 493
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
use std::io::{stdout, Write};
|
||||
use aoc::read_data;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ParsedLine {
|
||||
pub must: u32,
|
||||
pub isnt: u32,
|
||||
pub char: char,
|
||||
pub pass: String,
|
||||
pub raw: String
|
||||
}
|
||||
|
||||
fn parse_string_to_parts(input: &str) -> ParsedLine {
|
||||
let (both_ranges, balance) = input.split_once(" ").unwrap();
|
||||
let (low_count, high_count) = both_ranges.split_once('-').unwrap();
|
||||
let (find_char, balance) = balance.split_once(':').unwrap();
|
||||
|
||||
ParsedLine {
|
||||
must: low_count.parse().unwrap(),
|
||||
isnt: high_count.parse().unwrap(),
|
||||
char: find_char.chars().next().unwrap(),
|
||||
pass: balance.trim().to_string(),
|
||||
raw: input.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
// are the Nth characters a match, but only 1?
|
||||
fn is_valid(input: ParsedLine) -> bool {
|
||||
(input.pass.chars().nth((input.must -1) as usize).unwrap() == input.char) ^
|
||||
(input.pass.chars().nth((input.isnt - 1) as usize).unwrap() == input.char)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut num_valid = 0;
|
||||
|
||||
let binding = read_data("2020_02_data.txt");
|
||||
let lines = binding.lines();
|
||||
let params = lines;
|
||||
|
||||
for param in params {
|
||||
let parsed = parse_string_to_parts(param);
|
||||
|
||||
if is_valid(parsed) {
|
||||
num_valid += 1;
|
||||
}
|
||||
}
|
||||
println!("There are {num_valid} valid passwords.");
|
||||
}
|
||||
// 593
|
||||
@@ -0,0 +1,26 @@
|
||||
use aoc::read_data;
|
||||
|
||||
fn dips(input: &str) -> u32 {
|
||||
let mut last_reading = 0;
|
||||
let mut counter = 0;
|
||||
for line in input.lines() {
|
||||
let current_reading: u32 = line.parse().unwrap();
|
||||
if last_reading <= current_reading {
|
||||
counter += 1;
|
||||
println!("Increase from {} to {}", current_reading, last_reading);
|
||||
}
|
||||
last_reading = current_reading;
|
||||
}
|
||||
// first is always 0
|
||||
counter -= 1;
|
||||
println!("There were {counter} decreasing readings.");
|
||||
counter
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2021_01_data.txt");
|
||||
let lines = binding;
|
||||
println!("Test 1 -> {}", dips("199\n200\n208\n210\n200\n207\n240\n269\n260\n263"));
|
||||
// println!("Found {}", dips(lines.as_str()));
|
||||
}
|
||||
// 1791
|
||||
@@ -0,0 +1,33 @@
|
||||
use aoc::read_data;
|
||||
|
||||
enum CardinalDirection {
|
||||
North,
|
||||
East,
|
||||
South,
|
||||
West
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut facing = CardinalDirection::North;
|
||||
let (mut current_x, mut current_y) = (0u32, 0u32);
|
||||
let binding = read_data("2021_02_data.txt");
|
||||
let steps = binding.lines();
|
||||
for step in steps {
|
||||
let (direction, velocity) = step.split_once(" ").unwrap();
|
||||
let velocity: u32 = velocity.parse().unwrap();
|
||||
match direction {
|
||||
"forward" => {
|
||||
println!("Move forward {}", velocity);
|
||||
},
|
||||
"down" => {
|
||||
println!("Move Down {}", velocity);
|
||||
},
|
||||
"up" => {
|
||||
println!("Move UP {}", velocity);
|
||||
},
|
||||
_ => {
|
||||
unreachable!("Invalid direction");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2022_01_data.txt");
|
||||
let lines = binding.lines();
|
||||
let mut working_elf_count = 0;
|
||||
let mut most_carried = 0;
|
||||
|
||||
for line in lines {
|
||||
if line.trim() == "" {
|
||||
// time to record this as a total
|
||||
if working_elf_count > most_carried {
|
||||
most_carried = working_elf_count;
|
||||
}
|
||||
working_elf_count = 0;
|
||||
} else {
|
||||
let next_value: u32 = line.trim().parse().unwrap();
|
||||
working_elf_count += next_value;
|
||||
println!("Read {next_value} / {working_elf_count}");
|
||||
}
|
||||
}
|
||||
println!("Most carried = {most_carried}");
|
||||
}
|
||||
// 64929
|
||||
@@ -0,0 +1,51 @@
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2022_01_data.txt");
|
||||
let lines = binding.lines();
|
||||
let mut working_elf_count = 0;
|
||||
let mut most_carried = 0;
|
||||
let mut second_most_carried = 0;
|
||||
let mut third_most_carried = 0;
|
||||
|
||||
for line in lines {
|
||||
if line.trim().is_empty() {
|
||||
// record this elf
|
||||
if working_elf_count > most_carried {
|
||||
third_most_carried = second_most_carried;
|
||||
second_most_carried = most_carried;
|
||||
most_carried = working_elf_count;
|
||||
} else if working_elf_count > second_most_carried {
|
||||
third_most_carried = second_most_carried;
|
||||
second_most_carried = working_elf_count;
|
||||
} else if working_elf_count > third_most_carried {
|
||||
third_most_carried = working_elf_count;
|
||||
}
|
||||
working_elf_count = 0;
|
||||
} else {
|
||||
let next_value: u32 = line.trim().parse().unwrap();
|
||||
working_elf_count += next_value;
|
||||
}
|
||||
}
|
||||
|
||||
// flush last elf in case file doesn't end with blank line
|
||||
if working_elf_count > 0 {
|
||||
if working_elf_count > most_carried {
|
||||
third_most_carried = second_most_carried;
|
||||
second_most_carried = most_carried;
|
||||
most_carried = working_elf_count;
|
||||
} else if working_elf_count > second_most_carried {
|
||||
third_most_carried = second_most_carried;
|
||||
second_most_carried = working_elf_count;
|
||||
} else if working_elf_count > third_most_carried {
|
||||
third_most_carried = working_elf_count;
|
||||
}
|
||||
}
|
||||
|
||||
println!(
|
||||
"Most carried = {most_carried} + {second_most_carried} + {third_most_carried} = {}",
|
||||
most_carried + second_most_carried + third_most_carried
|
||||
);
|
||||
}
|
||||
// 193697
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
use aoc::read_data;
|
||||
use crate::RPSOutcome::{Loss, Tie, Win};
|
||||
use crate::RPSPlays::{Paper, Rock, Scissors};
|
||||
|
||||
enum RPSOutcome {
|
||||
Win,
|
||||
Loss,
|
||||
Tie
|
||||
}
|
||||
|
||||
enum RPSPlays {
|
||||
Rock,
|
||||
Paper,
|
||||
Scissors
|
||||
}
|
||||
|
||||
fn str_to_rps(input: &str) -> RPSPlays {
|
||||
match input {
|
||||
"A" | "X" => { Rock },
|
||||
"B" | "Y" => { Paper },
|
||||
"C" | "Z" => { Scissors },
|
||||
_ => { unreachable!("Invalid Conversion"); }
|
||||
}
|
||||
}
|
||||
|
||||
fn play_to_score(input: &str) -> u32 {
|
||||
match str_to_rps(input) {
|
||||
Rock => 1,
|
||||
Paper => 2,
|
||||
Scissors => 3
|
||||
}
|
||||
}
|
||||
|
||||
fn did_i_win(them: &str, me: &str) -> RPSOutcome {
|
||||
match (str_to_rps(them), str_to_rps(me)) {
|
||||
(Rock, Rock) | (Paper, Paper) | (Scissors, Scissors) => Tie,
|
||||
(Rock, Paper) | (Paper, Scissors) | (Scissors, Rock) => Win,
|
||||
(Rock, Scissors) | (Paper, Rock) | (Scissors, Paper) => Loss,
|
||||
_ => { unreachable!("Invalid Game"); }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut running_score = 0;
|
||||
let binding = read_data("2022_02_data.txt");
|
||||
let lines = binding.lines();
|
||||
for line in lines {
|
||||
let mut this_round = 0;
|
||||
let (them, me) = line.split_once(" ").unwrap();
|
||||
this_round = play_to_score(me);
|
||||
match did_i_win(them, me) {
|
||||
Win => {
|
||||
this_round += 6;
|
||||
}
|
||||
Loss => {
|
||||
// nothing.
|
||||
}
|
||||
Tie => {
|
||||
this_round += 3;
|
||||
}
|
||||
}
|
||||
running_score += this_round;
|
||||
}
|
||||
println!("Final = {running_score}");
|
||||
}
|
||||
// 14531
|
||||
@@ -0,0 +1,117 @@
|
||||
use aoc::read_data;
|
||||
use crate::RPSOutcome::{Loss, Tie, Win};
|
||||
use crate::RPSPlays::{Paper, Rock, Scissors};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum RPSOutcome {
|
||||
Win,
|
||||
Loss,
|
||||
Tie,
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
enum RPSPlays {
|
||||
Rock,
|
||||
Paper,
|
||||
Scissors,
|
||||
}
|
||||
|
||||
fn str_to_rps(input: &str) -> RPSPlays {
|
||||
println!("STR_TO_RPS -> {input}");
|
||||
match input {
|
||||
"A" => { Rock }
|
||||
"B" => { Paper }
|
||||
"C" => { Scissors }
|
||||
_ => { unreachable!("Invalid Conversion"); }
|
||||
}
|
||||
}
|
||||
|
||||
fn play_to_score(input: &str) -> u32 {
|
||||
match str_to_rps(input) {
|
||||
Rock => 1,
|
||||
Paper => 2,
|
||||
Scissors => 3
|
||||
}
|
||||
}
|
||||
|
||||
fn need_to_loose(them: RPSPlays) -> RPSPlays {
|
||||
match them {
|
||||
Rock => { Scissors }
|
||||
Paper => { Rock }
|
||||
Scissors => { Paper }
|
||||
}
|
||||
}
|
||||
|
||||
fn need_to_tie(them: RPSPlays) -> RPSPlays {
|
||||
them
|
||||
}
|
||||
|
||||
fn need_to_win(them: RPSPlays) -> RPSPlays {
|
||||
let result = match them {
|
||||
Rock => { Paper }
|
||||
Paper => { Scissors }
|
||||
Scissors => { Rock }
|
||||
};
|
||||
println!("Checking on {them:?} to win / {result:?}");
|
||||
result
|
||||
}
|
||||
|
||||
fn str_to_desired_outcome(input: &str) -> RPSOutcome {
|
||||
match input {
|
||||
"X" => { Loss }
|
||||
"Y" => { Tie }
|
||||
"Z" => { Win }
|
||||
_ => { unreachable!("Invalid Requested outcome {}", input); }
|
||||
}
|
||||
}
|
||||
|
||||
fn win_loose_tie_score(them: RPSPlays, me: RPSPlays) -> u32 {
|
||||
match (them, me) {
|
||||
(Rock, Rock) | (Paper, Paper) | (Scissors, Scissors) => 3,
|
||||
(Rock, Scissors) | (Paper, Rock) | (Scissors, Paper) => 0,
|
||||
_ => 6
|
||||
}
|
||||
}
|
||||
|
||||
fn points_for_play(to_score: RPSPlays) -> u32 {
|
||||
match to_score {
|
||||
Rock => { 1 }
|
||||
Paper => { 2 }
|
||||
Scissors => { 3 }
|
||||
}
|
||||
}
|
||||
|
||||
fn score_game(them: RPSPlays, me: RPSPlays) -> u32 {
|
||||
win_loose_tie_score(them, me.clone()) + points_for_play(me)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2022_02_data.txt");
|
||||
let mut running_total = 0;
|
||||
let mut goal = Win;
|
||||
let lines = binding.lines();
|
||||
for line in lines {
|
||||
println!("__________STARTING TO PROCESS ||[{line}]||");
|
||||
let (them, me) = line.split_once(" ").unwrap();
|
||||
let them_rps = str_to_rps(them);
|
||||
println!("MATCHED OUT TO ||{:?}||{:?}", them_rps, str_to_desired_outcome(me));
|
||||
let my_play = match str_to_desired_outcome(me) {
|
||||
Win => {
|
||||
need_to_win(them_rps.clone())
|
||||
}
|
||||
Loss => {
|
||||
goal = Loss;
|
||||
need_to_loose(them_rps.clone())
|
||||
}
|
||||
Tie => {
|
||||
goal = Tie;
|
||||
need_to_tie(them_rps.clone())
|
||||
}
|
||||
};
|
||||
let game_score = score_game(them_rps.clone(), my_play.clone());
|
||||
println!("They play {:?} I play {:?} to {:?}", them_rps, my_play, goal);
|
||||
println!("SCORE = {}", game_score);
|
||||
running_total += game_score;
|
||||
}
|
||||
println!("Total = {running_total}");
|
||||
}
|
||||
// 11258
|
||||
@@ -0,0 +1,43 @@
|
||||
use std::collections::HashSet;
|
||||
use std::io::BufRead;
|
||||
use aoc::read_data;
|
||||
|
||||
|
||||
fn char_to_value(input: char) -> u32 {
|
||||
let mut return_value = 0;
|
||||
if input.is_ascii_alphabetic() {
|
||||
let as_integer: u8 = input.to_string().bytes().collect::<Vec<_>>()[0];
|
||||
if as_integer >= 97 && as_integer <= 122 {
|
||||
return_value = as_integer - 96;
|
||||
} else {
|
||||
return_value = as_integer - 38; // 64 - 26
|
||||
}
|
||||
}
|
||||
return_value as u32
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut running_total = 0;
|
||||
let binding = read_data("2022_03_data.txt");
|
||||
let lines = binding.lines();
|
||||
|
||||
for line in lines {
|
||||
let line_len = line.len();
|
||||
let (bag1, bag2) = line.split_at(line_len / 2);
|
||||
println!("||{line}|| became ||{bag1}|| and ||{bag2}||");
|
||||
let (mut working_bag1, mut working_bag2) = (HashSet::new(), HashSet::new());
|
||||
for current_char in bag1.chars() {
|
||||
working_bag1.insert(current_char);
|
||||
}
|
||||
for current_char in bag2.chars() {
|
||||
working_bag2.insert(current_char);
|
||||
}
|
||||
|
||||
let duplicates: char = working_bag1.intersection(&working_bag2).cloned().collect::<Vec<_>>()[0];
|
||||
|
||||
println!("DUPES = {}", duplicates);
|
||||
running_total += char_to_value(duplicates);
|
||||
}
|
||||
println!("Final = {running_total}");
|
||||
}
|
||||
// 7848 too low
|
||||
@@ -0,0 +1,10 @@
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let binding = read_data("2022_03_data.txt");
|
||||
let lines: Vec<&str> = binding.lines().collect();
|
||||
for chunk in lines.chunks(3) {
|
||||
println!("{:?}", chunk);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
use aoc::read_data;
|
||||
|
||||
fn main() {
|
||||
let mut running_total = 0;
|
||||
let binding = read_data("2023_01_data.txt");
|
||||
let lines = binding.lines();
|
||||
|
||||
// let lines = "1abc2\npqr3stu8vwx\na1b2c3d4e5f\ntreb7uchet".lines();
|
||||
|
||||
for line in lines {
|
||||
let mut working_string = String::new();
|
||||
for char in line.chars() {
|
||||
if char.is_numeric() {
|
||||
working_string.push(char);
|
||||
}
|
||||
}
|
||||
// take first and last chars
|
||||
let this_round: u32 = match working_string.len() {
|
||||
1 => {
|
||||
let mut short = working_string.clone();
|
||||
short.push(working_string.chars().next().unwrap());
|
||||
short.parse().unwrap()
|
||||
},
|
||||
1 => working_string.parse().unwrap(),
|
||||
_ => {
|
||||
let last_char = working_string.len() - 1;
|
||||
let mut short_string = String::new();
|
||||
short_string.push(working_string.chars().next().unwrap());
|
||||
short_string.push(working_string.chars().last().unwrap());
|
||||
// println!("Unhandled ||{working_string}|| / {short_string}");
|
||||
short_string.parse().unwrap()
|
||||
}
|
||||
};
|
||||
running_total += this_round;
|
||||
println!("{line:>50} found number {working_string:>10}\t{this_round}\t{running_total}");
|
||||
}
|
||||
println!("running total = {running_total}");
|
||||
}
|
||||
// 54916 too low
|
||||
@@ -0,0 +1,20 @@
|
||||
fn num_to_change(input: &str) -> usize {
|
||||
let mut return_value = 0;
|
||||
let mut last_char = '\0';
|
||||
|
||||
for (index, current_char) in input.chars().enumerate() {
|
||||
if index != 0 {
|
||||
if last_char != current_char {
|
||||
return_value = index;
|
||||
break
|
||||
}
|
||||
}
|
||||
last_char = current_char
|
||||
}
|
||||
return_value
|
||||
}
|
||||
|
||||
fn main () {
|
||||
assert_eq!(num_to_change("01234567"), 1);
|
||||
assert_eq!(num_to_change("00000000001"), 10);
|
||||
}
|
||||
Reference in New Issue
Block a user