Created
January 14, 2022 15:07
-
-
Save raganwald/e9d5e570533a698bfb541675d5cddc70 to your computer and use it in GitHub Desktop.
Sketching out some solutions to the Pyramid Problem
This file contains 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
// handles primitives like integers and arrays of simple primitives | |
// all other behaviour is undefined | |
function superSimpleEquivalent(a, b) { | |
if (a instanceof Array && b instanceof Array) { | |
if (a.length != b.length) return false; | |
for (let i = 0; i < a.length; ++i) { | |
if (!superSimpleEquivalent(a[i], b[i])) return false; | |
} | |
return true; | |
} else if (a instanceof Position && b instanceof Position) { | |
return superSimpleEquivalent(a.rods, b.rods); | |
} else { | |
return a === b; | |
} | |
} | |
class Position { | |
constructor(rods = [[], [], []]) { | |
this.rods = rods; | |
} | |
toString() { | |
const rodStrings = this.rods.map(r => r.join(', ')); | |
return `<< ${rodStrings.join('; ')} >>`; | |
} | |
errors() { | |
if (this.rods.length != 3) { | |
return `There should be three rods, not ${this.rods.length}`; | |
} | |
const elements = this.elements(); | |
const elementSet = new Set(elements); | |
if (elements.length !== elementSet.size) { | |
const dups = [...elements]; | |
for (const uniq of elementSet) { | |
const i = dups.indexOf(uniq); | |
dups[i] = null; | |
} | |
const duplicatedElements = dups.filter(a => a != null); | |
return `Duplicate element(s): ${duplicatedElements.join(', ')}`; | |
} | |
for (const rodElements of this.rods) { | |
const sortedElements = [...rodElements].sort(); | |
if (!superSimpleEquivalent(rodElements, sortedElements)) { | |
return `Rod ${rodElements.join(', ')} is out-of-order`; | |
} | |
} | |
return false; | |
} | |
valid() { | |
return this.errors() === false; | |
} | |
havingMoved(fromIndex, toIndex) { | |
const fromRod = this.rods[fromIndex]; | |
const toRod = this.rods[toIndex]; | |
if (fromRod === undefined) { | |
return undefined; | |
} | |
if (toRod === undefined) { | |
return undefined; | |
} | |
if (fromIndex === toIndex) { | |
return undefined; | |
} | |
const topFrom = fromRod[0]; | |
const topTo = toRod[0]; | |
if (topFrom === undefined) { | |
return undefined; | |
} | |
if (topTo != undefined && topTo < topFrom) { | |
return undefined; | |
} | |
const resultRods = this.rods.map(rod => [...rod]); | |
resultRods[toIndex].push(resultRods[fromIndex].pop()); | |
return new Position(resultRods); | |
} | |
wouldBeValidMove(fromIndex, toIndex) { | |
return this.havingMoved(fromIndex, toIndex) != undefined; | |
} | |
elements() { | |
return this.rods.flatMap(x => x); | |
} | |
resembles(other) { | |
const mySortedElements = [...this.elements()].sort(); | |
const otherSortedElements = [...other.elements()].sort(); | |
return superSimpleEquivalent(mySortedElements, otherSortedElements); | |
} | |
} | |
console.log('----------------------------------------------------------------------'); | |
const testCases = [ | |
[[], false], | |
[[[], [], []], true], | |
[[[1], [2], [3, 4]], true], | |
[[[1], [2, 3], [3, 4]], false], | |
[[[1], [2, 3], [5, 4]], false] | |
]; | |
for (const [testCase, expectation] of testCases) { | |
const p = new Position(testCase); | |
const validity = p.valid(); | |
const passed = validity === expectation; | |
const passMessage = passed ? "Pass" : "Fail"; | |
if (validity) { | |
console.log(`${passMessage}: ${p.toString()} is valid`); | |
} else { | |
console.log(`${passMessage}: ${p.toString()} is invalid: ${p.errors()}`); | |
} | |
} | |
const testPosition = new Position([[1, 2], [], [3, 4]]); | |
const testMoveCases = [ | |
[0, 0, false], | |
[0, 1, true], | |
[0, 2, true], | |
[1, 0, false], | |
[1, 2, false], | |
[2, 0, false], | |
[2, 1, true] | |
]; | |
for (const [fromIndex, toIndex, expectation] of testMoveCases) { | |
const validity = testPosition.wouldBeValidMove(fromIndex, toIndex); | |
const passed = validity === expectation; | |
const passMessage = passed ? "Pass" : "Fail"; | |
console.log(`${passMessage}: ${fromIndex} -> ${toIndex} is ${expectation ? '' : 'not '}a valid move`); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment