11use 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;
54use std:: fs:: File ;
65use 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
2517struct 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) ;
0 commit comments