Convert the following expression to use only NAND gates - math

I have the following expression ( 'denotes NOT)...
e'(a+b)
First I expand...
e'a + e'b
DeMorgan's Law...
(e'a +e'b)'
((e'a)'(e'b)')'
Now I am stuck. Each NAND gate that I use can only accept a maximum of 2 inputs. I can use as many NAND gates as I want, but I should try to come up with an expression that uses the least amount of gates.
Am I on the right track? How do I continue further?

First, I would suggest taking this:
e'(a+b)
And writing it using a more verbose notation to make the transformations easier to recognize as having been done correctly:
(not e) and (a or b)
As Rory Daulton suggested, a good first step is to know how to render the basic logical operations using nand.
not e can be shown to be equivalent to e nand e, as Rory pointed out.
you can show that a and b is equivalent to not (a nand b) by the definition of nand. Using the above result, we recover the equivalent expression (a nand b) nand (a nand b) using only nand gates.
you can show that a or b is equivalent to not((not a) and (not b)) by De Morgan, hence (not a) nand (not b) by the definition of nand. We can use the above results to derive the equivalent expression (a nand a) nand (b nand b) using only nand gates.
Returning to our expression:
(not e) and (a or b)
I sort of like working outside-in, so we start with the outermost operation, and, and use the rule from 2 above to get:
(not e) and (a or b)
2=> ((not e) nand (a or b)) nand ((not e) nand (a or b))
Now that we have four subexpressions at the same level, we can start from the left and work our way right:
(not e) and (a or b)
2=> ((not e) nand (a or b)) nand ((not e) nand (a or b))
1=> ((e nand e) nand (a or b)) nand ((not e) nand (a or b))
3=> ((e nand e) nand ((a nand a) nand (b nand b))) nand ((not e) nand (a or b))
1=> ((e nand e) nand ((a nand a) nand (b nand b))) nand ((e nand e) nand (a or b))
3=> ((e nand e) nand ((a nand a) nand (b nand b))) nand ((e nand e) nand ((a nand a) nand (b nand b)))
A circuit for this might look like:
e--+---|\ e'
| > >o----------------------|\ (e'(a+b))'
+---|/ > >o--------+---|\
+---|/ | > >o--e'(a+b)
a--+---|\ a' | +---|/
| > >o--------|\ |
+---|/ > >o------+
+---|/ a+b
b--+---|\ |
| > >o----+
+---|/ b'

That does not look like the right track.
Your original expression has only three operations: NOT (e'), OR (a+b), and AND (between the last two expressions I gave). You should figure out how to do each of those three operations, then combine them into one overall structure. Knowing how to do each of these is critical in this kind of problem.
Here is how to do the first: NOT x is equivalent to x NAND x, therefore e' is equivalent to e NAND e. Continue from here.

Related

How to go count all of the atoms in a list (or a list of nested lists) when you use recursion

I am creating a recursive function that counts the number of atoms inside a list. It should be able to count the atoms of lists that are nested.
For example: (a (b c) e d) or (a (b c (g e)) e d), it should count b and c separately or b, c, e, and d separately and not as a whole.
This is the function that I have created:
(defun count-atoms (mylist)
(cond
((null mylist) 0)
((listp (car mylist)) (count-atoms (car mylist)))
((atom (car mylist)) (+ 1 (count-atoms (rest mylist))))
)
)
The output I get is 3 but it should be 5 (based from (a (b c) e d)). I am guessing that the function stops the moment it reaches c. How do i make the function not stop at c and make it go back to the outermost list.
Here's a way we can reason about the problem -
If the input is null, return zero
'( )
^
| 0 atoms
(inductive) Otherwise the input has at least one element. If car is a list, call count-elements on car and cdr. Add the two results together and return.
'( a b c d ... )
^ ^
| | count atoms in cdr <-
| \
| count atoms in sublist <------\_ add together
(inductive) Otherwise the input has at least one element that is not a list. Call count-elements on cdr. Add one to the result and return.
'( a b c d ... )
^ ^
| | count atoms in cdr <-
| \
| one atom <-----------------\_ add together
Do you see where your program differs?
Your mistake is that you are ignoring the tail in the second clause.
(defun count-atoms (tree)
"Count atoms in all leaves of the tree, ignoring terminating NIL."
(if tree
(+ (if (atom (car tree))
1
(count-atoms (car tree)))
(count-atoms (cdr tree)))
0))
now
(count-atoms '(a (b c) e d))
==> 5
(count-atoms '(a (b c (g e)) e d))
==> 7
(count-atoms '(a (b c (g e)) nil e d))
==> 8

Recursively calling function in scheme with let

Is it possible, in scheme, to do something like the following?
(define (foo a b c d e)
(let ((recurse (foo a b c (bar d) e))
(if (= d e)
#f
(recurse))))
I have a function with a rather lengthy set of arguments and some conditions that recursively call it and it's rather unsightly, I'd like to be able to shorthand it.
I've tried this a few different ways but I either get an infinite loop (I presume let is eagerly evaluating) or I get bad let form errors.
You need a thunk:
(define (foo a b c d e)
(let ((recurse (lambda () (foo a b c (bar d) e))))
(if (= d e)
#f
(recurse))))
This then permits you to add arguments if some but not all of the parameters change.
Since most of the arguments don't change you should consider using named let:
(define (foo a b c d e)
(let recurse ((d d))
(if (= d e)
#f
(recurse (cdr d)))))
This is basically the same as:
(define (foo a b c d e)
(define (recurse d)
(if (= d e)
#f
(recurse (cdr d))))
// start recursion
(recurse d))
All the other variables will be available through the closure.

Given A∧B what is the equivalent using just → and ⊕(Xor)

Consider the set of connectives consisting of just → and ⊕, where ⊕ is an exclusive OR connective: A⊕B is true if and only if A and B have the opposite truth values (one is true and the other one false).
Given A∧B what is the equivalent formula using only → and ⊕(Xor).
Assumming that -> is the material conditional.
A and B is equivalent to not(A implies not B)
not C is equivalent to (C implies C) xor C
so
not B is equivalent to (B implies B) xor B)
and
A implies not B equivalent to A implies ((B implies B) xor B))
finally the equivalent expression is
((A implies ((B implies B) xor B)) implies (A implies ((B implies B) xor B)))xor (A implies ((B implies B) xor B))
in your notation:
((A → ((B → B) ⊕ B)) → (A → ((B → B) ⊕ B)))⊕ (A → ((B → B) ⊕ B))
with some care you can surely minimize these formulas
Checking the final formula on wolfram alpha
A general framework to answer such questions is functional completness.
The people at mathoverflow might be helpful.
EDIT
i've made a mess of copying the long formulas, corrected now

If i know how a traced output looks, how can i begin creating my function? (Scheme)

I'm having a very hard time trying to learn to program in scheme. My professor says I keep falling into the trap of procedural thinking. I know he's right. I want to learn how to do this, however, reading books is becoming counter intuitive for me as these are supposed to be easy projects that shouldn't require a lot of reading and research anyways.
Conceptually, I understand how my traced function should look. (Although I might be wrong)
Here in this case I’m working on a program called ndelete which takes in a list and returns the list with every nth element removed.
Below I’ve traced what I think my function should look like.
ndelete( '( a b c d e) 2)
(a b c d e)
> (b c d e)
> > (c d e)
> > > (d e)
> > > > (e)
> > > > > ( )
< < < < < ( ) ; return null
< < < < (e) ; return e 1
< < < (e) ; return 'd 2 removed 'd,
< < (c e); return 'c 3
< (c e) ; return 'b 4 removed'b
(a c e) ; return 'a 5
I feel like I should know this easily, and it is very frustrating. Perhaps, someone could point me in the right direction or show me how I can utilize what I understand conceptually.
Here is my attempted code. I sort of haphazardly put it together using some example code that I thought I could use from my professor's examples.
(define x '(1 2 3 4 5 6 7 8 9 10))
(define ndelete(lambda (alist n)
(if '()
(car alist)
(ndelete (cdr alist)
(- n 1))
)))
(ndelete x 10)
It is a common practice to try to generalize from an example, provided:
You example is not too constrained. You want to be sure to cover all functional cases. A trace is good for that since the different cases occur generally at different depths for a recursive function. Also, you might need to try multiple examples to trust your solution.
you are confident that the trace represents an actual possible execution and is not just badly fabricated (e.g. skipping a step or returning suddenly a different result). You have keep in mind that the trace could be badly formed. You will eventually find out whether this is true by inspecting it closely and confronting your function with your examples.
Don't try to write everything at once, build your function step-by-step from what you see and can infer. I believe most experienced functional programmers still do the below steps, but maybe only in their heads (with time, patterns will start to emerge).
Here, you know that you are given a list and a number: you call them lst and n, because that's how everybody else does in Scheme. You also know that the function should return a list.
(a b c d e)
> (b c d e)
...
< (c e)
(a c e)
The second line from the top tells you that you should call the function recursively with (cdr lst), for the list argument.
The last line shows that you have to cons (car lst) on top of the resulting value.
You can write a first draft:
(define ndelete
(lambda (lst n)
(cons (car lst) (ndelete (cdr lst) n))))
But this is not enough, because your function does not explain other parts of the trace, like this:
> > > > > ( )
< < < < < ( )
Obviously there should be a base case for the empty list.
We update the function:
(define ndelete
(lambda (lst n)
(if (null? lst)
'()
(cons (car lst) (ndelete (cdr lst) n)))))
Here is another inconsistency:
> > > (d e)
> > > > (e)
....
< < < < (e)
< < < (e)
You don't always cons. In fact, you do it only when you have an even number of < in the trace, which corresponds to an even number of > when calling the function. You understand that 2 should be generalized to n and that you have to add a counter.
You might be tempted to reuse the existing n, but for a first draft, add another parameter. If really it can be derived from n, you'll have an opportunity to rewrite later.
Necessarily, the counter must be passed (and modified) from one level to another. I won't copy-paste it here, but the result is Chris Jester-Young's answer. He uses a local function but that is the kind of refactoring that can be done afterwards.

How does append-to-form work? (SICP's section on Logic Programming)

I am currently working through SICP's section on Logic Programming, but I got stuck in the examples regarding logical deductions, especially the append-to-form rules. How do they work? What I don't quite understand is how the second rule cdr-downs the first list. For example, given:
(rule (append-to-form () ?y ?y))
(rule (append-to-form (?u . ?v) ?y (?u . ?z))
(append-to-form ?v ?y ?z))
a) How do we reach from:
;;; Query input:
(append-to-form (a b) (c d) ?z)
to
;;; Query results:
(append-to-form (a b) (c d) (a b c d))
b) And what bout this one:
;;; Query input:
(append-to-form (a b) ?y (a b c d))
to
;;; Query results:
(append-to-form (a b) (c d) (a b c d))
c) And lastly:
;;; Query input:
(append-to-form ?x ?y (a b c d))
to
;;; Query results:
(append-to-form () (a b c d) (a b c d))
(append-to-form (a) (b c d) (a b c d))
(append-to-form (a b) (c d) (a b c d))
(append-to-form (a b c) (d) (a b c d))
(append-to-form (a b c d) () (a b c d))
I would be interested in the specific mental steps required to carry out the rule matching.
Thank you in advance.
Play interpreter by taking a piece of paper and writing down every single step. For every step you write down which rule was/can be triggered and what variable was bound to what value.
For example:
(append-to-form (a b) (c d) ?z)
triggers the rule
(rule (append-to-form (?u . ?v) ?y (?u . ?z))
(append-to-form ?v ?y ?z))
with
?u = a, ?v = (b), ?y = (c d), ?z = (a . ?z_2)
Note: ?z in the original query is supposed to be a different variable from ?z in the rule body, therefor rename the rule's ?z into ?z_2. A list (1 2 3) when matched to (?a . ?b) produces ?a = 1, ?b = (2 3) like when car/cdr'ing a list.
These bindings are applied to the body of the rule (append-to-form ?v ?y ?z) So we get
(append-to-form (b) (c d) ?z_2)
which again becomes
(append-to-form () (c d) ?z_3)
and triggers a different rule: (rule (append-to-form () ?y ?y)) binding ?z_3 to (c d).
Then recursion kicks in, ?z_2 was defined as (b . ?z_3), ?z was defined as (a . ?z2)
The original query (append-to-form (a b) (c d) ?z) gets applied to the bindings in which ?z = (a . (b . (c d))) and returns (append-to-form (a b) (c d) (a b c d))
The rest of the exercises are left to the reader ;)
The crucial concepts here are pattern matching and unification which can be found at section 4.2.2. The whole query evaluator is really the most difficult piece in SICP, so don't be discourage. It is well worth the effort. Try to run the code (in an R5RS Scheme) and fiddle with it, such as adding tracing.

Resources