RosettaCodeData/Task/Nonoblock/JavaScript/nonoblock.js

62 lines
1.8 KiB
JavaScript

const compose = (...fn) => (...x) => fn.reduce((a, b) => c => a(b(c)))(...x);
const inv = b => !b;
const arrJoin = str => arr => arr.join(str);
const mkArr = (l, f) => Array(l).fill(f);
const sumArr = arr => arr.reduce((a, b) => a + b, 0);
const sumsTo = val => arr => sumArr(arr) === val;
const zipper = arr => (p, c, i) => arr[i] ? [...p, c, arr[i]] : [...p, c];
const zip = (a, b) => a.reduce(zipper(b), []);
const zipArr = arr => a => zip(a, arr);
const hasInner = v => arr => arr.slice(1, -1).indexOf(v) >= 0;
const choose = (even, odd) => n => n % 2 === 0 ? even : odd;
const toBin = f => arr => arr.reduce(
(p, c, i) => [...p, ...mkArr(c, f(i))], []);
const looper = (arr, max, acc = [[...arr]], idx = 0) => {
if (idx !== arr.length) {
const b = looper([...arr], max, acc, idx + 1)[0];
if (b[idx] !== max) {
b[idx] = b[idx] + 1;
acc.push(looper([...b], max, acc, idx)[0]);
}
}
return [arr, acc];
};
const gapPerms = (grpSize, numGaps, minVal = 0) => {
const maxVal = numGaps - grpSize * minVal + minVal;
return maxVal <= 0
? (grpSize === 2 ? [[0]] : [])
: looper(mkArr(grpSize, minVal), maxVal)[1];
}
const test = (cells, ...blocks) => {
const grpSize = blocks.length + 1;
const numGaps = cells - sumArr(blocks);
// Filter functions
const sumsToTrg = sumsTo(numGaps);
const noInnerZero = compose(inv, hasInner(0));
// Output formatting
const combine = zipArr([...blocks]);
const choices = toBin(choose(0, 1));
const output = compose(console.log, arrJoin(''), choices, combine);
console.log(`\n${cells} cells. Blocks: ${blocks}`);
gapPerms(grpSize, numGaps)
.filter(noInnerZero)
.filter(sumsToTrg)
.map(output);
};
test(5, 2, 1);
test(5);
test(5, 5);
test(5, 1, 1, 1);
test(10, 8);
test(15, 2, 3, 2, 3);
test(10, 4, 3);
test(5, 2, 3);