Skip to content

Instantly share code, notes, and snippets.

@diestrin
Created September 23, 2017 16:50
Show Gist options
  • Select an option

  • Save diestrin/a62cc405243ba2d153511500fcecd34c to your computer and use it in GitHub Desktop.

Select an option

Save diestrin/a62cc405243ba2d153511500fcecd34c to your computer and use it in GitHub Desktop.
const cube =
`+---+
/ /|
+---+ |
| | +
| |/
+---+`.split('\n');
/**
* @typedef {{x: number, y: number, z: number}} Coords
*/
/**
* Utility to build ranges
*
* @param {number} from
* @param {number} to
* @return {number[]}
*/
function getRange(from, to) {
return '.'
.repeat(Math.abs(from - to) + 1)
.split('')
.map((dot, index) => from + index);
}
/**
* Converts the input array to a 3D space coords
*
* @param {number[][]} input
* @return {Coords}
*/
function getCoords(input) {
const x = input[0].length;
const y = input.length;
const z = input.reduce((highest, row) => {
const tower = row.reduce((_highest, tower) =>
_highest > tower ? _highest : tower
, 0);
return highest > tower ? highest : tower
}, 0);
return {x, y, z};
}
/**
* Generates the canvas with the correct width and height
*
* @param {number[][]} input
* @param {Coords} coords
* @return {string[]}
*/
function getLayout(input, coords) {
const height = input
.map(row =>
row.reduce((rowHighest, tower) =>
rowHighest > tower ? rowHighest : tower, 0))
.reverse()
.map((highest, index) => (highest * 3 + 1) + (index * 2) + 2)
.reduce((result, rowHighest) => result > rowHighest ? result : rowHighest);
const width = input
.map(row => row.filter(n => n).length)
.reverse()
.map((widest, index) => (widest * 4 + 1) + (index * 2) + 2)
.reduce((result, widest) => result > widest ? result : widest);
return ('.'.repeat(width) + '\n').repeat(height).split('\n');
}
/**
* Converts a 3D space point into a 2D space point on the X axys
*
* @param {Coords} coords
* @return {number}
*/
function getX({x, y}) {
const yPoints = (y - 1) * 2;
const xPoints = (x - 1) * 4;
return xPoints + yPoints;
}
/**
* Converts a 3D space point into a 2D space point on the Y axys
*
* @param {Coords} coords
* @return {number}
*/
function getY({y, z}, layout) {
const height = layout.length - 1;
const zPoints = (z - 1) * 3 + 6;
const yPoints = (y - 1) * 2;
const yBase = yPoints + zPoints;
return height - yBase;
}
/**
* Draw a single cube given the x,y,z coords
*
* @param {Coords} coords
* @param {string[]} layout
*/
function drawCube(coords, layout) {
const x = getX(coords);
const y = getY(coords, layout);
getRange(0, 5).forEach(i => {
const start = i < 2 ? 2 - i : 0;
const end = i >= 4 ? 10 - i : 7;
const line = layout[y + i];
layout[y + i] = line.slice(0, x + start) + cube[i] + line.slice(x + end);
});
}
/**
* Draw a specific row in a spacific floor
*
* @param {boolean[]} row
* @param {number} rowNum
* @param {number} floorNum
* @param {string[]} layout
*/
function drawRow(row, rowNum, floorNum, layout) {
row.forEach((shouldRender, index) => {
if (shouldRender) {
drawCube({x: index + 1, y: rowNum, z: floorNum}, layout);
}
});
}
/**
* Draw a specific floor
*
* @param {boolean[][]} floor
* @param {number} floorNum
* @param {number} layout
*/
function drawFloor(floor, floorNum, layout) {
floor.forEach((row, index, arr) => {
drawRow(row, arr.length - index, floorNum, layout);
});
}
/**
* Draw the whole table with all the cubes
*
* @param {number[][]} _input
*/
function cubes(input) {
const _input = [...input];
const coords = getCoords(_input);
const layout = getLayout(_input, coords);
getRange(1, coords.z)
.map(z => ({
floorNum: z,
floor: _input.reduce((result, row) => [
...result, row.map(cell => cell >= z)
], []),
}))
.forEach(result => drawFloor(result.floor, result.floorNum, layout));
return layout;
}
/**
* Print the result
*
* @param {string[]} layout
*/
function print(layout) {
console.log('\n' + layout.join('\n'));
}
print(cubes([
[2, 2, 1, 2, 2],
[2, 2, 1, 1, 2],
[3, 2, 1, 2, 2]
]));
print(cubes([
[3, 3, 3, 3, 3],
[2, 2, 2, 2, 2],
[1, 1, 1, 1, 1]
]));
print(cubes([
[1, 1, 1, 1, 1],
[2, 2, 2, 2, 2],
[3, 3, 3, 3, 3]
]));
print(cubes([
[1, 1, 1, 1, 1],
[2, 2, 2, 2, 2],
[1, 1, 1, 1, 1]
]));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment