Skip to content

Instantly share code, notes, and snippets.

@scolton99
Created December 4, 2022 14:44
Show Gist options
  • Save scolton99/ebf432c294e3b39fb267b1930df2b8c3 to your computer and use it in GitHub Desktop.
Save scolton99/ebf432c294e3b39fb267b1930df2b8c3 to your computer and use it in GitHub Desktop.
Thing to test random permutations of numbers representing Rubik's Cube arrangements to probabilistically verify possible orientations.
const { Worker, isMainThread, parentPort, workerData } = require('node:worker_threads');
const randIdx = vals => Math.floor(Math.random() * vals.length);
const permute4 = vals => {
const vCopy = [...vals];
if (vCopy.length !== 4)
throw new Error('Array must be of size 4');
const anchorIdx = randIdx(vCopy);
const anchorVal = vCopy.splice(anchorIdx, 1)[0];
const dir = Math.floor(Math.random() * 2) === 0;
if (dir) {
const cycle = vCopy.shift();
vCopy.push(cycle);
} else {
const cycle = vCopy.pop();
vCopy.unshift(cycle);
}
vCopy.splice(anchorIdx, 0, anchorVal);
return vCopy;
};
const work = (iters, parentPort) => {
const results = {};
let vals = [1, 2, 3, 4];
for (let i = 0; i < iters; ++i) {
vals = permute4(vals);
const key = vals.map(it => `${it}`).join('');
if (typeof(results[key]) === 'undefined')
results[key] = 0;
results[key]++;
if (i % 100 === 0)
parentPort.postMessage({ type: 'progress', value: i / (iters - 1) })
}
return results;
};
if (isMainThread) {
const total = 500_000_000;
const promises = [];
const progresses = new Array(16).fill(0);
for (let i = 0; i < 16; ++i) {
promises.push(new Promise((resolve, reject) => {
const worker = new Worker('./cube.js', { workerData: { iters: Math.ceil(total / 16) }});
worker.on('message', msg => {
if (msg.type === 'progress')
progresses[i] = msg.value;
else if (msg.type === 'result')
resolve(msg.value);
});
worker.on('error', reject);
worker.on('exit', code => {
if (code !== 0) reject(code);
});
}));
}
const interval = setInterval(() => {
const avg = progresses.reduce((a, b) => a + b) / progresses.length;
process.stdout.write(`Progress: ${Math.round(avg * 10000) / 100}% \r`);
}, 300);
Promise.all(promises).then(allResults => {
const results = {};
clearInterval(interval);
console.log('Progress: 100% ');
for (const resultStr of allResults) {
const resultObj = JSON.parse(resultStr);
for (const key of Object.keys(resultObj)) {
if (typeof(results[key]) === 'undefined')
results[key] = 0;
results[key] += resultObj[key];
}
}
console.log('');
console.log(JSON.stringify(results, null, 2));
});
} else {
const results = work(workerData.iters, parentPort);
parentPort.postMessage({ type: 'result', value: JSON.stringify(results) });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment