Cómo codificar una espiral de ulam

En primer lugar, debo agradecer al OP por hacer esta pregunta aquí en Quora. He aprendido mucho en el proceso de escribir este código. Esta es una de las preguntas más difíciles que he respondido aquí en Quora. En realidad, me llevó alrededor de 1 semana codificar este patrón correctamente 😛

La espiral de Ulam es básicamente esto …

Nota: si lo piensa, se dará cuenta de que el número de columnas para obtener este patrón siempre tendrá que ser un Número impar.

Tenga en cuenta que escribí este código en C ++ . Entonces, así es como va mi código …

#include
usando el espacio de nombres estándar;
int main ()
{
int n;
cout << "Ingrese el número de filas (un número impar):";
cin >> n;
int tl [n / 2], k = n, tr [n / 2];
si (n% 2! = 0)
{
para (int i = 0; i <(n + 1) / 2; i ++)
{
tl [i] = k * k-2 * (k-1);
tr [n / 2-i-1] = tl [i] -k;
para (int c = 1; c <i + 1; c ++)
{
int z = tl [c-1];
cout << z + i-c + 1 << "";
}
cout << tl [i] << "";
int p = tl [i] -1;
para (int j = 0; j <n-2 * i-1; j ++)
{
cout << p << "";
pags-;
}
k- = 2;
para (int m = 0; m <i; m ++)
{
cout << tr [n / 2-i + m] << "";
tr [n / 2-i + m] -;
}
cout << endl;
}
int bl [n / 2], br [n / 2], w = n;
para (int i = 0; i <n / 2; i ++)
{
bl [i] = w * w-2 * (w-1) + 2 * (w / 2);
br [n / 2-i-1] = w * w;
w = w-2;
}
para (int i = 0; i <n / 2; i ++)
{
int x = n / 2-1-i;
para (int j = 0; j <n / 2-i; j ++)
{
cout << bl [j] -x << "";
X-;
}
para (int a = 0; a <2 * (i + 1); a ++)
{
bl [n / 2-i-1] ++;
cout << bl [n / 2-i-1] << "";
}
para (int c = 0; c <n / 2-i-1; c ++)
{
int h = br [c + i] + c + 1;
cout << h << "";
}
cout << endl;
}
}
más
{
cout << "Abortado !!! \ nTío, debes ingresar un número impar: P";
}
devuelve 0;
}

Sé muy poco de C ++. No conozco formas o funciones avanzadas para acortar este código. Me disculpo por lo mismo.

Aquí hay algunas fotos de diferentes casos de prueba …

Por cierto, esto es lo que sucederá si intentas ingresar un número par …

Nota importante: Sé que las líneas de mi salida no están alineadas correctamente. En C ++, este problema surge porque podemos tener números que van desde un solo dígito hasta 3 dígitos en la misma línea. No digo que sea imposible hacerlo, pero ocupará más líneas de códigos. Y no estoy de humor para escribir más código para hacer que este programa sea aún más largo 😛

Unnikrishnan Menon y yo comenzamos a trabajar juntos en este desafío, creo que hace unas dos semanas. Quería que usara C / C ++, pero mis habilidades con ese lenguaje son demasiado oxidadas y sabía que un desafío como este requeriría que me mantuviera firme. Así que aquí va …

! Codificado con F90 / F95 en CodeBlocks
programa ulam_spiral
implícito ninguno
entero :: i, j, n, x, y, dimn
entero, asignable :: a (:)
carácter (1), asignable :: espiral (:, 🙂
personaje (2) :: sstr
personaje (10) :: fmt

escribir (*, *) “Ingrese la dimensión (número impar):”
leer (*, *) dimn
if (mod (dimn, 2) == 0) entonces
escribir (*, *) “Se requiere un número impar como entrada”
detener
terminara si

asignar (a (dimn * dimn))
asignar (espiral (dimn, dimn))
do i = 1, dimn * dimn
a (i) = i
fin hacer
espiral (dimn, dimn) = “”

n = 1
x = dimn / 2 + 1
y = x
if (isprime (a (n))) espiral (x, y) = “*”
n = n + 1

do i = 1, dimn-1,2
hacer j = 1, i
x = x + 1
if (isprime (a (n))) espiral (x, y) = “*”
n = n + 1
fin hacer

hacer j = 1, i
y = y-1
if (isprime (a (n))) espiral (x, y) = “*”
n = n + 1
fin hacer

hacer j = 1, i + 1
x = x-1
if (isprime (a (n))) espiral (x, y) = “*”
n = n + 1
fin hacer

hacer j = 1, i + 1
y = y + 1
if (isprime (a (n))) espiral (x, y) = “*”
n = n + 1
fin hacer
fin hacer

do j = 1, dimn-1
x = x + 1
if (isprime (a (n))) espiral (x, y) = “*”
n = n + 1
fin hacer

escribir (sstr, “(i0)”) dimn
fmt = “(” // sstr // “(a, 1x))”
do i = 1, dimn
escribir (*, fmt) espiral (:, i)
fin hacer

contiene

función isprime (número)
Logic :: isprime
entero, intento (in) :: número
entero :: i

si (número == 2) entonces
isprime = .true.
si no (número <2 .o mod. (número, 2) == 0) entonces
isprime = .false.
más
isprime = .true.
do i = 3, int (sqrt (real (número))), 2
if (mod (número, i) == 0) entonces
isprime = .false.
salida
terminara si
fin hacer
terminara si
función final

programa final

Esto también se hace con manos inexpertas. Nada demasiado elegante, pero ingresar un gran valor de [math] n [/ math] nos da una imagen familiar …

Vamos a intentarlo una vez más …

Ahí lo tenemos, claro parecido con la espiral de Ulam.

Por favor ignore los primeros caracteres. Desde que usé la entrada de caracteres, algo salió mal y no he podido solucionarlo hasta ahora. Ha pasado mucho, mucho tiempo desde que codifiqué una solución para un desafío tan grande.

Para una imagen generada más grande, haga clic aquí.

def get_val (t):
(j, i) = t
k = max (abs (i), abs (j))
ref = (2 * k + 1) ** 2
diff = 2 * k
si i == k y j> -k:
retorno ref + (j + k) – 1 * diff
elif j == k:
return ref + (k – i) – 4 * diff
elif i == -k:
retorno ref + (k – j) – 3 * diff
más: # j == -k:
retorno ref + (i + k) – 2 * diff

def is_prime (n):
si n == 1:
falso retorno
k = 2
mientras que (k * k <= n):
si (n% k == 0):
falso retorno
k + = 1
volver verdadero

def apply2D (arr, func):
return [[func (x) para x en fila] para fila en arr]

cruz def (A, B):
devuelve [[(x, y) para x en A] para y en B]

N = 200
eje = rango (-N, N + 1)
índice = cruz (eje, eje)
ulam_init = apply2D (index, get_val)
ulam_bool = apply2D (ulam_init, is_prime)

% matplotlib en línea
mpimg.imsave (‘ulam200.png’, ulam_bool)

Me divertí muchísimo escribiendo un código para eso (hecho en python). Pequeño gran proyecto. Publiqué el código y la explicación aquí: Hacer una espiral de Ulam

A continuación se muestra una espiral para el primer millón de primos.

También puede actualizar el código fácilmente para comenzar desde diferentes números (en lugar de que el número central sea 1)

Puede seguir este enlace para encontrar el código C ++:

CodeRhyno / Ulam-Spiral-new-in-CPP

La salida para 50 filas y 50 columnas es:

Debo decir que es una conjetura muy interesante.