Skip to content

Instantly share code, notes, and snippets.

@bozdoz
Created November 28, 2023 05:14
Show Gist options
  • Save bozdoz/c9acfcdf50957444fe5c37faa5af6bc8 to your computer and use it in GitHub Desktop.
Save bozdoz/c9acfcdf50957444fe5c37faa5af6bc8 to your computer and use it in GitHub Desktop.
2019 Advent of Code
// 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(())
}
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())
}
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(), ());
}
}
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