Skip to content

Commit 82502ba

Browse files
committed
Refactoring to modules
1 parent a558980 commit 82502ba

File tree

7 files changed

+452
-651
lines changed

7 files changed

+452
-651
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,7 @@ clap = "2.33.0"
99
glob = "0.3.0"
1010
rand = "0.6.5"
1111
rayon = "1.1.0"
12+
13+
[lib]
14+
name = "icfpc"
15+
path = "src/lib.rs"

src/bin/score.rs

Lines changed: 19 additions & 264 deletions
Original file line numberDiff line numberDiff line change
@@ -1,252 +1,8 @@
11
use clap::{App, Arg};
2-
use glob::glob;
3-
use std::cmp;
4-
use std::collections::{HashMap, VecDeque};
2+
use icfpc::models::*;
3+
use icfpc::parse::read_all_inputs;
54
use std::fs::File;
65
use std::io::Read;
7-
use std::iter::Peekable;
8-
use std::str::Chars;
9-
10-
fn find_files(input_root: &str) -> Vec<String> {
11-
glob(&format!("{}/prob-*.desc", input_root))
12-
.expect("glob pattern")
13-
.map(|p| {
14-
p.unwrap()
15-
.file_name()
16-
.unwrap()
17-
.to_str()
18-
.unwrap()
19-
.to_string()
20-
})
21-
.collect::<Vec<String>>()
22-
}
23-
24-
fn output_file_name(file_name: &str) -> String {
25-
format!("prob-{}.sol", &file_name[5..8])
26-
}
27-
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
28-
struct Point {
29-
x: usize,
30-
y: usize,
31-
}
32-
impl Point {
33-
fn new(x: usize, y: usize) -> Point {
34-
Point { x, y }
35-
}
36-
37-
fn move_with(&self, command: Command) -> Option<Point> {
38-
let (x, y) = (self.x, self.y);
39-
match command {
40-
Command::MoveUp => Some(Point::new(x, y + 1)),
41-
Command::MoveDown => match self.y {
42-
0 => None,
43-
_ => Some(Point::new(x, y - 1)),
44-
},
45-
Command::MoveRight => Some(Point::new(x + 1, y)),
46-
Command::MoveLeft => match self.x {
47-
0 => None,
48-
_ => Some(Point::new(x - 1, y)),
49-
},
50-
_ => Some(*self),
51-
}
52-
}
53-
}
54-
55-
#[derive(Debug, Clone)]
56-
enum BoosterType {
57-
NewHand,
58-
FastMove,
59-
Drill,
60-
Teleports,
61-
Unknown,
62-
}
63-
64-
type Booster = (BoosterType, Point);
65-
66-
#[derive(Debug, Clone)]
67-
struct Map(Vec<Point>);
68-
69-
enum Direction {
70-
Verticle,
71-
Horizontal,
72-
}
73-
74-
impl Map {
75-
fn iter_lines(&self) -> Vec<(Direction, Point, Point)> {
76-
let mut iter = self.0.iter().cloned().cycle().peekable();
77-
let mut res = Vec::new();
78-
for _ in 0..self.0.len() {
79-
let cur = iter.next().unwrap();
80-
let next = *iter.peek().unwrap();
81-
if cur.x == next.x {
82-
res.push((Direction::Verticle, cur, next));
83-
} else if cur.y == next.y {
84-
res.push((Direction::Horizontal, cur, next));
85-
} else {
86-
unreachable!();
87-
}
88-
}
89-
res
90-
}
91-
92-
fn enumerate_points(&self) -> Vec<Point> {
93-
let g_min_x = self.0.iter().map(|p| p.x).min().unwrap();
94-
let g_max_x = self.0.iter().map(|p| p.x).max().unwrap();
95-
let mut cross_y_map = HashMap::new();
96-
for (dir, p, q) in self.iter_lines() {
97-
if let Horizontal = dir {
98-
let min_x = cmp::min(p.x, q.x);
99-
let max_x = cmp::max(p.x, q.x);
100-
for x in min_x..max_x {
101-
cross_y_map.entry(x).or_insert_with(|| Vec::new()).push(p.y);
102-
}
103-
}
104-
}
105-
let mut res = Vec::new();
106-
for x in g_min_x..g_max_x {
107-
let v = cross_y_map.get_mut(&x).unwrap();
108-
assert!(v.len() % 2 == 0);
109-
v.sort();
110-
let mut iter = v.iter();
111-
while let Some(lb) = iter.next() {
112-
let ub = iter.next().unwrap();
113-
for y in *lb..*ub {
114-
res.push(Point::new(x, y));
115-
}
116-
}
117-
}
118-
res
119-
}
120-
}
121-
122-
#[derive(Debug, Clone)]
123-
struct Input {
124-
map: Map,
125-
initial: Point,
126-
obstacles: Vec<Map>,
127-
boosters: Vec<Booster>,
128-
}
129-
130-
#[derive(Debug, Clone, Copy)]
131-
enum Command {
132-
MoveUp,
133-
MoveDown,
134-
MoveLeft,
135-
MoveRight,
136-
Noop,
137-
TurnRight,
138-
TurnLeft,
139-
}
140-
141-
fn skip(iter: &mut Peekable<Chars>, expected: char) {
142-
let c = iter.next().unwrap();
143-
assert!(c == expected);
144-
}
145-
146-
fn skip_or_empty(iter: &mut Peekable<Chars>, expected: char) {
147-
if let Some(c) = iter.next() {
148-
assert!(c == expected);
149-
}
150-
}
151-
152-
fn read_point(iter: &mut Peekable<Chars>) -> Point {
153-
skip(iter, '(');
154-
let mut x = 0;
155-
loop {
156-
let c = iter.next().unwrap();
157-
if c.is_digit(10) {
158-
x = x * 10 + (c as u8 - '0' as u8);
159-
} else {
160-
assert!(c == ',');
161-
break;
162-
}
163-
}
164-
let mut y = 0;
165-
loop {
166-
let c = iter.next().unwrap();
167-
if c.is_digit(10) {
168-
y = y * 10 + (c as u8 - '0' as u8);
169-
} else {
170-
assert!(c == ')');
171-
break;
172-
}
173-
}
174-
Point::new(x as usize, y as usize)
175-
}
176-
177-
fn read_map_internal(mut iter: &mut Peekable<Chars>) -> (Map, char) {
178-
let mut points = Vec::new();
179-
points.push(read_point(&mut iter));
180-
loop {
181-
let c = iter.next().unwrap();
182-
if c != ',' {
183-
return (Map(points), c);
184-
}
185-
points.push(read_point(&mut iter));
186-
}
187-
}
188-
189-
fn read_map(mut iter: &mut Peekable<Chars>) -> Map {
190-
let (m, c) = read_map_internal(&mut iter);
191-
assert!(c == '#');
192-
m
193-
}
194-
195-
fn read_initial(mut iter: &mut Peekable<Chars>) -> Point {
196-
let p = read_point(&mut iter);
197-
skip(iter, '#');
198-
p
199-
}
200-
201-
fn read_obstacles(mut iter: &mut Peekable<Chars>) -> Vec<Map> {
202-
let mut res = Vec::new();
203-
if *iter.peek().unwrap() == '#' {
204-
iter.next();
205-
return res;
206-
}
207-
208-
loop {
209-
let (m, c) = read_map_internal(&mut iter);
210-
res.push(m);
211-
if c == '#' {
212-
break;
213-
}
214-
assert!(c == ';');
215-
}
216-
res
217-
}
218-
219-
fn read_boosters(mut iter: &mut Peekable<Chars>) -> Vec<Booster> {
220-
let mut res = Vec::new();
221-
while let Some(c) = iter.next() {
222-
let booster_type = match c {
223-
'B' => BoosterType::NewHand,
224-
'F' => BoosterType::FastMove,
225-
'L' => BoosterType::Drill,
226-
'X' => BoosterType::Unknown,
227-
'R' => BoosterType::Teleports,
228-
_ => panic!("unknown type {}", c),
229-
};
230-
let point = read_point(&mut iter);
231-
res.push((booster_type, point));
232-
skip_or_empty(&mut iter, ';');
233-
}
234-
res
235-
}
236-
237-
fn read_input(s: &str) -> Input {
238-
let mut iter = s.chars().peekable();
239-
let map = read_map(&mut iter);
240-
let initial = read_initial(&mut iter);
241-
let obstacles = read_obstacles(&mut iter);
242-
let boosters = read_boosters(&mut iter);
243-
Input {
244-
map,
245-
initial,
246-
obstacles,
247-
boosters,
248-
}
249-
}
2506

2517
struct ScoreInfo {
2528
width: usize,
@@ -267,10 +23,11 @@ impl ScoreInfo {
26723

26824
fn debug(&self) -> String {
26925
format!(
270-
"1000.0 * {:5.2} * {:4.2} = {:8.2}",
26+
"1000.0 * {:5.2} * {:4.2} = {:8.2} ({:6} steps)",
27127
self.log_wh(),
27228
self.ratio(),
273-
self.score()
29+
self.score(),
30+
self.team_time
27431
)
27532
}
27633

@@ -279,8 +36,8 @@ impl ScoreInfo {
27936
}
28037
}
28138

282-
fn score_small(input: Input, output_len: usize) -> ScoreInfo {
283-
let map_points = input.map.enumerate_points();
39+
fn score_small(task: Task, output_len: usize) -> ScoreInfo {
40+
let map_points = task.map.enumerate_points();
28441

28542
let width = map_points.iter().map(|p| p.x).max().unwrap() + 1;
28643
let height = map_points.iter().map(|p| p.y).max().unwrap() + 1;
@@ -294,7 +51,7 @@ fn score_small(input: Input, output_len: usize) -> ScoreInfo {
29451
remaining += 1;
29552
}
29653

297-
for o in &input.obstacles {
54+
for o in &task.obstacles {
29855
for p in o.enumerate_points().iter() {
29956
if p.y < height && p.x < width && valid[p.y][p.x] {
30057
valid[p.y][p.x] = false;
@@ -330,21 +87,19 @@ fn main() {
33087
.get_matches();
33188
let input_root = matches.value_of("input").expect("no input specified");
33289
let output_root = matches.value_of("output").expect("no output specified");
333-
let files = find_files(&input_root);
90+
let inputs = read_all_inputs(input_root);
33491

33592
let mut sum_scores = 0.0;
336-
for f in files.iter() {
337-
let input_path = format!("{}/{}", input_root, f);
338-
let mut input_file = File::open(&input_path).unwrap();
339-
let output_path = format!("{}/{}", output_root, output_file_name(&f));
340-
let mut output_file = File::open(&output_path).unwrap();
341-
let mut input_str = String::new();
342-
input_file.read_to_string(&mut input_str);
343-
let mut output_str = String::new();
344-
output_file.read_to_string(&mut output_str);
345-
let output_len = output_str.trim_end().len();
346-
let score_info = score_small(read_input(&input_str), output_len);
347-
eprintln!("{}: {}", f, score_info.debug());
93+
for input in inputs {
94+
let output_len = {
95+
let output_path = format!("{}/{}", output_root, input.output_file_name());
96+
let mut output_file = File::open(&output_path).unwrap();
97+
let mut output_str = String::new();
98+
output_file.read_to_string(&mut output_str).unwrap();
99+
output_str.trim_end().len()
100+
};
101+
let score_info = score_small(input.task, output_len);
102+
eprintln!("{}: {}", input.id, score_info.debug());
348103
sum_scores += score_info.score();
349104
}
350105
println!("output: {}", output_root);

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub mod models;
2+
pub mod parse;
3+
pub mod solve;

0 commit comments

Comments
 (0)