2022-12-08 06:19:28 +00:00
|
|
|
#![feature(iterator_try_collect)]
|
|
|
|
|
|
|
|
use std::fs;
|
|
|
|
use std::str;
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
// not that type of crate
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
|
|
struct Crate(char);
|
|
|
|
|
|
|
|
impl FromStr for Crate {
|
|
|
|
type Err = &'static str;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
if let Some(c) = s.trim_matches(&['[', ']'] as &[_]).chars().next() {
|
|
|
|
Ok(Crate(c))
|
|
|
|
} else {
|
|
|
|
Err("Expected a character")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct CrateStack(Vec<Crate>);
|
|
|
|
|
|
|
|
impl CrateStack {
|
|
|
|
fn new() -> Self {
|
|
|
|
Self(Vec::new())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn push(&mut self, cr: Crate) {
|
|
|
|
self.0.push(cr)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn pop(&mut self) -> Option<Crate> {
|
|
|
|
self.0.pop()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromStr for CrateStack {
|
|
|
|
type Err = &'static str;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
Ok(CrateStack(
|
|
|
|
s.lines().flat_map(|l| l.parse::<Crate>()).collect(),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
struct Dock(Vec<CrateStack>);
|
|
|
|
|
2022-12-08 09:29:54 +00:00
|
|
|
trait Crane {
|
|
|
|
fn run_directive(dock: &mut Dock, directive: &MoveDirective) -> bool;
|
|
|
|
}
|
|
|
|
|
2022-12-08 08:39:59 +00:00
|
|
|
impl Dock {
|
2022-12-08 09:29:54 +00:00
|
|
|
fn tops(&self) -> impl Iterator<Item = Option<&Crate>> {
|
|
|
|
self.0.iter().map(|s| s.0.iter().last())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CrateMover9000;
|
|
|
|
|
|
|
|
impl Crane for CrateMover9000 {
|
|
|
|
fn run_directive(dock: &mut Dock, directive: &MoveDirective) -> bool {
|
|
|
|
if directive.source >= dock.0.len() {
|
2022-12-08 08:39:59 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-12-08 09:29:54 +00:00
|
|
|
if directive.dest >= dock.0.len() {
|
2022-12-08 08:39:59 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for _ in 0..directive.number {
|
2022-12-08 09:29:54 +00:00
|
|
|
if let Some(s) = dock.0[directive.source].pop() {
|
|
|
|
dock.0[directive.dest].push(s)
|
2022-12-08 08:39:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
2022-12-08 09:29:54 +00:00
|
|
|
}
|
2022-12-08 08:39:59 +00:00
|
|
|
|
2022-12-08 09:29:54 +00:00
|
|
|
struct CrateMover9001;
|
|
|
|
|
|
|
|
impl Crane for CrateMover9001 {
|
|
|
|
fn run_directive(dock: &mut Dock, directive: &MoveDirective) -> bool {
|
|
|
|
if directive.source >= dock.0.len() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if directive.dest >= dock.0.len() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
let source_vec = &mut dock.0[directive.source].0;
|
|
|
|
|
|
|
|
let drained: Vec<Crate> = source_vec
|
|
|
|
.drain((source_vec.len() - usize::try_from(directive.number).unwrap())..)
|
|
|
|
.collect();
|
|
|
|
dock.0[directive.dest].0.extend(drained);
|
|
|
|
|
|
|
|
true
|
2022-12-08 08:39:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-08 06:19:28 +00:00
|
|
|
impl FromStr for Dock {
|
|
|
|
type Err = &'static str;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
let rows: Vec<Vec<Option<Crate>>> = s
|
|
|
|
.lines()
|
|
|
|
.rev()
|
|
|
|
.skip(1)
|
|
|
|
.map(|l| {
|
|
|
|
l.as_bytes()
|
|
|
|
.chunks(4)
|
|
|
|
.map(|c| str::from_utf8(c).unwrap().trim().parse::<Crate>().ok())
|
|
|
|
.collect()
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
let mut result = Vec::<CrateStack>::new();
|
|
|
|
for row in rows {
|
|
|
|
while row.len() > result.len() {
|
|
|
|
result.push(CrateStack::new())
|
|
|
|
}
|
|
|
|
|
|
|
|
for i in 0..row.len() {
|
|
|
|
if let Some(r) = row[i] {
|
|
|
|
result[i].push(r);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(Dock(result))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-08 08:39:59 +00:00
|
|
|
#[derive(Debug)]
|
|
|
|
struct MoveDirective {
|
|
|
|
number: u32,
|
|
|
|
source: usize,
|
|
|
|
dest: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
struct MoveError;
|
|
|
|
|
|
|
|
impl FromStr for MoveDirective {
|
|
|
|
type Err = MoveError;
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
let (count, movement_str) = s
|
|
|
|
.trim_start_matches("move ")
|
|
|
|
.split_once(" from ")
|
|
|
|
.ok_or(MoveError)?;
|
|
|
|
let (first, second) = movement_str.split_once(" to ").ok_or(MoveError)?;
|
|
|
|
|
|
|
|
let source: usize = first.parse().map_err(|_| MoveError)?;
|
|
|
|
let dest: usize = second.parse().map_err(|_| MoveError)?;
|
|
|
|
|
|
|
|
Ok(MoveDirective {
|
|
|
|
number: count.parse().map_err(|_| MoveError)?,
|
|
|
|
source: source - 1,
|
|
|
|
dest: dest - 1,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-08 06:19:28 +00:00
|
|
|
fn main() {
|
|
|
|
let filename = "etc/p05.txt";
|
|
|
|
let string = fs::read_to_string(filename).expect("Can't open file");
|
|
|
|
|
2022-12-08 08:39:59 +00:00
|
|
|
let mut split = string.split("\n\n");
|
|
|
|
|
|
|
|
let dock: Dock = split
|
|
|
|
.next()
|
|
|
|
.expect("first section")
|
|
|
|
.parse::<Dock>()
|
|
|
|
.expect("can't parse dock");
|
|
|
|
|
|
|
|
let moves: Vec<MoveDirective> = split
|
|
|
|
.next()
|
|
|
|
.expect("Can't find moves")
|
|
|
|
.lines()
|
|
|
|
.map(|l| l.parse::<MoveDirective>().expect("Can't parse move"))
|
|
|
|
.collect();
|
2022-12-08 06:19:28 +00:00
|
|
|
|
|
|
|
println!("PART ONE ---------------");
|
2022-12-08 08:39:59 +00:00
|
|
|
part1(dock, &moves);
|
2022-12-08 06:19:28 +00:00
|
|
|
|
2022-12-08 09:29:54 +00:00
|
|
|
let dock2: Dock = string
|
|
|
|
.split("\n\n")
|
|
|
|
.next()
|
|
|
|
.expect("first section")
|
|
|
|
.parse::<Dock>()
|
|
|
|
.expect("can't parse dock");
|
|
|
|
|
2022-12-08 06:19:28 +00:00
|
|
|
println!("\n PART TWO ---------------");
|
2022-12-08 09:29:54 +00:00
|
|
|
part2(dock2, &moves);
|
2022-12-08 06:19:28 +00:00
|
|
|
}
|
|
|
|
|
2022-12-08 08:39:59 +00:00
|
|
|
fn part1(mut dock: Dock, moves: &[MoveDirective]) {
|
|
|
|
for m in moves {
|
2022-12-08 09:29:54 +00:00
|
|
|
CrateMover9000::run_directive(&mut dock, m);
|
2022-12-08 08:39:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
dbg!(dock.tops().flatten().map(|c| c.0).collect::<String>());
|
|
|
|
}
|
2022-12-08 06:19:28 +00:00
|
|
|
|
2022-12-08 09:29:54 +00:00
|
|
|
fn part2(mut dock: Dock, moves: &[MoveDirective]) {
|
|
|
|
for m in moves {
|
|
|
|
CrateMover9001::run_directive(&mut dock, m);
|
|
|
|
}
|
2022-12-08 06:19:28 +00:00
|
|
|
|
2022-12-08 09:29:54 +00:00
|
|
|
dbg!(dock.tops().flatten().map(|c| c.0).collect::<String>());
|
2022-12-08 06:19:28 +00:00
|
|
|
}
|