Skip to content

Instantly share code, notes, and snippets.

@varmais
Last active December 29, 2017 16:23
Show Gist options
  • Save varmais/bf1fc5c54b437d7643cd905b2cb5a763 to your computer and use it in GitHub Desktop.
Save varmais/bf1fc5c54b437d7643cd905b2cb5a763 to your computer and use it in GitHub Desktop.
const map1 = `
@---A---+
|
x-B-+ C
| |
+---+
`;
const map2 = `
@
| C----+
A | |
+---B--+
| x
| |
+---D--+
`;
const map3 = `
@---+
B
K-----|--A
| | |
| +--E |
| | |
+--E--Ex C
| |
+--F--+
`;
class PathFinder {
constructor(map) {
this.map = this.stringToArrays(map);
this.position = this.getStartPosition();
this.route = [];
this.direction = undefined;
this.previousDirection = undefined;
}
getStartPosition() {
for (let i = 0; i < this.map.length; i++) {
for (let j = 0; j < this.map[i].length; j++) {
if (this.isStartChar(this.map[i][j])) {
return {y: i, x: j};
}
}
}
}
travel() {
while (!this.isFinished()) {
const char = this.currentChar();
if (this.isLetterChar(char)) {
this.route.push(char);
}
if (this.isTurnChar(char) || this.isStartChar(char)) {
this.turn();
} else if (this.isPathChar(char)) {
this.step(this.direction);
} else if (this.isLetterChar(char)) {
if (this.shouldJumpOverLetter()) {
this.step(this.direction)
} else {
this.turn();
}
}
}
}
print() {
console.log(this.route.join('-'));
}
shouldJumpOverLetter () {
const positionOver = this.getPositionInDirection(this.direction);
const charOver = this.charAtPosition(positionOver);
return this.isPositionOnPath(positionOver) || this.isTurnChar(charOver) || this.isFinishChar(charOver)
}
turn() {
const {up, down, left, right} = this.DIRECTIONS;
let directions = [up, down, left, right].map(this.checkDirection.bind(this)).filter(d => d);
if (directions.length > 1) {
directions = directions.filter(this.filterPreviousDirection.bind(this));
}
if (directions.length === 1) {
return this.step(directions[0]);
}
throw new Error('No way found!');
}
checkDirection (direction) {
const position = this.getPositionInDirection(direction);
if (!this.isPositionOnMap(position) && this.isPositionOnPath(position)) {
return direction;
}
}
getPositionInDirection(direction) {
return {
x: this.position.x + direction.x,
y: this.position.y + direction.y
};
}
step(direction) {
this.previousDirection = this.direction;
this.direction = direction;
this.position = this.getPositionInDirection(direction);
}
isPositionOnMap(position) {
const {x, y} = position;
const xMin = 0;
const yMin = 0;
const xMax = this.map[0].length - 1;
const yMax = this.map.length - 1;
return !((x >= xMin && x <= xMax) && (y >= yMin && y <= yMax));
}
isPositionOnPath(position) {
const char = this.charAtPosition(position);
const {letter, path} = this.CHARACTERS;
return letter.includes(char) || path.includes(char);
}
filterPreviousDirection(direction) {
if (!this.previousDirection) {
return false;
}
const {x, y} = this.previousDirection;
if (direction.x === x && direction.y === -y) {
return false;
}
return !(direction.y === y && direction.x === -x);
}
isStartChar (char) {
return this.CHARACTERS.start.includes(char);
}
isPathChar (char) {
return this.CHARACTERS.path.includes(char);
}
isLetterChar (char) {
return this.CHARACTERS.letter.includes(char);
}
isTurnChar (char) {
return this.CHARACTERS.turn.includes(char);
}
isFinishChar (char) {
return this.CHARACTERS.finish.includes(char);
}
isFinished() {
return this.isFinishChar(this.currentChar());
}
currentChar() {
return this.charAtPosition(this.position);
}
charAtPosition(position) {
const {x, y} = position;
return this.map[y][x];
}
}
PathFinder.prototype.CHARACTERS = {
start: ['@'],
finish: ['x'],
turn: ['+'],
path: ['-', '|'],
letter: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
};
PathFinder.prototype.DIRECTIONS = {
right: {x: 1, y: 0},
down: {x: 0, y: 1},
left: {x: -1, y: 0},
up: {x: 0, y: -1}
};
PathFinder.prototype.stringToArrays = function (string) {
return string.split('\n').filter(line => line.length).map(row => row.split(''));
};
const maps = [map1, map2, map3];
maps.forEach((map) => {
const mapper = new PathFinder(map);
mapper.travel();
mapper.print();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment