working5
This commit is contained in:
parent
5eec977c10
commit
0cd663ae2a
4 changed files with 441 additions and 97 deletions
12
Cargo.toml
12
Cargo.toml
|
@ -6,8 +6,6 @@ edition = "2018"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "day1"
|
name = "day1"
|
||||||
path = "src/day1/main.rs"
|
path = "src/day1/main.rs"
|
||||||
|
@ -18,4 +16,12 @@ path = "src/day2/main.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "day3"
|
name = "day3"
|
||||||
path = "src/day3/main.rs"
|
path = "src/day3/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "day4"
|
||||||
|
path = "src/day4/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "day5"
|
||||||
|
path = "src/day5/main.rs"
|
188
src/day3/main.rs
188
src/day3/main.rs
|
@ -4,120 +4,120 @@ use std::iter::FromIterator;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Step {
|
enum Step {
|
||||||
Up(usize),
|
Up(usize),
|
||||||
Down(usize),
|
Down(usize),
|
||||||
Left(usize),
|
Left(usize),
|
||||||
Right(usize),
|
Right(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Step {
|
impl Step {
|
||||||
fn draw(&self, map: &mut Vec<Point>, start: &mut Point) {
|
fn draw(&self, map: &mut Vec<Point>, start: &mut Point) {
|
||||||
let mover: (i64, i64, &usize) = match self {
|
let mover: (i64, i64, &usize) = match self {
|
||||||
Step::Up(s) => (0, 1, s),
|
Step::Up(s) => (0, 1, s),
|
||||||
Step::Down(s) => (0, -1, s),
|
Step::Down(s) => (0, -1, s),
|
||||||
Step::Left(s) => (-1, 0, s),
|
Step::Left(s) => (-1, 0, s),
|
||||||
Step::Right(s) => (1, 0, s),
|
Step::Right(s) => (1, 0, s),
|
||||||
};
|
};
|
||||||
let (x, y, steps) = mover;
|
let (x, y, steps) = mover;
|
||||||
map.reserve(*steps);
|
map.reserve(*steps);
|
||||||
for _ in 0..*steps {
|
for _ in 0..*steps {
|
||||||
start.x += x;
|
start.x += x;
|
||||||
start.y += y;
|
start.y += y;
|
||||||
map.push(start.clone());
|
map.push(start.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&[u8]> for Step {
|
impl From<&[u8]> for Step {
|
||||||
fn from(b: &[u8]) -> Self {
|
fn from(b: &[u8]) -> Self {
|
||||||
let steps: usize = b[0..]
|
let steps: usize = b[0..]
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|i| **i >= b'0' && **i <= b'9')
|
.filter(|i| **i >= b'0' && **i <= b'9')
|
||||||
.fold(0, |s, i| ((i - b'0') as usize + 10 * s));
|
.fold(0, |s, i| ((i - b'0') as usize + 10 * s));
|
||||||
match b[0] {
|
match b[0] {
|
||||||
b'U' => Step::Up(steps),
|
b'U' => Step::Up(steps),
|
||||||
b'D' => Step::Down(steps),
|
b'D' => Step::Down(steps),
|
||||||
b'L' => Step::Left(steps),
|
b'L' => Step::Left(steps),
|
||||||
b'R' => Step::Right(steps),
|
b'R' => Step::Right(steps),
|
||||||
_ => panic!("unknown directions"),
|
_ => panic!("unknown directions"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash, Clone, Copy, Debug)]
|
#[derive(Eq, PartialEq, Hash, Clone, Copy, Debug)]
|
||||||
struct Point {
|
struct Point {
|
||||||
x: i64,
|
x: i64,
|
||||||
y: i64,
|
y: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Point {
|
impl Point {
|
||||||
fn dist_to_00(&self) -> u64 {
|
fn dist_to_00(&self) -> u64 {
|
||||||
(self.x.abs() + self.y.abs()) as u64
|
(self.x.abs() + self.y.abs()) as u64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(i64, i64)> for Point {
|
impl From<(i64, i64)> for Point {
|
||||||
fn from(xy: (i64, i64)) -> Self {
|
fn from(xy: (i64, i64)) -> Self {
|
||||||
Point { x: xy.0, y: xy.1 }
|
Point { x: xy.0, y: xy.1 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
let commands = load();
|
let commands = load();
|
||||||
let mut wires: Vec<Vec<Point>> = vec![];
|
let mut wires: Vec<Vec<Point>> = vec![];
|
||||||
commands.iter().enumerate().for_each(|(_, wire)| {
|
commands.iter().enumerate().for_each(|(_, wire)| {
|
||||||
let mut map = Vec::new();
|
let mut map = Vec::new();
|
||||||
let mut p: Point = (0, 0).into();
|
let mut p: Point = (0, 0).into();
|
||||||
wire.iter().for_each(|step| {
|
wire.iter().for_each(|step| {
|
||||||
step.draw(&mut map, &mut p);
|
step.draw(&mut map, &mut p);
|
||||||
});
|
});
|
||||||
wires.push(map);
|
wires.push(map);
|
||||||
});
|
});
|
||||||
let wire_sets: Vec<HashSet<&Point>> = wires
|
let wire_sets: Vec<HashSet<&Point>> = wires
|
||||||
.iter()
|
.iter()
|
||||||
.map(|wire| HashSet::from_iter(wire.iter()))
|
.map(|wire| HashSet::from_iter(wire.iter()))
|
||||||
.collect();
|
.collect();
|
||||||
let closest = wire_sets[0]
|
let closest = wire_sets[0]
|
||||||
.intersection(&wire_sets[1])
|
.intersection(&wire_sets[1])
|
||||||
.fold(None, |min, point| {
|
.fold(None, |min, point| {
|
||||||
let dist = point.dist_to_00();
|
let dist = point.dist_to_00();
|
||||||
match min {
|
match min {
|
||||||
None => Some(dist),
|
None => Some(dist),
|
||||||
Some(min) => Some(if dist < min { dist } else { min }),
|
Some(min) => Some(if dist < min { dist } else { min }),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.expect("no mataching points found");
|
.expect("no mataching points found");
|
||||||
let shortest = wire_sets[0]
|
let shortest = wire_sets[0]
|
||||||
.intersection(&wire_sets[1])
|
.intersection(&wire_sets[1])
|
||||||
.map(|point| {
|
.map(|point| {
|
||||||
wires[0].iter().position(|p| p == *point).unwrap()
|
wires[0].iter().position(|p| p == *point).unwrap()
|
||||||
+ wires[1].iter().position(|p| p == *point).unwrap()
|
+ wires[1].iter().position(|p| p == *point).unwrap()
|
||||||
+ 2
|
+ 2
|
||||||
})
|
})
|
||||||
.fold(None, |min, dist| {
|
.fold(None, |min, dist| {
|
||||||
Some(match min {
|
Some(match min {
|
||||||
None => dist,
|
None => dist,
|
||||||
Some(d) => {
|
Some(d) => {
|
||||||
if dist < d {
|
if dist < d {
|
||||||
dist
|
dist
|
||||||
} else {
|
} else {
|
||||||
d
|
d
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.expect("no matching points found");
|
.expect("no matching points found");
|
||||||
println!("closest: {}", closest);
|
println!("closest: {}", closest);
|
||||||
println!("shortest: {}", shortest);
|
println!("shortest: {}", shortest);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load() -> Vec<Vec<Step>> {
|
fn load() -> Vec<Vec<Step>> {
|
||||||
let stdin = io::stdin();
|
let stdin = io::stdin();
|
||||||
stdin
|
stdin
|
||||||
.lock()
|
.lock()
|
||||||
.split(b'\n')
|
.split(b'\n')
|
||||||
.filter_map(|i| i.ok())
|
.filter_map(|i| i.ok())
|
||||||
.map(|line| line.split(|b| *b == b',').map(|i| Step::from(i)).collect())
|
.map(|line| line.split(|b| *b == b',').map(|i| Step::from(i)).collect())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
40
src/day4/main.rs
Normal file
40
src/day4/main.rs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
use std::io::{self};
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
let count = (152085..670283)
|
||||||
|
.map(|i| i.to_string())
|
||||||
|
.filter(|pass| {
|
||||||
|
let mut chars = pass.chars();
|
||||||
|
let mut last = chars.next().unwrap();
|
||||||
|
for char in chars {
|
||||||
|
if char < last {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
last = char;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
})
|
||||||
|
.filter(|pass| {
|
||||||
|
let mut matches: Vec<usize> = vec![];
|
||||||
|
let mut chars = pass.chars();
|
||||||
|
let mut last = chars.next().unwrap();
|
||||||
|
let mut matchlen = 1;
|
||||||
|
for char in chars {
|
||||||
|
if char == last {
|
||||||
|
matchlen += 1;
|
||||||
|
} else {
|
||||||
|
matches.push(matchlen);
|
||||||
|
matchlen = 1;
|
||||||
|
}
|
||||||
|
last = char;
|
||||||
|
}
|
||||||
|
matches.push(matchlen);
|
||||||
|
if let Some(_) = matches.iter().position(|i| *i == 2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
})
|
||||||
|
.count();
|
||||||
|
println!("count: {}", count);
|
||||||
|
Ok(())
|
||||||
|
}
|
298
src/day5/main.rs
Normal file
298
src/day5/main.rs
Normal file
|
@ -0,0 +1,298 @@
|
||||||
|
use std::env;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{self, BufRead, BufReader, Write};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
enum Mode {
|
||||||
|
Position,
|
||||||
|
Immediate,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Mode {
|
||||||
|
fn default() -> Self {
|
||||||
|
Mode::Position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<bool> for Mode {
|
||||||
|
fn from(b: bool) -> Self {
|
||||||
|
match b {
|
||||||
|
false => Mode::Position,
|
||||||
|
true => Mode::Immediate,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
|
struct Modes {
|
||||||
|
a: Mode,
|
||||||
|
b: Mode,
|
||||||
|
c: Mode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<(Mode, Mode, Mode)> for Modes {
|
||||||
|
fn from(modes: (Mode, Mode, Mode)) -> Self {
|
||||||
|
Modes {
|
||||||
|
a: modes.0,
|
||||||
|
b: modes.1,
|
||||||
|
c: modes.2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&ModedOpcode> for Modes {
|
||||||
|
fn from(mo: &ModedOpcode) -> Self {
|
||||||
|
mo.modes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
enum Opcode {
|
||||||
|
Add,
|
||||||
|
Multiply,
|
||||||
|
Input,
|
||||||
|
Output,
|
||||||
|
JumpIfTrue,
|
||||||
|
JumpIfFalse,
|
||||||
|
LessThan,
|
||||||
|
Equals,
|
||||||
|
Halt,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&ModedOpcode> for Opcode {
|
||||||
|
fn from(mo: &ModedOpcode) -> Self {
|
||||||
|
mo.op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i64> for Opcode {
|
||||||
|
fn from(i: i64) -> Self {
|
||||||
|
match i {
|
||||||
|
1 => Opcode::Add,
|
||||||
|
2 => Opcode::Multiply,
|
||||||
|
3 => Opcode::Input,
|
||||||
|
4 => Opcode::Output,
|
||||||
|
5 => Opcode::JumpIfTrue,
|
||||||
|
6 => Opcode::JumpIfFalse,
|
||||||
|
7 => Opcode::LessThan,
|
||||||
|
8 => Opcode::Equals,
|
||||||
|
99 => Opcode::Halt,
|
||||||
|
_ => panic!("invalid opcode {}", i),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ModedOpcode {
|
||||||
|
modes: Modes,
|
||||||
|
op: Opcode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<i64> for ModedOpcode {
|
||||||
|
fn from(i: i64) -> Self {
|
||||||
|
let code = i % 100;
|
||||||
|
let a = i % 1000 >= 100;
|
||||||
|
let b = i % 10000 >= 1000;
|
||||||
|
let c = i > 10000;
|
||||||
|
let modes = (Mode::from(a), Mode::from(b), Mode::from(c)).into();
|
||||||
|
ModedOpcode {
|
||||||
|
modes: modes,
|
||||||
|
op: Opcode::from(code),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
println!("Hello, i am {}.", env::args().next().unwrap());
|
||||||
|
let filename = env::args().nth(1).expect("provide file as first param");
|
||||||
|
let computer = Computer::from(File::open(filename)?);
|
||||||
|
computer.clone().run();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Computer {
|
||||||
|
pos: usize,
|
||||||
|
program: Vec<i64>,
|
||||||
|
modes: Modes,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Computer {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Computer {
|
||||||
|
pos: 0,
|
||||||
|
program: self.program.clone(),
|
||||||
|
modes: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<File> for Computer {
|
||||||
|
fn from(f: File) -> Self {
|
||||||
|
let f = BufReader::new(f);
|
||||||
|
let program: Vec<i64> = f
|
||||||
|
.split(b',')
|
||||||
|
.map(|o| {
|
||||||
|
let o = o.unwrap();
|
||||||
|
let mut o = o.iter().peekable();
|
||||||
|
let sign = if o.peek() == Some(&&b'-') { -1 } else { 1 };
|
||||||
|
o.filter(|i| **i >= b'0' && **i <= b'9')
|
||||||
|
.fold(0, |s, i| ((i - b'0') as i64 + 10 * s))
|
||||||
|
* sign
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
program.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Vec<i64>> for Computer {
|
||||||
|
fn from(program: Vec<i64>) -> Self {
|
||||||
|
Computer {
|
||||||
|
pos: 0,
|
||||||
|
program: program,
|
||||||
|
modes: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Computer {
|
||||||
|
fn update(&mut self, u: Vec<(usize, i64)>) -> Computer {
|
||||||
|
let mut computer = self.clone();
|
||||||
|
for (pos, val) in u {
|
||||||
|
computer.program[pos] = val;
|
||||||
|
}
|
||||||
|
computer
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&mut self) -> i64 {
|
||||||
|
loop {
|
||||||
|
let instruction = self.program[self.pos];
|
||||||
|
let instruction = ModedOpcode::from(instruction);
|
||||||
|
self.modes = (&instruction).into();
|
||||||
|
let advance = match (&instruction).into() {
|
||||||
|
Opcode::Add => self.add(),
|
||||||
|
Opcode::Multiply => self.multiply(),
|
||||||
|
Opcode::Input => self.input(),
|
||||||
|
Opcode::Output => self.output(),
|
||||||
|
Opcode::JumpIfTrue => self.jump_if_true(),
|
||||||
|
Opcode::JumpIfFalse => self.jump_if_false(),
|
||||||
|
Opcode::LessThan => self.less_than(),
|
||||||
|
Opcode::Equals => self.equals(),
|
||||||
|
Opcode::Halt => return self.program[0],
|
||||||
|
};
|
||||||
|
self.pos += advance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_a(&self) -> i64 {
|
||||||
|
let a = self.program[self.pos + 1];
|
||||||
|
match self.modes.a {
|
||||||
|
Mode::Position => self.program[a as usize],
|
||||||
|
Mode::Immediate => a,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_a(&mut self, value: i64) {
|
||||||
|
let a = self.program[self.pos + 1];
|
||||||
|
match self.modes.a {
|
||||||
|
Mode::Position => self.program[a as usize] = value,
|
||||||
|
Mode::Immediate => self.program[self.pos] = value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_b(&self) -> i64 {
|
||||||
|
let b = self.program[self.pos + 2];
|
||||||
|
match self.modes.b {
|
||||||
|
Mode::Position => self.program[b as usize],
|
||||||
|
Mode::Immediate => b,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_c(&mut self, value: i64) {
|
||||||
|
let c = self.program[self.pos + 3];
|
||||||
|
match self.modes.c {
|
||||||
|
Mode::Position => self.program[c as usize] = value,
|
||||||
|
Mode::Immediate => self.program[self.pos] = value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add(&mut self) -> usize {
|
||||||
|
self.set_c(self.get_a() + self.get_b());
|
||||||
|
4
|
||||||
|
}
|
||||||
|
|
||||||
|
fn multiply(&mut self) -> usize {
|
||||||
|
self.set_c(self.get_a() * self.get_b());
|
||||||
|
4
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input(&mut self) -> usize {
|
||||||
|
let mut line = String::new();
|
||||||
|
print!("input: ");
|
||||||
|
io::stdout().flush().expect("unable to flush output");
|
||||||
|
io::stdin().lock().read_line(&mut line).expect("input failed");
|
||||||
|
let value = line.trim().parse().expect("numeric input required");
|
||||||
|
self.set_a(value);
|
||||||
|
2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output(&mut self) -> usize {
|
||||||
|
println!("output: {}", self.get_a());
|
||||||
|
2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn jump_if_true(&mut self) -> usize {
|
||||||
|
if self.get_a() > 0 {
|
||||||
|
self.pos = self.get_b() as usize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn jump_if_false(&mut self) -> usize {
|
||||||
|
if self.get_a() == 0 {
|
||||||
|
self.pos = self.get_b() as usize;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn less_than(&mut self) -> usize {
|
||||||
|
if self.get_a() < self.get_b() {
|
||||||
|
self.set_c(1)
|
||||||
|
} else {
|
||||||
|
self.set_c(0)
|
||||||
|
}
|
||||||
|
4
|
||||||
|
}
|
||||||
|
|
||||||
|
fn equals(&mut self) -> usize {
|
||||||
|
if self.get_a() == self.get_b() {
|
||||||
|
self.set_c(1)
|
||||||
|
} else {
|
||||||
|
self.set_c(0)
|
||||||
|
}
|
||||||
|
4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example1() {
|
||||||
|
let program: Vec<i64> = vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50];
|
||||||
|
assert_eq!(Computer::from(program).run(), 3500)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example2() {
|
||||||
|
let program: Vec<i64> = vec![1, 0, 0, 0, 99];
|
||||||
|
assert_eq!(Computer::from(program).run(), 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example3() {
|
||||||
|
let program: Vec<i64> = vec![1, 1, 1, 4, 99, 5, 6, 0, 99];
|
||||||
|
assert_eq!(Computer::from(program).run(), 30)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue