|
41
|
Programación / Python / Ayuda para poner prints en código que no entiendo bien.
|
en: 14 Enero 2025, 15:32 pm
|
El programa genera las combinaciones de 2 letras. Carga un diccionario en inglés y otro en español. Anota las combinaciones de 2 letras que hay en las palabras. Luego anota las combinaciones de 2 letras que ocurren cuando 2 palabras se unen. Así por ejemplo se obtiene zh, por nariz y hoy. Finalmente, muestra las combinaciones que no ocurrieron, lo hace quitando de la 1er lista (la del inicio) las que anotó. Eso si funciona bien, no sé. Lo que quiero es que cuando anote una combinación, me diga cual anotó. Así me entero de cómo se forma qq por ejemplo. import itertools def cargar_diccionario(ruta): """Carga el diccionario desde un archivo .txt y devuelve un conjunto de palabras en minúsculas.""" with open(ruta, 'r', encoding='utf-8') as archivo: return set(palabra.strip().lower() for palabra in archivo) def generar_combinaciones(alfabeto): """Genera todas las combinaciones posibles de dos letras del alfabeto.""" return {a + b for a, b in itertools.product(alfabeto, repeat=2)} def buscar_combinaciones(diccionario, combinaciones): """Busca combinaciones dentro de las palabras del diccionario.""" presentes = set() # Buscar combinaciones dentro de palabras individuales for palabra in diccionario: for i in range(len(palabra) - 1): presentes.add(palabra[i:i+2]) # Buscar combinaciones entre palabras consecutivas lista_palabras = sorted(diccionario) # Ordenar las palabras for i in range(len(lista_palabras) - 1): ultima_letra = lista_palabras[-1] primera_letra = lista_palabras[i + 1][0] presentes.add(ultima_letra + primera_letra) return combinaciones - presentes # Paso 1: Cargar diccionarios diccionario_es = cargar_diccionario('diccionario_es.txt') diccionario_en = cargar_diccionario('diccionario_en.txt') # Paso 2: Generar combinaciones posibles alfabeto_es = 'abcdefghijklmnñopqrstuvwxyz' alfabeto_en = 'abcdefghijklmnopqrstuvwxyz' combinaciones_es = generar_combinaciones(alfabeto_es) combinaciones_en = generar_combinaciones(alfabeto_en) # Paso 3: Buscar combinaciones inexistentes en cada diccionario inexistentes_es = buscar_combinaciones(diccionario_es, combinaciones_es) inexistentes_en = buscar_combinaciones(diccionario_en, combinaciones_en) # Paso 4: Combinar resultados y mostrar combinaciones inexistentes en ambos idiomas inexistentes_totales = inexistentes_es.intersection(inexistentes_en) print(f"Combinaciones inexistentes en ambos idiomas ({len(inexistentes_totales)}):") print(sorted(inexistentes_totales)) input("Presione Enter para continuar ...")
|
|
|
43
|
Foros Generales / Dudas Generales / ¿Qué es un archivo .nsm?
|
en: 13 Enero 2025, 21:42 pm
|
No conseguí la respuesta.
Al abrirlo con el bloc de notas no aparece algo claro, es mucho espacio vacío y caracteres raros.
Es de 2002 dice, aunque quién sabe.
Pesa 22,9 KB (23.530 bytes).
El nombre prefiero no decirlo por las dudas, pero no es algo vergonzoso ni algo así xP
¿Cómo averiguo qué es?
|
|
|
44
|
Media / Diseño Gráfico / Reducir tamaño de la hoja, no de la imagen.
|
en: 13 Enero 2025, 20:41 pm
|
Hace mucho, cuando pegaba una imagen en Paint más grande que la hoja actual, me parecía absurdo que me preguntara si quería agrandar la hoja ¡obvio que sí!
Pero con el tiempo, me empezó a servir poner que no, porque si tomaba una foto pero sólo quería una parte, y luego tomaba otras fotos, porque era un video por ejemplo, me servía que el tamaño de la hoja se mantuviera como lo dejé, para guardar los archivos más rápido, de modo que se viera lo que yo quería y no la foto entera.
Desde que tengo Windows 7, Paint agranda la hoja sin preguntarme, y no veo la opción de modificarle el tamaño (la opción que veo modifica también la imagen, antes creo que no era así, yo no quiero que se agrande/achique la imagen, sólo la hoja), así que ¿con qué programa y cómo podría lograr lo que quiero?
Son varias fotos de un archivo de Flash, que al tomar foto sale el menú y las herramientas, podría modificar algunas cosas pero si cada vez que quiera tomar fotos debo hacer eso no me conviene.
Tomo una foto, supongamos que es así: xxxx xAAx xAAx xxxx Yo sólo quiero guardar la parte de las A. Para eso pego la imagen en Paint, la muevo hacia arriba e izquierda para quitar las x de esos sitios, y me queda así: AAxb AAxb xxxb bbbb Donde b es blanco, y yo ahora quiero reducir la hoja de modo que sólo queden las A. Debería ser fácil...
|
|
|
45
|
Programación / Programación General / IA para 2 en línea horizontal.
|
en: 12 Enero 2025, 23:55 pm
|
El juego es una simplificación del 3 en línea: - El tablero en vez de ser de 3x3 casilleros es de 2x2. - Lo que debe formarse, en vez de ser una línea horizontal, vertical o diagonal de 3 signos iguales, debe ser de 2 pero horizontal. Claro que es menos interesante que el original, es que se me complicó. Hay a grandes rásgos 3 tipos de IA, díganme otras si me faltan: A- La que sabe jugar como el programador le dijo, no aprende. B- La que sabe jugar según lo que entrenó, aprendió todo lo necesario. C- La que está aprendiendo, aprende mientras juega. El problema de A es que si el juego es complejo, no hay persona que sepa el modo ideal de jugar, y tampoco es fácil expresarlo. B requiere más tiempo lograrse entre más complejo sea el juego, por lo que llaman explosión combinatoria o algo así. C, entre más complejo sea el juego, menos útil es, porque difícilmente llegue a aprender todo lo necesario para jugar bien. El jugador podría hacer cosas distintas hasta el cansancio y en tales casos la IA sería como si recién empezara. Supongo que pueden pulirse de distintos modos, pero no sé bien cómo. A, en este caso simple sería así creo: Si IA usa X: // Intentar ganar: Si Casillero1_1 == "" && Casillero1_2 == "X" Poner X en 1_1 sino si Casillero1_1 == "X" && Casillero1_2 == "" Poner X en 1_2 Si Casillero2_1 == "" && Casillero2_2 == "X" Poner X en 2_1 sino si Casillero2_1 == "X" && Casillero2_2 == "" Poner X en 2_2 sino // Ya no es posible ganar (perder nunca fue): Poner en cualquiera vacío. sino // Evitar perder: Si Casillero1_1 == "" && Casillero1_2 == "X" Poner 0 en 1_1 sino si Casillero1_1 == "X" && Casillero1_2 == "" Poner 0 en 1_2 Si Casillero2_1 == "" && Casillero2_2 == "X" Poner 0 en 2_1 sino si Casillero2_1 == "X" && Casillero2_2 == "" Poner 0 en 2_2 sino // Ya no es posible perder: Poner en el único vacío que queda. Sobre C no pensé mucho. B es más difícil de lo que creí, a ver si me dan ideas. Mi idea es algo así: - En la situación inicial (tablero todo vacío), se prueban las acciones posibles y si se llega a una situación que no está en la lista de situaciones no resueltas, se agrega. Al principio esa lista está vacía, ahora habrá 4 porque 4 son las posibles consecuencias de las 4 posibles acciones. - Se genera una de las situaciones de la lista. Probamos las posibles acciones, ahora el signo es 0 en vez de X. Si obtenemos situaciones que no estén en la lista, de nuevo, las anotamos. - Repetimos eso con cada situación, el signo a poner depende de cuales sean, y llegará un punto en que poner un signo causará una victoria, por ejemplo en esta: XV 0V (V es vacío) La acción nro 2 (casillero 1_2, al lado de la X) causa victoria. Cuando eso ocurre, creamos unas variables cuyos nombres implican la situación anterior a la victoria, en el ejemplo sería XV0V, y ponemos una S delante para menos lío, sabemos que S significa situación. Bueno, las variables van a ser por ejemplo: SXV0VBestAction = 2 SXV0VDistanciaDeVictoria = 1 Significa que en esa situación conviene la acción 2 y que hace falta sólo 1 acción para llegar a la victoria. Eliminamos esa acción de la lista de situaciones sin resolver. - Cuando hayamos recorrido la lista de situaciones, comenzamos a recorrerla de nuevo, pero no sé bien qué debería hacerse ahora específicamente. En programas "similares" que había hecho, lo que se hacía era que si se llega a una situación cuya DistanciaDeVictoria fuese 1, a la anterior situación se le asignaba que DistanciaDeVictoria fuese 2, y así se repite realizar acciones, asignar "puntajes" a las situaciones, eliminarlas de la lista, y en cada nueva repetición aumentar el número asignado a DistanciaDeVictoria, hasta que ya no queden situaciones a investigar. Pero en este caso no se puede porque hay turnos, hay rivales, a ver: Si sólo hubiera X, sería así: Comenzamos investigando la situación VV VV Probamos una acción XV VV Anotamos esa situación en la lista de no resueltas. Probamos otra acción en la situación que estamos investigando, nos queda: VX VV En fin, en cierto punto vamos a investigar esta: XV VV Realizamos una acción que causa victoria XX VV Entonces definimos: SXVVVBestAction=2 SXV0VDistanciaDeVictoria = 1 Y en otro punto, cuando volvamos a investigar situaciones aún no resueltas, como esta: VV VV Cuando hagamos esto: XV VV Llegamos a una que la tenemos evaluada como 1, entonces a la anterior (la que puse arriba, todo V) le vamos a poner 2. Está clarísimo, se requieren 2 acciones para ganar desde el inicio. Pero hay 0, así que luego de hallar todas las victorias posibles, cuando volvamos a investigar situaciones aún no resueltas, como esta: XV VV Sabemos que es turno del 0, que si pone en 2_1 o 2_2 se llegará a una situación cuya DistanciaDeVictoria es 1, pero para X, para 0 es 1 de la derrota, así que el programa no puede ponerle 2, eso se interpretaría como que a 0 le hacen falta 2 acciones para ganar, que es segurto que ganará, lo cual no es así. ¿La solución es crear otra variable? ¿que exista DistanciaDeVictoriaDeX y DistanciaDeVictoriaDe0? Hay que tener en cuenta la explosión combinatoria, no conviene crear variables en lo posibñe, además no veo bien cómo eso lo resolvería. A ver, si no llega a una situación cuya DistanciaDeVictoriaDe0 sea 1 (cosa imposible, 0 no puede ganar), nada se anota al respecto. Y cuando la distancia de X es 1, se anota que de 0 es -1, es decir que está a 1 acción de ser derrotado. La distancia ideal es positiva y en 2nda instancia lo más cercana a 0 posible. Bueno... cuando en una búsqueda no se anoten cosas, es decir no se llegue a situaciones resueltas, se comenzaría a anotar las que lleguen a distancias -1, luego a -2, y así, podría ser que se llegue a resolver todas las situaciones. ¿Creen que eso funcionará? ¿no, por qué? ¿Es posible usar sólo una distancia? ¿sí, cómo? ¿Cómo sería un método más rápido y eficiente? Imagino que deduciendo en base a rotar el tablero o considerar simetría, pero creo que debe haber algo como aprender la regla, aprender un código a seguir, no esto de aprender qué hacer en la situación 1, 2, 3... Cuando juegue, sería bueno que siga un código como el que puse al inicio, en vez de "llamar a la función SXVVV" (o sea, cargar los datos de esa situación a ver qué acción conviene en ella), porque cuando sean MUCHAS posibles situaciones, es un disparate hacerlo así, por la explosión ¿no? Imagina un 5 en línea en un tablero de 25x25 con 5 jugadores, por decir algo.
|
|
|
46
|
Programación / Programación General / En muchos lenguajes, tempArray = array ¿es una referencia y les parece bien?
|
en: 12 Enero 2025, 21:51 pm
|
A esto: https://foro.elhacker.net/programacion_general/iquestque_metodo_es_recomendado_para_ordenar_al_azar_un_array-t522940.0.html...quería agregarle eficientemente que el nuevo array pudiera tener menos elementos que el original. Como no se me ocurrió bien cómo, consulté a GPT: En Macromedia Flash 5 tengo un array de 3 elementos y quiero que se genere otro array con 2 de esos elementos al azar, y ordenados al azar ¿cómo? En **Macromedia Flash 5**, puedes usar `ActionScript` para lograr lo que necesitas: generar un nuevo array con dos elementos seleccionados al azar del array original, y luego ordenarlos aleatoriamente. Aquí tienes un ejemplo de código que hace exactamente eso:
```actionscript // Array original con 3 elementos var originalArray = ["Elemento1", "Elemento2", "Elemento3"];
// Función para seleccionar 2 elementos al azar del array original function getRandomElements(array) { // Copiar el array original para no modificarlo var tempArray = array.slice(0); var randomArray = []; // Seleccionar 2 elementos al azar for (var i = 0; i < 2; i++) { var randomIndex = Math.floor(Math.random() * tempArray.length); randomArray.push(tempArray[randomIndex]); // Remover el elemento seleccionado para evitar duplicados tempArray.splice(randomIndex, 1); } // Mezclar los elementos seleccionados randomArray.sort(function() { return Math.random() - 0.5; }); return randomArray; }
// Generar el nuevo array con 2 elementos al azar y ordenados al azar var newArray = getRandomElements(originalArray);
// Mostrar el resultado trace("Array original: " + originalArray); trace("Nuevo array: " + newArray); ```
### Explicación del código:
1. **Copia del array original**: - Usamos `slice(0)` para crear una copia del array original, de modo que no lo modifiquemos al eliminar elementos.
2. **Selección aleatoria**: - En el loop, se seleccionan dos elementos al azar usando `Math.random()` y se eliminan del array temporal (`tempArray`) con `splice()`, para evitar duplicados.
3. **Orden aleatorio**: - Usamos `sort()` con una función de comparación que devuelve un valor aleatorio para mezclar los elementos seleccionados.
4. **Resultado**: - El nuevo array (`newArray`) contiene dos elementos seleccionados al azar del array original, y están ordenados de manera aleatoria.
### Ejemplo de salida:
Si el array original es `["Elemento1", "Elemento2", "Elemento3"]`, la salida podría ser algo como:
``` Array original: Elemento1,Elemento2,Elemento3 Nuevo array: Elemento2,Elemento1 ```
Cada vez que ejecutes el código, la selección y el orden serán diferentes. ¿por qué pones var tempArray = array.slice(0); en vez de tempArray = array; ? La razón por la que usé:
```actionscript var tempArray = array.slice(0); ```
en lugar de:
```actionscript tempArray = array; ```
es para **crear una copia del array original**, en lugar de simplemente referenciarlo.
### Diferencia entre copiar y referenciar un array:
- **`tempArray = array;`** Esto no crea un nuevo array. En lugar de ello, `tempArray` apunta al mismo espacio de memoria que el array original (`array`). Si modificas `tempArray` (como eliminar elementos con `splice()`), también estarás modificando el array original, porque ambos comparten el mismo contenido.
- **`tempArray = array.slice(0);`** Esto crea una **copia del array original**. Cualquier cambio que hagas en `tempArray` no afectará al array original, ya que ahora son dos arrays independientes.
### ¿Por qué es importante en este caso?
En el código, usamos `splice()` para eliminar elementos del array temporal (`tempArray`) mientras seleccionamos elementos aleatorios. Si no hacemos una copia (usando `slice()`), también estaríamos eliminando elementos del array original, lo cual probablemente no sea lo que queremos.
### Ejemplo práctico:
Supongamos que tienes este código:
```actionscript var originalArray = ["Elemento1", "Elemento2", "Elemento3"]; var tempArray = originalArray;
// Modificar tempArray tempArray.splice(0, 1);
// Imprimir ambos arrays trace("originalArray: " + originalArray); trace("tempArray: " + tempArray); ```
**Salida:**
``` originalArray: Elemento2,Elemento3 tempArray: Elemento2,Elemento3 ```
Como ves, al modificar `tempArray`, también se modifica `originalArray`, porque ambos apuntan al mismo array.
Ahora, usando `slice(0)`:
```actionscript var originalArray = ["Elemento1", "Elemento2", "Elemento3"]; var tempArray = originalArray.slice(0);
// Modificar tempArray tempArray.splice(0, 1);
// Imprimir ambos arrays trace("originalArray: " + originalArray); trace("tempArray: " + tempArray); ```
**Salida:**
``` originalArray: Elemento1,Elemento2,Elemento3 tempArray: Elemento2,Elemento3 ```
Aquí, `originalArray` permanece intacto, porque `tempArray` es una copia independiente.
### Conclusión:
Usar `slice(0)` asegura que puedas trabajar con un array temporal sin modificar el array original. Esto es crucial cuando necesitas preservar el estado del array original para otros usos o simplemente para evitar efectos secundarios no deseados. Poner un nombre, luego = y luego un valor, es crear una variable cuyo nombre es el indicado en nombre y su valor es indicado luego del signo =, no es una referencia ¿o estoy equivocado? Estás en lo correcto en términos generales: cuando haces algo como:
```actionscript var nombre = valor; ```
estás creando una variable llamada `nombre` y asignándole el valor de `valor`. Sin embargo, **el comportamiento de la variable depende del tipo de dato que estés asignando**. En ActionScript (y en muchos lenguajes de programación), los tipos de datos se dividen principalmente en dos categorías:
1. **Tipos primitivos** (números, cadenas, booleanos, etc.). 2. **Tipos complejos o de referencia** (objetos, arrays, etc.).
La diferencia clave radica en cómo se asignan y manejan los valores en memoria.
---
### Tipos primitivos: Copia del valor
Cuando asignas un tipo primitivo a una variable, se copia su valor directamente en la nueva variable. Por ejemplo:
```actionscript var a = 5; var b = a; b = 10;
trace(a); // 5 trace(b); // 10 ```
Aquí, `a` y `b` son independientes, porque el número `5` (un tipo primitivo) se copió en `b`. Cambiar `b` no afecta a `a`.
---
### Tipos complejos (como arrays): Referencia en memoria
Cuando trabajas con tipos complejos, como arrays u objetos, lo que realmente estás asignando no es el "valor" en sí, sino una **referencia en memoria** al lugar donde se almacenan esos datos. Esto significa que si usas el operador `=` para asignar un array a otra variable, ambas variables apuntarán al mismo array en memoria. Por ejemplo:
```actionscript var originalArray = [1, 2, 3]; var otherArray = originalArray;
otherArray.push(4);
trace(originalArray); // [1, 2, 3, 4] trace(otherArray); // [1, 2, 3, 4] ```
Aquí, tanto `originalArray` como `otherArray` apuntan al mismo array en memoria. Al modificar `otherArray`, también estás modificando `originalArray`.
Si quieres evitar este comportamiento y trabajar con una copia independiente del array, necesitas crear una copia explícita, como con el método `slice()`:
```actionscript var originalArray = [1, 2, 3]; var otherArray = originalArray.slice(0);
otherArray.push(4);
trace(originalArray); // [1, 2, 3] trace(otherArray); // [1, 2, 3, 4] ```
Ahora, `originalArray` y `otherArray` son arrays completamente separados, y los cambios en uno no afectan al otro.
---
### Conclusión
Cuando haces:
```actionscript tempArray = array; ```
no estás creando un nuevo array. Estás haciendo que `tempArray` apunte al mismo array en memoria que `array`. Por eso, cualquier cambio que hagas en `tempArray` también se verá reflejado en `array`.
Si quisieras que `tempArray` sea una copia independiente del contenido de `array` (sin afectar al original), necesitas usar algo como:
```actionscript tempArray = array.slice(0); ```
Esto crea un nuevo array con el mismo contenido, pero almacenado en un espacio de memoria diferente.
En resumen: la diferencia entre **valor** y **referencia** es lo que causa este comportamiento. ¿Por qué lo hicieron así? Implementar arrays y objetos como **tipos por referencia** en lenguajes como ActionScript (y otros lenguajes como javascript, Python, etc.) no es algo arbitrario, tiene razones prácticas y de diseño. Aquí te explico por qué **los arrays y objetos funcionan por referencia** y no como copias directas:
---
## 1. **Eficiencia en memoria y rendimiento** Cuando trabajas con tipos complejos como arrays u objetos, estos pueden contener grandes cantidades de información. Si cada vez que los asignaras a una nueva variable se hiciera una copia completa de los datos, esto consumiría mucha memoria y sería muy lento.
Por ejemplo, considera este caso:
```actionscript var arrayGrande = [1, 2, 3, ..., 100000]; // Un array con 100,000 elementos var copia = arrayGrande; // ¿Qué pasaría si fuera una copia completa? ```
Si el lenguaje copiara todo el array al asignarlo, el programa tendría que:
1. Reservar **el doble** de espacio en memoria para almacenar los mismos datos. 2. Copiar cada uno de los 100,000 elementos al nuevo array.
Esto haría que las operaciones de asignación fueran lentas y que el uso de memoria se disparara rápidamente en aplicaciones que manejan muchos datos.
**Por referencia**, en cambio, el lenguaje simplemente crea un "puntero" o "referencia" al espacio de memoria donde ya está almacenado el array. Esto es mucho más rápido y eficiente porque no duplica los datos, sino que solo comparte la referencia.
---
## 2. **Facilita la mutabilidad** Cuando trabajas con objetos y arrays, muchas veces necesitas que todos los cambios se reflejen en el mismo lugar. Si los arrays fueran siempre copiados al asignarlos, sería complicado coordinar los cambios entre diferentes partes de tu código.
Por ejemplo:
```actionscript var config = { ancho: 800, alto: 600 }; var referencia = config;
referencia.ancho = 1024;
trace(config.ancho); // 1024 ```
Aquí, tanto `config` como `referencia` apuntan al mismo objeto. Si cambias un valor en `referencia`, también se refleja en `config`, porque ambos son referencias al mismo objeto. Esto facilita que múltiples variables o funciones trabajen con los mismos datos sin necesidad de copiar y sincronizar los cambios manualmente.
Si los objetos fueran copiados automáticamente, el cambio en `referencia` no afectaría a `config`, y tendrías que buscar formas más complicadas de mantenerlos sincronizados.
---
## 3. **Es coherente con el diseño de programación orientada a objetos** Los lenguajes como ActionScript están diseñados para manejar objetos de manera flexible. En este paradigma, los objetos y arrays suelen comportarse como entidades compartidas, **en lugar de duplicarse automáticamente**. Esto es clave para trabajar con estructuras de datos dinámicas, como listas enlazadas, árboles, o gráficos, donde las relaciones entre los elementos son importantes.
Por ejemplo:
```actionscript var nodo1 = { valor: 1, siguiente: null }; var nodo2 = { valor: 2, siguiente: nodo1 };
trace(nodo2.siguiente.valor); // 1 ```
Este tipo de estructuras serían mucho más difíciles de implementar si cada asignación hiciera copias completas de los datos.
---
## 4. **Consistencia con otros lenguajes** ActionScript heredó muchas de sus características de javascript (que, a su vez, está inspirado en otros lenguajes como Java). En todos estos lenguajes, los objetos y arrays funcionan por referencia. Esto hace que el comportamiento sea predecible y **consistente con el estándar de la industria**, lo que facilita a los programadores aprender y trabajar con lenguajes similares.
---
## ¿Por qué no hacerlo todo por valor? Si trabajar por referencia es tan eficiente, podrías preguntarte por qué no todos los tipos de datos funcionan así. La razón es que **los tipos primitivos (como números, cadenas y booleanos)** son mucho más simples y pequeños en términos de tamaño en memoria. Duplicarlos no es costoso y, en la mayoría de los casos, es más útil que sean independientes.
Por ejemplo:
```actionscript var a = 5; var b = a; b = 10;
trace(a); // Todavía es 5 trace(b); // Es 10 ```
En este caso, trabajar **por valor** tiene sentido porque los números son pequeñas cantidades de datos y se espera que sean independientes.
---
## Conclusión Los arrays y objetos funcionan por referencia porque:
1. **Es más eficiente** en términos de memoria y rendimiento. 2. **Facilita la mutabilidad**, permitiendo que los cambios se reflejen automáticamente en todas las referencias. 3. **Es coherente** con el diseño de programación orientada a objetos. 4. **Sigue un estándar** que es consistente con otros lenguajes.
Aunque este comportamiento puede parecer confuso al principio, con el tiempo te darás cuenta de que es una decisión lógica y práctica para manejar datos complejos. Si necesitas una copia independiente, siempre puedes usar métodos como `slice()` o técnicas específicas para clonar objetos y arrays. No le veo sentido, si quiero crear una copia debería poder hacerlo normalmente no con "slice", si consume mucho entonces el programador debería saberlo y no usarlo salvo que sea útil ¿por qué limitarnos? Claro que no entendí todos los motivos que dice ahí, que una variable tenga 2 nombres puede ser útil pero... Si fuese así, debería poder hacerse con variables simples, y sobretodo debería poder hacerse de otro modo. Que una misma expresión, tan básica, haga cosas distintas según el tipo de variable parece absurdo. ¿Qué opinan? Edit: Sabía que había excepciones a eso, tenemos por ejemplo que Número+Número es una suma pero si alguno de esos números es cadena entonces el + es concatenar. Pero vamos, no es lo mismo el + que el =. El = es sagrado xP Edit2: Es como si al copiar un archivo en Windows, este en vez de eso copiara un acceso directo. Joder, si quiero una copia porque voy a modificar una, dejame copiar tranquilo 
|
|
|
47
|
Programación / Programación General / ¿Cual es el método más eficiente para ver si hay una línea de S signos?
|
en: 7 Enero 2025, 18:05 pm
|
Conocen el juego 3 en línea, tic tac toe, tateti, etc. Yo estoy haciendo un S en línea, es decir, que el juego permita elegir cuántos signos debe haber en la línea (y qué tan grande es el tablero). Anduve pensando cual es el método más eficiente de ver si alguien ganó. Se me ocurrieron 2 métodos. El 1ero es bastante bruto, más o menos así: Se apunta al superior izquierdo. Repetir: Si no está vacío: Se miran sus contiguos de diagonal derecha-arriba: Si no hay o no marcan victoria: Se miran sus contiguos de la derecha: Si no hay o no marcan victoria: Se miran sus contiguos de diagonal derecha-abajo: Si no hay o no marcan victoria: Se miran sus contiguos de abajo: Si no hay o no marcan victoria: Si hay un casillero hacia abajo: Se empieza a mirar ese. sino si hay casilleros en la derecha: Se empieza a mirar el superior de esa columna. No es necesario que los ifs se repitan, sólo que al escribirlo así nomás quedaba más claro. El otro método intentaba usar menos repeticiones o variaciones de variables, pero a medida que lo analicé llegó un punto en que me parecía igual. En la misma repetición, se apunta a 2 casilleros (al principio son el mismo), y en cada repetición se varía a cual se apunta (y analiza como puse arriba), el 1ero es cada vez más hacia la derecha y el 2ndo hacia abajo. Cuando no quedan, se apunta al diagonal derecho-abajo y se repite el proceso hasta que el apuntado sea el inferior derecho. Empecé a aplicar el método 1: // Por practicidad al calcular, las filas se cuentan desde 0: Fila = -1; // Las columnas no, desde 1: Columna = 0; do { Fila++; SemiReferenciaAlCas = "Casillero"+Fila+"_"; do { Columna++; // Si el casillero no está vacío: if (eval(SemiReferenciaAlCas+Columna != 2)) { // Esto va variando qué siguientes... // casilleros se analizan: Extra = 0; do { Extra++; //
Ahí iría lo de analizar hacia la diagonal arriba-derecha, y el resto de las cosas. Pero siento que es tan poco eficiente que prefiero que me digan algo mejor, que probablemente haya. Sino, más adelante le pregunto a GPT. Por cierto, tengo pensado que la máquina aprenda a jugar experimentando, por eso los valores de los casilleros están grabados de 2 formas, por ejemplo el superior izquierdo: // 2 es vacío, 1 es cruz, 0 es 0. Casillero1 = 2; Casillero1_1 = 2; Porque al hacer referencia a una situación es más fácil variar sólo una variable (no fila y columna). Lo necesito para hacer árboles, no sé cómo lo hacen uds, hablaremos en otra ocasión de eso. Mientras hacía el tema me di cuenta que alcanza con analizar solamente las líneas que impliquen al casillero recién modificado  así que intentaré eso y podría borrar todo esto, pero igual puede ser interesante, luego pongo lo que logre.
|
|
|
48
|
Programación / Programación General / ¿Qué método es recomendado para ordenar al azar un array?
|
en: 7 Enero 2025, 07:16 am
|
Probablemente los lenguajes modernos tienen una función que lo hace, no busco eso. Yo había pensado algo así: Colores = ["Azul", "Rojo", "Verde", "Blanco", "Negro"]; // Esto habría que hacerlo con loop pero no es lo relevante: PesoDeElementos = [Math.random(), Math.random(), Math.random(), Math.random(), Math.random()]; Elemento1aReubicarse = -1; ReordenarHasta = 4; do { Elemento1aReubicarse++; Elemento2aReubicarse = Elemento1aReubicarse+1; if (PesoDeElementos[Elemento1aReubicarse] > PesoDeElementos[Elemento2aReubicarse]) { // Intercambiar esos 2 elementos: SaveDeElemento1 = Colores[Elemento1aReubicarse]; Colores[Elemento1aReubicarse] = Colores[Elemento2aReubicarse]; Colores[Elemento1aReubicarse] = SaveDeElemento1; } if (Elemento2aReubicarse == ReordenarHasta) { // Hacia la derecha ya está reordenado, volver a la izquierda: Elemento1aReubicarse = -1; ReordenarHasta--; } } while (ReordenarHasta > 0);
Pero suponiendo que podía haber algo más sencillo (esa cosa la acabo de hacer, no sé si funciona), le pregunté a GPT. Me dijo un método de Fisher o algo así que no entendí. En Wikipedia tampoco. Pero se me ocurrió (o puede ser igual a lo que no entendí) un método que recorra los elementos, hasta el central, intercambiando los de un lado con los de otro, y luego el central con cualquiera, pero tenía dudas de cómo sería exactamente y ahora noto que no sería justo, es decir, el 1er elemento nunca quedaría 2ndo (salvo que fuesen menos de 4), y además: - Si siempre hay intercambio, nunca podrían quedar en el lugar original, lo cual debería poder suceder. - Si puede no haber intercambio, la probabilidad de que queden igual varios de ellos es muy alta. Así que eso no sirve ¿pero cual es entonces un buen método? Copio la conversación que tuve con GPT: En **Macromedia Flash 5**, que utiliza **ActionScript 1.0**, puedes implementar un algoritmo para reordenar un array al azar utilizando un enfoque conocido como el algoritmo de **Fisher-Yates Shuffle**. Aquí tienes el código que puedes usar para reordenar al azar el array `PosiblesColores`:
```actionscript // Array original PosiblesColores = [0xFFFFFF, 0xFF0000, 0]; // Puedes agregar hasta 10 elementos
// Función para reordenar el array al azar function shuffleArray(array) { var i, j, temp; for (i = array.length - 1; i > 0; i--) { j = Math.floor(Math.random() * (i + 1)); // Genera un índice aleatorio válido // Intercambia los elementos array y array[j] temp = array; array = array[j]; array[j] = temp; } }
// Llama a la función para mezclar el array shuffleArray(PosiblesColores);
// Imprime el array reordenado para verificar for (var i = 0; i < PosiblesColores.length; i++) { trace(PosiblesColores); } ```
### Explicación del código: 1. **Algoritmo Fisher-Yates**: - Este algoritmo recorre el array desde el último elemento hasta el primero. - En cada iteración, selecciona un índice aleatorio entre `0` y el índice actual, e intercambia los dos elementos. - Esto garantiza que cada permutación del array sea igualmente probable.
2. **`Math.random()`**: - Genera un número decimal aleatorio entre `0` y `1`. - Multiplicamos este número por el rango necesario (`i + 1`) para obtener un índice aleatorio válido.
3. **Intercambio de elementos**: - Usamos una variable temporal (`temp`) para almacenar el valor de uno de los elementos mientras realizamos el intercambio.
4. **`trace()`**: - Esta función imprime los valores en el panel de salida para que puedas verificar el resultado del reordenamiento.
### Ejemplo de salida: Si el array original es:
```actionscript PosiblesColores = [0xFFFFFF, 0xFF0000, 0]; ```
Después de ejecutar el código, el array podría quedar como:
```actionscript [0, 0xFFFFFF, 0xFF0000] ```
O cualquier otra permutación aleatoria de los elementos.
Puedes modificar el array `PosiblesColores` para agregar más elementos, y el algoritmo seguirá funcionando correctamente. quisiera que el índice vaya subiendo en vez de bajando y que uses while en vez de for ¡Claro! Aquí está el código modificado para que el índice vaya **subiendo** y se use un bucle `while` en lugar de `for`. El algoritmo sigue siendo equivalente al **Fisher-Yates Shuffle**, pero adaptado a tus especificaciones:
```actionscript // Array original PosiblesColores = [0xFFFFFF, 0xFF0000, 0]; // Puedes agregar hasta 10 elementos
// Función para reordenar el array al azar function shuffleArray(array) { var i = 0; // Empieza desde el primer índice var len = array.length;
while (i < len - 1) { // Genera un índice aleatorio entre i y el último índice var j = Math.floor(Math.random() * (len - i)) + i;
// Intercambia los elementos array y array[j] var temp = array; array = array[j]; array[j] = temp;
// Incrementa el índice i++; } }
// Llama a la función para mezclar el array shuffleArray(PosiblesColores);
// Imprime el array reordenado para verificar var index = 0; while (index < PosiblesColores.length) { trace(PosiblesColores[index]); index++; } ```
### Cambios realizados: 1. **Uso de `while`**: - El índice `i` comienza en `0` y se incrementa en cada iteración hasta el penúltimo elemento (`len - 1`). - El bucle `while` se detiene cuando el índice `i` alcanza el penúltimo elemento.
2. **Generación de índice aleatorio (`j`)**: - En lugar de seleccionar un índice aleatorio para cualquier posición del array, `j` se selecciona entre `i` (el índice actual) y el final del array. - Esto asegura que cada elemento solo sea intercambiado con los elementos que aún no han sido procesados.
3. **Intercambio de elementos**: - Igual que antes, usamos una variable temporal `temp` para realizar el intercambio entre `array` y `array[j]`.
4. **Impresión con `while`**: - Se utiliza un bucle `while` para imprimir cada elemento del array después de ser mezclado.
### Ejemplo de salida: Dado el array original:
```actionscript PosiblesColores = [0xFFFFFF, 0xFF0000, 0]; ```
Después de ejecutar el código, podrías obtener una permutación como:
```actionscript [0xFF0000, 0, 0xFFFFFF] ```
O cualquier otra ordenación aleatoria.
Este código es completamente funcional y cumple con las especificaciones que pediste. Intenté imitarlo pero como no sé exacto cómo funciona y esos nombres j e i me entreveran, decidí buscar en Wikipedia. https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffleCreo que ahora entiendo, va desde derecha a izquierda y "rolled" significa que eligió intercambiar con ese, el elemento posible de intercambiarse era el 4 y "rolled" un 1, yo interpretaba que había elegido por azar el 1 y no sabía de dónde había sacado el 4. ¿Es así? ¿hay otro mejor?
|
|
|
50
|
Programación / Programación General / ¿Qué tanto sentido tiene programar?
|
en: 4 Enero 2025, 07:16 am
|
Para ver todos los dibujos posibles uno a uno, hice un programa que los genera así, aunque por ahora sólo son en blanco y negro, de esos 2 colores nada más. Luego indiqué que no mostrara dibujos que no cumplieran ciertas características. A: Luego empecé a indicar cómo pasar de uno aceptable al siguiente aceptable, para evitar generar los que no van a mostrarse. Por si no se entiende: Supongamos que quieres ver todos los números divisibles entre 3. Puedes generar todos los enteros y mostrar sólo los divisibles entre 3 (se genera el 1 pero no se muestra, luego el 2 pero tampoco, el 3 sí, luego el 4 pero no...), o puedes simplemente indicar que se generen sólo los necesarios (3, 6...). Pero no en todo contexto es simple.
Noté una falla en eso que hice. Tengo una idea sobre cómo corregirlo pero, si lo que hice antes estuvo mal ¿por qué creer que ahora estará bien? Tampoco es que deba creer que estará mal, no se debe creer que se puede prever el futuro tanto, es cuestión de probar, pero me tiene un poco cansado, no sé, me pregunto hasta qué punto tiene sentido fallar, fallar, fallar y cuando no se notan errores no estar seguro de si no hay o uno está fallando en detectarlos. Es como "Mejor que lo haga otro, alguien que no falle tanto". Había concluido que lo mejor era dejar de intentar hacer A, pero eso en última instancia es como creer que no tiene sentido intentar programar, es dejar de programar. Por eso estoy un poco confuso, el programa en sí tampoco tiene mucho sentido, los dibujos que muestra es como que son nada, grandes cuadrados cerca, así o asá. Una IA o como se llame, hoy en día hace dibujos bastante bien de lo que se le pida, así que pa qué. En parte era porque quería demostrar que los dibujos no son una creación, que deba tener dueño, es algo que puede ser generado pintando ciertos puntos de ciertos colores, duh, y se puede lograr probando combinaciones. Y por ver dibujos interesantes, no sé. Ah, y era una práctica para otras cosas, no puedo generar películas o representaciones de cerebros, si no puedo generar dibujos... Mejor empezar por lo más fácil. No sé si es un error dejar esto o no. Y la cuestión es más profunda que eso, quizá debería dejar la programación misma, pero para hacer qué, no sé, si igual la cuestión de que puedo fallar sigue. Probablemente no es un tema de programación entonces, pero aquí lo dejo, como "testimonio" de lo que es programar sin saber hacerlo bien, o el problema que sea. Recientemente vi este video: https://www.youtube.com/watch?v=4zk6uodm7tYYo no entendí Matrix y no recordaba tanto, aparentemente el programador comete fallas que no sabe corregir.
|
|
|
|
|
|
|