I’m going to poke around and see how much it would take to stretch this into a basic Turing machine emulator.
I don't know how I feel about the message "This is optimal!" displaying when you use one NAND gate to build an inverter at level 2. Level 1 forces you to build an NAND gate out of (1) an AND gate, plus (2) an inverter. It feels like it'd be more optimal to just reuse that inverter.
(And then level 3 is an AND gate, the other primitive† you started with...)
† Technically, you start with two primitives, implementing f(a, b) = a ∧ b and g(a,b) = ¬(b ⟶ a). You also get the ability to provide 0 and 1 as fixed inputs, thus ¬a ≡ g(a,1). What you lose after implementing the NAND gate is the ability to provide a fixed 1 input - instead, you are informed that you assume all gates automatically draw from this. Worst of all possible worlds.
and my implementation of the projects: https://github.com/porridgewithraisins/nand2tetris
alias NAND="AND | NEG"
Also, a NAND command would need to have 2 stdin’s.Sorry? Take a second to think about what you're saying.
In what conceivable sense is "doing a logical and" one thing while "doing a logical nand" isn't?
You can equally claim that
x & y
is really just (x ↑ y) ↑ (x ↑ y)What did you think I meant by this question?
>> In what conceivable sense is "doing a logical and" one thing while "doing a logical nand" isn't?
NAND is more complex than AND, in the sense that it is more expressive than AND (having functional completeness which AND does not).
Similarly, it can be built from other less complex operators (AND and NAND).
If you're taking "One thing" to the extreme, in terms of the granularity or complexity of that "one thing", NAND is not as granular or simple as AND - and therefore isn't taking it to as far "to the extreme".
+---+---+-------+
| a | b | a ↑ b |
+---+---+-------+
| 0 | 0 | 1 |
+---+---+-------+
| 0 | 1 | 1 |
+---+---+-------+
| 1 | 0 | 1 |
+---+---+-------+
| 1 | 1 | 0 |
+---+---+-------+
AND is defined like this: +---+---+-------+
| a | b | a & b |
+---+---+-------+
| 0 | 0 | 0 |
+---+---+-------+
| 0 | 1 | 0 |
+---+---+-------+
| 1 | 0 | 0 |
+---+---+-------+
| 1 | 1 | 1 |
+---+---+-------+
You may notice that they are almost exactly the same.> It seems naively obvious to me that a(b(x)) is more complex than b(x).
This is just obvious gibberish; if you define b(x, y) = x & y and a(x) = ~x, then you can say "I think a(b(x, y)) looks more complex than b(x, y)", but how do you respond to "when c(x, y) = x ↑ y, I think c(c(x,y), c(x,y)) looks more complex than c(x,y)"? The two claims can't both be true!
Everything, no matter how simple, can be described as the end of an arbitrarily long chain of functions. So what?