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);