Skip to content

Commit 827943b

Browse files
committed
Partial puzzle solver
1 parent 6cae83e commit 827943b

File tree

9 files changed

+335
-22
lines changed

9 files changed

+335
-22
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/target
22
**/*.rs.bk
33
solutions/test
4+
blocks

Diff for: src/bin/mining.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use icfpc::mine::Client;
22

33
fn main() {
4-
let _client = Client::new();
4+
let mut client = Client::new();
5+
client.execute();
56
}

Diff for: src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ pub mod models;
66
pub mod parse;
77
pub mod solve;
88
pub mod utils;
9+
pub mod puzzle;

Diff for: src/mine.rs

+50-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
use jsonrpc_client_http::{HttpHandle, HttpTransport};
2+
use rand::prelude::*;
23
use serde::{Deserialize, Serialize};
34
use serde_json::Value;
5+
use std::collections::{HashMap, HashSet, VecDeque};
6+
use std::{thread, time};
7+
8+
use crate::models::*;
9+
use crate::parse::{read_puzzle, read_task};
10+
use crate::puzzle::solve_pazzle;
11+
use crate::solve::solve_small;
412

513
#[derive(Debug, Serialize, Deserialize)]
614
pub struct BlockChainInfo {
@@ -13,14 +21,22 @@ pub struct BlockChainInfo {
1321
#[derive(Debug, Serialize, Deserialize)]
1422
pub struct MiningInfo {
1523
block: usize,
16-
excluded: Vec<usize>,
24+
//excluded: Vec<usize>,
25+
puzzle: String,
26+
task: String,
27+
}
28+
29+
#[derive(Debug, Serialize, Deserialize)]
30+
pub struct BlockInfo {
31+
block: usize,
1732
puzzle: String,
1833
task: String,
1934
}
2035

2136
jsonrpc_client!(pub struct LambdaClient {
2237
pub fn getblockchaininfo(&mut self) -> RpcRequest<BlockChainInfo>;
2338
pub fn getmininginfo(&mut self) -> RpcRequest<MiningInfo>;
39+
pub fn getblockinfo(&mut self, block: usize) -> RpcRequest<BlockInfo>;
2440
pub fn submit(&mut self, block: usize, task_sol_path: &str, pazzle_sol_path: &str) -> RpcRequest<Value>;
2541
});
2642

@@ -41,4 +57,37 @@ impl Client {
4157
let client = LambdaClient::new(transport_handle);
4258
Client { api: client }
4359
}
60+
61+
pub fn solve(&self, block: usize, puzzle: &str, task: &str) {
62+
let mut rand = thread_rng();
63+
let puzzle = read_puzzle(puzzle);
64+
eprintln!("{:?}", puzzle);
65+
let task = read_task(task);
66+
//let commands = solve_small(task);
67+
68+
let puzzle_answer = solve_pazzle(puzzle);
69+
println!("{:?}", puzzle_answer);
70+
}
71+
72+
pub fn execute(&mut self) {
73+
loop {
74+
match self.api.getmininginfo().call() {
75+
Ok(x) => {
76+
for b in 0..x.block {
77+
let b = self.api.getblockinfo(b).call().unwrap();
78+
let puzzle = read_puzzle(&b.puzzle);
79+
let puzzle_answer = solve_pazzle(puzzle);
80+
println!("{:?}", puzzle_answer);
81+
}
82+
self.solve(x.block, &x.puzzle, &x.task);
83+
}
84+
Err(e) => {
85+
println!("{}", e);
86+
}
87+
}
88+
89+
let one_sec = time::Duration::from_secs(60);
90+
thread::sleep(one_sec);
91+
}
92+
}
4493
}

Diff for: src/models.rs

+49
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ impl Add for Point {
1717
}
1818
}
1919

20+
impl fmt::Display for Point {
21+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
22+
write!(f, "({},{})", self.x, self.y)?;
23+
Ok(())
24+
}
25+
}
26+
2027
impl Point {
2128
pub fn new(x: i32, y: i32) -> Point {
2229
Point { x, y }
@@ -53,6 +60,13 @@ pub enum Direction {
5360
#[derive(Debug, Clone, Eq, PartialEq)]
5461
pub struct Map(pub Vec<Point>);
5562

63+
impl fmt::Display for Map {
64+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65+
write!(f, "{}", self.0.iter().map(|p| format!("{}", p)).collect::<Vec<_>>().join(","))?;
66+
Ok(())
67+
}
68+
}
69+
5670
impl Map {
5771
pub fn new(ps: Vec<Point>) -> Map {
5872
Map(ps)
@@ -111,6 +125,10 @@ impl Map {
111125
}
112126
res
113127
}
128+
129+
pub fn len(&self) -> usize {
130+
self.0.len()
131+
}
114132
}
115133

116134
#[derive(Debug, Clone, Eq, PartialEq)]
@@ -123,6 +141,19 @@ pub enum BoosterType {
123141
Spawn,
124142
}
125143

144+
impl fmt::Display for BoosterType {
145+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146+
match self {
147+
BoosterType::NewHand => write!(f, "B"),
148+
BoosterType::FastMove => write!(f, "F"),
149+
BoosterType::Drill => write!(f, "L"),
150+
BoosterType::Teleports => write!(f, "R"),
151+
BoosterType::Cloning => write!(f, "C"),
152+
BoosterType::Spawn => write!(f, "X"),
153+
}
154+
}
155+
}
156+
126157
#[derive(Debug, Clone, Eq, PartialEq)]
127158
pub struct Booster {
128159
pub kind: BoosterType,
@@ -135,6 +166,12 @@ impl Booster {
135166
}
136167
}
137168

169+
impl fmt::Display for Booster {
170+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171+
write!(f, "{}{}", self.kind, self.point)
172+
}
173+
}
174+
138175
#[derive(Debug, Clone, Eq, PartialEq)]
139176
pub struct Task {
140177
pub width: usize,
@@ -145,6 +182,17 @@ pub struct Task {
145182
pub boosters: Vec<Booster>,
146183
}
147184

185+
impl fmt::Display for Task {
186+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
187+
write!(f, "{}#", self.map)?;
188+
write!(f, "{}#", self.initial)?;
189+
write!(f, "{}#", self.obstacles.iter().map(|o| format!("{}", o)).collect::<Vec<_>>().join(";"))?;
190+
write!(f, "{}", self.boosters.iter().map(|b| format!("{}", b)).collect::<Vec<_>>().join(";"))?;
191+
Ok(())
192+
}
193+
}
194+
195+
148196
#[derive(Debug, Clone, Eq, PartialEq)]
149197
pub enum Move {
150198
MoveUp,
@@ -185,6 +233,7 @@ impl fmt::Display for Command {
185233
}
186234
}
187235

236+
#[derive(Debug)]
188237
pub struct Puzzle {
189238
pub block: usize,
190239
pub epock: usize,

Diff for: src/parse.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ fn read_boosters(mut iter: &mut Peekable<Chars>) -> Vec<Booster> {
132132
res
133133
}
134134

135-
fn read_task(s: &str) -> Task {
135+
pub fn read_task(s: &str) -> Task {
136136
let mut iter = s.chars().peekable();
137137
let map = read_map(&mut iter);
138138
let initial = read_initial(&mut iter);
@@ -164,7 +164,7 @@ fn find_files(input_root: &str) -> Vec<String> {
164164
.collect::<Vec<String>>()
165165
}
166166

167-
fn read_puzzle(s: &str) -> Puzzle {
167+
pub fn read_puzzle(s: &str) -> Puzzle {
168168
let mut iter = s.chars().peekable();
169169
let block = read_usize(&mut iter, ',');
170170
let epock = read_usize(&mut iter, ',');

Diff for: src/puzzle.rs

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
use crate::models::*;
2+
use crate::utils::Range;
3+
use rand::prelude::*;
4+
use std::collections::VecDeque;
5+
6+
fn construct_map_from_ranges(ranges: &[Range]) -> Map {
7+
let len = ranges.len();
8+
let mut vertexes = Vec::new();
9+
vertexes.push(Point::new(0, ranges[0].start as i32));
10+
vertexes.push(Point::new(0, ranges[0].end as i32));
11+
for y in 0..len - 1 {
12+
if ranges[y].end != ranges[y + 1].end {
13+
vertexes.push(Point::new((y + 1) as i32, ranges[y].end as i32));
14+
vertexes.push(Point::new((y + 1) as i32, ranges[y + 1].end as i32));
15+
}
16+
}
17+
vertexes.push(Point::new(len as i32, ranges[len - 1].end as i32));
18+
vertexes.push(Point::new(len as i32, ranges[len - 1].start as i32));
19+
for y in (0..len - 1).rev() {
20+
if ranges[y].start != ranges[y + 1].start {
21+
vertexes.push(Point::new((y + 1) as i32, ranges[y + 1].start as i32));
22+
vertexes.push(Point::new((y + 1) as i32, ranges[y].start as i32));
23+
}
24+
}
25+
Map::new(vertexes)
26+
}
27+
28+
fn consume_points_for(source: &mut VecDeque<Point>, num: usize, kind: BoosterType) -> Vec<Booster> {
29+
let mut res = Vec::new();
30+
for _ in 0..num {
31+
res.push(Booster::new(kind.clone(), source.pop_front().unwrap()));
32+
}
33+
res
34+
}
35+
36+
pub fn solve_pazzle(puzzle: Puzzle) -> Option<Task> {
37+
let len = puzzle.max_length - 1;
38+
assert!(puzzle.includes.iter().all(|p| p.x < len as i32));
39+
assert!(puzzle.includes.iter().all(|p| p.y < len as i32));
40+
assert!(puzzle.excludes.iter().all(|p| p.x < len as i32));
41+
assert!(puzzle.excludes.iter().all(|p| p.y < len as i32));
42+
43+
let mut include_xs = vec![vec![]; len];
44+
let mut exclude_xs = vec![vec![]; len];
45+
for p in &puzzle.excludes {
46+
exclude_xs[p.y as usize].push(p.x as usize);
47+
}
48+
for p in &puzzle.includes {
49+
include_xs[p.y as usize].push(p.x as usize);
50+
}
51+
52+
let global_range = Range::new(0, len);
53+
let mut x_ranges = vec![vec![]; len];
54+
for y in 0..len {
55+
let exs = &mut exclude_xs[y];
56+
if exs.is_empty() {
57+
x_ranges[y].push(global_range);
58+
} else {
59+
exs.sort();
60+
x_ranges[y].push(global_range.split(exs[0]).0);
61+
x_ranges[y].push(global_range.split(exs[exs.len() - 1]).1);
62+
for i in 0..exs.len() - 1 {
63+
x_ranges[y].push(global_range.split(exs[i]).1.split(exs[i + 1]).0);
64+
}
65+
}
66+
}
67+
let mut reachables = vec![vec![]; len];
68+
for r in &x_ranges[0] {
69+
let ixs = &include_xs[0];
70+
if r.contains_all(ixs) {
71+
reachables[0].push((*r, *r));
72+
}
73+
}
74+
for y in 1..len {
75+
let mut next = Vec::new();
76+
let ixs = &include_xs[y];
77+
for to in &x_ranges[y] {
78+
if !to.contains_all(ixs) {
79+
continue;
80+
}
81+
for (from, _) in &reachables[y - 1] {
82+
if !to.intersect(*from) {
83+
continue;
84+
}
85+
next.push((*to, *from));
86+
break;
87+
}
88+
}
89+
reachables[y].extend(next);
90+
}
91+
92+
if reachables[len - 1].is_empty() {
93+
eprintln!("unreachable");
94+
return None;
95+
}
96+
97+
let mut ranges = Vec::new();
98+
let (mut cur_r, mut next_r) = reachables[len - 1][0];
99+
ranges.push(cur_r);
100+
for y in (0..len - 1).rev() {
101+
let (new_cur_r, new_next_r) = reachables[y]
102+
.iter()
103+
.cloned()
104+
.find(|(r, _)| *r == next_r)
105+
.unwrap();
106+
cur_r = new_cur_r;
107+
next_r = new_next_r;
108+
ranges.push(cur_r);
109+
}
110+
ranges.reverse();
111+
112+
let map = construct_map_from_ranges(&ranges);
113+
114+
if map.len() < puzzle.vertex_min {
115+
eprintln!(
116+
"NG: vertex {} is less than {}",
117+
map.len(),
118+
puzzle.vertex_min
119+
);
120+
return None;
121+
}
122+
123+
if map.len() > puzzle.vertex_max {
124+
eprintln!(
125+
"NG: vertex {} is greater than {}",
126+
map.len(),
127+
puzzle.vertex_max
128+
);
129+
return None;
130+
}
131+
132+
let mut points = map.enumerate_points();
133+
if points.len() < len * len / 5 {
134+
eprintln!("NG: area {} is less than {}", points.len(), len * len / 5);
135+
return None;
136+
}
137+
138+
let mut rand = thread_rng();
139+
points.shuffle(&mut rand);
140+
let mut point_source = points.into_iter().collect::<VecDeque<_>>();
141+
let initial = point_source.pop_front().unwrap();
142+
143+
let mut boosters = Vec::new();
144+
boosters.extend(consume_points_for(
145+
&mut point_source,
146+
puzzle.hand_count,
147+
BoosterType::NewHand,
148+
));
149+
boosters.extend(consume_points_for(
150+
&mut point_source,
151+
puzzle.fast_count,
152+
BoosterType::FastMove,
153+
));
154+
boosters.extend(consume_points_for(
155+
&mut point_source,
156+
puzzle.drill_count,
157+
BoosterType::Drill,
158+
));
159+
boosters.extend(consume_points_for(
160+
&mut point_source,
161+
puzzle.tele_count,
162+
BoosterType::Teleports,
163+
));
164+
boosters.extend(consume_points_for(
165+
&mut point_source,
166+
puzzle.clone_count,
167+
BoosterType::Cloning,
168+
));
169+
boosters.extend(consume_points_for(
170+
&mut point_source,
171+
puzzle.spawn_count,
172+
BoosterType::Spawn,
173+
));
174+
175+
let task = Task {
176+
width: len,
177+
height: len,
178+
map,
179+
initial,
180+
obstacles: Vec::new(),
181+
boosters,
182+
};
183+
184+
Some(task)
185+
}

0 commit comments

Comments
 (0)