Java / JUnit - AssertionError testing a pre-defined polynomial - java

I have a Term class to define a polynomial:
public class Term
{
final private int coef;
final private int expo;
private static Term zero, unit;
static
{
try
{
zero = new Term(0, 0); // the number zero
unit = new Term(1, 0); // the number one
}
catch (Exception e)
{
// constructor will not throw an exception here anyway
}
}
/**
*
* #param c
* The coefficient of the new term
* #param e
* The exponent of the new term (must be non-negative)
* #throws NegativeExponent
*/
public Term(int c, int e) throws NegativeExponent
{
if (e < 0)
throw new NegativeExponent();
coef = c;
expo = (coef == 0) ? 1 : e;
}
final public static Term Zero = zero;
final public static Term Unit = unit;
public boolean isConstant()
{
boolean isConst = false;
if (this.expo == 0)
{
isConst = true;
}
return isConst;
}
}
And I have the JUnit test as follows:
/*
* const1 isConstant(zero) => true (0,0)
* const2 isConstant(unit) => true (1,0)
* const3 isConstant(0,5) => true
* const4 isConstant(5,1) => false
*/
#Test
public void const1() throws TError { assertTrue(Term.Zero.isConstant()); }
#Test
public void const2() throws TError { assertTrue(Term.Unit.isConstant()); }
#Test
public void const3() throws TError { assertTrue(new Term(0,5).isConstant()); }
#Test
public void const4() throws TError { assertFalse(new Term(5,1).isConstant()); }
Tests 2 and 4 pass as they should, but Tests 1 and 3 come up as failures and I cannot work out why, "Zero" is defining the polynomial as (0,0) and the other is defining it as (0,5). So by my thinking, the 1st one should give a green tick and the 3rd test should give a red cross as it has 5 as the exponent.
Any ideas?

Please review your constructor:
public Term(int c, int e) throws NegativeExponent{
if (e < 0) throw new NegativeExponent();
coef = c;
expo = (coef == 0) ? 1 : e;
}
When coef == 0, then exp is assigned with 1.
This makes zero as (0,1) not (0,0). this is the reason for test outcome as below:
const1 -> false as expo = 1-->failure as expecting true
const2 -> true as expo = 0 -->success as expecting true
const3 -> false as expo = 5.-->failure as expecting true
const4 -> false as expo = 1.-->success as expecting false
EDIT: To reverse fix your code to make the test cases pass, I think you may update your constructor as below:
public Term(int c, int e) throws NegativeExponent{
if (e < 0) throw new NegativeExponent();
coef = c;
expo = (c == 0 && e != 0) ? 0 : e;
}
Here, I have updated the constructor to set expo as 0, if coef is 0 as any expo for coef 0 is immaterial.

Yogendra covered why your first test fails. Your const3() fails (for me at least) because new Term(0, 5) has a expo of 5, which gets replaced with 1 b/c of the coef, but 1 is still not 0 so new Term(0, 5) is NOT constant.
Not that you asked, but I'll also give you some general Java pointers for the future...
1) Use all caps for static constants
public static final Term ZERO = new Term(0, 0);
public static final Term UNIT = new Term(1, 0);
this is just a convention that the Java community expects.
2) Give your test cases meaningful names. One powerful use of test cases is that they can double as documentation of your assumptions at the time. Rather than const1() which tells a fellow developer nothing, use a descriptive name like zeroShouldBeAConstant(). This tells the next person who looks at your code that Zero should be considered a constant in this system.
3) Whenever you are returning a boolean variable, consider just returning the statement. Compare the function below to yours and tell me which one is more readable:
public boolean isConstant()
{
return expo == 0;
}
It is less code and hopefully easier to read.
Good luck!

Related

Replace null check with Optional

I would like to know since i'm fan of java 14 if replacing null checks with Optional.ofNullable
is safe for this language. I know a simple null check doesn't cost any memory while new creating new objects like optional cost but i guess it has zero performance impact or memory impact. Can someone enlight me?
The code for my game was like:
if (item!= null)
{
if (item.getCrystal() == Crystal.A)
{
player.getInventory().addItem(inventoryItem);
}
}
to something which i enjoy and i find cool
Optional.ofNullable(item).filter(i -> i.getCrystal() == Crystal.A).ifPresent(k -> player.getInventory.addItem(i));
Can someone enlight me that i'm ok with it? Maybe is cool but cost a lot? I don't know.
Thanks a lot.
In simple cases like this, the just in time compiler can likely elide the object allocation, or at least allocate it on the stack, so the overhead is negligible.
Here's a small benchmark:
public abstract class Benchmark {
final String name;
public Benchmark(String name) {
this.name = name;
}
#Override
public String toString() {
return name + "\t" + time() + " ns / iteration";
}
private BigDecimal time() {
try {
// automatically detect a reasonable iteration count (and trigger just in time compilation of the code under test)
int iterations;
long duration = 0;
for (iterations = 1; iterations < 1_000_000_000 && duration < 1_000_000_000; iterations *= 2) {
long start = System.nanoTime();
run(iterations);
duration = System.nanoTime() - start;
cleanup();
}
return new BigDecimal((duration) * 1000 / iterations).movePointLeft(3);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
/**
* Executes the code under test.
* #param iterations
* number of iterations to perform
* #return any value that requires the entire code to be executed (to
* prevent dead code elimination by the just in time compiler)
* #throws Throwable
* if the test could not complete successfully
*/
protected abstract Object run(int iterations) throws Throwable;
/**
* Cleans up after a run, setting the stage for the next.
*/
protected void cleanup() {
// do nothing
}
public static void main(String[] args) throws Exception {
Integer[] a = {null, -1, null, 1}; // mix nulls and real values
System.out.println(new Benchmark("Optional") {
#Override
protected Object run(int iterations) throws Throwable {
int[] sum = {0};
for (int i = 0; i < iterations; i++) {
Optional.ofNullable(a[i & 3]).filter(k -> k > 0).ifPresent(k -> sum[0] += k);
}
return sum[0];
}
});
System.out.println(new Benchmark("if != null") {
#Override
protected Object run(int iterations) throws Throwable {
int[] sum = {0};
for (int i = 0; i < iterations; i++) {
var k = a[i & 3];
if (k != null && k % 2 != 0) {
sum[0] += k;
}
}
return sum[0];
}
});
}
}
This shows that the overhead of using an Optional is about 1 ns, i.e. a modern CPU can construct and evaluate about 1 billion Optional objects per second. In all but the most extreme and contrived of workloads, the use of Optional will not affect performance enough for humans to notice.
The decision to use Optional should therefore not be guided by performance considerations, but by which version allows yourself to express yourself more clearly and simply.
In this case, I'd argue that the if statement is actually more readable. Sure, you've squashed everything onto a single line, but you could do the same with an if statement:
if (item != null && item.getCrystal() == Crystal.A) player.getInventory().addItem(inventoryItem);
If you do that, you'll notice that the if statement is actually shorter and more to the point than your version:
Optional.ofNullable(item).filter(i -> i.getCrystal() == Crystal.A).ifPresent(k -> player.getInventory.addItem(i));
Of course, in real code you'll probably want to keep your lines reasonably short, so the comparison is
if (item != null && item.getCrystal() == Crystal.A) {
player.getInventory().addItem(inventoryItem);
}
vs
Optional.ofNullable(item).filter(i -> i.getCrystal() == Crystal.A)
.ifPresent(k -> player.getInventory.addItem(i));
Again, I find the first version more readable, because it contains fewer words.

Fermat's primality test and Carmichael number

I am playing with prime numbers and Fermat's Little Theorem. I read about Carmichael numbers and that they should pass the tests. The problem is, when I test it and use two different conditions it should end with the same result, but it isn't.
Code :
import java.math.BigInteger;
public class FermatTest {
public static boolean passesAllFermatTests(BigInteger n) {
BigInteger testValue = BigInteger.ONE;
while (testValue.compareTo(n) == -1) {
if (!passesFermatTest(n, testValue)) {
return false;
}
testValue = testValue.add(BigInteger.ONE);
}
return true;
}
public static boolean passesFermatTest(BigInteger n, BigInteger a) {
//if( !a.modPow(n.subtract(BigInteger.ONE), n).equals(BigInteger.ONE)) {
if(! a.modPow(n, n).equals(a)) {
return false;
}
return true;
}
public static void main(String[] args) {
System.out.println(passesAllFermatTests(BigInteger.valueOf((long) 561)));
}
}
When I run it with this condition, it returns true ( pass it ). If I run it with the commented condition, it returns false. It should be the same, isn't it? Is there an error in my code or I misunderstood something?
The problem is when a = 3, your commented condition return false, it is because 3 and 561 is not relatively prime! Carmichael number require gcd(a,n) = 1 (please refer to the wikipedia: https://en.wikipedia.org/wiki/Carmichael_number).
So in your program, you should first check "a" and "n" is relatively prime first before applying the commented condition.

Return statement best practices in java?

I want to know the difference between these two codes even though they produce the same output:
CODE 1:
class ret {
public static int add(int x) {
if(x!=0)
return x+add(x-1);
return x;
}
public static void main(String args[]) {
System.out.println(add(5));
}
}
CODE 2:
class ret {
public static int add(int x) {
if(x!=0)
return x+add(x-1);
return 0;
}
public static void main(String args[]) {
System.out.println(add(5));
}
}
They both output 15 but how come the second code also output's 15 instead of zero?My understanding is that the last call would be add(0) for code 2 and it would return zero.I also want to know is it okay to use multiple return statements or use a single return statement and replace the rest with local variables.I remember reading that single entry single exit model is a good practice.
This is a recursive method, so when x != 0, you will return the result of "x added to calling the method again with (x-1)". The final call will always return x == 0 or constant = 0, so you will return 15 from both versions.
Single return vs. multiple return is a matter of debate. The former should be preferred as a rule. Generally it will be obvious where multiple return statements are acceptable as it will be simpler to understand the method with them than with the alternative code constructs required to engineer a single exit point. Also note you could rewrite add as:
public static int add(int x) {
return x == 0 ? 0 : (x + add(x-1));
}
Version 1:
add(5)
call add(4)
call add(3)
call add(2)
call add(1)
call add(0)
return (x = 0)
return (x = 1) + (add(x-1) = 0) = 1
return (x = 2) + (add(x-1) = 1) = 3
return (x = 3) + (add(x-1) = 3) = 6
return (x = 4) + (add(x-1) = 6) = 10
return (x = 5) + (add(x-1) = 10) = 15
Version 2:
add(5)
call add(4)
call add(3)
call add(2)
call add(1)
call add(0)
return (constant = 0) // the only difference
return (x = 1) + (add(x-1) = 0) = 1
return (x = 2) + (add(x-1) = 1) = 3
return (x = 3) + (add(x-1) = 3) = 6
return (x = 4) + (add(x-1) = 6) = 10
return (x = 5) + (add(x-1) = 10) = 15
The use of multiple return statement versus using a single exit point cannot be answered with an easy one-line answer. I guess the best answer you can get is "it depends on your company's standards".
Single exit point is a very good standard, even though I don't personally endorse it. You end up having methods that always have a single return statement at the end, so you never get in a position where you are looking for those many possible return statement while editing someone else's code. I believe that developers that used to code in C tend to follow this standard (see this question).
I, for one, perfer using multiple return statements when it can help simplify the code. One case where I like to use it is to prevent cascading braces in my code. For instance, in the following example:
private int doSomething (int param) {
int returnCode;
if (param >= 0) {
int someValue = param * CONSTANT_VALUE;
if (isWithinExpectedRange (someValue)) {
if (updateSomething (someValue)) {
returnCode = 0;
} else {
returnCode = -3;
}
} else {
returnCode = -2;
}
} else {
returnCode = -1;
}
return returnCode;
}
I find this type of coding to be very confusing when reading it. I tend to change this type of code to:
private int doSomething (int param) {
if (param < 0) {
return -1;
}
int someValue = param * CONSTANT_VALUE;
if (!isWithinExpectedRange (someValue)) {
return -2;
}
if (!updateSomething (someValue)) {
return -3;
}
return 0;
}
The second example looks cleaner, and clearer, to me. Even more when the actual code has some extra coding in the else blocks.
Again, this is personal tastes. Some company might enforce a single exit point, some might not, and some developers prefer single exit point. The bottom line is, if there's a guideline available for you to follow in your environment, then do so. If not, then you can chose your own preference base partly on these arguments.

In Java, how do I test whether a list of `Double` contains a particular value

Background: Floating point numbers have rounding issues, so they should never be compared with "==".
Question: In Java, how do I test whether a list of Double contains a particular value. I am aware of various workarounds, but I am looking for the most elegant solution, presumably the ones that make use of Java or 3rd party library features.
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
// should be 1.38, but end up with 1.3800000000000001
Double d1 = new Double(1.37 + 0.01);
System.out.println("d1=" + d1);
// won't be able to test the element for containment
List<Double> list = new ArrayList<Double>();
list.add(d1);
System.out.println(list.contains(1.38));
}
}
Output is:
d1=1.3800000000000001
false
Thank you.
The general solution would be to write a utility method that loops through the list and checks if each element is within a certain a threshold of the target value. We can do slightly better in Java 8, though, using Stream#anyMatch():
list.stream().anyMatch(d -> (Math.abs(d/d1 - 1) < threshold))
Note that I am using the equality test suggested here.
If you're not using Java 8, I would write a simple utility method along the lines of this:
public static boolean contains(Collection<Double> collection, double key) {
for (double d : collection) {
if (Math.abs(d/key - 1) < threshold)
return true;
}
return false;
}
Note that you might need to add a special case to both of these approaches to check if the list contains 0 (or use the abs(x - y) < eps approach). That would just consist of adding || (abs(x) < eps && abs(y) < eps) to the end of the equality conditions.
Comparing bits wasn't a good idea. Similar to another post, but deals with NaN and Infinities.
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
// should be 1.38, but end up with 1.3800000000000001
Double d1 = 1.37d + 0.01d;
System.out.println("d1=" + d1);
// won't be able to test the element for containment
List<Double> list = new ArrayList<>();
list.add(d1);
System.out.println(list.contains(1.38));
System.out.println(contains(list, 1.38d, 0.00000001d));
}
public static boolean contains(List<Double> list, double value, double precision) {
for (int i = 0, sz = list.size(); i < sz; i++) {
double d = list.get(i);
if (d == value || Math.abs(d - value) < precision) {
return true;
}
}
return false;
}
}
You could wrap the Double in another class that provides a 'close enough' aspect to its equals method.
package com.michaelt.so.doub;
import java.util.HashSet;
import java.util.Set;
public class CloseEnough {
private Double d;
protected long masked;
protected Set<Long> similar;
public CloseEnough(Double d) {
this.d = d;
long bits = Double.doubleToLongBits(d);
similar = new HashSet<Long>();
masked = bits & 0xFFFFFFFFFFFFFFF8L; // 111...1000
similar.add(bits);
similar.add(bits + 1);
similar.add(bits - 1);
}
Double getD() {
return d;
}
#Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof CloseEnough)) {
return false;
}
CloseEnough that = (CloseEnough) o;
for(Long bits : this.similar) {
if(that.similar.contains(bits)) { return true; }
}
return false;
}
#Override
public int hashCode() {
return (int) (masked ^ (masked >>> 32));
}
}
And then some code to demonstrate it:
package com.michaelt.so.doub;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<CloseEnough> foo = new ArrayList<CloseEnough>();
foo.add(new CloseEnough(1.38));
foo.add(new CloseEnough(0.02));
foo.add(new CloseEnough(1.40));
foo.add(new CloseEnough(0.20));
System.out.println(foo.contains(new CloseEnough(0.0)));
System.out.println(foo.contains(new CloseEnough(1.37 + 0.01)));
System.out.println(foo.contains(new CloseEnough(0.01 + 0.01)));
System.out.println(foo.contains(new CloseEnough(1.39 + 0.01)));
System.out.println(foo.contains(new CloseEnough(0.19 + 0.01)));
}
}
The output of this code is:
false
true
true
true
true
(that first false is the compare with 0, just to show that it isn't finding things that aren't there)
CloseEnough is just a simple wrapper around the double that masks the lowest three bits for the hash code (enough that and also stores the valid set of similar numbers in a set. When doing an equals comparison, it uses the sets. Two numbers are equal if they contain a common element in their sets.
That said, I am fairly certain that there are some values that would be problematic with a.equals(b) being true and a.hashCode() == b.hashCode() being false that may still occur at edge conditions for the proper bit patterns - this would make some things (like HashSet and HashMap) 'unhappy' (and would likely make a good question somewhere.
Probably a better approach to this would instead be to extend ArrayList so that the indexOf method handles the similarity between the numbers:
package com.michaelt.so.doub;
import java.util.ArrayList;
public class SimilarList extends ArrayList<Double> {
#Override
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < this.size(); i++) {
if (get(i) == null) {
return i;
}
}
} else {
for (int i = 0; i < this.size(); i++) {
if (almostEquals((Double)o, this.get(i))) {
return i;
}
}
}
return -1;
}
private boolean almostEquals(Double a, Double b) {
long abits = Double.doubleToLongBits(a);
long bbits = Double.doubleToLongBits(b);
// Handle +0 == -0
if((abits >> 63) != (bbits >> 63)) {
return a.equals(b);
}
long diff = Math.abs(abits - bbits);
if(diff <= 1) {
return true;
}
return false;
}
}
Working with this code becomes a bit easier (pun not intended):
package com.michaelt.so.doub;
import java.util.ArrayList;
public class ListTest {
public static void main(String[] args) {
ArrayList foo = new SimilarList();
foo.add(1.38);
foo.add(1.40);
foo.add(0.02);
foo.add(0.20);
System.out.println(foo.contains(0.0));
System.out.println(foo.contains(1.37 + 0.01));
System.out.println(foo.contains(1.39 + 0.01));
System.out.println(foo.contains(0.19 + 0.01));
System.out.println(foo.contains(0.01 + 0.01));
}
}
The output of this code is:
false
true
true
true
true
In this case, the bit fiddling is done in the SimilarList based on the code HasMinimalDifference. Again, the numbers are converted into bits, but this time the math is done in the comparison rather than trying to work with the equality and hash code of a wrapper object.
Background: Floating point numbers have rounding issues, so they should never be compared with "==".
This is false. You do need to be awake when writing floating-point code, but reasoning about the errors that are possible in your program is in many cases straightforward. If you cannot do this, it behooves you to at least get an empirical estimate of how wrong your computed values are and think about whether the errors you're seeing are acceptably small.
What this means is that you cannot avoid getting your hands dirty and thinking about what your program is doing. If you're going to work with approximate comparisons, you need to have some idea of what differences mean that two values really are different and what differences mean that two quantities might be the same.
// should be 1.38, but end up with 1.3800000000000001
This is also false. Notice that the closest double to 1.37 is 0x1.5eb851eb851ecp+0 and the closest double to 0.01 is 0x1.47ae147ae147bp-7. When you add these, you get 0x1.6147ae147ae14f6p+0, which rounds to 0x1.6147ae147ae15p+0. The closest double to 1.38 is 0x1.6147ae147ae14p+0.
There are several reasons why two slightly different doubles do not compare ==. Here are two:
If they did so, that would break transitivity. (There would be a, b, and c such that a == b and b == c but !(a == c).
If they did so, carefully-written numerical code would stop working.
The real issue with trying to find a double in a list is that NaN does not compare == to itself. You may try using a loop that checks needle == haystack[i] || needle != needle && haystack[i] != haystack[i].

Construct a model of an electric circuit in java

I was recently in a job interview for a position as Java Developer. I was given a task: To think about a good way to represent an electric circuit (such as the one in the figure below) in Java.
A circuit is a combination of logic gates XOR, AND, OR etc.. Each gate has two input ports and an output port. Each output is connected to an input of another gate, which goes all the way to a higher gate (as in the picture). Make the system simple, no cycles are allowed (although real life circuits can have them).
I was asked to think about a good way to represent this model in Java, using the following guidelines:
I am given a circuit and a list of values which should be provided to its inputs.
I need to create a model to represent the circuit in Java, i.e., I need to define classes and an API that could be used to represent the circuit.
According to the input values and how the gates are connected, I need to calculate the output that the represented circuit would produce.
I need to think about a way to represent the board, use abstract classes or interfaces, and show understanding of the model (and if needed to use pattern design).
I chose to design the system as a tree and the interviewer told me it was a good choice. Then I build those classes:
Node
public class gate_node {
gate_node right_c,left_c;
Oprtator op;
int value;
int right_v,left_v;
public gate_node(gate_node right,gate_node left,Oprtator op){
this.left_c=left;
this.right_c=right;
this.op=op;
right_v=left_v=0;
}
}
Tree
public class tree {
gate_node head;
tree(gate_node head) {
this.head = head;
}
void go_right() {
head = head.right_c;
}
void go_left() {
head = head.left_c;
}
static int arr[] = { 0, 0, 1, 0 };
static int counter=0;
static int compute(gate_node head) {
if ((head.left_c == null) && (head.right_c == null))
{
int ret=(head.op.calc(arr[counter], arr[counter+1]));
counter++;
counter++;
return ret;
}
return (head.op.calc(compute(head.left_c), compute(head.right_c)));
}
public static void main(String[] args) {
tree t = new tree(new gate_node(null, null, new and()));
t.head.left_c = new gate_node(null, null, new and());
t.head.right_c = new gate_node(null, null, new or());
System.out.println(tree.compute(t.head));
}
}
Oprtator class:
public abstract class Oprtator {
abstract int calc(int x, int y);
}
OR gate:
public class or extends Oprtator {
public int calc(int x, int y){
return (x|y);
}
}
In the above code, I implemented the board as a tree with its a current head (which can go down to the left/right children). Every node has 2 children (also node type), 2 entries (0/1), a value and an operator (abstract class, could be extended by OR/AND..).
I used a counter and an array to insert the values to the appropriate leafs of the tree (as mentioned in the code).
It works but still I got a feeling that my interviewer wanted something more. Is my code is correct? Does anyone have a better way of represent this electrical board and how to give a good output (in terms of complexity or using better connection from one class to another, design patterns, something else?)
It's not a "perfect" answer, but you can solve this using a few classes to hold the logical connection/evaluation and then recursively evaluate the circuit.
Create a base class LogicalNode and give it a list of inputs to manage. Give it a base class function to evaluate all the inputs and return an output. This gets overridden in derived classes. Each type of node (INPUT, NOT, AND, OR) gets a derived class with a special "ComputOutput" overridden version. If you compute the output at the output node, it should recurse up the tree, computing all inputs of inputs of inputs, etc., till it reaches the "INPUT" nodes, which are fixed/logical inputs to the system.
You can create new types fairly quickly (see code). Not a lot of comments here, but it should be somewhat self explanatory.
Something like this (in C#):
public class LogicalNode
{
private List<LogicalNode> _inputs = new List<LogicalNode>();
private String _name = "Not Set";
public override string ToString()
{
return String.Format("Node {0}", _name);
}
public void Reset()
{
_inputs.Clear();
}
public void SetName(String name)
{
_name = name;
}
protected List<LogicalNode> GetInputs()
{
return _inputs;
}
public void AddInput(LogicalNode node)
{
_inputs.Add(node);
}
protected virtual bool ComputeOutputInternal()
{
return false;
}
public bool ComputeOutput()
{
// Console.WriteLine("Computing output on {0}.", _name);
return ComputeOutputInternal();
}
}
public class LogicalInput : LogicalNode
{
private bool _state = true;
public void SetState(bool state)
{
_state = state;
}
public bool GetState() { return _state; }
protected override bool ComputeOutputInternal()
{
return _state;
}
}
public class LogicalAND : LogicalNode
{
protected override bool ComputeOutputInternal()
{
List<LogicalNode> inputs = GetInputs();
bool result = true;
for (Int32 idx = 0; idx < inputs.Count && result; idx++)
{
result = result && inputs[idx].ComputeOutput();
}
return result;
}
}
public class LogicalOR : LogicalNode
{
protected override bool ComputeOutputInternal()
{
List<LogicalNode> inputs = GetInputs();
bool result = false;
for (Int32 idx = 0; idx < inputs.Count; idx++)
{
result = inputs[idx].ComputeOutput();
if (result)
// If we get one true, that is enough.
break;
}
return result;
}
}
public class LogicalNOT : LogicalNode
{
protected override bool ComputeOutputInternal()
{
List<LogicalNode> inputs = GetInputs();
if (inputs.Count > 0)
{ // NOTE: This is not an optimal design for
// handling distinct different kinds of circuits.
//
// It it demonstrative only!!!!
return !inputs[0].ComputeOutput();
}
return false;
}
And then to (quickly) test it:
static void Main(string[] args)
{
// The test circuit
// !((A&&B) || C)
// A B C Out
// 1 1 1 0
// 1 1 0 0
// 1 0 1 0
// 1 0 0 1
// 0 1 1 0
// 0 1 0 1
// 0 0 1 0
// 0 0 0 1
//
//
//
/* ------- -------
* A - | | | |
* | AND |-----| | -------
* B - | (D) | | | | |
* ------- | OR |----| NOT |----
* | (E) | | (F) |
* C --------------| | | |
* ------- -------
*/
LogicalInput A = new LogicalInput();
LogicalInput B = new LogicalInput();
LogicalInput C = new LogicalInput();
LogicalAND D = new LogicalAND();
LogicalOR E = new LogicalOR();
LogicalNOT F = new LogicalNOT();
A.SetName("A");
B.SetName("B");
C.SetName("C");
D.SetName("D");
E.SetName("E");
F.SetName("F");
D.AddInput(A);
D.AddInput(B);
E.AddInput(D);
E.AddInput(C);
F.AddInput(E);
// Truth Table
bool[] states = new bool[]{ true, false };
for(int idxA = 0; idxA < 2; idxA++)
{
for(int idxB = 0; idxB < 2; idxB++)
{
for(int idxC = 0; idxC < 2; idxC++)
{
A.SetState(states[idxA]);
B.SetState(states[idxB]);
C.SetState(states[idxC]);
bool result = F.ComputeOutput();
Console.WriteLine("A = {0}, B = {1}, C = {2}, Output = {3}",
A.GetState(), B.GetState(), C.GetState(), result.ToString());
}
}
}
}
}
With output:
A = True, B = True, C = True, Output = False
A = True, B = True, C = False, Output = False
A = True, B = False, C = True, Output = False
A = True, B = False, C = False, Output = True
A = False, B = True, C = True, Output = False
A = False, B = True, C = False, Output = True
A = False, B = False, C = True, Output = False
A = False, B = False, C = False, Output = True
Was this helpful?
While I obviously can't say exactly what the interviewer was looking for, if I were interviewing you I would probably press you to make your compute method a non-static member of your gate_node class. This way, your networks do not have to be "balanced" (they can be deeper, have more inputs) on one side or the other.
Put another way, looking at your compute code, I do not believe it would work for general circuits.
Perhaps something like the following (in gate_node):
int compute() {
/* The following use of a static sInputCounter assumes that the static/global
* input array is ordered from left to right, irrespective of "depth". */
final int left = (null != left_c ? left_c.compute() : sInput[sInputCounter++]);
final int right = (null != right_c ? right_c.compute() : sInput[sInputCounter++]);
return op.calc(left, right);
}
This way, the "tree" can just be represented by the head/root gate_node (although you still probably want a class like your tree class -- I might call it "network" just to avoid confusion, with static methods for constructing the tree, setting up the inputs, etc.) and you trigger the network evaluation by calling head.compute().
Of course, you are still left with the non-trivial problem of constructing a network from some external specification. I imagine that another issue for the interviewer could have been that this aspect was not well-specified in your solution. (Nor in mine here either, I'm sorry.)

Categories

Resources