Mostrando las entradas con la etiqueta números vampiros. Mostrar todas las entradas
Mostrando las entradas con la etiqueta números vampiros. Mostrar todas las entradas

jueves, julio 28, 2011

Verificación de Números Vampiros

Con este programa se pretende evaluar si cuatro dígitos recibidos forman un número vampiro:

public class Test1 {
    public static void testVampiro(int d1, int d2, int d3, int d4) {
        // Este método recibe cuatro dígitos y verifica en todas las posibles parejas de números
        // si la multiplicación de dos de ellas es igual a alguno de los números que se generan
        // con los 4 dígitos
        
        int[] v = { d1, d2, d3, d4 } ; // Se crea un vector con los 4 dígitos leídos
        int[] posibles = new int[24] ; // Con 4 dígitos solo se pueden formar 24 posibles valores 
        int   cont     = 0;
        int   a,b,c;
        boolean haySolucion = false;
        
        for(int i=0; i<v.length; i++) {
            for(int j=0; j<v.length; j++) {
                if(v[i]==v[j]) continue;  // No se pueden repetir
                for(int k=0; k<v.length; k++) {
                    if(v[k]==v[i]||v[k]==v[j]) continue;    // No se puede repetir
                    for(int l=0; l<v.length; l++) {
                        if(v[l]==v[i]||v[l]==v[j]|| v[l]==v[k]) continue;   // No se puede repetir
                        posibles[cont++] = v[i]*1000+v[j]*100+v[k]*10+v[l];
                    } // fin for l
                } // fin for k
            } // fin for j
        } // fin for i
        // Para probar los numeros posibles usar esta instrucción:
        // for(int x: posibles) System.out.println(x);
        
        // Para generar las parejas se hace el siguiente ciclo:
        ciclo:
        for(int i=0; i<v.length; i++) {
            for(int j=0; j<v.length; j++) {
                if(v[i]==v[j]) continue;  // No se pueden repetir
                a = v[i]*10 + v[j];       // Se obtiene el primer valor de dos dígitos
                for(int k=0; k<v.length; k++) {
                    if(v[k]==v[i]||v[k]==v[j]) continue;    // No se puede repetir
                    for(int l=0; l<v.length; l++) {
                        if(v[l]==v[i]||v[l]==v[j]|| v[l]==v[k]) continue;   // No se puede repetir
                        b = v[k]*10+v[l];   // Se obtiene el segundo valor de dos digitos
                        c = a*b ;           // Se obtiene la multiplicación de los dos valores
                        // Se verifica si el número generado está entre los posibles resultados
                        // y de ser así se escribe la respuesta y se termina el proceso
                        for(int x: posibles) {
                            if(c==x) {
                                System.out.println("Respuesta encontrada: "+a+" x " +b+" = "+c);
                                haySolucion=true;
                                break ciclo;
                            }  // fin if
                        } // fin for x
                    } // fin for l
                } // fin for k
            } //fin for j
        } // fin for i
        if(!haySolucion) System.out.println("No hay un numero vampiro con los digitos " + d1+", "+d2+", "+d3+" y "+d4);
        
    }
    public static void main(String[] args) {
        testVampiro(1,2,3,4);
        testVampiro(1,3,9,5);
        testVampiro(3,9,1,5);
    }
}

martes, octubre 12, 2010

Mejorando la generación de números vampiros

En la siguiente versión del método generarVampiros, se va a modificar la salida con tres parámetros booleanos que permitirán generar hasta 8 listas diferentes teniendo en cuenta si los factores que se multiplican para formar el número vampiro tienen el mismo número de dígitos (vMitad); si dichos factores son números primos o no (vPrimo); y si tanto los factores como el número generado no tienen dígitos repetidos (vUnico).

De esta manera, la ejecución del método generarVampiros(8, true, true, true) generará solamente números vampiros de 8 dígitos formados por la multiplicación de dos números de 4 dígitos que sean primos y que no contengan dígitos repetidos. En este caso, la respuesta del programa es la siguiente:

10.349.527 = 2.579 x 4.013
10.429.753 = 2.309 x 4.517
17.204.359 = 2.309 x 7.451
18.647.023 = 2.741 x 6.803
54.918.067 = 5.801 x 9.467
64.781.293 = 7.691 x 8.423



public static Vector<String> generarVampiros(int digitos, boolean vMitad, 
                                             boolean vPrimo, boolean vUnico) {
        // vMitad: true para factores del mismo tamaño
        // vPrimo: true para factores primos
        // vUnico: true para factores sin dígitos repetidos
        Vector<Integer> va, vb, vc;
        Vector<String>  respuesta = new Vector<String>();
        long numFinal = (long) Math.pow(10,digitos)-1;    // último vampiro posible
        long numBase  = (long) Math.pow(10,digitos-1);    // primer vampiro posible
        long numMin   = (long) Math.pow(10,digitos/2-1);  // menor factor tamaño n/2
        long numMax   = (long) Math.pow(10,digitos/2)-1;  // mayor factor tamaño n/2
        long factorInicialA=0;
        long factorFinalA=0;
        long factorInicialB=0;
        long factorFinalB=0;
        if(vMitad) {
            factorInicialA = numMin;
            factorFinalA   = numMax;
        }
        else {
            factorInicialA = 1;
            factorFinalA   = numFinal;
        }
        for(long a = factorInicialA; a<=factorFinalA; a++) {
            if(vPrimo && !Algoritmos.esPrimoV6(a)) continue;
            va = vectorDigitos(a);
            if(vMitad) {
                factorInicialB=Math.max(a+1,numBase/a);
                factorFinalB=numMax;
            }
            else {
                factorInicialB = Math.max(a+1,numBase/a);
                factorFinalB = numFinal;
            }
            for(long b = factorInicialB; b<=factorFinalB; b++) {
                if(vPrimo && !Algoritmos.esPrimoV6(b)) continue;
                long c = a*b;
                if(c>numFinal) { b=numFinal; continue; }
                if(c<numBase) continue;
                vb = vectorDigitos(b);
                vc = vectorDigitos(c);
                if(vUnico) {
                    Set<Integer> sa = new TreeSet<Integer>();
                    Set<Integer> sc = new TreeSet<Integer>();
                    sa.addAll(va);
                    sa.addAll(vb);
                    sc.addAll(vc);
                    if(sc.size()==digitos && sa.equals(sc)) {
                        respuesta.add(String.format("%,12d = %,6d x %,6d",c, a,b));
                    }
                }
                else {
                    for(int x: va) vb.add(x);
                    Collections.sort(vb);
                    Collections.sort(vc);
                    if(vb.equals(vc)) {
                        respuesta.add(String.format("%,12d = %,6d x %,6d",c, a,b));
                    }
                }
            }
        }
        Collections.sort(respuesta);
        return respuesta;
    }

martes, octubre 05, 2010

Números Vampiros

Los números vampiros son aquellos números con número par de dígitos que son resultado del producto de dos enteros de igual número de dígitos y que tienen como característica que están formados en su totalidad por los dígitos que conforman a sus dos factores.

Por ejemplo, para el caso de los números de 4 dígitos existen 7 números vampiros que se calculan así:

15 x 93 = 1.395
21 x 60 = 1.260
21 x 87 = 1.827
27 x 81 = 2.187
30 x 51 = 1.530
35 x 41 = 1.435
80 x 86 = 6.880

En este programa en JAVA se presenta una aproximación a la generación de números vampiros de 6 dígitos, pero que puede ser fácilmente configurable para generar números vampiros de cualquier tamaño. Para efectos de prueba el programa genera los números en un arreglo de cadenas, solamente por la facilidad de mostrar los factores que lo producen, pero también puede ser modificado para generar solamente los números vampiros en un arreglo o vector de números enteros o enteros grandes:


import java.util.*;

public class Vampiros {
    public static void main(String[] args) {
        Vector<String> respuesta = generarVampiros(6);
        System.out.println(respuesta.size());
        for(String x: respuesta) {
            System.out.println(x);
        }
    }
    public static Vector<String> generarVampiros(int digitos) {
        Vector<Integer> va, vb, vc;
        Vector<String>  respuesta = new Vector<String>();
        int numFinal = (int) Math.pow(10,digitos)-1;
        int numMin   = (int) Math.pow(10,digitos/2-1);
        int numMax   = (int) Math.pow(10,digitos/2)-1;
        for(int a = numMin; a<=numMax; a  ) {
            va = vectorDigitos(a);
            for(int b = a+1; b<=numMax; b  ) {
                int c = a*b;
                if(c>numFinal) { b=numFinal; continue; }
                vb = vectorDigitos(b);
                vc = vectorDigitos(c);
                for(int x: va) vb.add(x);
                Collections.sort(vb);
                Collections.sort(vc);
                if(vb.equals(vc)) {
                    respuesta.add(String.format("%,6d x %,6d = %,8d",a,b,c));
                }
            }
        }
        return respuesta;
    }

    public static Vector<Integer> vectorDigitos(int tmp) {
        int x=tmp;
        Vector<Integer> respuesta = new Vector<Integer>();
        while(x>=1) {
            respuesta.add(x % 10);
            x/=10;
        }
        return respuesta;
    }
}

Multiprocesamiento recursivo en JAVA 7

Una de las estrategias de diseño de algoritmos más comunes es la de "divide y vencerás", en la cual, un problema de tamaño relativ...