« Hey niño, quieres un trabajo? en google? | Main | Recordando »

Cómo se resuelve el problema del post anterior.

Me da gusto que no haya sido necesario usar fuerza bruta computacional para resolver el problema anterior. En realidad no me gusta esperar hasta 3 días, como por ejemplo para obtener un password.

Si quieren saber cómo se resuelve, continuén leyendo.

Para empezar entendí mal el problema. Yo entendí el primer número primo de 10 dígitos encontrado en el número e, osea el más pequeño, no el primero en aparecer. De ser así, la respuesta sería 1,000,000,007; el primer número primo de 10 dígitos que eventualmente tendría que aparecer en e ya que es un número infinito (la demostración matemática de ello no la he hecho, pero sólo hace falta demostrar que los dígitos en e se distribuyen como ruido).

El primer paso fue conseguir el número e (para no gastar valioso cpu time calculándolo). Ahora necesitamos todos los dígitos, en grupos de 10 para facilitar su manejo.

Ahora debemos encontrar los primos en estos números. Debemos probar los factores hasta el 99,999 (raiz cuadrada entera de 10 000 000 000, podríamos usar 100 000, pero lo podemos descartar por no ser primo). La razón para elegir este número es que según el teorema fundamental de la aritmética cualquier número se puede descomponer como una multiplicación de números primos. Ahora suponemos que los 2 números más grandes son a y b y que a>=b. Lo más grande que puede ser b (o lo más pequeño que puede ser a) es cuando a=b en este caso los factores más grandes son la raiz cuadrada. No puede haber un número múltiplo de a más grande que divida x, puesto que llevaría otro factor primo más pequeño, y si fuera más grande no se cumpliría a>=b. También la demostración se deja de ejercicio para el lector.

Como 100,000 es un número relativamente pequeño, obtenemos todos los primos por medio de la criba de eratóstenes. El código aquí:

public class primos
{
 public static void main(String[]  args)
 {
  primos e= new primos();
  e.init();
 }
 public void init()
 {
  boolean criba[] = new boolean[100000];
  for(int i=0; i<100000; i++)
   criba[i]=true;
  for(int i=2; i<317; i++)
   for(int j=i*2;j<100000;j=j+i)
    criba[j]=false;
  for(int i=0; i<100000; i++)
   if(criba[i])
    System.out.println(i);
 }
}
Ahora procesamos un poco nuestra lista de números. Retiramos los números menores a 1,000,000,000 por tener menos de 10 dígitos con el siguiente código. También aprovecho para retirar los pares y ahorrarme una pasada en el siguiente paso.
   BufferedReader archivo=new BufferedReader(new FileReader("elist.txt"));

   long j=0;  

   while(archivo.ready())
   {
    j=Long.parseLong(archivo.readLine());
    if(j>1000000000&&j%2==1)
     System.out.println(j);
   }

El siguiente código prueba todos los primos menores a 100,000 sobre los números de 10 dígitos en e y borra todos los múltiplos de los números del primer conjunto que encuentre. Como resultado tenemos todos los primos de 10 dígitos que se encuentran en el primer millón de dígitos de e

import java.util.*;

import java.io.*;

public class primos10
{
 public static void main(String[]  args)
 {
  primos10 e= new primos10();
  e.init();
 }
 public void init()
 {
  TreeSet a=new TreeSet(),b=new TreeSet();
  BufferedReader archivo;
  try
  {
   archivo=new BufferedReader(new FileReader("primos.txt"));
   while (archivo.ready())
   {
    a.add(new Long(archivo.readLine()));
   }
   System.err.println("Primos cargados");
   archivo=new BufferedReader(new FileReader("less"));
   while (archivo.ready())
   {
    b.add(new Long(archivo.readLine()));
   }
   System.err.println("Numeros e cargados");
  }
  catch(Exception e){}
  Iterator ita=a.iterator(),itb;
  while(ita.hasNext())
  {
   long t=((Long)ita.next()).longValue();
   itb=b.iterator();
   System.err.println("probando con "+t);
   while(itb.hasNext())
   {
    if(((Long)itb.next()).longValue()%t==0)
     itb.remove();
   }
  }
  itb=b.iterator();
  while(itb.hasNext())
   System.out.println(itb.next());
 }
}

El problema que tenemos ahora es que el resultado está ordenado (la parte donde entendí mal el problema). Ahora lo que nos interesa es la primera ocurrencia de uno de estos números primos en e, para eso el siguiente código:

import java.util.*;

import java.io.*;

public class correccion
{
 public static void main(String[]  args)
 {
  correccion e= new correccion();
  e.init();
 }
 public void init()
 {
  TreeSet a=new TreeSet();
  BufferedReader archivo;
 try
{
   /*
    Cargamos la lista de primos de 10 dígitos encontrados en 'e' calculados previamente
   */
   archivo=new BufferedReader(new FileReader("less"));
   while (archivo.ready())
   {
    a.add(new Long(archivo.readLine()));
   }
   archivo=new BufferedReader(new FileReader("list.txt"));
   Long t;
   while (archivo.ready())
   {
    t=new Long(archivo.readLine());
    /*Comparamos contra el número 'e' completo para encontrar la primera ocurrencia de un número primo*/
    if(a.contains(t))
    {  
     System.out.println(t);
     break;
    }
   }
} catch (Exception e){}
  }
}

Así obtenemos el URL que buscábamos. Ahora nos encontramos con el siguiente problema:

f(1)= 7182818284
f(2)= 8182845904
f(3)= 8747135266
f(4)= 7427466391
f(5)= __________

Al principio no encontré ninguna relación entre los números, Todos se encuentran en e, pero sólo el 4o es primo (además de ser el URL), por lo que pensé que la función era en realidad de los índices en e. Así, estos sería 2,6,24 y 100. Tampoco encontré una función o una serie que produjera estos números y que para f(5) diera un índice válido. Gracias a un foro que luis me pasó vi que en realidad todos los dígitos en los números sumaban 49. Así que sólo había que encontrar el siguiente índice que tenga un número cuyos dígitos sumen 49, en este caso 128. El número es 5966290435. Todo eso para que nos llevaran a un simple anuncio de empleos en GOOGLE.

Creative Commons License
Nada más la Puntita by Dan Alonso is licensed under a Creative Commons Reconocimiento-Compartir bajo la misma licencia 2.5 México License.
Permissions beyond the scope of this license may be available at http://dan-alonso.org/trabajos-derivados.

Post a comment