const nand= (a, b) => (a==1 && b==1 ? 0 : 1)
const not = (a) => (nand(a, a))
const and = (a, b) => (not(nand(a, b)))
const or = (a, b) => (not(and(not(a), not(b))))
const xor = (a, b) => (or(and(not(a), b), and(a, not(b))))
const mux = (a, b, sel) => (or(and(a, not(sel)), and(b, sel)))
const dmux = (a, sel) => ([and(a, not(sel)), and(a, sel)])
const not16 = (a) => (a.map((_) => not(_)))
const and16 = (a, b) => (_.zipWith(a, b, (x, y) => (and(x, y))))
const or16 = (a, b) => (_.zipWith(a, b, (x, y) => (or(x, y))))
const mux16 = (a, b, sel) => (_.zipWith(a, b, (x, y) => (mux(x, y, sel))))
const mux4way16 = (a, b, c, d, sel) => ( mux16( mux16(a, b, sel[0]), mux16(c, d, sel[0]), sel[1]) );
const mux8Way16 = (a, b, c, d, e, f, g, h, sel) => ( mux16( mux16(a, b, sel[0]), mux16(c, d, sel[0]), sel[1]) );
const dmux4way = (input, sel) => {
const sel0 = dmux(input, sel[0]);
const ac = dmux(sel0[0], sel[1]);
const bd = dmux(sel0[0], sel[1])
return {
a: ac[0],
b: bd[0],
c: ac[1],
d: bd[1]
}
}
const dmux8way = (input, sel) => {
const aecgbfdh = dmux(input, sel[0]);
const aecg = dmux(aecgbfdh[0], sel[1]);
const bfdh = dmux(aecgbfdh[1], sel[1]);
const ae = dmux(aecg[0], sel[2]);
const cg = dmux(aecg[1], sel[2]);
const bf = dmux(bfdh[0], sel[2]);
const dh = dmux(bfdh[1], sel[2]);
return {
a: ae[0],
b: bf[0],
c: cg[0],
d: dh[0],
e: ae[1],
f: bf[1],
g: cg[1],
h: dh[1]
}
}