Truth table: Difference between revisions

Content added Content deleted
(→‎{{header|Java}}: Fixed indentation)
Line 1,317: Line 1,317:


public class TruthTable {
public class TruthTable {
public static void main( final String... args ) {
public static void main( final String... args ) {
System.out.println( new TruthTable( args ) );
System.out.println( new TruthTable( args ) );
}
}


private interface Operator {
private interface Operator {
boolean evaluate( Stack<Boolean> s );
boolean evaluate( Stack<Boolean> s );
}
}


/**
/**
* Supported operators and what they do. For more ops, add entries here.
* Supported operators and what they do. For more ops, add entries here.
*/
*/
private static final Map<String,Operator> operators = new HashMap<String,Operator>() {{
private static final Map<String,Operator> operators = new HashMap<String,Operator>() {{
// Can't use && or || because shortcut evaluation may mean the stack is not popped enough
// Can't use && or || because shortcut evaluation may mean the stack is not popped enough
put( "&", stack -> Boolean.logicalAnd( stack.pop(), stack.pop() ) );
put( "&", stack -> Boolean.logicalAnd( stack.pop(), stack.pop() ) );
put( "|", stack -> Boolean.logicalOr( stack.pop(), stack.pop() ) );
put( "|", stack -> Boolean.logicalOr( stack.pop(), stack.pop() ) );
put( "!", stack -> ! stack.pop() );
put( "!", stack -> ! stack.pop() );
put( "^", stack -> ! stack.pop().equals ( stack.pop() ) );
put( "^", stack -> ! stack.pop().equals ( stack.pop() ) );
}};
}};


private final List<String> variables;
private final List<String> variables;
private final String[] symbols;
private final String[] symbols;


/**
/**
* Constructs a truth table for the symbols in an expression.
* Constructs a truth table for the symbols in an expression.
*/
*/
public TruthTable( final String... symbols ) {
public TruthTable( final String... symbols ) {
final Set<String> variables = new LinkedHashSet<>();
final Set<String> variables = new LinkedHashSet<>();


for ( final String symbol : symbols ) {
for ( final String symbol : symbols ) {
if ( ! operators.containsKey( symbol ) ) {
if ( ! operators.containsKey( symbol ) ) {
variables.add( symbol );
variables.add( symbol );
}
}
}
}
this.variables = new ArrayList<>( variables );
this.variables = new ArrayList<>( variables );
this.symbols = symbols;
this.symbols = symbols;
}
}


@Override
@Override
public String toString () {
public String toString () {
final StringBuilder result = new StringBuilder();
final StringBuilder result = new StringBuilder();


for ( final String variable : variables ) {
for ( final String variable : variables ) {
result.append( variable ).append( ' ' );
result.append( variable ).append( ' ' );
}
}
result.append( ' ' );
result.append( ' ' );
for ( final String symbol : symbols ) {
for ( final String symbol : symbols ) {
result.append( symbol ).append ( ' ' );
result.append( symbol ).append ( ' ' );
}
}
result.append( '\n' );
result.append( '\n' );
for ( final List<Boolean> values : enumerate( variables.size () ) ) {
for ( final List<Boolean> values : enumerate( variables.size () ) ) {
final Iterator<String> i = variables.iterator();
final Iterator<String> i = variables.iterator();


for ( final Boolean value : values ) {
for ( final Boolean value : values ) {
result.append(
result.append(
String.format(
String.format(
"%-" + i.next().length() + "c ",
"%-" + i.next().length() + "c ",
value ? 'T' : 'F'
value ? 'T' : 'F'
)
)
);
);
}
}
result.append( ' ' )
result.append( ' ' )
.append( evaluate( values ) ? 'T' : 'F' )
.append( evaluate( values ) ? 'T' : 'F' )
.append( '\n' );
.append( '\n' );
}
}


return result.toString ();
return result.toString ();
}
}


/**
/**
* Recursively generates T/F values
* Recursively generates T/F values
*/
*/
private static List<List<Boolean>> enumerate( final int size ) {
private static List<List<Boolean>> enumerate( final int size ) {
if ( 1 == size )
if ( 1 == size )
return new ArrayList<List<Boolean>>() {{
return new ArrayList<List<Boolean>>() {{
add( new ArrayList<Boolean>() {{ add(false); }} );
add( new ArrayList<Boolean>() {{ add(false); }} );
add( new ArrayList<Boolean>() {{ add(true); }} );
add( new ArrayList<Boolean>() {{ add(true); }} );
}};
}};


return new ArrayList<List<Boolean>>() {{
return new ArrayList<List<Boolean>>() {{
for ( final List<Boolean> head : enumerate( size - 1 ) ) {
for ( final List<Boolean> head : enumerate( size - 1 ) ) {
add( new ArrayList<Boolean>( head ) {{ add(false); }} );
add( new ArrayList<Boolean>( head ) {{ add(false); }} );
add( new ArrayList<Boolean>( head ) {{ add(true); }} );
add( new ArrayList<Boolean>( head ) {{ add(true); }} );
}
}
}};
}};
}
}


/**
/**
* Evaluates the expression for a set of values.
* Evaluates the expression for a set of values.
*/
*/
private boolean evaluate( final List<Boolean> enumeration ) {
private boolean evaluate( final List<Boolean> enumeration ) {
final Iterator<Boolean> i = enumeration.iterator();
final Iterator<Boolean> i = enumeration.iterator();
final Map<String,Boolean> values = new HashMap<>();
final Map<String,Boolean> values = new HashMap<>();
final Stack<Boolean> stack = new Stack<>();
final Stack<Boolean> stack = new Stack<>();


variables.forEach ( v -> values.put( v, i.next() ) );
variables.forEach ( v -> values.put( v, i.next() ) );
for ( final String symbol : symbols ) {
for ( final String symbol : symbols ) {
final Operator op = operators.get ( symbol );
final Operator op = operators.get ( symbol );


// Reverse Polish notation makes this bit easy
// Reverse Polish notation makes this bit easy
stack.push(
stack.push(
null == op
null == op
? values.get ( symbol )
? values.get ( symbol )
: op.evaluate ( stack )
: op.evaluate ( stack )
);
);
}
}
return stack.pop();
return stack.pop();
}
}
}</lang>
}</lang>
{{out}}
{{out}}