🚀 improve clean layer

This commit is contained in:
platane
2020-10-24 11:19:49 +02:00
parent 4f9ff10741
commit b9c67baa6a
3 changed files with 86 additions and 48 deletions

View File

@@ -0,0 +1,59 @@
/**
* clean layer is too expensive with solution branching
* do not branch for faster result ( at the cost of finding a minimal step number )
*/
import { copyGrid, setColorEmpty } from "@snk/types/grid";
import { getHeadX, getHeadY } from "@snk/types/snake";
import { getAvailableRoutes } from "./getAvailableRoutes";
import type { Snake } from "@snk/types/snake";
import type { Grid } from "@snk/types/grid";
import type { Point } from "@snk/types/point";
export const getAvailableWhiteListedRoute = (
grid: Grid,
snake: Snake,
whiteList: Point[]
) => {
let solution: Snake[] | null;
getAvailableRoutes(grid, snake, (chain) => {
const hx = getHeadX(chain[0]);
const hy = getHeadY(chain[0]);
if (!whiteList.some(({ x, y }) => hx === x && hy === y)) return false;
solution = chain;
return true;
});
// @ts-ignore
return solution;
};
export const cleanLayer = (grid0: Grid, snake0: Snake, chunk0: Point[]) => {
const chunk = chunk0.slice();
const grid = copyGrid(grid0);
let snake = snake0;
const chain: Snake[] = [];
while (chunk.length) {
const chainN = getAvailableWhiteListedRoute(grid, snake, chunk);
if (!chainN) throw new Error("some cells are unreachable");
chain.unshift(...chainN);
snake = chain[0];
const x = getHeadX(snake);
const y = getHeadY(snake);
setColorEmpty(grid, x, y);
const i = chunk.findIndex((c) => c.x === x && c.y === y);
chunk.splice(i, 1);
}
return chain;
};

View File

@@ -30,28 +30,6 @@ const createGetHeuristic = (grid: Grid, chunk0: Point[]) => {
return (chunk: any[]) => chunk.length * k; return (chunk: any[]) => chunk.length * k;
}; };
export const getAvailableWhiteListedRoutes = (
grid: Grid,
snake: Snake,
whiteList: Point[]
) => {
let solution: Snake[] | null;
getAvailableRoutes(grid, snake, (chain) => {
const hx = getHeadX(chain[0]);
const hy = getHeadY(chain[0]);
if (!whiteList.some(({ x, y }) => hx === x && hy === y)) return false;
solution = chain;
return true;
});
// @ts-ignore
return solution;
};
export const cleanLayer = (grid0: Grid, snake0: Snake, chunk0: Point[]) => { export const cleanLayer = (grid0: Grid, snake0: Snake, chunk0: Point[]) => {
const getH = createGetHeuristic(grid0, chunk0); const getH = createGetHeuristic(grid0, chunk0);
@@ -74,9 +52,9 @@ export const cleanLayer = (grid0: Grid, snake0: Snake, chunk0: Point[]) => {
if (o.chunk.length === 0) return unwrap(o).slice(0, -1); if (o.chunk.length === 0) return unwrap(o).slice(0, -1);
const chain = getAvailableWhiteListedRoutes(o.grid, o.snake, o.chunk); const chains = getAvailableWhiteListedRoutes(o.grid, o.snake, o.chunk);
if (chain) { for (const chain of chains) {
const snake = chain[0]; const snake = chain[0];
const x = getHeadX(snake); const x = getHeadX(snake);
const y = getHeadY(snake); const y = getHeadY(snake);
@@ -101,32 +79,34 @@ export const cleanLayer = (grid0: Grid, snake0: Snake, chunk0: Point[]) => {
} }
} }
} }
throw new Error("some cells are unreachable");
}; };
// export const getAvailableWhiteListedRoutes = ( export const getAvailableWhiteListedRoutes = (
// grid: Grid, grid: Grid,
// snake: Snake, snake: Snake,
// whiteList0: Point[], whiteList0: Point[],
// n = 3 n = 3
// ) => { ) => {
// const whiteList = whiteList0.slice(); const whiteList = whiteList0.slice();
// const solutions: Snake[][] = []; const solutions: Snake[][] = [];
// getAvailableRoutes(grid, snake, (chain) => { getAvailableRoutes(grid, snake, (chain) => {
// const hx = getHeadX(chain[0]); const hx = getHeadX(chain[0]);
// const hy = getHeadY(chain[0]); const hy = getHeadY(chain[0]);
// const i = whiteList.findIndex(({ x, y }) => hx === x && hy === y); const i = whiteList.findIndex(({ x, y }) => hx === x && hy === y);
// if (i >= 0) { if (i >= 0) {
// whiteList.splice(i, 1); whiteList.splice(i, 1);
// solutions.push(chain); solutions.push(chain);
// if (solutions.length >= n || whiteList.length === 0) return true; if (solutions.length >= n || whiteList.length === 0) return true;
// } }
// return false; return false;
// }); });
// return solutions; return solutions;
// }; };

View File

@@ -1,6 +1,6 @@
import { copyGrid, isEmpty } from "@snk/types/grid"; import { copyGrid, isEmpty } from "@snk/types/grid";
import { pruneLayer } from "./pruneLayer"; import { pruneLayer } from "./pruneLayer";
import { cleanLayer } from "./cleanLayer"; import { cleanLayer } from "./cleanLayer-monobranch";
import type { Snake } from "@snk/types/snake"; import type { Snake } from "@snk/types/snake";
import type { Color, Grid } from "@snk/types/grid"; import type { Color, Grid } from "@snk/types/grid";
@@ -15,8 +15,7 @@ export const getBestRoute = (grid0: Grid, snake0: Snake) => {
const gridN = copyGrid(grid); const gridN = copyGrid(grid);
const chunk = pruneLayer(grid, color, snakeN); const chunk = pruneLayer(grid, color, snakeN);
const c = cleanLayer(gridN, chain[0], chunk); const c = cleanLayer(gridN, chain[0], chunk);
if (c) chain.unshift(...c); chain.unshift(...c);
else throw new Error("some cells are unreachable");
} }
return chain.reverse().slice(1); return chain.reverse().slice(1);