Challenge 2: TLang

_________________________________________________________________________
We use a variety of languages and technologies here at Tuenti. Sometimes we even develop our own languages and tools. Here is an example from a programming language that we use when we want to blow our minds. Your task is to interpret it!

Sample input

^= 1 2$ ^# 2 2$ ^@ 3 1$

Sample output

3 4 2

TEST

^= ^# ^# 297 246$ ^@ 172$$ 168$ 
^@ ^# 212 ^# 186 251$$$ 
^= 56 ^# 104 32$$ 
^# ^= 10 ^# 252 244$$ 196$ 
^= ^@ 17 6$ ^@ 187 262$$ 

_________________________________________________________________________

UserInterface Class:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * Clase encargada de mantener el bucle de ejecución del programa hasta el fin de linea.
 * @author Javier de Pedro López
 */
public class UserInterface {

    /**
     * Permite mantener el bucle de lecutra.
     */
    public void run() throws IOException, InvalidOperationException{
        String line;
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        //Bucle que realiza las lecturas hasta que lo recibido sea EOF (null)
        do{
            line = reader.readLine();
            if  (line != null && !line.trim().equals("")){
                Interpret analize = new Interpret(line);
                System.out.println(analize.interpret());
            }
        } while(line != null);
    }
}

Interpret Class:

import java.math.BigInteger;
import java.util.Stack;
import java.util.StringTokenizer;

/**
 * El objeto de esta clase es realizar la interpretacion de una linea que se le pasa.
 * @author Javier de Pedro López
 */
public class Interpret {

    //CONSTANTES//
    private final String SUMA = "^=";
    private final String RESTA = "^@";
    private final String MULTI = "^#";

    //ATRIBUTOS//
    private Stack _stack;
    private String _line;

    //CONSTRUCTOR//
    /**
     * Innstancia un nuevo interprete.
     * @param line linea que se pretende interpretar.
     */
    public Interpret (String line){
        _line = line;
        _stack = new Stack();
    }

    //METODOS//
    /**
     * Realiza la interpretacion de la cadena a interpretar.
     * @param line linea sobre la que se trata de interpretar.
     * @return el valor correspondiente a la operacion
     * @throws InvalidOperationException error al realizar la operacion.
     */
    public BigInteger interpret () throws InvalidOperationException{
        StringTokenizer tokens = new StringTokenizer(_line," ");
        while (tokens.hasMoreElements()){
            String actualToken = tokens.nextToken();
            int index = actualToken.indexOf("$");
            if (index != -1){
                String number = actualToken.substring(0, index);
                _stack.push(number);
                for (int i = index; i < actualToken.length(); i++){
                    _stack.push("$");
                    updateStack();
                }
            }else{
                _stack.push(actualToken);
            }
        }
        return new BigInteger(_stack.peek());
    }

    /**
     * Actualiza la pila de las operaciones.
     * @throws InvalidOperationException error de operacion no valida.
     */
    private void updateStack() throws InvalidOperationException{
        String number1 = null;
        String number2 = null;
        String op = null;
        //Si en la cima hay un $ entonces realizamos la operacion
        if (_stack.peek().equals("$")){
            _stack.pop();
            number2 = _stack.pop();
            if (!isOperation(_stack.peek())){
                number1 = _stack.pop();
                op = _stack.pop();
                _stack.push(operate(op,number1,number2));
            }else{
                op = _stack.pop();
                _stack.push(operate(op,number2));
            }
        }
    }

    /**
     * Permite saber si un determinado String se corresponde con una operacion
     * @param op string a considerar como operacion.
     * @return true si es una operacion y false si no lo es.
     */
    private boolean isOperation(String op){
        return (op.equals(SUMA) || op.equals(RESTA) || op.equals(MULTI));
    }

    /**
     * Realiza la operacion solicitada.
     * @param op operacion solicitada.
     * @param number1 primer numero de la operacion.
     * @param number2 segundo numero de la operacion.
     * @return el numero correspondiente a la operacion solicitada.
     * @throws InvalidOperationException error de operacion no valida.
     */
    private String operate(String op, String number1, String number2) throws InvalidOperationException{
        BigInteger num1 = new BigInteger(number1);
        BigInteger num2 = new BigInteger(number2);
        if (op.equals(SUMA)){
            return num1.add(num2).toString();
        }else if (op.equals(RESTA)){
            return num1.subtract(num2).toString();
        }else if (op.equals(MULTI)){
            return num1.multiply(num2).toString();
        }else throw new InvalidOperationException("La operacion solicitada esta soportada.");
    }

    /**
     * Realiza la operacion solicitada.
     * @param op operacion solicitada.
     * @param number1 primer numero de la operacion.
     * @return el numero correspondiente a la operacion solicitada.
     * @throws InvalidOperationException error de operacion no valida.
     */
    private String operate(String op, String number1) throws InvalidOperationException{
        BigInteger num1 = new BigInteger(number1);
        if (op.equals(SUMA)){
            return num1.toString();
        }else if (op.equals(RESTA)){
            return num1.negate().toString();
        }else if (op.equals(MULTI)){
            return num1.toString();
        }else throw new InvalidOperationException("La operacion solicitada esta soportada.");
    }
}

InvalidOperationException Class:

/**
 * La operacion que se solicita realizar no esta soportada por el programa.
 * @author Javier de Pedro López
 */
public class InvalidOperationException extends Exception {

    /**
     * Crea una nueva instancia de <code>InvalidOperationException</code>
     * sin un mensaje detallado.
     */
    public InvalidOperationException() {
    }

    /**
     * Crea una nueva instancia de <code>InvalidOperationException</code> con un mensaje
     * detallando el error.
     * @param msg mensaje detallado con el error.
     */
    public InvalidOperationException(String msg) {
        super(msg);
    }
}

2 pensamientos en “Challenge 2: TLang

  1. Comment moved from other entry
    lagunex on junio 20, 2011 en 10:54 pm said: [Edit]
    Es bueno que practiques la orientación a objetos aunque para este tipo de competencias terminas matando una mosca con una escopeta. Si tu finalidad era más practicar programación y OO, está justificado. Te recomendaría intentar aplicar polimorfismo en este problema. Se puede aprovechar bastante como práctica.

    La idea de usar la pila es correcta aunque me parece un poco complicada la implementación. Es cuestión de gustos.

    Otra cosa, tu método operate de un solo String pudo ser

    private String operate(String op, String number1) {
    operate(op, “0″, number1);
    }

    para aprovechar la reusabilidad. Eso sí, aceptando una interpretación de “multiplicar por cero”. Que como igual era algo que dejaron abiertos los organizadores…

    Finalmente, debes darle un repaso a la clase Scanner (la que te recomendaron en el problema 1). Simplifica muchísimo la lectura de datos y sirve tanto de BufferedReader como de StringTokenizer a la vez. Hasta el JDK1.4 leer datos en Java era una pesadilla… y llegó la clase Scanner.

    • Comment moved from other entry
      feantury
      on junio 20, 2011 en 11:26 pm said: [Edit]
      Muy buenas Lagunex.

      La razón por la que he usado java es porque es el lenguaje que más domino. Ten en cuenta que tengo 19 años y todavía estoy en 2º de carrera, así que me queda mucho por aprender. Pero evidentemente, comentarios como el tuyo ayudan a mejorar cada día.

      Muchas gracias por los consejos.
      Un saludo.

$- Leave your comment

Fill in your details below or click an icon to log in:

Logo de WordPress.com

You are commenting using your WordPress.com account. Log Out / Cambiar )

Twitter picture

You are commenting using your Twitter account. Log Out / Cambiar )

Facebook photo

You are commenting using your Facebook account. Log Out / Cambiar )

Connecting to %s