-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
117 lines (106 loc) · 2.9 KB
/
index.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
const roads = [
"Alice's House-Bob's House",
"Alice's House-Cabin",
"Alice's House-Post Office",
"Bob's House-Town Hall",
"Daria's House-Ernie's House",
"Daria's House-Town Hall",
"Ernie's House-Grete's House",
"Grete's House-Farm",
"Grete's House-Shop",
"Marketplace-Farm",
"Marketplace-Post Office",
"Marketplace-Shop",
"Marketplace-Town Hall",
"Shop-Town Hall",
];
function buildGraph(edges) {
let graph = Object.create(null);
function addEdge(from, to) {
if (graph[from] == null) {
graph[from] = [to];
} else {
graph[from].push(to);
}
}
for (let [from, to] of edges.map((r) => r.split("-"))) {
addEdge(from, to);
addEdge(to, from);
}
return graph;
}
const roadGraph = buildGraph(roads);
function randomPick(array) {
let choice = Math.floor(Math.random() * array.length);
return array[choice];
}
function randomRobot(state) {
return { direction: randomPick(roadGraph[state.place]) };
}
class VillageState {
constructor(place, parcels) {
this.place = place;
this.parcels = parcels;
}
move(destination) {
if (!roadGraph[this.place].includes(destination)) {
return this;
} else {
let parcels = this.parcels
.map((p) => {
if (p.place != this.place) return p;
return { place: destination, address: p.address };
})
.filter((p) => p.place != p.address);
return new VillageState(destination, parcels);
}
}
}
VillageState.random = function (parcelCount = 5) {
let parcels = [];
for (let i = 0; i < parcelCount; i++) {
let address = randomPick(Object.keys(roadGraph));
let place;
do {
place = randomPick(Object.keys(roadGraph));
} while (place == address);
parcels.push({ place, address });
}
return new VillageState("Post Office", parcels);
};
function runRobot(state, robot, memory) {
for (let turn = 0; ; turn++) {
if (state.parcels.length == 0) {
console.log(`Done in ${turn} turns`);
break;
}
let action = robot(state, memory);
state = state.move(action.direction);
memory = action.memory;
console.log(`Moved to ${action.direction}`);
}
}
function findRoute(graph, from, to) {
let work = [{ at: from, route: [] }];
for (let i = 0; i < work.length; i++) {
let { at, route } = work[i];
for (let place of graph[at]) {
if (place == to) return route.concat(place);
if (!work.some((w) => w.at == place)) {
work.push({ at: place, route: route.concat(place) });
}
}
}
}
function goalOrientedRobot({ place, parcels }, route) {
if (route.length == 0) {
let parcel = parcels[0];
if (parcel.place != place) {
route = findRoute(roadGraph, place, parcel.place);
} else {
route = findRoute(roadGraph, place, parcel.address);
}
}
return { direction: route[0], memory: route.slice(1) };
}
runRobotAnimation(VillageState.random(), goalOrientedRobot, []);