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;
    }
}

No comments:

Post a Comment