I wanted to create a program that, given a logic formula by the user, for example ((¬A ∧ B) ∨ C) ∧ A, calculates its truth table.
In this case the formula would be true if A=1, B=0, C=1, or if A=1, B=1, C=1, and it would be false in any other case.
But, I don't know how to create a method that can read the expression given, and then calculate all the possible outcomes.
I don't know how to create a method that can read the expression given, and then calculate all the possible outcomes.
OK, so let's start with the task breakdown into subtasks.
Here's what you need to do ...
Parse the string you get as input into some internal data structures used by your program. This is a hard task. Make sure to cover relevant methods by unit tests.
Calculate the truth tables. This is easier. You just need to iterate over all possible sets of inputs. These will be binary numbers from 0 to 2^n-1 where n is the number of boolean inputs.
Let's see what resources you can use ...
For the parse part you can adapt this
To generate all possible inputs you can use this
Also, please, make sure to cover your methods by unit tests. Its easy to make a mistake in complicated logic like this, which will take hours to debug. Therefore, unit tests will save you loads of time.
Does this solve your problem ? Tell me in the comments.
Try this.
interface Bool {
boolean get();
default Bool and(Bool r) { return () -> get() ? r.get() : false; }
default Bool or(Bool r) { return () -> get() ? true : r.get(); }
default Bool not() { return () -> !get(); }
}
static class TruthTable {
String formula;
int index, ch;
List<Character> variables;
Map<Character, Boolean> map;
Bool bool;
int get() {
return ch = index < formula.length() ? formula.charAt(index++) : -1;
}
boolean match(int expect) {
if (ch == expect) {
get();
return true;
}
return false;
}
Bool element() {
Bool b;
if (match('(')) {
b = expression();
if (!match(')'))
throw new RuntimeException("')' expected");
} else if (Character.isAlphabetic(ch)) {
char v = (char) ch;
get();
if (!variables.contains(v))
variables.add(v);
b = () -> map.get(v);
} else
throw new RuntimeException("unknown char: " + (char) ch);
return b;
}
Bool factor() {
if (match('¬'))
return element().not();
return element();
}
Bool term() {
Bool b = factor();
while (match('∧'))
b = b.and(factor());
return b;
}
Bool expression() {
Bool b = term();
while (match('∨'))
b = b.or(term());
return b;
}
String str(boolean b) {
return b ? "T" : "F";
}
void print() {
for (char v : variables)
System.out.print(str(map.get(v)) + " ");
System.out.println(str(bool.get()));
}
void test(int i) {
if (i >= variables.size())
print();
else {
char c = variables.get(i);
map.put(c, true);
test(i + 1);
map.put(c, false);
test(i + 1);
}
}
public void make(String formula) {
this.formula = formula.replaceAll("\\s", "");
index = 0;
variables = new ArrayList<>();
map = new HashMap<>();
get();
bool = expression();
if (ch != -1)
throw new RuntimeException(
"extra string '" + formula.substring(index - 1) + "'");
for (char v : variables)
System.out.print(v + " ");
System.out.println(formula);
test(0);
System.out.println();
}
}
And
public static void main(String[] args) {
new TruthTable().make("¬A");
new TruthTable().make("¬A ∧ B");
new TruthTable().make("(¬A ∧ B) ∨ C");
new TruthTable().make("((¬A ∧ B) ∨ C) ∧ A");
}
output:
A ¬A
T F
F T
A B ¬A ∧ B
T T F
T F F
F T T
F F F
A B C (¬A ∧ B) ∨ C
T T T T
T T F F
T F T T
T F F F
F T T T
F T F T
F F T T
F F F F
A B C ((¬A ∧ B) ∨ C) ∧ A
T T T T
T T F F
T F T T
T F F F
F T T F
F T F F
F F T F
F F F F
Related
**I wrote a simple code that have to compare to numbers, but when I run it compiler say me that has a error with boolean values. I dont understand why it doesnt work **
{
public static void main(String[] args) {
compare(8,22);
}
static void compare(int a, int b){
switch (a) {
case (a > b) -> System.out.println(a + " > " + b);
case (b < a) -> System.out.println(a + " < " + b);
case (a == b) -> System.out.println(a + " = " + b);
default -> System.out.println("Something is wrong !");
}
}
}```
Change it to:
{
public static void main( String... args )
{
compare( 8, 22 );
}
static void compare( final int a, final int b )
{
switch( Integer.signum( Integer.compare( a, b ) ) )
{
case 1 -> System.out.println( a + " > " + b );
case -1 -> System.out.println( a + " < " + b );
case 0 -> System.out.println( a + " = " + b );
default -> System.out.println( "Something is wrong !" );
}
}
}
And it should work!
case requires distinct constant expressions, and the terms that you use ((a > b), (b < a) and (a == b)) are no constants (not to mention that (a > b) and (b < a) are equivalent). They also return a boolean. switch does not handle a boolean switch selector directly.
In JShell, (only) this works for switch with "boolean":
boolean flag = …
switch( Boolean.toString( flag ) )
{
case "true" -> …
case "false" -> …
default -> throw new Error( "Hä?" );
}
This question already has answers here:
Ternary Operator
(4 answers)
Closed 2 years ago.
(comparison > 0 ? n : m).subtract(comparison > 0 ? m : n);
I'm trying to figure out what this inline conditional statement means and how to convert it into a regular if statement. The .subtract is just a method that will subtract the second () from the first().
I think that the first (comparison > 0 ? n : m) is the same as if(comparison > 0) { m = n; }
not sure how that works with the subtract function. The code runs correctly but I'm trying to fix the warning to not use inline conditionals.
Thank you!
The ternary ?: operator is what is used here.
a ? b : c means
if (a) {
b;
} else {
c;
}
So (comparison > 0 ? n : m).subtract(comparison > 0 ? m : n); means.
if (comparsion > 0) {
n.subtract(m);
} else {
m.subtract(n);
}
In this case n and m must be objects that have a subtract method as follows which prints:
result = -3 when comparison = -5
result = 3 when comparison = 5
public class TernaryDemo {
public static void main(String[] args) {
for (int comparison : new int[] { -5, 5 }) {
MyClass n = new MyClass(10);
MyClass m = new MyClass(7);
MyClass result = (comparison > 0 ? n : m)
.subtract(comparison > 0 ? m : n);
System.out.println("result = " + result
+ " when comparison = " + comparison);
}
}
}
class MyClass {
int v;
public MyClass(int v) {
this.v = v;
}
public MyClass subtract(MyClass cls) {
return new MyClass(this.v - cls.v);
}
public String toString() {
return v + "";
}
}
This is stuff you can test yourself.
However, it translates to:
Subtractable sub, sub2; // This is how I am going to call the class that has the subtract method
if(comparison > 0)
sub = n;
else
sub = m;
// You could put these in the same if statement, but this is closer to what actually happens.
if(comparison > 0)
sub2 = m;
else
sub2 = n;
sub.subtract(sub2);
I am a new in java and programming in general.
I am currently doing complex numbers. I know that there might be an answer for this online, but it will also reveal if I used the correct algorithm and so on, so I am trying to avoid other answers around here.
My main issue is that I am having trouble with the Divide class that I made, since in complex number division we are going to return a fraction as an answer, I can't figure out how to have the program return the 2 statements that it calculate, can someone advise what can be done? Here is the part of the division code, it works fine when I check both part 1 and then part 2, but how can i get it to return both of them when calling using that class.
I attached my full code that I made, I know it can be tweaked to have less coding, but that is not my current concern.
Thanks for your help in advance.
class complexN {
int R, I;
complexN(int R, int I) {
this.R = R;
this.I = I;
}
complexN AddCN(complexN A) {
return new complexN(this.R + A.R, this.I + A.I);
}
complexN SubCN(complexN A) {
int AnsR = this.R - A.R;
int AnsI = this.I - A.I;
complexN Sum = new complexN(AnsR, AnsI);
return Sum;
}
complexN MulCN(complexN A) {
int AnsI = (this.R * A.I) + (this.I * A.R);
int AnsR = (this.R * A.R) - (this.I * A.I);
complexN Sum = new complexN(AnsR, AnsI);
return Sum;
}
complexN DivCN(complexN A) {
complexN ComCon = new complexN(A.R, (A.I * -1));
complexN part1 = new complexN(this.R, this.I).MulCN(ComCon);
complexN part2 = A.MulCN(ComCon);
return part1;
}
void print() {
String i = (this.I == 1 ? "" : (this.I == -1 ? "-" : "" + this.I));
if (this.R != 0 && this.I > 0) {
System.out.println(this.R + "+" + i + "i");
}
if (this.R != 0 && this.I < 0) {
System.out.println(this.R + i + "i");
}
if (this.R != 0 && this.I == 0) {
System.out.println(this.R);
}
if (this.R == 0 && this.I != 0) {
System.out.println(i + "i");
}
if (this.R == 0 && this.I == 0) {
System.out.println("0");
}
}
}
class complex {
public static void main(String[] args) {
// TODO Auto-generated method stub
complexN z1 = new complexN(5, 2);
complexN z2 = new complexN(3, -4);
System.out.print("z1 = ");
z1.print();
System.out.print("z2 = ");
z2.print();
System.out.println("---------");
z1.DivCN(z2).print();
}
}
I am gettings strings as the input for a program, but those could be represented in various formats. E.g.:
8900
8.9E+3
89E+2
8900.000
All those numbers are equal mathematically and the following program also tells a match:
public class BigDecimalMain {
public static void main(String... args) {
BigDecimal a = new BigDecimal("8900");
BigDecimal b = new BigDecimal("8.9E+3");
BigDecimal c = new BigDecimal("89E+2");
BigDecimal d = new BigDecimal("8900.000");
System.out.println(a.compareTo(b));
System.out.println(a.compareTo(c));
System.out.println(a.compareTo(d));
}
}
Output:
0
0
0
My program uses .equals to match objects and it fails to give the right answer in the case above.
Question: How to parse string into BigDecimal uniformly? I mean the following:
find a function PARSE, that
for any STR1 && STR2
PARSE(STR1).compareTo(PARSE(STR2)) == 0 <=> PARSE(STR1).equals(PARSE(STR2))
With a common scale you could use setScale(xxx):
{
BigDecimal a = new BigDecimal("8900");
BigDecimal b = new BigDecimal("8.9E+3");
BigDecimal c = new BigDecimal("89E+2");
BigDecimal d = new BigDecimal("8900.000");
System.out.println(a.compareTo(b));
System.out.println(a.compareTo(c));
System.out.println(a.compareTo(d));
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(a.equals(d));
}
{
BigDecimal a = new BigDecimal("8900").setScale(5);
BigDecimal b = new BigDecimal("8.9E+3").setScale(5);
BigDecimal c = new BigDecimal("89E+2").setScale(5);
BigDecimal d = new BigDecimal("8900.000").setScale(5);
System.out.println(a.compareTo(b));
System.out.println(a.compareTo(c));
System.out.println(a.compareTo(d));
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(a.equals(d));
}
shows
0
0
0
false
false
false
0
0
0
true
true
true
Consider the following approach:
class UniformDecimal {
private final BigDecimal decimal;
public UniformDecimal(BigDecimal decimal) {
this.decimal = decimal;
}
#Override
public int hashCode() {
return decimal.toBigInteger().mod(BigInteger.valueOf((1<<31)-1)).intValue();
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UniformDecimal that = (UniformDecimal) o;
return that.decimal.compareTo(this.decimal)==0;
}
}
Though, I'm not sure about hashCode implementation
UPDATE. It seems that stripTrailingZeros() does the thing!
Found something useful at here: HiveDecimal
private static BigDecimal normalize(BigDecimal bd, boolean allowRounding) {
if (bd == null) {
return null;
}
bd = trim(bd);
int intDigits = bd.precision() - bd.scale();
if (intDigits > MAX_PRECISION) {
return null;
}
int maxScale = Math.min(MAX_SCALE, Math.min(MAX_PRECISION - intDigits, bd.scale()));
if (bd.scale() > maxScale) {
if (allowRounding) {
bd = bd.setScale(maxScale, RoundingMode.HALF_UP);
// Trimming is again necessary, because rounding may introduce new trailing 0's.
bd = trim(bd);
} else {
bd = null;
}
}
return bd;
}
private static BigDecimal trim(BigDecimal d) {
if (d.compareTo(BigDecimal.ZERO) == 0) {
// Special case for 0, because java doesn't strip zeros correctly on that number.
d = BigDecimal.ZERO;
} else {
d = d.stripTrailingZeros();
if (d.scale() < 0) {
// no negative scale decimals
d = d.setScale(0);
}
}
return d;
}
It is question from OCJP 6 exam, so it is intentionally not fully correct (but legal).
Given code:
class ToDos {
String day;
public ToDos(String d) {
day = d;
}
public boolean equals(Object o) {
return ((ToDos) o).day == day;
}
public int hashCode() { return 9; }
}
public class MapEQ {
public static void main(String[] args) {
Map<ToDos, String> map = new HashMap<ToDos, String>();
ToDos t1 = new ToDos("Monday");
ToDos t2 = new ToDos("Mond" + "a" + "y");
ToDos t3 = new ToDos("Tuesday");
map.put(t1, "a");
map.put(t2, "b");
map.put(t3, "c");
System.out.println(map.size());
}
}
Why output is 2? I mean, equals method is not overriden corretcly, so t1.day == t2.day supposed to be false! Am I'm missed something?
It's because:
"Mond" + "a" + "y"
is evaluated at compile time to "Monday" thus resulting in just one instance in string pool. There is a much simpler test to examine this behavior:
System.out.println("Mond" + "a" + "y" == "Monday"); //true
String y = "y";
System.out.println("Mond" + "a" + y == "Monday"); //false
final String y2 = "y";
System.out.println("Mond" + "a" + y2 == "Monday"); //true
Examples above should give you some overview on how the compiler treats string concatenation.
And to be on the safe side, always use:
return ((ToDos) o).day.equals(day);
Just adding to previous answers ... another example illustrating the point:
String a = "Monday";
String b = new String("Monday");
String c = "Monday";
(a == b) // false
(a.equals(b)) // true
(a == c) // true
(a.equals(c)) // true
Both a and c point to the same object in the String pool.