Skip to content

Commit 62f061e

Browse files
committed
Implement beam
1 parent efba392 commit 62f061e

File tree

4 files changed

+69
-12
lines changed

4 files changed

+69
-12
lines changed

src/main.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
use clap::{App, Arg};
2-
use rayon::prelude::*;
2+
use indicatif::ProgressBar;
33
use std::fs::File;
44
use std::io::Write;
5-
use indicatif::ProgressBar;
5+
use rayon::prelude::*;
6+
67

78
use icfpc::models::*;
89
use icfpc::parse::read_all_inputs;
9-
use icfpc::solve::solve_small;
10+
use icfpc::solve::solve_beam;
1011

1112

1213
fn solve<W: Write>(task: Task, f: &mut W) {
13-
let cmds = solve_small(task);
14+
let cmds = solve_beam(task);
1415
for cmd in cmds {
1516
write!(f, "{}", cmd).unwrap();
1617
}

src/models.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::collections::HashMap;
33
use std::fmt;
44
use std::ops::Add;
55

6-
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
6+
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
77
pub struct Point {
88
pub x: i32,
99
pub y: i32,
@@ -50,7 +50,7 @@ pub enum Direction {
5050
Horizontal,
5151
}
5252

53-
#[derive(Debug, Clone)]
53+
#[derive(Debug, Clone, Eq, PartialEq)]
5454
pub struct Map(Vec<Point>);
5555

5656
impl Map {
@@ -113,7 +113,7 @@ impl Map {
113113
}
114114
}
115115

116-
#[derive(Debug, Clone)]
116+
#[derive(Debug, Clone, Eq, PartialEq)]
117117
pub enum BoosterType {
118118
NewHand,
119119
FastMove,
@@ -123,7 +123,7 @@ pub enum BoosterType {
123123
Unknown,
124124
}
125125

126-
#[derive(Debug, Clone)]
126+
#[derive(Debug, Clone, Eq, PartialEq)]
127127
pub struct Booster {
128128
pub kind: BoosterType,
129129
pub point: Point,
@@ -135,7 +135,7 @@ impl Booster {
135135
}
136136
}
137137

138-
#[derive(Debug, Clone)]
138+
#[derive(Debug, Clone, Eq, PartialEq)]
139139
pub struct Task {
140140
pub width: usize,
141141
pub height: usize,
@@ -145,7 +145,7 @@ pub struct Task {
145145
pub boosters: Vec<Booster>,
146146
}
147147

148-
#[derive(Debug, Clone)]
148+
#[derive(Debug, Clone, Eq, PartialEq)]
149149
pub enum Move {
150150
MoveUp,
151151
MoveDown,
@@ -154,7 +154,7 @@ pub enum Move {
154154
Noop,
155155
}
156156

157-
#[derive(Debug, Clone)]
157+
#[derive(Debug, Clone, Eq, PartialEq)]
158158
pub enum Command {
159159
Move(Move),
160160
TurnRight,

src/solve.rs

+56-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ use crate::utils::Matrix;
33

44
use rand::seq::SliceRandom;
55
use rand::thread_rng;
6-
use std::collections::VecDeque;
6+
use std::cmp::Ordering;
7+
use std::collections::{BinaryHeap, HashSet, VecDeque};
78

9+
#[derive(Clone, Eq, PartialEq)]
810
pub struct State<'a> {
911
task: &'a Task,
1012
current_point: Point,
@@ -202,6 +204,15 @@ impl<'a> State<'a> {
202204

203205
self.remaining > 0
204206
}
207+
208+
pub fn finished(&self) -> bool {
209+
self.remaining == 0
210+
}
211+
212+
// min is better
213+
fn score(&self) -> usize {
214+
self.remaining
215+
}
205216
}
206217

207218
pub fn solve_small(task: Task) -> Vec<Command> {
@@ -213,3 +224,47 @@ pub fn solve_small(task: Task) -> Vec<Command> {
213224
}
214225
state.commands
215226
}
227+
228+
#[derive(Clone, Eq, PartialEq)]
229+
struct BeamEntry<'a>(State<'a>);
230+
231+
impl<'a> Ord for BeamEntry<'a> {
232+
fn cmp(&self, other: &BeamEntry) -> Ordering {
233+
let cmd = other.0.commands.len().cmp(&self.0.commands.len());
234+
let score = other.0.score().cmp(&self.0.score());
235+
cmd.then(score)
236+
}
237+
}
238+
239+
impl<'a> PartialOrd for BeamEntry<'a> {
240+
fn partial_cmp(&self, other: &BeamEntry) -> Option<Ordering> {
241+
Some(self.cmp(other))
242+
}
243+
}
244+
245+
pub fn solve_beam(task: Task) -> Vec<Command> {
246+
let mut beam = BinaryHeap::new();
247+
let beam_length = 3;
248+
let branch = 3;
249+
beam.push(BeamEntry(State::initialize(&task)));
250+
loop {
251+
let mut next_beam = BinaryHeap::new();
252+
let mut points_set = HashSet::new();
253+
for entry in beam.into_iter().take(beam_length) {
254+
let state = entry.0;
255+
if state.finished() {
256+
return state.commands;
257+
}
258+
for _ in 0..branch {
259+
let mut state = state.clone();
260+
state.next_state();
261+
if points_set.contains(&state.current_point) {
262+
continue;
263+
}
264+
points_set.insert(state.current_point);
265+
next_beam.push(BeamEntry(state));
266+
}
267+
}
268+
beam = next_beam;
269+
}
270+
}

src/utils.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::models::Point;
22

3+
#[derive(Debug, Clone, Eq, PartialEq)]
34
pub struct Matrix<T> {
45
width: usize,
56
height: usize,

0 commit comments

Comments
 (0)