const fs = require('fs'); const readline = require('readline'); Array.prototype.count = function(fnc) { return this.reduce((total, i, index) => fnc(i, index) ? total+1 : total, 0); } Array.prototype.countUnique = function(fnc) { return this.reduce((total, i, index) => (total.indexOf(i) === -1 && fnc(i, index)) ? total.concat(i):total, []).length; } function getAdjascents(pos) { return [ [ pos.coords[0] -1, pos.coords[1], pos.coords[2] ], [ pos.coords[0] +1, pos.coords[1], pos.coords[2] ], [ pos.coords[0], pos.coords[1] +1, pos.coords[2] ], [ pos.coords[0], pos.coords[1] -1, pos.coords[2] ], [ pos.coords[0], pos.coords[1], pos.coords[2] +1 ], [ pos.coords[0], pos.coords[1], pos.coords[2] -1 ] ]; } function countShards(map) { return Object.keys(map).reduce((acc, i) => acc +getAdjascents(map[i]).map(i => i.join(',')).count(i => !map[i]), 0); } function isTrapped(map, arr, obj) { // FIXME return false; } function countShards2(map) { const keys = Object.keys(map); if (keys.length < 8) return countShards(map); // trivial out return Object.keys(map).reduce((acc, i) => acc +getAdjascents(map[i]).map(i => i.join(',')).count(i => !map[i] && !isTrapped(map, i)), 0); } function manhatan(a, b) { return a.reduce((acc, val, index) => acc + Math.abs(b[index]-val), 0); } function mergeIds(map, oldId, newId) { Object.keys(map).forEach(i => { if (map[i].gid === oldId) map[i].gid = newId;}); } function computeShardShape(map) { const keys = Object.keys(map); let ids = []; let maxId = 0; for (let i =0; i < keys.length; ++i) { if (map[keys[i]].gid !== undefined) { for (let j = 0; j < i; ++j) { if (map[keys[i]].gid !== map[keys[j]].gid && manhatan(map[keys[i]].coords, map[keys[j]].coords) === 1) mergeIds(map, map[keys[i]].gid, map[keys[j]].gid); } continue; } map[keys[i]].gid = ++maxId; ids.push(maxId); for (let j = 1; j < keys.length; ++j) if (manhatan(map[keys[i]].coords, map[keys[j]].coords) === 1) { if (map[keys[j]].gid !== undefined) mergeIds(map, maxId, map[keys[j]].gid); else map[keys[j]].gid = maxId; } } return ids.map(i => keys.filter(j => i === map[j].gid).map(i => map[i])).filter(i => i.length).map(i => i.reduce((acc, i) => { acc[i.id] = i; return acc; }, {})); } async function main() { let shards = {}; for await (let line of readline.createInterface({ input: process.stdin })) { shards[line] = { coords: line.split(',').map(i => parseInt(i)), gid: undefined, id: line } } let extShards = countShards(shards); console.log(extShards); //console.log(require('util').inspect(computeShardShape(shards), { showHidden: false, depth: null, colors: true })); console.log(computeShardShape(shards).reduce((acc, i) => countShards2(i)+acc, 0)); }; (main());