Created
November 28, 2023 05:14
-
-
Save bozdoz/c9acfcdf50957444fe5c37faa5af6bc8 to your computer and use it in GitHub Desktop.
2019 Advent of Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// to find the fuel required for a module, take its mass, divide by three, round down, and subtract 2. | |
use std::fs; | |
use std::io::Error; | |
fn main() -> Result<(), Error> { | |
let contents = fs::read_to_string("./src/input.txt"); | |
let data = match contents { | |
Ok(c) => c, | |
Err(e) => return Err(e), | |
}; | |
let numbers: Vec<u32> = data.lines().map(|x| x.parse::<u32>().unwrap()).collect(); | |
let mut sum = 0; | |
for n in numbers { | |
let mut m = n; | |
while m > 2 { | |
let mut f = m / 3; | |
if f < 2 { | |
f = 0; | |
} else { | |
f -= 2; | |
} | |
sum += f; | |
m = f; | |
} | |
} | |
println!("{}", sum); | |
Ok(()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use lib::get_part; | |
use std::{fs, time::Instant}; | |
fn program(opcode: &mut Vec<u32>) -> Vec<u32> { | |
// opcodes: | |
// 1 means add | |
// 2 means multiply | |
// 99 means stop | |
// next two are inputs, last is output | |
let mut i = 0; | |
loop { | |
let cur = opcode[i]; | |
match cur { | |
1 => { | |
let one = opcode[opcode[i + 1] as usize]; | |
let two = opcode[opcode[i + 2] as usize]; | |
let result = opcode[i + 3]; | |
opcode[result as usize] = one + two; | |
} | |
2 => { | |
let one = opcode[opcode[i + 1] as usize]; | |
let two = opcode[opcode[i + 2] as usize]; | |
let result = opcode[i + 3]; | |
opcode[result as usize] = one * two; | |
} | |
99 => { | |
break; | |
} | |
_ => { | |
panic!("Damn, not sure what this is: {}", cur) | |
} | |
} | |
i += 4; | |
} | |
opcode.clone() | |
} | |
fn find(opcode: &Vec<u32>, num: u32) -> Option<Vec<u32>> { | |
for x in 0..=99 { | |
for y in 0..=99 { | |
let mut newopcode = opcode.clone(); | |
newopcode[1] = x; | |
newopcode[2] = y; | |
let newopcode = program(&mut newopcode); | |
if newopcode[0] == num { | |
return Some(newopcode); | |
} | |
} | |
} | |
None | |
} | |
fn main() { | |
let (one, two) = get_part(); | |
let start = Instant::now(); | |
let contents = fs::read_to_string("./src/input.txt").expect("couldn't open input.txt"); | |
let original: Vec<u32> = contents.trim().split(",").map(|x| x.parse::<u32>().unwrap()).collect(); | |
if one { | |
let mut opcode = original.clone(); | |
// before running the program, replace position 1 with the value 12 and replace position 2 with the value 2. | |
opcode[1] = 12; | |
opcode[2] = 2; | |
let opcode = program(&mut opcode); | |
println!("Part One: {:?}", opcode[0]) | |
} | |
if two { | |
if let Some(opcode) = find(&original, 19690720) { | |
println!("Part Two: {:?}", 100 * opcode[1] + opcode[2]) | |
} else { | |
println!("nothing found for part two!"); | |
} | |
} | |
println!("Elapsed: {:?}", start.elapsed()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::{fs, time::Instant}; | |
use lib::get_part; | |
const FILENAME: &str = "./src/input.txt"; | |
#[derive(Clone, Copy, Debug)] | |
struct Point { | |
x: i32, | |
y: i32, | |
} | |
impl Point { | |
fn add(mut self, other: Point) -> Self { | |
self.x += other.x; | |
self.y += other.y; | |
self | |
} | |
} | |
#[derive(Clone, Copy, Debug)] | |
enum Line { | |
Vertical((Point, Point)), | |
Horizontal((Point, Point)), | |
Empty, | |
} | |
impl Line { | |
fn from(prev: &Line, input: &str) -> Line { | |
let dir = input.chars().nth(0).unwrap(); | |
let len = input[1..].parse::<i32>().unwrap(); | |
let origin: Point = match prev { | |
Line::Empty => { Point { x: 0, y: 0 } } | |
Line::Horizontal(a) => { a.1 } | |
Line::Vertical(a) => { a.1 } | |
}; | |
match dir { | |
'U' => { | |
Line::Vertical((origin, origin.add(Point { x: 0, y: len }))) | |
} | |
'D' => { | |
Line::Vertical((origin, origin.add(Point { x: 0, y: -len }))) | |
} | |
'R' => { | |
Line::Horizontal((origin, origin.add(Point { x: len, y: 0 }))) | |
} | |
'L' => { | |
Line::Horizontal((origin, origin.add(Point { x: -len, y: 0 }))) | |
} | |
_ => { Line::Empty } | |
} | |
} | |
fn intersects(&self, b: &Line) -> Option<Point> { | |
match (self, b) { | |
| (Line::Vertical(v), Line::Horizontal(h)) | |
| (Line::Horizontal(h), Line::Vertical(v)) => { | |
// lines are perpendicular | |
let (v1, v2) = v; | |
let (h1, h2) = h; | |
let vx = v1.x; | |
let hy = h1.y; | |
if is_between(vx, h1.x, h2.x) && is_between(hy, v1.y, v2.y) { | |
Some(Point { x: vx, y: hy }) | |
} else { | |
None | |
} | |
} | |
_ => { None } | |
} | |
} | |
} | |
fn is_between<T: std::cmp::PartialOrd>(a: T, b: T, c: T) -> bool { | |
let (start, end) = if b < c { (b, c) } else { (c, b) }; | |
a >= start && a <= end | |
} | |
fn parse_data(data: &String) -> Vec<Vec<Line>> { | |
let mut out: Vec<Vec<Line>> = vec![]; | |
let lines = data.lines(); | |
let mut cur_line = Line::Empty; | |
for line in lines { | |
let mut current: Vec<Line> = vec![]; | |
let directions = line.split(","); | |
for direction in directions { | |
cur_line = Line::from(&cur_line, direction); | |
current.push(cur_line); | |
} | |
out.push(current); | |
cur_line = Line::Empty; | |
} | |
out | |
} | |
fn part_one(data: Vec<Vec<Line>>) -> u32 { | |
let first = &data[0]; | |
let second = &data[1]; | |
let mut intersections: Vec<Point> = vec![]; | |
for f in first { | |
for s in second { | |
if let Some(inter) = f.intersects(s) { | |
intersections.push(inter); | |
} | |
} | |
} | |
let shortest = if let Some(point) = intersections.get(1) { | |
point | |
} else { | |
&Point{ x: 0, y: 0 } | |
}; | |
let mut shortest = manhattan_distance(*shortest); | |
for point in intersections.iter().skip(2) { | |
let d = manhattan_distance(*point); | |
if d < shortest { | |
shortest = d; | |
} | |
} | |
shortest | |
} | |
fn manhattan_distance(p: Point) -> u32 { | |
p.x.wrapping_abs() as u32 + p.y.wrapping_abs() as u32 | |
} | |
fn part_two() {} | |
fn main() { | |
let (one, two) = get_part(); | |
let start = Instant::now(); | |
let contents = fs | |
::read_to_string(FILENAME) | |
.expect("couldn't open input.txt"); | |
let parsed = parse_data(&contents); | |
if one { | |
let ans = part_one(parsed); | |
println!("Part one: {} {:?}", ans, start.elapsed()) | |
} | |
if two { | |
part_two(); | |
println!("Part two: "); | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
// Import the necessary items from the standard library for testing | |
use super::*; | |
// A basic unit test for the main function | |
#[test] | |
fn test_main() { | |
// Use the assert_eq! macro to check if the output matches the expected result | |
assert_eq!(main(), ()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::env; | |
pub fn get_part() -> (bool, bool) { | |
let args = env::args().skip(1); | |
let mut hasone = false; | |
let mut hastwo = false; | |
for arg in args { | |
if arg.contains(&String::from("one")) { | |
hasone = true; | |
} | |
if arg.contains(&String::from("two")) { | |
hastwo = true; | |
} | |
} | |
if !hasone && !hastwo { | |
// run them both by default | |
hasone = true; | |
hastwo = true; | |
} | |
(hasone, hastwo) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment