Skip to content
Permalink
Browse files

Use fast wheel

  • Loading branch information...
ichyo committed Jun 22, 2019
1 parent 6dcf99c commit feb49a8e502dfffd14f74dbf59b0ca09717baf9f
Showing with 50 additions and 22 deletions.
  1. +3 −4 src/main.rs
  2. +8 −6 src/models.rs
  3. +39 −12 src/solve.rs
@@ -1,7 +1,7 @@
use clap::{App, Arg};
use rayon::prelude::*;
use std::fs::File;
use std::io::{Write};
use std::io::Write;

use icfpc::models::*;
use icfpc::parse::read_all_inputs;
@@ -37,15 +37,14 @@ fn main() {

let inputs = read_all_inputs(&input_root);
inputs.into_par_iter().for_each(|input| {
eprintln!("{}", input.output_file_name());
let mut output_file: Box<Write> = match output_root {
Some(output_root) => {
let output_path = format!("{}/{}", output_root, input.output_file_name());
let output_file = File::create(&output_path).unwrap();
Box::new(output_file)
}
None => {
Box::new(std::io::stdout())
}
None => Box::new(std::io::stdout()),
};
solve(input.task, &mut output_file);
});
@@ -13,22 +13,22 @@ impl Point {
Point { x, y }
}

pub fn add(&self, p: &Point) -> Point {
pub fn add(self, p: Point) -> Point {
Point::new(self.x + p.x, self.y + p.y)
}

pub fn move_with(&self, kind: &Move) -> Point {
pub fn move_with(self, kind: &Move) -> Point {
let (x, y) = (self.x, self.y);
match kind {
Move::MoveUp => Point::new(x, y + 1),
Move::MoveDown => Point::new(x, y - 1),
Move::MoveRight => Point::new(x + 1, y),
Move::MoveLeft => Point::new(x - 1, y),
_ => *self,
_ => self,
}
}

pub fn revert_with(&self, kind: &Move) -> Point {
pub fn revert_with(self, kind: &Move) -> Point {
let (x, y) = (self.x, self.y);
match kind {
Move::MoveUp => Point::new(x, y - 1),
@@ -78,7 +78,7 @@ impl Map {
let min_x = cmp::min(p.x, q.x);
let max_x = cmp::max(p.x, q.x);
for x in min_x..max_x {
cross_y_map.entry(x).or_insert_with(|| Vec::new()).push(p.y);
cross_y_map.entry(x).or_insert_with(Vec::new).push(p.y);
}
}
}
@@ -135,7 +135,7 @@ pub enum Move {
MoveDown,
MoveLeft,
MoveRight,
Noop
Noop,
}

#[derive(Debug, Clone)]
@@ -144,6 +144,7 @@ pub enum Command {
TurnRight,
TurnLeft,
NewHand(Point),
FastWheel,
}

impl fmt::Display for Command {
@@ -157,6 +158,7 @@ impl fmt::Display for Command {
Command::TurnRight => write!(f, "E"),
Command::TurnLeft => write!(f, "Q"),
Command::NewHand(p) => write!(f, "B({}, {})", p.x, p.y),
Command::FastWheel => write!(f, "F"),
}
}
}
@@ -66,6 +66,8 @@ pub fn solve_small(task: Task) -> Vec<Command> {
Point::new(0, 1),
]);
let mut hand_count = 0;
let mut fast_wheel_count = 0;
let mut fast_wheel_turns = 0;

while remaining > 0 {
while hand_count > 0 && !new_bodies.is_empty() {
@@ -74,16 +76,26 @@ pub fn solve_small(task: Task) -> Vec<Command> {
bodies_diff.push(new_hand);
res.push(Command::NewHand(new_hand));
}
if fast_wheel_count > 0 && fast_wheel_turns == 0 {
fast_wheel_count -= 1;
res.push(Command::FastWheel);
fast_wheel_turns = 50;
}

let mut data: Matrix<Option<Move>> = Matrix::new(width, height, None);
let mut data: Matrix<Option<(Move, usize)>> = Matrix::new(width, height, None);
let mut queue = VecDeque::new();
queue.push_back(cp);
data.set(cp, Some(Move::Noop));
data.set(cp, Some((Move::Noop, 0)));
let mut reached = false;
while let Some(c) = queue.pop_front() {
let cost = match data.get(c) {
Some(Some((_, cost))) => *cost,
_ => panic!("no data is expected"),
};

let bodies = bodies_diff
.iter()
.map(|diff| c.add(diff))
.map(|diff| c.add(*diff))
.collect::<Vec<_>>();
let not_passed = bodies.iter().any(|p| {
if let Some(false) = passed.get(*p) {
@@ -102,18 +114,29 @@ pub fn solve_small(task: Task) -> Vec<Command> {
let mut local_cmds = Vec::new();
let mut iter = c;
while iter != cp {
if let Some(Some(BoosterType::NewHand)) = booster_map.get(iter) {
booster_map.set(iter, None);
hand_count += 1;
match booster_map.get(iter) {
Some(Some(BoosterType::NewHand)) => {
booster_map.set(iter, None);
hand_count += 1;
}
Some(Some(BoosterType::FastMove)) => {
booster_map.set(iter, None);
fast_wheel_count += 1;
}
_ => {}
}
if let Some(Some(mv)) = data.get(iter) {
let (mv, cost) = match data.get(iter) {
Some(Some((mv, cost))) => (mv, cost),
_ => panic!("no data"),
};
iter = iter.revert_with(mv);
if *cost - 1 < fast_wheel_turns {
iter = iter.revert_with(mv);
local_cmds.push(Command::Move(mv.clone()));
} else {
panic!("cannot revert command");
}
local_cmds.push(Command::Move(mv.clone()));
}
local_cmds.reverse();
fast_wheel_count -= std::cmp::min(fast_wheel_count, local_cmds.len());
res.extend(local_cmds);

cp = c;
@@ -122,10 +145,14 @@ pub fn solve_small(task: Task) -> Vec<Command> {
}
moves.shuffle(&mut rng);
for m in &moves {
let nc = c.move_with(m);
let nc = if cost < fast_wheel_turns {
c.move_with(m).move_with(m)
} else {
c.move_with(m)
};
if let Some(None) = data.get(nc) {
if let Some(true) = valid.get(nc) {
data.set(nc, Some(m.clone()));
data.set(nc, Some((m.clone(), cost + 1)));
queue.push_back(nc);
}
}

0 comments on commit feb49a8

Please sign in to comment.
You can’t perform that action at this time.