cssAudio - ActiveCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - Activehtmlicon-personicon-teamoctocatspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External CSS

These stylesheets will be added in this order and before the code you write in the CSS editor. You can also add another Pen here, and it will pull the CSS from it. Try typing "font" or "ribbon" below.

Quick-add: + add another resource

Add External JavaScript

These scripts will run in this order and before the code in the JavaScript editor. You can also link to another Pen here, and it will run the JavaScript from it. Also try typing the name of any popular library.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              <h1>Advent Of Code 7</h1>
<textarea id="instructions">
NOT dq -> dr
kg OR kf -> kh
ep OR eo -> eq
44430 -> b
NOT gs -> gt
dd OR do -> dp
eg AND ei -> ej
y AND ae -> ag
jx AND jz -> ka
lf RSHIFT 2 -> lg
z AND aa -> ac
dy AND ej -> el
bj OR bi -> bk
kk RSHIFT 3 -> km
NOT cn -> co
gn AND gp -> gq
cq AND cs -> ct
eo LSHIFT 15 -> es
lg OR lm -> ln
dy OR ej -> ek
NOT di -> dj
1 AND fi -> fj
kf LSHIFT 15 -> kj
NOT jy -> jz
NOT ft -> fu
fs AND fu -> fv
NOT hr -> hs
ck OR cl -> cm
jp RSHIFT 5 -> js
iv OR jb -> jc
is OR it -> iu
ld OR le -> lf
NOT fc -> fd
NOT dm -> dn
bn OR by -> bz
aj AND al -> am
cd LSHIFT 15 -> ch
jp AND ka -> kc
ci OR ct -> cu
gv AND gx -> gy
de AND dk -> dm
x RSHIFT 5 -> aa
et RSHIFT 2 -> eu
x RSHIFT 1 -> aq
ia OR ig -> ih
bk LSHIFT 1 -> ce
y OR ae -> af
NOT ca -> cb
e AND f -> h
ia AND ig -> ii
ck AND cl -> cn
NOT jh -> ji
z OR aa -> ab
1 AND en -> eo
ib AND ic -> ie
NOT eh -> ei
iy AND ja -> jb
NOT bb -> bc
ha OR gz -> hb
1 AND cx -> cy
NOT ax -> ay
ev OR ew -> ex
bn RSHIFT 2 -> bo
er OR es -> et
eu OR fa -> fb
jp OR ka -> kb
ea AND eb -> ed
k AND m -> n
et RSHIFT 3 -> ev
et RSHIFT 5 -> ew
hz RSHIFT 1 -> is
ki OR kj -> kk
NOT h -> i
lv LSHIFT 15 -> lz
as RSHIFT 1 -> bl
hu LSHIFT 15 -> hy
iw AND ix -> iz
lf RSHIFT 1 -> ly
fp OR fv -> fw
1 AND am -> an
ap LSHIFT 1 -> bj
u LSHIFT 1 -> ao
b RSHIFT 5 -> f
jq AND jw -> jy
iu RSHIFT 3 -> iw
ih AND ij -> ik
NOT iz -> ja
de OR dk -> dl
iu OR jf -> jg
as AND bd -> bf
b RSHIFT 3 -> e
jq OR jw -> jx
iv AND jb -> jd
cg OR ch -> ci
iu AND jf -> jh
lx -> a
1 AND cc -> cd
ly OR lz -> ma
NOT el -> em
1 AND bh -> bi
fb AND fd -> fe
lf OR lq -> lr
bn RSHIFT 3 -> bp
bn AND by -> ca
af AND ah -> ai
cf LSHIFT 1 -> cz
dw OR dx -> dy
gj AND gu -> gw
jg AND ji -> jj
jr OR js -> jt
bl OR bm -> bn
gj RSHIFT 2 -> gk
cj OR cp -> cq
gj OR gu -> gv
b OR n -> o
o AND q -> r
bi LSHIFT 15 -> bm
dy RSHIFT 1 -> er
cu AND cw -> cx
iw OR ix -> iy
hc OR hd -> he
0 -> c
db OR dc -> dd
kk RSHIFT 2 -> kl
eq LSHIFT 1 -> fk
dz OR ef -> eg
NOT ed -> ee
lw OR lv -> lx
fw AND fy -> fz
dz AND ef -> eh
jp RSHIFT 3 -> jr
lg AND lm -> lo
ci RSHIFT 2 -> cj
be AND bg -> bh
lc LSHIFT 1 -> lw
hm AND ho -> hp
jr AND js -> ju
1 AND io -> ip
cm AND co -> cp
ib OR ic -> id
NOT bf -> bg
fo RSHIFT 5 -> fr
ip LSHIFT 15 -> it
jt AND jv -> jw
jc AND je -> jf
du OR dt -> dv
NOT fx -> fy
aw AND ay -> az
ge LSHIFT 15 -> gi
NOT ak -> al
fm OR fn -> fo
ff AND fh -> fi
ci RSHIFT 5 -> cl
cz OR cy -> da
NOT ey -> ez
NOT ju -> jv
NOT ls -> lt
kk AND kv -> kx
NOT ii -> ij
kl AND kr -> kt
jk LSHIFT 15 -> jo
e OR f -> g
NOT bs -> bt
hi AND hk -> hl
hz OR ik -> il
ek AND em -> en
ao OR an -> ap
dv LSHIFT 1 -> ep
an LSHIFT 15 -> ar
fo RSHIFT 1 -> gh
NOT im -> in
kk RSHIFT 1 -> ld
hw LSHIFT 1 -> iq
ec AND ee -> ef
hb LSHIFT 1 -> hv
kb AND kd -> ke
x AND ai -> ak
dd AND do -> dq
aq OR ar -> as
iq OR ip -> ir
dl AND dn -> do
iu RSHIFT 5 -> ix
as OR bd -> be
NOT go -> gp
fk OR fj -> fl
jm LSHIFT 1 -> kg
NOT cv -> cw
dp AND dr -> ds
dt LSHIFT 15 -> dx
et RSHIFT 1 -> fm
dy RSHIFT 3 -> ea
fp AND fv -> fx
NOT p -> q
dd RSHIFT 2 -> de
eu AND fa -> fc
ba AND bc -> bd
dh AND dj -> dk
lr AND lt -> lu
he RSHIFT 1 -> hx
ex AND ez -> fa
df OR dg -> dh
fj LSHIFT 15 -> fn
NOT kx -> ky
gk OR gq -> gr
dy RSHIFT 2 -> dz
gh OR gi -> gj
lj AND ll -> lm
x OR ai -> aj
bz AND cb -> cc
1 AND lu -> lv
as RSHIFT 3 -> au
ce OR cd -> cf
il AND in -> io
dd RSHIFT 1 -> dw
NOT lo -> lp
c LSHIFT 1 -> t
dd RSHIFT 3 -> df
dd RSHIFT 5 -> dg
lh AND li -> lk
lf RSHIFT 5 -> li
dy RSHIFT 5 -> eb
NOT kt -> ku
at OR az -> ba
x RSHIFT 3 -> z
NOT lk -> ll
lb OR la -> lc
1 AND r -> s
lh OR li -> lj
ln AND lp -> lq
kk RSHIFT 5 -> kn
ea OR eb -> ec
ci AND ct -> cv
b RSHIFT 2 -> d
jp RSHIFT 1 -> ki
NOT cr -> cs
NOT jd -> je
jp RSHIFT 2 -> jq
jn OR jo -> jp
lf RSHIFT 3 -> lh
1 AND ds -> dt
lf AND lq -> ls
la LSHIFT 15 -> le
NOT fg -> fh
at AND az -> bb
au AND av -> ax
kw AND ky -> kz
v OR w -> x
kk OR kv -> kw
ks AND ku -> kv
kh LSHIFT 1 -> lb
1 AND kz -> la
NOT kc -> kd
x RSHIFT 2 -> y
et OR fe -> ff
et AND fe -> fg
NOT ac -> ad
jl OR jk -> jm
1 AND jj -> jk
bn RSHIFT 1 -> cg
NOT kp -> kq
ci RSHIFT 3 -> ck
ev AND ew -> ey
1 AND ke -> kf
cj AND cp -> cr
ir LSHIFT 1 -> jl
NOT gw -> gx
as RSHIFT 2 -> at
iu RSHIFT 1 -> jn
cy LSHIFT 15 -> dc
hg OR hh -> hi
ci RSHIFT 1 -> db
au OR av -> aw
km AND kn -> kp
gj RSHIFT 1 -> hc
iu RSHIFT 2 -> iv
ab AND ad -> ae
da LSHIFT 1 -> du
NOT bw -> bx
km OR kn -> ko
ko AND kq -> kr
bv AND bx -> by
kl OR kr -> ks
1 AND ht -> hu
df AND dg -> di
NOT ag -> ah
d OR j -> k
d AND j -> l
b AND n -> p
gf OR ge -> gg
gg LSHIFT 1 -> ha
bn RSHIFT 5 -> bq
bo OR bu -> bv
1 AND gy -> gz
s LSHIFT 15 -> w
NOT ie -> if
as RSHIFT 5 -> av
bo AND bu -> bw
hz AND ik -> im
bp AND bq -> bs
b RSHIFT 1 -> v
NOT l -> m
bp OR bq -> br
g AND i -> j
br AND bt -> bu
t OR s -> u
hz RSHIFT 5 -> ic
gk AND gq -> gs
fl LSHIFT 1 -> gf
he RSHIFT 3 -> hg
gz LSHIFT 15 -> hd
hf OR hl -> hm
1 AND gd -> ge
fo OR fz -> ga
id AND if -> ig
fo AND fz -> gb
gr AND gt -> gu
he OR hp -> hq
fq AND fr -> ft
ga AND gc -> gd
fo RSHIFT 2 -> fp
gl OR gm -> gn
hg AND hh -> hj
NOT hn -> ho
gl AND gm -> go
he RSHIFT 5 -> hh
NOT gb -> gc
hq AND hs -> ht
hz RSHIFT 3 -> ib
hz RSHIFT 2 -> ia
fq OR fr -> fs
hx OR hy -> hz
he AND hp -> hr
gj RSHIFT 5 -> gm
hf AND hl -> hn
hv OR hu -> hw
NOT hj -> hk
gj RSHIFT 3 -> gl
fo RSHIFT 3 -> fq
he RSHIFT 2 -> hf
</textarea>
            
          
!
            
              class Wire {
  constructor(name, value) {
    this.name = name;
    this.value = value;
  }
}

class Gate1 {
  constructor(in1, out) {
    this.in1 = in1;
    this.out = out;
  }
  canRun() {
    return this.in1.value !== undefined;
  }
}

class Gate2 extends Gate1 {
  constructor(in1, in2, out) {
    super(in1, out)
    this.in2 = in2;
  }
  canRun() {
    return this.in1.value !== undefined && this.in2.value !== undefined;
  }
}

class And extends Gate2 {
  run() {
    if(this.canRun()) {
      this.out.value = this.in1.value & this.in2.value;  
    }
  }
}

class Or extends Gate2 {
  run() {
    if(this.canRun()) {
      this.out.value = this.in1.value | this.in2.value;  
    }
  }
}

class Lshift extends Gate1 {
  constructor(in1, shiftBy, out) {
    super(in1, out)
    this.shiftBy = shiftBy;
  }
  
  run() {
    if(this.canRun()) {
      this.out.value = this.in1.value << this.shiftBy;  
    }
  }
}

class Rshift extends Gate1 {
  constructor(in1, shiftBy, out) {
    super(in1, out)
    this.shiftBy = shiftBy;
  }
  
  run() {
    if(this.canRun()) {
      this.out.value = this.in1.value >>> this.shiftBy;
    }
  }
}

class Not extends Gate1 {
  run() {
    if(this.canRun()) {
      this.out.value = ~(this.in1.value) & 0xFFFF;
    }
  }
}

class Copy extends Gate1 {
  run() {
    if(this.canRun()) {
      this.out.value = this.in1.value;
    }
  }
}


class Circuit {
  findOrCreateWire(wireName) {
    var wire = this.wires[wireName];
    if(wire === undefined) {
      wire = new Wire(wireName);
      this.wires[wireName] = wire;
    }
    return wire;
  }

  constructor(instructions) {
    this.wires = [];
    this.gates = [];
  
    // Ugly code block warning!!
    instructions.forEach(instruction => {
      var instructionsArray = instruction.split(" ");
      var value = parseInt(instructionsArray[0]);
      if(instructionsArray[1] === "->") {
        if(Number.isInteger(value)) {
          var wireName = instructionsArray[2];
          var wire = this.findOrCreateWire(wireName);
          wire.value = value;
        } else {
          var inWire = this.findOrCreateWire(instructionsArray[0]);
          var outWire = this.findOrCreateWire(instructionsArray[2]);
          this.gates.push(new Copy(inWire, outWire));
        }
      } else if(instructionsArray[1] === "AND") {
        var firstWire;
        if(Number.isInteger(value)) {
          // Hard coded value in instructions
          firstWire = new Wire(value, value);
        } else {
          firstWire = this.findOrCreateWire(instructionsArray[0]);
        }
        var secondWire = this.findOrCreateWire(instructionsArray[2]);
        var thirdWire = this.findOrCreateWire(instructionsArray[4]);
        this.gates.push(new And(firstWire, secondWire, thirdWire));
      } else if(instructionsArray[1] === "OR") {
        var firstWire = this.findOrCreateWire(instructionsArray[0]);
        var secondWire = this.findOrCreateWire(instructionsArray[2]);
        var thirdWire = this.findOrCreateWire(instructionsArray[4]);
        this.gates.push(new Or(firstWire, secondWire, thirdWire));
      } else if(instructionsArray[1] === "LSHIFT") {
        var firstWire = this.findOrCreateWire(instructionsArray[0]);
        var shiftBy = parseInt(instructionsArray[2]);
        var thirdWire = this.findOrCreateWire(instructionsArray[4]);
        this.gates.push(new Lshift(firstWire, shiftBy, thirdWire));
      } else if(instructionsArray[1] === "RSHIFT") {
        var firstWire = this.findOrCreateWire(instructionsArray[0]);
        var shiftBy = parseInt(instructionsArray[2]);
        var thirdWire = this.findOrCreateWire(instructionsArray[4]);
        this.gates.push(new Rshift(firstWire, shiftBy, thirdWire));
      } else if(instructionsArray[0] === "NOT") {
        var inWire = this.findOrCreateWire(instructionsArray[1]);
        var outWire = this.findOrCreateWire(instructionsArray[3]);
        this.gates.push(new Not(inWire, outWire));
      }
    });
  }  
  
  // Starts with the wire you specify and recursively
  // walks through all wires and gates to find a value.
  getValueForWire(wireName) {
    if(this.wires[wireName].value !== undefined) {
      return this.wires[wireName].value;
    }
    var gate = this.gates.find(gate => {
      if(gate.out.name === wireName) {
        return gate;
      }
    });
    if(gate.in1.value === undefined) {
      gate.in1.value = this.getValueForWire(gate.in1.name);
    }
    // For single wire gates, gate.in2 === undefined
    if(gate.in2 !== undefined && gate.in2.value === undefined) {
      gate.in2.value = this.getValueForWire(gate.in2.name);
    }
    
    gate.run();
    var value = gate.out.value; 
    return value;
  }
  
  setValueForWire(wireName, value) {
    this.wires[wireName].value = value;
  }
}


///////////
// Tests //
///////////


describe("Gate", function() {
  it("should put 123 on wire", function() {
    var x = new Wire("x", 123);
    expect(x.value).toBe(123);
  });
  
  it("should provide no signal until all inputs are provided", function() {
    var x = new Wire("x", 2);
    var y = new Wire("y");
    var d = new Wire("d");
    var and = new And(x, y, d);
    and.run();
    expect(d.value).toBeUndefined();
    
    y = new Wire("y", 7);
    and = new And(x, y, d);
    and.run();
    expect(d.value).toBe(2);
  });
  
  it("should return bitwise AND of two wires", function() {
    var x = new Wire("x", 7);
    var y = new Wire("y", 2);
    var z = new Wire("z");
    var and = new And(x, y, z);
    and.run();
    expect(z.value).toBe(2);
  });
  
  it("should return bitwise OR of two wires", function() {
    var x = new Wire("x", 1);
    var y = new Wire("y", 2);
    var z = new Wire("z");
    var or = new Or(x, y, z);
    or.run();
    expect(z.value).toBe(3);
  });
  
  it("should return bitwise LSHIFT 3 of input wire", function() {
    var p = new Wire("p", 8);
    var q = new Wire("q");
    var lshift = new Lshift(p, 3, q);
    lshift.run();
    expect(q.value).toBe(64);
  });
  
  it("should return bitwise RSHIFT 2 of input wire", function() {
    var p = new Wire("p", 8);
    var q = new Wire("q");
    var rshift = new Rshift(p, 2, q);
    rshift.run();
    expect(q.value).toBe(2);
  });
  
  it("should return bitwise complement (NOT) of input wire", function() {
    var p = new Wire("p", 8);
    var q = new Wire("q");
    var not = new Not(p, q);
    not.run();
    expect(q.value).toBe(65527);
  });
  
  // 123 -> x
  // 456 -> y
  // x AND y -> d
  // x OR y -> e
  // x LSHIFT 2 -> f
  // y RSHIFT 2 -> g
  // NOT x -> h
  // NOT y -> i
  it("should return correct outputs for whole thing", function() {
    var gates = [];
    var x = new Wire("x", 123);
    var y = new Wire("y", 456);
    var d = new Wire("d");
    var e = new Wire("e");
    var f = new Wire("f");
    var g = new Wire("g");
    var h = new Wire("h");
    var i = new Wire("i");
    gates.push(new And(x, y, d));
    gates.push(new Or(x, y, e));
    gates.push(new Lshift(x, 2, f));
    gates.push(new Rshift(y, 2, g));
    gates.push(new Not(x, h));
    gates.push(new Not(y, i));
    
    gates.forEach(gate => {
      gate.run();
    });
    
    expect(d.value).toBe(72);
    expect(e.value).toBe(507);
    expect(f.value).toBe(492);
    expect(g.value).toBe(114);
    expect(h.value).toBe(65412);
    expect(i.value).toBe(65079);
    expect(x.value).toBe(123);
    expect(y.value).toBe(456);
  });
});


describe("Circuit", function() {
  it("should put 123 on wire x", function() {
    var circuit = new Circuit(["123 -> x"]);
    expect(circuit.getValueForWire("x")).toBe(123);
  });
  
  it("should put 123 on wire y", function() {
    var circuit = new Circuit([
      "x -> y",
      "123 -> x"
    ]);
    expect(circuit.getValueForWire("y")).toBe(123);
  });
  
  it("should put 72 on wire d through ANDing x and y", function() {
    var instructions = [
      "123 -> x",
      "456 -> y",
      "x AND y -> d"
    ];
    var circuit = new Circuit(instructions);
    expect(circuit.getValueForWire("x")).toBe(123);
    expect(circuit.getValueForWire("y")).toBe(456);
    expect(circuit.getValueForWire("d")).toBe(72);
  });

  it("should put 72 on wire d, order of instructions does not matter", function() {
    var instructions = [
      "x AND y -> d",
      "123 -> x",
      "456 -> y"
    ];
    var circuit = new Circuit(instructions);
    expect(circuit.getValueForWire("d")).toBe(72);
  });

  it("should put 72 on wire d through ANDing 123 and y", function() {
    var instructions = [
      "456 -> y",
      "123 AND y -> d"
    ];
    var circuit = new Circuit(instructions);
    expect(circuit.getValueForWire("d")).toBe(72);
  });

  it("should return bitwise LSHIFT 3 of input wire", function() {
    var instructions = [
      "8 -> p",
      "p LSHIFT 3 -> q"
    ];
    var circuit = new Circuit(instructions);
    expect(circuit.getValueForWire("q")).toBe(64);
  });
  
  it("should return bitwise RSHIFT 2 of input wire", function() {
    var instructions = [
      "8 -> p",
      "p RSHIFT 2 -> q"
    ];
    var circuit = new Circuit(instructions);
    expect(circuit.getValueForWire("q")).toBe(2);
  });
  
  it("should parse and run the whole thing", function() {
    var instructions = [
      "123 -> x",
      "456 -> y",
      "x AND y -> d",
      "x OR y -> e",
      "x LSHIFT 2 -> f",
      "y RSHIFT 2 -> g",
      "NOT x -> h",
      "NOT y -> i"
    ];
    var circuit = new Circuit(instructions);
    expect(circuit.getValueForWire("x")).toBe(123);
    expect(circuit.getValueForWire("y")).toBe(456);
    expect(circuit.getValueForWire("d")).toBe(72);
    expect(circuit.getValueForWire("e")).toBe(507);
    expect(circuit.getValueForWire("f")).toBe(492);
    expect(circuit.getValueForWire("g")).toBe(114);
    expect(circuit.getValueForWire("h")).toBe(65412);
    expect(circuit.getValueForWire("i")).toBe(65079);
  });
  
  it("should put 64 on wire e, order of instructions does not matter", function() {
    var instructions = [
      "71 AND d -> e",
      "x AND y -> d",
      "123 -> x",
      "456 -> y"
    ];
    var circuit = new Circuit(instructions);
    expect(circuit.getValueForWire("e")).toBe(64);
  });

});

// For replacing &gt; with >
function htmlDecode(input){
  var e = document.createElement('div');
  e.innerHTML = input;
  return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}

var instructions = htmlDecode(document.getElementById("instructions").innerHTML).split("\n");
var circuit = new Circuit(instructions);

var a = circuit.getValueForWire("a");
console.log("Signal on wire a: " + a);

circuit = new Circuit(instructions);
circuit.setValueForWire("b", a);
a = circuit.getValueForWire("a");
console.log("Signal on wire a: " + a);

            
          
!
999px
Close

Asset uploading is a PRO feature.

As a PRO member, you can drag-and-drop upload files here to use as resources. Images, Libraries, JSON data... anything you want. You can even edit them anytime, like any other code on CodePen.

Go PRO

Loading ..................

Console