Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
This is the answer to the equation, but I do not understand why. Please help!
If you apply the Laws of Boolean Algebra one by one, the solution is a direct result:
de Morgan´s Theorem: The complement of two terms joined together by OR is the same as the complements of two terms joined by AND, and vice versa (i.e. NOT(A + B) = NOT(A) * NOT(B) and NOT(A * B) = NOT(A) + NOT(B)).
Commutative Law: The order of joining two separate terms with AND or OR is not important.
Complement Law: A term joined with its complement with AND equals 0 respectively with OR equals 1 (i.e. A * NOT(A) = 0 and A + NOT(A) = 1).
Annulment Law: A term joined with AND with 0 equals 0 and joined with OR with a 1 equals 1 (i.e. A * 0 = 0 and A + 1 = 1).
Identity Law: A term joined with 1 by AND or with 0 by OR is equal to itself (i.e. A * 1 = A and A + 0 = A).
(there are more, but you don't need them here)
Applied to your term:
(A + NOT(B*C)) * (B + NOT(B*C)) * (C + NOT(B*C))
[with 1.] = (A + NOT(B) + NOT(C)) * (B + NOT(B) + NOT(C)) * (C + NOT(B) + NOT(C))
[with 2.] = (A + NOT(B) + NOT(C)) * (B + NOT(B) + NOT(C)) * (C + NOT(C) + NOT(B))
[with 3.] = (A + NOT(B) + NOT(C)) * (1 + NOT(C)) * (1 + NOT(B))
[with 4.] = (A + NOT(B) + NOT(C)) * 1 * 1
[with 5.] = (A + NOT(B) + NOT(C))
[with 1.] = (A + NOT(B*C))
Anyone can help me reduce this to 4 literals?
F = ( A + C + D) ( A + C + D') (A + C' + D) ( A + B')
i tested in logic friday the answer was F = C D B' + A.
Assuming the ⋅ operator represents binary conjunction, the + binary disjunction and the ' or the ¬ unary negation, I would apply the laws of Boolean algebra this way:
(a + c + d)⋅(a + c + ¬d)⋅(a + ¬c + d)⋅(a + ¬b)
((a + d) + (c⋅¬c))⋅(a + c + ¬d)⋅(a + ¬b) //distributivity
((a + d) + (0))⋅(a + c + ¬d)⋅(a + ¬b) //complementation: c⋅¬c = 0
(a + d)⋅(a + c + ¬d)⋅(a + ¬b) //identity for +: (a + d) + (0) = (a + d)
(a) + (d⋅(c + ¬d)⋅¬b) //distributivity
(a) + ((d⋅c + d⋅¬d))⋅¬b) //distributivity: d⋅(c + ¬d) = (d⋅c + d⋅¬d)
(a) + ((d⋅c + 0))⋅¬b) //complementation: d⋅¬d = 0
(a) + (d⋅c⋅¬b) //identity for +: (d⋅c + 0) = d⋅c
a + ¬b⋅c⋅d
The final line is the minimal DNF. You can also transform it to it's minimal CNF this way:
(a) + (¬b⋅c⋅d)
(a + ¬b)⋅(a + c)⋅(a + d) //distributivity
For this small number of variables, you could have used Karnaugh maps to quickly find the minimal forms or to control your result. In the following picture (generated using latex) is the original expression next to it's minimal DNF and minimal CNF.
After finding the mean term you can use
Quine McCluskey Technique to solve the experssion. The result will same as K-Map. But it is fast technique for many veriable boolean expression.
Quine McCluskey online solver
I'm currently attempting to learn functional programming (and Scala) together. I'm porting some code from a FORTRAN routine for calculating a particular modified normalisation of the associated Legendre polynomials. My direct imperative translation of the original code is modpLgndr1 (which I have checked against the original algorithm). My initial attempt at writing the code in a functional form is in modpLgdnr2.
import math.pow, abs, sqrt, Pi
def xfact(m: Int): Double = {
if (m <= 1) 1.0
else {
if (m % 2 == 1) m.toDouble / sqrt(m.toDouble) * xfact(m - 1)
else 1.0 / sqrt(m.toDouble) * xfact(m - 1)
}
}
//this is a very un-scala function....
def modpLgndr1(l: Int, m: Int, x: Double): Double = {
assert(0 <= m && m <= l && abs(x) <= 1.0)
val dl = l.toDouble
val dm = m.toDouble
val norm = sqrt(2.0 * dl + 1.0) / sqrt(4.0 * Pi)
var pmm = norm
if (m != 0) pmm = (pow(-1, m)).toDouble * pmm * xfact(2 * m) * pow((1.0-x * x), (dm / 2.0))
if (l == m) pmm
else {
var pmmp1 = x * pmm * sqrt(2.0 * m + 1.0)
if (l == m + 1) pmmp1
else {
var pll = 0.0
var dll = 0.0
for (ll <- m + 2 to l) {
dll = ll.toDouble
pll = (x * (2.0 * dll - 1.0) * pmmp1 - sqrt(pow((dll - 1.0), 2.0) - dm * dm) * pmm) / sqrt(pow(dll, 2.0) - pow(dm, 2.0))
pmm = pmmp1
pmmp1 = pll
}
pll
}
}
}
def modpLgndr2(l: Int, m: Int, x: Double): Double = {
assert(0 <= m && m <= l && abs(x) <= 1.0)
val dl = l.toDouble
val dm = m.toDouble
val norm = sqrt(2.0 * dl + 1.0) / sqrt(4.0 * Pi)
val pmm = if (m == 0) norm else (pow(-1, m)).toDouble * norm * xfact(2 * m) * pow((1.0-x * x), (dm / 2.0))
if (l == m) pmm
else {
val pmmp1 = x * pmm * sqrt(2.0 * m + 1.0)
if (l == m + 1) pmmp1
else {
def mplacc(ll: Int, acc1: Double, acc2: Double): Double = {
val dll = ll.toDouble
val pll = (x * (2.0 * dll - 1.0) * acc2 - sqrt(pow((dll - 1.0), 2.0) - dm * dm) * acc1) / sqrt(pow(dll, 2.0) - pow(dm, 2.0))
if (ll == m + 2) pll
else mplacc(ll - 1, acc2, pll)
}
mplacc(l, pmm, pmmp1)
}
}
}
If I call the two functions I get output like this:
scala> for (i <- 0 to 10) println(modpLgndr1(10,i,0.2))
0.16685408398957746
-0.2769345073769805
-0.1575129272628402
0.2948210515201088
0.12578847877176355
-0.3292975894931367
-0.058267280378036426
0.37448134558730417
-0.08024600262585084
-0.40389602261165075
0.4424459249420354
scala> for (i <- 0 to 10) println(modpLgndr2(10,i,0.2))
0.16685408398957752
-0.2772969351441124
-0.1578618478786792
0.29654926805696474
0.1349402872678466
-0.33707342609134694
-0.06901634276825179
0.38912154672892657
-0.08024600262585084
-0.40389602261165075
0.4424459249420354
Essentially, for m = 0, l-2, l-1, l the code agrees; otherwise there is a significant discrepancy. That seems to tell me that the problem is in calling the mplacc function. To me, mplacc just looks like a recursive form of the for loop in modpLgndr1. Why am I wrong?
I'm trying to solve this:
So far I have:
a) a+b+c
b) a+bc
c) a+b
d) a+b
But for e) I can't progress further since I don't know how to deal with a'bc in this case. Can anyone help?
e) The expression is [a + (~a)bc + (~b)c]
a + [(~a)b + (~b)]c we can say that [(~a)b + (~b)] <--> [(~a) + (~b)] (Prove it by yourself:-)
a + [(~a) + (~b)]c
a + (~a)c + (~b)c we can say that [a + (~a)c] <--> [a + c]
a + c + (~b)c it is obvious that [c + (~b)c] <--> [c]
So [a + c] is the reduced expression.
In a for-comprehension, I can't just put a print statement:
def prod (m: Int) = {
for (a <- 2 to m/(2*3);
print (a + " ");
b <- (a+1) to m/a;
c = (a*b)
if (c < m)) yield c
}
but I can circumvent it easily with a dummy assignment:
def prod (m: Int) = {
for (a <- 2 to m/(2*3);
dummy = print (a + " ");
b <- (a+1) to m/a;
c = (a*b)
if (c < m)) yield c
}
Being a side effect, and only used (so far) in code under development, is there a better ad hoc solution?
Is there a serious problem why I shouldn't use it, beside being a side effect?
update showing the real code, where adapting one solution is harder than expected:
From the discussion with Rex Kerr, the necessity has risen to show the original code, which is a bit more complicated, but did not seem to be relevant for the question (2x .filter, calling a method in the end), but when I tried to apply Rex' pattern to it I failed, so I post it here:
def prod (p: Array[Boolean], max: Int) = {
for (a <- (2 to max/(2*3)).
filter (p);
dummy = print (a + " ");
b <- (((a+1) to max/a).
filter (p));
if (a*b <= max))
yield (em (a, b, max)) }
Here is my attempt -- (b * a).filter is wrong, because the result is an int, not a filterable collection of ints:
// wrong:
def prod (p: Array[Boolean], max: Int) = {
(2 to max/(2*3)).filter (p).flatMap { a =>
print (a + " ")
((a+1) to max/a).filter (p). map { b =>
(b * a).filter (_ <= max).map (em (a, b, max))
}
}
}
Part II belongs to the comments, but can't be read, if written there - maybe I delete it in the end. Please excuse.
Ok - here is Rex last answer in code layout:
def prod (p: Array[Boolean], max: Int) = {
(2 to max/(2*3)).filter (p).flatMap { a =>
print (a + " ")
((a+1) to max/a).filter (b => p (b)
&& b * a < max).map { b => (m (a, b, max))
}
}
}
This is how you need to write it:
scala> def prod(m: Int) = {
| for {
| a <- 2 to m / (2 * 3)
| _ = print(a + " ")
| b <- (a + 1) to (m / a)
| c = a * b
| if c < m
| } yield c
| }
prod: (m: Int)scala.collection.immutable.IndexedSeq[Int]
scala> prod(20)
2 3 res159: scala.collection.immutable.IndexedSeq[Int] = Vector(6, 8, 10, 12, 14
, 16, 18, 12, 15, 18)
Starting Scala 2.13, the chaining operation tap, has been included in the standard library, and can be used with minimum intrusiveness wherever we need to print some intermediate state of a pipeline:
import util.chaining._
def prod(m: Int) =
for {
a <- 2 to m / (2 * 3)
b <- (a + 1) to (m / a.tap(println)) // <- a.tap(println)
c = a * b
if c < m
} yield c
prod(20)
// 2
// 3
// res0: IndexedSeq[Int] = Vector(6, 8, 10, 12, 14, 16, 18, 12, 15, 18)
The tap chaining operation applies a side effect (in this case println) on a value (in this case a) while returning the value (a) untouched:
def tap[U](f: (A) => U): A
It's very convenient when debugging as you can use a bunch of taps without having to modify the code:
def prod(m: Int) =
for {
a <- (2 to m.tap(println) / (2 * 3)).tap(println)
b <- (a + 1) to (m / a.tap(println))
c = (a * b).tap(println)
if c < m
} yield c
I generally find that style of coding rather difficult to follow, since loops and intermediate results and such get all mixed in with each other. I would, instead of a for loop, write something like
def prod(m: Int) = {
(2 to m/(2*3)).flatMap { a =>
print(a + " ")
((a+1) to m/a).map(_ * a).filter(_ < m)
}
}
This also makes adding print statements and such easier.
It doesn't seem like good style to put a side-effecting statement within a for-comprehension (or indeed in the middle of any function), execept for debugging in which case it doesn't really matter what you call it ("debug" seems like a good name).
If you really need to, I think you'd be better separating your concerns somewhat by assigning an intermediate val, e.g. (your original laid out more nicely):
def prod (p: Array[Boolean], max: Int) = {
for {
a <- (2 to max / (2 * 3)) filter p
debug = print (a + " ")
b <- ((a + 1) to max / a) filter p
if a * b <= max
} yield em(a, b, max)
}
becomes
def prod2 (p: Array[Boolean], max: Int) = {
val as = (2 to max / (2 * 3)) filter p
for(a <- as) print(a + " ")
as flatMap {a =>
for {
b <- ((a + 1) to max / a) filter p
if a * b <= max
} yield em(a, b, max)
}
}