Last active
February 7, 2020 06:29
-
-
Save bluepnume/3b57e5340330513713ce1e6037280fe5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Number of nodes | |
let NUM_NODES = 10; | |
// Connections between nodes | |
let CONNECTIONS = { | |
0: [ 1, 3 ], | |
1: [ 2, 3, 4 ], | |
2: [ 5 ], | |
3: [ 6 ], | |
4: [ 5, 7 ], | |
5: [ 7, 8 ], | |
6: [ 7, 9 ] | |
}; | |
// Limit for active nodes to win game | |
let MAX_ACTIVE = 5; | |
// Starting node index to link | |
let START_NODE = 2; | |
// End node index to link | |
let END_NODE = 9; | |
// Range of numbers from 0..n | |
let range = (n) => { | |
return Array(n).fill(0).map((_, i) => i); | |
} | |
// Node instance | |
let node = (index) => { | |
let active = false; | |
let linkedNodes = []; | |
let getIndex = () => { | |
return index; | |
} | |
let isActive = () => { | |
return active; | |
} | |
let deactivate = () => { | |
active = false | |
} | |
let toggle = (toggleLinkedNodes = true) => { | |
active = !active; | |
if (toggleLinkedNodes) { | |
linkedNodes.forEach(linkedNode => linkedNode.toggle(false)); | |
} | |
}; | |
let getActiveSiblingNodes = () => { | |
return linkedNodes.filter(sibling => sibling.isActive()); | |
}; | |
let link = (otherNode) => { | |
linkedNodes.push(otherNode); | |
}; | |
return { getIndex, isActive, deactivate, toggle, link, getActiveSiblingNodes }; | |
} | |
// Set all nodes to inactive | |
let reset = (nodes) => { | |
nodes.forEach(node => node.deactivate()); | |
} | |
// Check if we won the game | |
let didWin = (nodes, startIndex, endIndex, maxActive) => { | |
let count = 0; | |
let currentNode = nodes[startIndex]; | |
let visitedNodes = {}; | |
if (nodes.filter(node => node.isActive()).length > MAX_ACTIVE) { | |
return false; | |
} | |
while (count < maxActive) { | |
count += 1; | |
let currentIndex = currentNode.getIndex(); | |
if (visitedNodes[currentIndex]) { | |
return false; | |
} | |
visitedNodes[currentIndex] = true; | |
if (currentIndex === endIndex) { | |
return true; | |
} | |
let unvisitedSiblingNodes = currentNode.getActiveSiblingNodes() | |
.filter(siblingNode => !visitedNodes[siblingNode.getIndex()]); | |
if (unvisitedSiblingNodes.length !== 1) { | |
return false; | |
} | |
currentNode = unvisitedSiblingNodes[0]; | |
} | |
return false; | |
} | |
// Get array of linked nodes | |
let setupNodes = (numNodes, connections) => { | |
let nodes = range(numNodes).map(node); | |
for (let i in connections) { | |
i = parseInt(i); | |
for (let j of connections[i]) { | |
nodes[i].link(nodes[j]); | |
nodes[j].link(nodes[i]); | |
} | |
} | |
return nodes; | |
} | |
// Get all unique permutations from [ 0 * length ] to [ range * length ] | |
let permutations = (options, length, callback) => { | |
options.forEach(option => { | |
if (length === 1) { | |
callback([ option ]); | |
} else { | |
permutations(options.filter(opt => opt !== option), length -1, (permutation) => { | |
callback([ option, ...permutation ]); | |
}); | |
} | |
}); | |
} | |
let attemptMoves = (nodes, moves) => { | |
reset(nodes); | |
moves.forEach(move => { | |
nodes[move].toggle(); | |
}); | |
if (didWin(nodes, START_NODE, END_NODE, MAX_ACTIVE)) { | |
return true; | |
} | |
return false; | |
} | |
let playGame = () => { | |
let nodes = setupNodes(NUM_NODES, CONNECTIONS); | |
let attempted = {}; | |
let numMoves = 1; | |
while (numMoves <= NUM_NODES) { | |
console.log('Attempting to win in', numMoves, 'moves'); | |
permutations(range(NUM_NODES), numMoves, (moves) => { | |
moves.sort(); | |
if (attempted[moves]) { | |
return; | |
} | |
attempted[moves] = true; | |
if (attemptMoves(nodes, moves)) { | |
console.log('Winner winner:', moves.map(move => move + 1).join(' -> ')); | |
} | |
}); | |
numMoves += 1; | |
} | |
} | |
playGame(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment