Showing posts with label Divide and conquere. Show all posts
Showing posts with label Divide and conquere. Show all posts

Saturday, June 13, 2015

Number to word spanish translator

This is an implementation of a number to word  translator with a divide and conquered approach.
Here are some enumeration y used for the tens, suffix and units:

Enums


package numberTranslator;

import java.util.Arrays;
import java.util.Comparator;


public enum ExSpanishSufix {

 
    ciento("s",2), 
    mil("",3),
    millon("es",6), 
    billon("es",9),
    trillon("es",12),
    quadrillion("es",15);
 
 
    private String plural;
    private int exponent;
    private long value;
 
    private ExSpanishSufix(String plural, int exponent){
  
        this.plural= plural;
        this.exponent=exponent;
        this.value=(long)Math.pow(10, exponent);
  
    } 
 
    public static ExSpanishSufix[] getSorted(){
  
        ExSpanishSufix[] values= ExSpanishSufix.values();
        Arrays.sort(values, 
          Comparator.comparing((ExSpanishSufix hex) -> hex.getExponent()));
  
        return values;
    }
 
    public String isPlural(long number){
  
        return this.name()+(number>1?plural:"");
    }
 
    public int getExponent(){
  
        return exponent;
    }
 
    public long getValue(){
  
        return value;
    }
 
 
}
package numberTranslator;

import java.util.Arrays;
import java.util.Comparator;

public enum SpanishDigits {

    cero(0), uno(1),dos(2),tres(3),cuatro(4),cinco(5),seis(6),siete(7),ocho(8),
    nueve(9), dies(10), once(11), doce(12), trece(13), catorce(14), quince(15);
 
    private int number;
 
    private SpanishDigits(int pnumber){
        number=pnumber;
    }
 
    public static SpanishDigits[] getSorted(){
  
        SpanishDigits[] values= SpanishDigits.values();
        Arrays.sort(values, 
            Comparator.comparing((SpanishDigits hex) -> hex.getNumber()));
        return values;
    }
 
 
    public int getNumber(){
  
        return number;
    }
 
}
package numberTranslator;

import java.util.Arrays;
import java.util.Comparator;

public enum SpanishTens {

    dies(10,"dieci"), veinte(20,"veinti"), treinta(30), cuarenta(40), 
    cincuenta(50), sesenta(60), setenta(70), ochenta(80), 
    noventa(90), cien(100);
 
    private int number;
    private String plural;
 
 
    private SpanishTens(int pnumber, String pplural){
  
        number= pnumber;
        plural=pplural;
  
    }
    private SpanishTens(int pnumber){
  
        this(pnumber,"");
    }
 
    public String isPlural(int pnumber){
  
        if(pnumber>number && plural!="")
            return plural;
  
        return name(); 
    }
 
    public static SpanishTens[] getSorted(){
  
        SpanishTens[] values= SpanishTens.values();
        Arrays.sort(values, 
            Comparator.comparing((SpanishTens des) -> des.getNumber()));
        return values;
    }
 
    public int getNumber(){
  
        return number;
    }
 
}

Interface 


package numberTranslator;

public interface ILangNumber {

    public ILangNumber add(ILangNumber number);
    public ILangNumber multiply(ILangNumber number);
    public ILangNumber divide(ILangNumber number);
    public ILangNumber pow(ILangNumber exponent);
    public long getNumber();
 
}
package numberTranslator;

public abstract class AbstractLangNumber implements ILangNumber {

    private long number;
    private String parseNumber;
 
    public AbstractLangNumber(long number){
   
        this.number=number;
        parseNumber=parseNumber(number);
  
    } 
 
    @Override
    public ILangNumber add(ILangNumber number) {
  
        long add= getNumber()+ number.getNumber(); 
        return createNumber(add);
    }

    @Override
    public ILangNumber multiply(ILangNumber number) {
  
        long mult= getNumber()*number.getNumber();
        return createNumber(mult);
    }

    @Override
    public ILangNumber divide(ILangNumber number) {
  
        long divide= getNumber()/number.getNumber();
        return createNumber(divide);
    }

    @Override
    public ILangNumber pow(ILangNumber exponent) {

        long pow= (long)Math.pow(getNumber(), exponent.getNumber());
        return createNumber(pow);
    }

    @Override
    public long getNumber() {
        return number;
    }
 
 
    abstract protected String parseNumber(long number);
 
    abstract protected ILangNumber createNumber(long number);

    @Override
    public String toString(){
  
        return parseNumber;
    }
}

Implementation 


package numberTranslator;

public class SpanishNumber  extends AbstractLangNumber{


    public static SpanishDigits[] digits= SpanishDigits.getSorted();
    public static SpanishTens[] tens= SpanishTens.getSorted();
    public static ExSpanishSufix[] exponents= ExSpanishSufix.getSorted();
 
    public SpanishNumber(long number) {
        super(number);
    }
 
    @Override
    protected String parseNumber(long number) {
  
        if(number == Long.MIN_VALUE)
            throw new IllegalArgumentException();
  
        StringBuilder sb= new StringBuilder();
        sb.append(getSing(number));
        format(Math.abs(number),sb);  
  
        return especialCases(sb.toString());
    }

    @Override
    protected ILangNumber createNumber(long number) {
        return new SpanishNumber(number);
    }
 

    private void format( long number, StringBuilder sb){

        if(number<=100)
            baseCase((int)number, sb);
        else
        {
    
            ExSpanishSufix suf= findSufix(number);
            long leading= number/suf.getValue();

            if(leading > 1) 
                format(leading, sb);

            sb.append((suf.getExponent() == 2 ? "" : " "))
            .append(suf.isPlural(leading)).append(" ");

            format( number % suf.getValue(), sb);
        }

    }

    private String especialCases(String numero){
        if(numero.isEmpty())
            return "cero";
 
        return numero.replaceAll("cincocientos", "quinientos")
        .replaceAll("nuevecientos", "novecientos")
        .replaceAll("sietecientos", "setecientos");
    }
 
    private void baseCase(int magnitud, StringBuilder sb) {
  
        if(magnitud<16)
            sb.append(magnitud>0?digits[magnitud].name():"");
        else
        {
            sb.append(tens[(magnitud/10)-1].isPlural(magnitud));
            getUnits(magnitud,digits,sb);
        }
    }
 
    private ExSpanishSufix findSufix(long number)
    {
        long expon= nearestPowerOf10(number);
  
        int suf=0;
  
        while(suf<exponents.length-1 && expon>=exponents[suf+1].getExponent())
           ++suf;

        return exponents[suf];
  
    }
 
    private String getSing(long numero){
   
        return numero<0?"menos ":"";
    }
 
    private void getUnits(int numero, SpanishDigits[] digits, StringBuilder sb){

        int residuo=numero%10;

        if(residuo!=0)
        { 
            String divisor= numero>30?" y ":"";
            sb.append(divisor).append(digits[residuo]);
        }
     }
 
    private int nearestPowerOf10(long number){
   
        int n = 0;
        long f[]={10000000000000000L,100000000,10000,100,10};
        for(int i =0, j=16; i<f.length; i++, j/=2)
        { 
            if(number>=f[i])
            { 
                number/=f[i];
                n+=j; 
            }
        }
        return  n;
    }
}