Skip to Content

No te olvides de visitar:

Programación

Programación

Reto PHP II: Test de Primalidad

Encaramos la llegada de los primeros fríos invernales con un nuevo reto PHP, está vez se trata de obtener un algoritmo que nos diga (con 100% de seguridad, nada de probabilidades) si un número (sea cual sea el tamaño) es primo o no.

El reto consiste en crear una función a la que pasamos una cadena con un número, y nos devuelve true (en caso que sea primo) o false (en caso que no sea primo). Tened en cuenta que el número que le pasemos puede tener cualquier tamaño, así que ya podéis echar mano de las librerías que hay en php para manejo de grandes números.

En esta ocasión ganará el algoritmo que devuelva el resultado correcto en el menor tiempo posible (la batería de pruebas cubrirá números pequeños, grandes, etc...).

  • Fecha Límite: 1 de Diciembre

Suerte y al lío.

PD: No se pueden utilizar funciones que hagan el trabajo por nosotros, como por ejemplo "gmp_prob_prime" o "gmp_nextprime".

Resultados del Reto PHP I

Hola a todos, compañeros y amigos....después de un mes de intriga e incertidumbre, aquí llegamos con los resultados del 1º Reto PHP del Rincón de Tolito.

La participación ha sido bastante más alta de lo esperado...como podéis ver en los comentarios del reto (además de los que me lo habéis enviado al correo). Así que sin más preámbulos vamos a por los resultados.

PREMIO A LA BREVEDAD

Para Víctor con 63 caracteres:

function reto($n){for($i=$n;$i;$i--)($n%$i)||$a[]=$i;return$a;}

PREMIO A LA VELOCIDAD

Para Guti (al que quiero felicitar desde aquí por su blog, y por el algoritmo) con este algoritmo:

function reto($piNumero)
{
  $aRes=array($piNumero);
  for ($iDivisor=$piNumero>>1; $iDivisor>0; $iDivisor--)
  {
    if (!($piNumero % $iDivisor))
    {
      array_push($aRes, $iDivisor);
    }
  }
  return($aRes);
}

VERSIÓN PROPIA

Yo, aunque no participo en el concurso, he desarrollado un algoritmo que, aunque no es la panacea, si que mejora infinitamente el tiempo de respuesta (en números grandes la mejora es muy notable). Lo que hace es recorrer el bucle for entre 0 y la raíz del número, con lo cual nos ahorramos muchas pasadas por el bucle, aquí os dejo el algoritmo desarrollado:

function reto($x)
{
  $t=ceil(sqrt($x));
  if ($t*$t==$x)
    $d[]=$t;
  for ($n=1;$n<$t;$n++)
  {
    if (!($x%$n))
    {
      $d[]=$n;
      $d[]=$x/$n;        
    }
  }
  return $d;
}

Un saludo a todos

Nota: Guti ha enviado una versión que precalculaba las factorizaciones de todos los números indicados y los guardaba en un archivo (unos 500 Gb(para el rango de enteros de php) calcula él que ocuparía). Yo la verdad no tengo espacio en disco suficiente para probarlo (ni paciencia para generar el archivo que precalcula los datos), pero creo que la búsqueda de un número en un archivo de texto de 500 Gb no debe ser una cosa muy rápida.

Reto PHP I: Obtener los divisores de un número

Hoy desde "El Rincón de Tolito" inauguramos una nueva sección: "RETOS PHP", la idea es la siguiente: yo(podéis enviarme ideas para nuevos retos) propongo desde aquí un reto con sus condiciones, y vosotros vais enviándome vuestras soluciones en forma de comentario del post (los comentarios están moderados, y por tanto no aparecerán publicados hasta el final del concurso), o por correo electrónico (tolito(arroba)gmail(dot)com). Una vez terminado el plazo publicaré los códigos ganadores, así como sus autores. Así que vamos al lío con el primer reto:

RETO PHP I

Enunciado: Desarrollar una función llamada "reto" a la cual la pasemos un número (integer) y nos devuelva un array (divisor[0]=x....divisor[n]=y) con todos los divisores de dicho número, incluyendo el 1 y el propio número.

Códigos Ganadores: Hay 2 premios:

  • Código veloz: Después de una batería de pruebas(serán las mismas para todos) se verá cual es el código más rápido de todos los participantes.
  • Código breve: Este premio se lo llevará el código que menos ocupe, así que a abreviar...

Condiciones:

  • Las pruebas se llevarán a cabo en un servidor Ubuntu con Apache y PHP 5.2.5.
  • Cada usuario puede enviar 2 programas, así puede optar a los 2 premios a la vez, ya que es complicado que el mismo código gane los 2 premios, aunque nunca se sabe...
  • El envío debe incluir el nick del autor, una dirección de correo electrónico (no se hará publica para evitar spameos), y el código de la función.
  • Fecha límite para el envío de respuestas: 30 de Septiembre del 2009
  • El código que no funcione, o que de errores no será considerado valido. Puede dar warnings o notice siempre que funcione correctamente

¡Animo a todos y a optimizar código!

Actualización [28 Agosto 2009 - 14:41]: Ya hemos recibido los primeros programas...

Actualización [01 Septiembre 2009 - 10:50]: Siguen llegando programas, pero todos son para el premio de brevedad...a ver si alguien se anima a optimizar el código para mejorar su rendimiento.

Actualización [02 Septiembre 2009 -19:21]: En el premio a la brevedad solo se tendrá en cuenta la función, no os preocupeis de etiquetas php y demás historias...

Script PHP para obtener los enlaces de una página Web

Categoría:

Vamos a ver como gracias a la "DOM Extension" de PHP podemos extraer todos los enlaces de una página web con un sencillo script PHP, sin necesidad de complicarnos con expresiones regulares.

Aquí os dejo un ejemplo muy sencillo comentado para que veáis como funciona:

<?php
  //Decimos a libxml que no muestre errores
  $original_config = libxml_use_internal_errors(true);
  libxml_clear_errors();

  //Cargamos el archivo html
  $html = new DOMDocument();
  $html->loadHtmlFile('http://www.chungarratadas.com');

  //Usamos DOMXPath para buscar los enlaces (/a)
  $xpath = new DOMXPath($html); 
  $enlaces = $xpath->query('//a'); 

  //Recorremos todos los enlaces encontrados y mostramos la url(href)
  foreach ($enlaces as $enlace) 
  { 
    echo $enlace->getAttribute('href')."<br/>";
  } 

  //Devolvemos a su estado original el reporte de errores de libxml
  libxml_clear_errors(); 
  libxml_use_internal_errors($original_config); 

?>

Un saludo a todos!

Los 10 principios generales del diseño de interfaces de usuario

Categoría:

Hoy estaba leyendo unos documentos sobre usabilidad y me he encontrado con "Los 10 principios generales del diseño de interfaces de usuario" de Jakob Nielsen (una eminencia en el mundo de la usabilidad web). Me parece que es algo que todo desarrollador/diseñador debe tener en cuenta, aquí tenéis la lista:

  • Visibilidad del estado del sistema: el sistema siempre debería mantener informados a los usuarios de lo que está ocurriendo, a través de retroalimentación apropiada dentro de un tiempo razonable.
  • Relación entre el sistema y el mundo real: el sistema debería hablar el lenguaje de los usuarios mediante palabras, frases y conceptos que sean familiares al usuario, más que con términos relacionados con el sistema. Seguir las convenciones del mundo real, haciendo que la información aparezca en un orden natural y lógico.
  • Control y libertad del usuario: hay ocasiones en que los usuarios elegirán las funciones del sistema por error y necesitarán una “salida de emergencia” claramente marcada para dejar el estado no deseado al que accedieron, sin tener que pasar por una serie de pasos. Se deben apoyar las funciones de deshacer y rehacer.
  • Consistencia y estándares: los usuarios no deberían cuestionarse si acciones, situaciones o palabras diferentes significan en realidad la misma cosa; siga las convenciones establecidas.
  • Prevención de errores: mucho mejor que un buen diseño de mensajes de error es realizar un diseño cuidadoso que prevenga la ocurrencia de problemas.
  • Reconocimiento antes que recuerdo: se deben hacer visibles los objetos, acciones y opciones, El usuario no tendría que recordar la información que se le da en una parte del proceso, para seguir adelante. Las instrucciones para el uso del sistema deben estar a la vista o ser fácilmente recuperables cuando sea necesario.
  • Flexibilidad y eficiencia de uso: la presencia de aceleradores, que no son vistos por los usuarios novatos, puede ofrecer una interacción más rápida a los usuarios expertos que la que el sistema puede proveer a los usuarios de todo tipo. Se debe permitir que los usuarios adapte el sistema para usos frecuentes.
  • Estética y diseño minimalista: los diálogos no deben contener información que es irrelevante o poco usada. Cada unidad extra de información en un diálogo, compite con las unidades de información relevante y disminuye su visibilidad relativa.
  • Ayudar a los usuarios a reconocer, diagnosticar y recuperarse de errores: los mensajes de error se deben entregar en un lenguaje claro y simple, indicando en forma precisa el problema y sugerir una solución constructiva al problema.
  • Ayuda y documentación: incluso en los casos en que el sistema pueda ser usado sin documentación, podría ser necesario ofrecer ayuda y documentación. Dicha información debería ser fácil de buscar, estar enfocada en las tareas del usuario, con una lista concreta de pasos a desarrollar y no ser demasiado extensa.

Un saludo!

Pseint, completo IDE de pseudocódigo

Categoría:

Como todos ustedes sabrán, queridos lectores/programadores, el pseudocódigo es un lenguaje intermedio entre el lenguaje natural y los lenguajes de programación. Es utilizado para:

    • Aprender a programar
    • Ver como responde un algoritmo antes de codificarlo en nuestro lenguaje de programación

Aquí tenéis un pequeño ejemplo de un programa en pseudocódigo que calcula el modulo (el resto de la división):

  Proceso Modulo
	 Escribir "Ingrese el numero: ";
	 Leer N;
	 Escribir "Ingrese el divisor: ";
	 Leer M;
	 Si N mod M = 0 Entonces
	 	Escribir M," es divisor exacto de ",N,".";
	 Sino
	 	Escribir "El resto de dividir ",N," por ",M," es: ",N mod M;
	 FinSi
  FinProceso

Para probar nuestros programas en psuedocódigo podemos utilizar una magnifica herramienta que me recomendo mi ex-profesor y amigo Ismael: PseInt. PseInt cuenta con un completo IDE para probar nuestro pseudocódigo paso a paso, viendo donde falla, en donde podemos mejorar nuestros algoritmos, etc...

Además de todo eso, tiene una utilidad que nos puede generar(y exportar a jpg) el diagrama de flujo de nuestro algoritmo (muy útil a la hora de documentar nuestras aplicaciones). Los programadores de C/C++ están de enhorabuena por que PseInt nos da la posibilidad de exportar nuestro psuedocódigo a lenguaje C/C++, ¿alguien da más? Pues lo mejor de todo es que todo esto es Open source y gratuito...Os podéis descargar PseInt en:

Un saludo y a pseudocodigear que es gerundio...o no...o yo que se...:P

Piet, lenguaje de programación gráfico y raro...

Categoría:

Buscando buscando me he encontrado con esta joya de lengauje de programación llamado Piet. Se trata de un lenguaje de programación bastante peculiar basado en imágenes abstractas; como ejemplo aquí tenéis esta galería con ejemplos de programas en Piet.

Este curioso lenguaje de programación toma el nombre del pintor Piet Mondrian, autor de "Composición en Rojo, Amarillo y Azul". El lenguaje esta basado en cuadros de distintos colores, que combinan de unas maneras muy bonitas...o no. Aquí podéis ver un ejemplo de "Hola Mundo" en Piet:

Hola Mundo

Si queréis probar a hacer algo con este lenguaje tan esotérico, han creado un IDE Online en Javascript en el que podéis probar vuestras habilidades informático-pictóricas.

Un saludo a todos!

Python 3000 aka Py3k aka Python 3.0

Categoría:

Python es un lenguaje de programación que ya tiene sus añitos (desde 1994 que apareció la 1.0 ya ha llovido). Después de tantos años Guido van Rossum, su creador, ha intentado dar un giro de 180 grados al lenguaje para convertir Python 3.0 en un lenguaje de programación "serio" (no quiero decir con ello que no lo fuera, pero tenía algunas cosas que no cuadraban muy bien).

La versión final de Python 3.0 será liberado a finales de este mes (Octubre del 2008), de momento están siendo lanzadas una serie de RC para rematar la fase de pruebas. Uno de los puntos más polemicos de esta nueva versión es que el código creado para Python 3.0 no será compatible con el código de versiones anteriores de Python...pero no hay que preocuparse, ya que este problema queda medio-solucionado gracias a 2to3, una herramienta de la factoría Guido para traducir código Python 2.x a Python 3000.

La cantidad de novedades en la nueva versión es interminable, quizás las más destacables sean las siguientes:

    • print pasa de ser una expresión a ser una función de una libreria.
    • Todas las cadenas de caracteres utilizarán Unicode.
    • Cuantiosas mejoras en la programación de hebras(threads) y procesos, gracias a la libreria multiprocessing.
    • Range devolverá un interador en lugar de una lista.
    • Los decoradores pueden aplicarse a las clases (antes solo se podían aplicar a funciones o a métodos de clases).
    • Etc...

Si quereis ver el resto de novedades podeís echar un vistazo a este artículo, o bien revisar el changelog de Python 3000.

Veremos si Python 3.0 es todo lo que promete...o si nos quedamos con el 2.x

Curioso programita en C

Categoría:

Aquí dejo este pequeño, a la par que curioso programita en C:

    #include <stdio.h>
    #include <math.h>
    main()
    {
       int i=5;
       for(;i;)
          printf("%c\n",(int)(81+7.3*sin(i---5.75)));
    }

Los que quieran ver que hace ya saben:

    • gcc programa.c -o programa -lm
    • ./programa

Muchas gracias a mi buen amigo Ismael por hacerme llegar esta pequeña perla, y a Marco Foglia que es el creador.

¡Un saludo a todos!

Algoritmo para calcular el día de la semana de una fecha

Categoría:

Hoy vamos a ver un "sencillo algoritmo" (ideado por el maestro Lewis Carroll) para, a partir de una fecha, obtener el día de la semana en que cae esa fecha. Vamos a ver los pasos que tenemos que seguir:

    • Cogemos las 2 últimas cifras del año, y realizamos la siguiente operación (modulo indica el resto de la división y div el cociente):
        • x= ((año mod 100) + ((año mod 100) div 4)) mod 7
    • Asignamos un número al mes según este orden (033614625035, 0 -> Enero, 3 ->Febrero, 3 -> Marzo, etc...). A este numero lo llamaremos y.
    • Cogemos el día del mes tal cual, lo llamaremos z.
    • Ajuste del siglo: según el siglo al que pertenezca cogemos un valor de los siguientes (lo llamaremos t):
        • 1800 -> 2
        • 1900 -> 0
        • 2000 -> 6
        • 2100 -> 4
        • 2200 -> 2
        • 2300 -> 0
    • Sumamos x+y+z+t y obtenemos el resto de la división por 7
        • (y+y+z+t) mod 7
    • El número obtenido indica el día de la semana 0 -> Doming, 1 -> Lunes, 2 -> Martes, etc...

Como veis es bastante sencillo, ahora veremos un ejemplo, el 7 de Julio del 2008:

    • x= (08+ (08 div 4)) mod 7 =3
    • y= Julio -> 6
    • z= 7 (día del mes)
    • t= 6 (ajuste del siglo)
    • Resultado=(3+6+7+6) mod 7=1 -> Lunes

Un saludo a todos!

Distribuir contenido