Task: Truth table




Go: package main

import (
    "bufio"
    "errors"
    "fmt"
    "go/ast"
    "go/parser"
    "go/token"
    "os"
    "reflect"
)

func main() {
    in := bufio.NewScanner(os.Stdin)
    for {
        fmt.Print("Expr:  ")
        in.Scan()
        if err := in.Err(); err != nil {
            fmt.Println(err)
            return
        }
        if !tt(in.Text()) {
            return
        }
    }
}

func tt(expr string) bool {
    
    tree, err := parser.ParseExpr(expr)
    if err != nil {
        fmt.Println(err)
        return false
    }
    
    e := &evaluator{nil, map[string]bool{}, tree}
    
    
    ast.Walk(e, tree)
    
    for _, n := range e.names {
        fmt.Printf("%-6s", n)
    }
    fmt.Println(" ", expr)
    
    e.evalVar(0)
    return true
}

type evaluator struct {
    names []string        
    val   map[string]bool 
    tree  ast.Expr        
}



func (e *evaluator) Visit(n ast.Node) ast.Visitor {
    if id, ok := n.(*ast.Ident); ok {
        if !e.val[id.Name] {
            e.names = append(e.names, id.Name)
            e.val[id.Name] = true
        }
    }
    return e
}





func (e *evaluator) evalVar(nx int) bool {
    if nx == len(e.names) {
        
        v, err := evalNode(e.tree, e.val)
        if err != nil {
            fmt.Println(" ", err)
            return false
        }
        
        for _, n := range e.names {
            fmt.Printf("%-6t", e.val[n])
        }
        
        fmt.Println(" ", v)
        return true
    }
    
    for _, v := range []bool{false, true} {
        e.val[e.names[nx]] = v
        if !e.evalVar(nx + 1) {
            return false
        }
    }
    return true
}


func evalNode(nd ast.Node, val map[string]bool) (bool, error) {
    switch n := nd.(type) {
    case *ast.Ident:
        return val[n.Name], nil
    case *ast.BinaryExpr:
        x, err := evalNode(n.X, val)
        if err != nil {
            return false, err
        }
        y, err := evalNode(n.Y, val)
        if err != nil {
            return false, err
        }
        switch n.Op {
        case token.AND:
            return x && y, nil
        case token.OR:
            return x || y, nil
        case token.XOR:
            return x != y, nil
        default:
            return unsup(n.Op)
        }
    case *ast.UnaryExpr:
        x, err := evalNode(n.X, val)
        if err != nil {
            return false, err
        }
        switch n.Op {
        case token.XOR:
            return !x, nil
        default:
            return unsup(n.Op)
        }
    case *ast.ParenExpr:
        return evalNode(n.X, val)
    }
    return unsup(reflect.TypeOf(nd))
}

func unsup(i interface{}) (bool, error) {
    return false, errors.New(fmt.Sprintf("%v unsupported", i))
}


Java: import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

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

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

    
    private static final Map<String,Operator> operators = new HashMap<String,Operator>() {{
        
        put( "&", stack -> Boolean.logicalAnd( stack.pop(), stack.pop() ) );
        put( "|", stack -> Boolean.logicalOr( stack.pop(), stack.pop() ) );
        put( "!", stack -> ! stack.pop() );
        put( "^", stack -> ! stack.pop().equals ( stack.pop() ) );
    }};

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

    
    public TruthTable( final String... symbols ) {
        final Set<String> variables = new LinkedHashSet<>();

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

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

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

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

        return result.toString ();
    }

    
    private static List<List<Boolean>> enumerate( final int size ) {
        if ( 1 == size )
            return new ArrayList<List<Boolean>>() {{
                add( new ArrayList<Boolean>() {{ add(false); }} );
                add( new ArrayList<Boolean>() {{ add(true);  }} );
            }};

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

    
    private boolean evaluate( final List<Boolean> enumeration ) {
        final Iterator<Boolean>   i      = enumeration.iterator();
        final Map<String,Boolean> values = new HashMap<>();
        final Stack<Boolean>      stack  = new Stack<>();

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

            
            stack.push(
                null == op
                    ? values.get ( symbol )
                    : op.evaluate ( stack )
            );
        }
        return stack.pop();
    }
}