-
Notifications
You must be signed in to change notification settings - Fork 17
/
(hard) The Bridge.js
103 lines (87 loc) · 3.17 KB
/
(hard) The Bridge.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/**
* The Bridge
* https://www.codingame.com/training/hard/the-bridge-episode-2
* Statement:
* The goal of the puzzle is to drive a group of motorbikes along a road,
* avoiding holes and regulating your speed. This puzzle requires to predict
* all the situations the motorbikes can perform along the time and chose
* the most optimized choice.
* Story:
* Take the control of the resistance against the machines. You have
* injected a virus in a Moto-Terminator and you have to send it onto a
* platform to capture it.
*/
// M - the amount of motorbikes to control
// V - the minimum amount of motorbikes that must survive
const [M, V] = [+readline(), +readline()];
const roads = Array(4).fill().map(_ => readline().split``.map(c => c === '.'));
const roadLength = roads[0].length;
const copy = (bikes) => bikes.map(b => ({x: b.x, y: b.y, speed: b.speed}));
const findPath = (original, V) => {
const results = [];
const applyMove = (bikes, move) => bikes.map(bike => {
const next = bike.x + bike.speed;
let nextLane = bike.y;
let checked = roads[bike.y].slice(bike.x, next);
if (move === 'UP' || move === 'DOWN') {
if (move === 'UP' && bike.y === 0 || move === 'DOWN' && bike.y === 3) {
checked = [];
bikes = [];
} else {
nextLane = bike.y + (move === 'UP' ? -1 : 1);
checked.push(...roads[nextLane].slice(bike.x, next));
}
}
if (checked.some(x => !x) && move !== 'JUMP' || next < roadLength && !roads[nextLane][next]) {
return null;
}
[bike.x, bike.y] = [next, nextLane];
return bike;
}).filter(b => b);
for (let move of ['SPEED', 'WAIT', 'JUMP', 'DOWN', 'UP', 'SLOW']) {
let bikes = copy(original);
if (move === 'SPEED') {
bikes.forEach(b => b.speed++);
} else if (move === 'SLOW') {
bikes.forEach(b => b.speed--);
if (bikes[0].speed === 0) {
bikes = [];
}
}
bikes = applyMove(bikes, move);
bikes.length >= V && results.push({move: move, bikes: bikes});
}
return results;
};
const backtrack = (bikes, V) => {
const [stack, moves] = [[bikes], []];
while(stack.length) {
bikes = stack[0];
!bikes.next && (bikes.next = findPath(bikes, V), bikes.id = 0);
if (bikes[0].x >= roadLength) {
return moves.reverse();
}
if (bikes.id < bikes.next.length) {
let next = bikes.next[bikes.id++];
stack.unshift(next.bikes);
moves.unshift(next.move);
} else {
stack.shift();
moves.shift();
}
}
return null;
};
let move = null;
// game loop
while (true) {
const [speed, bikes] = [+readline(), []];
for (let i = 0; i < M; i++) {
let [x, y, active] = readline().split` `.map(n => +n);
active && bikes.push({x, y, speed});
}
for (let expected = bikes.length; !move && expected >= V; expected--) {
move = backtrack(copy(bikes), expected);
}
print(move.shift() || 'WAIT');
}