[Python] Espiral de Ulam

Iniciado por engel lex, 19 Enero 2015, 07:15 AM

0 Miembros y 1 Visitante están viendo este tema.

engel lex

Los que me conocen por aquí saben que e gusta jugar con las mates... esta vez le toco el turno a la espiral de Ulam (articulo de la wiki)

me dio curiosidad su representación y quería jugar un poco con gráficos en Python... entonces esto quedó...

primero lo intenté con kivy... a 200 capas consumió 4gb de ram y congeló el pc... entonces decidí probar pygame, mucho más rápido y eficiente para esto...

a 100 capas es rápido... sobre eso vayan con cuidado... tiene una cantidad de segundos marcados para detener el calculo (cuando estaba probando con kivy era eso o mi pc)

lo punedo hacer sin problemas a 500 capas (el tamaño es limitante), pero le calculo es bastante rapido...

el algoritmo de recorrido lo basé en

suponiendo direcciones del 1 al 4 como en el codigo, sigue un patron
1,1,2,2,3,3,3,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,3,0,0,0,0,0...
cada 2 direccionas crece la repetición... "control" maneja esa cantidad de repeticiones, menor maneja que sean 2 direcciones por repeticion, mayor maneja la cantidad de capas en general

ya despues de mucho decir, aquí el código
Código (python) [Seleccionar]
import sys
import pygame
import pygame.gfxdraw
import time
pygame.init()

#globales
tamano = 0 #tamano del punto, 0 = 1px, 1=3px... etc
separacion = 1 #el desplazamiento entre punto y punto, 1px
niveles = 100 #cuantas capas tendra la espiral
tiempo_maximo = 10 #si no termina de dibujar en este tiempo detiene el trabajo... switch de seguridad si tienen un pc poco potente
PRIMO = (255,255,255) #color si es primo
NO_PRIMO = (64,64,64) #color si no es primo
pantalla = {"w":niveles*2+100,"h":niveles*2+100} #tamano de la pantalla... suficiente para puntos de 1px + 100px de margen

window = pygame.display.set_mode((pantalla["w"], pantalla["h"]))




def dibujar():
posicion = {"x":pantalla["w"]/2, "y":pantalla["h"]/2} #cursor en centro de pantalla
direccion = 1 #0 derecha, 1 arriba, 2 izquierda, 3 abajo
control = 2 #variable de control
cantidad = 1 #cantidad de puntos dibujados
dibCir(posicion, PRIMO) #punto central... direccion va por "referencia"

inicio = time.clock() + tiempo_maximo #calcular tiempo para finalizar
for i in range(2):#dibuja los primeros 2 puntos
mover_dibujar(direccion, posicion, separacion, PRIMO)
direccion += 1
cantidad += 1
puntos_totales = (niveles*2 + 1)**2 - 1 #cantidad de puntos a dibujar

detener = False

for mayor in range(niveles*2):
for menor in range(2):
for punto in range(control):
if esPrimo(cantidad): #color a dibujar
mover_dibujar(direccion, posicion, separacion, PRIMO)
else:
mover_dibujar(direccion, posicion, separacion)

if time.clock() > inicio: detener=True #si se pasa del tiempo
if (cantidad == puntos_totales): detener=True #si se dibujaron los puntos necesarios
cantidad +=1
if(detener): break
direccion = (direccion+1)%4 #cambia la direccion del recorrido
if(detener): break
control += 1
if(detener): break
pygame.display.flip() #dibuja la capa calculada
print cantidad #imprime los puntos dibujados en la consola
return 0


def mover_dibujar(direccion, posicion, separacion, color=NO_PRIMO): #dirije el recorrido y dibuja
if direccion == 0: posicion["x"] -= separacion
if direccion == 1: posicion["y"] += separacion
if direccion == 2: posicion["x"] += separacion
if direccion == 3: posicion["y"] -= separacion
dibCir(posicion, color)

def dibCir(posicion, color ,r=tamano):
pygame.gfxdraw.filled_circle(window, posicion["x"],posicion["y"], r, color) #dibuja el circulo
#pygame.gfxdraw.aacircle(window, posicion["x"],posicion["y"], r, color) #lo suaviza mas


def esPrimo(n): #calcula si es primo
  if n <= 3:
      return n >= 2
  if n % 2 == 0 or n % 3 == 0:       return False
  for i in range(5, int(n ** 0.5) + 1, 6):
      if n % i == 0 or n % (i + 2) == 0:
          return False
  return True



dibujar() #ejecuta todo


#input handling (somewhat boilerplate code):

while True:  #copypaste para mentener abierta la ventana
  time.sleep( 1 ) #sin esto se consume todos los recursos
  for event in pygame.event.get():
     if event.type == pygame.QUIT:
         sys.exit(0)
     #else:
     #   print event

El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

Gh057

Gracias por el aporte engel lex, esta noche lo miro con detalle ya que es muy interesante el trabajo de Ulam, y me llamó muchísimo la atención esta implementación en Python. (también soy un apasionado de las matemáticas jajaaa es más, ayer intentaba -sin lograrlo- volver a instalar stream para hacer unas cositas con la gpu amd, y la biblioteca gmp... seguiré otro día en algún rato libre)
4 d0nd3 1r4 3l gh057? l4 r3d 3s 74n v4s74 3 1nf1n1t4...