initial commit
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
Generated
+7
@@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wynn-mounts"
|
||||||
|
version = "0.1.0"
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "wynn-mounts"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
pub type Int = i16;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default, PartialEq, Debug)]
|
||||||
|
pub struct Mount {
|
||||||
|
pub speed: Int,
|
||||||
|
pub accel: Int,
|
||||||
|
pub altitude: Int,
|
||||||
|
pub energy: Int,
|
||||||
|
pub handling: Int,
|
||||||
|
pub toughness: Int,
|
||||||
|
pub boost: Int,
|
||||||
|
pub training: Int,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum Mat {
|
||||||
|
Ingot,
|
||||||
|
Gem,
|
||||||
|
Wood,
|
||||||
|
Paper,
|
||||||
|
String,
|
||||||
|
Grains,
|
||||||
|
Oil,
|
||||||
|
Meat,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! mtch {
|
||||||
|
($struct:ident $($mat:ident {$($field:ident $amt:expr)*},)*) => {
|
||||||
|
impl $struct {
|
||||||
|
pub fn apply(&mut self, mat: Mat) {
|
||||||
|
match mat {
|
||||||
|
$(Mat::$mat => {
|
||||||
|
$(self.$field -= $amt;)*
|
||||||
|
},)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn undo(&mut self, mat: Mat) {
|
||||||
|
match mat {
|
||||||
|
$(Mat::$mat => {
|
||||||
|
$(self.$field += $amt;)*
|
||||||
|
},)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn useless(&self, mat: Mat) -> bool {
|
||||||
|
match mat {
|
||||||
|
$(Mat::$mat => {
|
||||||
|
$(self.$field <= 0 &&)* true
|
||||||
|
},)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
mtch! { Mount
|
||||||
|
Ingot { energy 4 toughness 8 },
|
||||||
|
Gem { speed 4 energy 2 training 6 },
|
||||||
|
Wood { speed 2 accel 6 toughness 4 },
|
||||||
|
Paper { altitude 8 boost 4 },
|
||||||
|
String { accel 2 handling 4 boost 6 },
|
||||||
|
Grains { speed 8 altitude 4 },
|
||||||
|
Oil { altitude 2 handling 6 training 4 },
|
||||||
|
Meat { accel 4 energy 8 },
|
||||||
|
}
|
||||||
+141
@@ -0,0 +1,141 @@
|
|||||||
|
mod data;
|
||||||
|
mod solve;
|
||||||
|
pub use data::*;
|
||||||
|
pub use solve::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut priority = vec![
|
||||||
|
Mat::Wood,
|
||||||
|
Mat::Paper,
|
||||||
|
Mat::Grains,
|
||||||
|
Mat::String,
|
||||||
|
Mat::Oil,
|
||||||
|
Mat::Meat,
|
||||||
|
Mat::Ingot,
|
||||||
|
Mat::Gem,
|
||||||
|
];
|
||||||
|
print_priority(&priority);
|
||||||
|
let input = std::io::stdin();
|
||||||
|
for line in input.lines() {
|
||||||
|
let Ok(line) = line else {
|
||||||
|
println!("error reading line");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let Some((cmd, args)) = line.split_once(" ") else {
|
||||||
|
println!("space expected after command");
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
match cmd {
|
||||||
|
"solve" => run_solve(args, &priority),
|
||||||
|
"priority" => run_priority(args, &mut priority),
|
||||||
|
_ => {
|
||||||
|
println!("unknown command");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_solve(args: &str, priority: &Priority) {
|
||||||
|
let parts = args.split(" ");
|
||||||
|
let mut attrs = [0; 8];
|
||||||
|
let mut i = 0;
|
||||||
|
for part in parts {
|
||||||
|
if part.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if i == 8 {
|
||||||
|
i += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let Some((limit, max)) = part.split_once("/") else {
|
||||||
|
println!("bad stat input");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Ok(limit): Result<Int, _> = limit.parse() else {
|
||||||
|
println!("bad stat input");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let Ok(max): Result<Int, _> = max.parse() else {
|
||||||
|
println!("bad stat input");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
attrs[i] = max - limit;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
if i != 8 {
|
||||||
|
println!("wrong number of parts ({i}, need 8)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mount = Mount {
|
||||||
|
speed: attrs[0],
|
||||||
|
accel: attrs[1],
|
||||||
|
altitude: attrs[2],
|
||||||
|
energy: attrs[3],
|
||||||
|
handling: attrs[4],
|
||||||
|
toughness: attrs[5],
|
||||||
|
boost: attrs[6],
|
||||||
|
training: attrs[7],
|
||||||
|
};
|
||||||
|
println!("requirements: {mount:?}");
|
||||||
|
let res = solve(mount, priority);
|
||||||
|
println!("{}: {res:?}", res.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_priority(args: &str, priority: &mut Priority) {
|
||||||
|
let parts = args.split(" ");
|
||||||
|
let mut new = Vec::new();
|
||||||
|
for (i, part) in parts.enumerate() {
|
||||||
|
if part.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if i == 8 {
|
||||||
|
println!("too many materials provided");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
new.push(match part.to_lowercase().as_str() {
|
||||||
|
"ingot" => Mat::Ingot,
|
||||||
|
"gem" => Mat::Gem,
|
||||||
|
"wood" => Mat::Wood,
|
||||||
|
"paper" => Mat::Paper,
|
||||||
|
"string" => Mat::String,
|
||||||
|
"grains" => Mat::Grains,
|
||||||
|
"oil" => Mat::Oil,
|
||||||
|
"meat" => Mat::Meat,
|
||||||
|
_ => {
|
||||||
|
println!("unknown material {part}");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if validate_priority(&new) {
|
||||||
|
*priority = new;
|
||||||
|
print_priority(priority);
|
||||||
|
} else {
|
||||||
|
println!("invalid priority (2+ of a material)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_priority(priority: &Priority) {
|
||||||
|
println!("priority:");
|
||||||
|
for (i, mat) in priority.iter().enumerate() {
|
||||||
|
println!(" {}: {mat:?}", i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_priority(priority: &Priority) -> bool {
|
||||||
|
let mut used = std::collections::HashSet::new();
|
||||||
|
for p in priority {
|
||||||
|
if !used.insert(p) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage() {
|
||||||
|
println!("Usage:");
|
||||||
|
println!(" > solve 41/63 50/60 55/55 43/64 60/66 51/55 48/59 41/63");
|
||||||
|
println!(" solves for the least number of materials needed given a priority");
|
||||||
|
println!(" > priority wood paper grains string oil meat");
|
||||||
|
println!(" sets the material priority for solving (what to use and what to try first)");
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
pub use crate::data::*;
|
||||||
|
|
||||||
|
pub fn solve(mut mount: Mount, priority: &Priority) -> Vec<Mat> {
|
||||||
|
let mut best = Vec::new();
|
||||||
|
let mut stack = vec![0];
|
||||||
|
loop {
|
||||||
|
let mut mat_i = *stack.last().unwrap();
|
||||||
|
let mat = priority[mat_i];
|
||||||
|
if !mount.useless(mat) {
|
||||||
|
mount.apply(mat);
|
||||||
|
if mount.finished() {
|
||||||
|
if best.is_empty() || stack.len() < best.len() {
|
||||||
|
best = stack.clone();
|
||||||
|
}
|
||||||
|
} else if best.is_empty() || stack.len() + 1 < best.len() {
|
||||||
|
stack.push(mat_i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mount.undo(mat);
|
||||||
|
}
|
||||||
|
while mat_i == priority.len() - 1 {
|
||||||
|
stack.pop();
|
||||||
|
if let Some(&prev) = stack.last() {
|
||||||
|
mat_i = prev;
|
||||||
|
} else {
|
||||||
|
return best.into_iter().map(|i| priority[i]).collect();
|
||||||
|
}
|
||||||
|
mount.undo(priority[mat_i]);
|
||||||
|
}
|
||||||
|
*stack.last_mut().unwrap() += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mat {
|
||||||
|
pub fn first() -> Self {
|
||||||
|
Self::Wood
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Mount {
|
||||||
|
pub fn finished(&self) -> bool {
|
||||||
|
self.speed <= 0
|
||||||
|
&& self.accel <= 0
|
||||||
|
&& self.altitude <= 0
|
||||||
|
&& self.energy <= 0
|
||||||
|
&& self.handling <= 0
|
||||||
|
&& self.toughness <= 0
|
||||||
|
&& self.boost <= 0
|
||||||
|
&& self.training <= 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Priority = Vec<Mat>;
|
||||||
Reference in New Issue
Block a user