¿Ordenar turnos por velocidad?

Iniciado por Tachikomaia, 8 Agosto 2021, 06:06 AM

0 Miembros y 2 Visitantes están viendo este tema.

Tachikomaia

Ejemplo de input:
Player1Speed = 2
Player2Speed = 3
Player3Speed = 1
Player4Speed = 4
(pueden ser más)

Para ese input quiero que el output sea:
Turn1 = Player4
Turn2 = Player2
Turn3 = Player1
Turn4 = Player3

¿Cómo hacer eso sin for ni arrays? Es que no me gustan.

3n31ch

#1
¿Como es eso de que no te gustan los fors ni arrays?  :xD :xD :xD

En que lenguaje, ¿python? lo puedes hacer con eval(), exec() y while.. pero vamos, es una tontería no usar arrays  :xD.

Quizás lo haga para entretenerme un rato, pero me mataste con ese comentario  ;-) ;-) ;-) :laugh:

Modifico este mensaje en un rato hahahaha.

Código (python) [Seleccionar]

# Seteo de variables
Player1Speed = 2
Player2Speed = 3
Player3Speed = 1
Player4Speed = 4

# Calculo la cantidad de jugadores y seteo los turnos (sin ordenar) con la velocidad
l = 1
while True:
try:
var = eval('Player'+str(l)+'Speed')
exec('Turn'+str(l)+' = '+str(var))
l += 1
except:
l -= 1
break

# El bubble sort mas feo del mundo
i = 1
while i < l:
j = 1
while j < l:
v1 = eval('Turn'+str(j))
v2 = eval('Turn'+str(j + 1))
if v1 < v2:
exec('Turn'+str(j)+' = '+str(v2))
exec('Turn'+str(j + 1)+' = '+str(v1))
j += 1
i += 1

# Remplazo las velocidades por los jugadores (uso la misma varialbe turn)
i = 1
while i <= l:
name = 'Player' + str(i)
speed = eval(name+'Speed')
j = 1
while j <= l:
turn = eval('Turn'+str(j))
if speed == turn:
exec( 'Turn'+str(j) + ' = "' + name + '"')
break
j += 1
i += 1

#Imprimo el resultado ordenado
i = 1
while i <= l:
var = eval('Turn' + str(i))
print('Turn' + str(i) + ' = ' + var)
i += 1

Tachikomaia

Cita de: 3n31ch en  8 Agosto 2021, 09:02 AM
¿Como es eso de que no te gustan los fors ni arrays?  :xD :xD :xD
Well... los for siempre me parecieren contra intuitivos, o mal redactados, y que yo sepa los whiles pueden hacer lo mismo. Ahora que recuerdo tampoco me gustan los case, aunque tal vez esos ayuden bastante a que el código sea más legible.
Yo uso Macromedia Flash 5, al comienzo porque era el último Flash que tenía la función de guardar variables en un archivo txt, o al menos tenía una forma fácil de hacerlo. Pero si las variables eran arrays entonces no funcionaba, por eso empecé a no usar arrays y me resultó más comprensible.

Tu código parece muy complicado, no pensé que fuera tanto  :o Me tomará un tiempo comprenderlo.

3n31ch

#3
Bueno, al margen de lo del for, el tema de los arrays es lo que hace complicado el código que lees. No sé nada de macromedia flash, así que te lo explicaré según lo que escribí en python (tu haces la traducción luego).

Aca los metódos claves son:
eval()  eval se usa para evaluar una sola expresión de Python generada dinámicamente. Le paso un string (código), esta la ejecuta y me retorna el resultado. Por ejemplo, le paso el nombre de una variable y de existir me dará el resultado, en caso contrarió me tirara un error (el mismo error que arrojaría si yo intentara acceder al valor de una variable que no existe).
exec() exec se usa para ejecutar código de Python generado dinámicamente. Le paso un string y lo ejecuta. Lo utilizó para crear una variable, osea: eval("variable = 5"), sería lo mismo que directamente escribir variable = 5 (solo que lo puedo hacer desde un string, en tiempo de ejecución).

El código se divide en 5 partes (identificadas por los comentarios):

1.- Seteo de variables: Esto ya lo entenderás así que no lo explicaré.

2.- Cálculo de cantidad de jugadores: Dado que no puedo usar arrays o diccionarios lo que hice fue usar un while que tuviera un contador incremental que parte desde 1. En cada ciclo uso la función eval para obtener el valor de la variable (iteración 1: Player1Speed, iteración 2: Player2Speed, etc.), y exec para guardar dicho valor en Turn1, Turn2, Turn3, etc. Cuando eval me tire un error de que la variable que intento acceder no existe entonces salgo del while. Como resultado de este bloque de código obtengo 2 cosas: La creación de variables Turn1, Turn2, Turn3, etc. con las velocidades en desorden y la cantidad de variables de entrada (obtenida a partir del contador resultante). Ejemplo:


l = 4
Turn1 = 2
Turn2 = 3
Turn3 = 1
Turn4 = 4


3.- El bubble sort mas feo del mundo: Aca no hay mucho que explicar. Si no lo conoces, busca bubble sort en internet y ya está. (Se podrían haber usado otros métodos de ordenamiento, pero este es el mas facil que se me ocurrió). Como resultado de este método obtengo las velocidades ordenadas (estas velocidades están guardadas dentro de Turn1, Turn2, Turn3, etc). Ejemplo:


Turn1 = 4
Turn2 = 3
Turn3 = 2
Turn4 = 1


4.- Remplazar velocidades por jugadores: Acá recorro la "lista" de jugadores, y por cada uno de estos, recorro la lista de turnos. Si la velocidad del jugador corresponde a la velocidad del turno, remplazo la velocidad del turno por el nombre del jugador y avanzo al siguiente jugador, así hasta que todos los valores sean remplazados. Ejemplo:


Turn1 = "Player4"
Turn2 = "Player2"
Turn3 = "Player1"
Turn4 = "Player3"



5.- Imprimir resultado ordenado: Nada que decir, solo recorro la lista de turnos e imprimo el resultado.

PD: Si el problema es no poder guardar arrays en un txt, entonces lee el txt, guarda esa lectura en un array de objetos con el nombre del jugador y su velocidad, y ejecuta un metodo de ordenamiento. Te será mucho mas simple.

PD2: No se nada de macromedia flash, pero esto no estaba muerto? Es una duda, no una critica, no te lo tomes a mal hahaha.

Tachikomaia

eval es igual que en M. Flash 5, y exec parece "set variable" o (aunque hace mucho que no uso esto) una expresión como por ejemplo llamar a una variable (o dinámica, si se dice así) función.

Código (python) [Seleccionar]
# Calculo la cantidad de jugadores y seteo los turnos (sin ordenar) con la velocidad
l = 1
while True:
try:
var = eval('Player'+str(l)+'Speed')
exec('Turn'+str(l)+' = '+str(var))
l += 1
except:
l -= 1
break
¿Cual es el resultado de esta parte?

Creas una variable var que contiene la Speed del player 1.
var = 2

Luego parece que creas otra llamada Turn1 que contiene la variable creada.
Turn1 = 2

No entiendo cómo i pasa a ser negativo, pero parece que el resultado del código es crear 4 variables Turn.

Seguiré analizando...

CitarPD: Si el problema es no poder guardar arrays en un txt, entonces lee el txt, guarda esa lectura en un array de objetos con el nombre del jugador y su velocidad, y ejecuta un metodo de ordenamiento. Te será mucho mas simple.
O el problema era no poder cargar los array del txt, fue hace mucho... Ya no uso archivos externos (como los txt).

CitarPD2: No se nada de macromedia flash, pero esto no estaba muerto? Es una duda, no una critica, no te lo tomes a mal hahaha.
MF según veo es del año 2000. Fue comprado por Adobe e hicieron varias nuevas versiones. Ni idea si siguen haciendo, pero como sea, el programa que yo uso es viejo, pero es el lenguaje (actionscript) y entorno que más entiendo.

Luego está el tema del Flash Player, que creo ya no se usa (los navegadores tienen sus propios reproductores, creo que Htlm 5) salvo quizá para los archivos swf, que se crean con Flash.

3n31ch

#5
Explico linea por linea

Código (python) [Seleccionar]

   # Calculo la cantidad de jugadores y seteo los turnos (sin ordenar) con la velocidad
   l = 1 # dado que la primera variable es Player1Speed, l parte en uno
   while True: #se repite por siempre (hasta que ocurra el break)
    try: #contengo el error que ocurrira cuando intente acceder a una variable PlayerNSpeed que no exista
    var = eval('Player'+str(l)+'Speed') #Accedo a la variable PlayerlSpeed (siendo l el número), de no existir se ejecuta exepct
    exec('Turn'+str(l)+' = '+str(var)) #Creo una variable TurnX = PlayerlSpeed
    l += 1 # Le sumo 1 a l, para que la siguiente iteración sea con un número mas.
    except: #lo de abajo se ejecuta en caso de que la variable PlayerlSpeed no exista
    l -= 1 #dado que PlayerlSpeed no existe, tengo que restar 1 a l, (osea si el total de players eran 4, cuando ocurra el error l será 5, me interesa que vuelva a 4
    break #salgo del ciclo while


Como ves l nunca es negativo. Un ejemplo de la ejecución del código con dos players sería:


Player1Speed = 2
Player2Speed = 1
l = 1
Iteración 1:

var = Player1Speed
Turn1 = var
l = l + 1 #osea 2

Iteración 2:
var = Player2Speed
Turn2 = var
l = l  + 1 #osea 3

Iteración 3:
var  = Player3Speed <- #ERORR!!!! ESTO NO SE PUEDE EJECUTAR PORQUE LA VARIABLE NO EXISTE.
l =  l -1 #Osea vuelve a dos
break #dejo de iterar

#RESULTADOS OBTENIDOS POR EL CÓDIGO DE ARRIBA
Turn1 = 1 #velocidad del primer jugador
Turn2 = 2 #velocidad del segundo jugador
l = 2 #cantidad de jugadores


PD: Yo separe eval de exec, pero en vez de pasar de Player1Speed a var y de var a Turn1 puedes hacerlo directo: Turn1 = Player1Speed

Recomendación:
No sigas por este camino, los arrays existen por algo, trabajar con variables independientes hará que tu código sea dificil de leer y mantener. Puedo entender que no quieras usar switch y case, o incluso que no quieras usar for (aun cuando es mucho mas "controlable" que while), pero no usar arrays solo te limitará como programador. Es tu decisión, pero no puedo evitar hacerte esta recomendación.

Danielㅤ

Hola, una pequeña mejora y recomendación al código del compañero 3n31ch es la siguiente:

Se puede cambiar ésto:

Código (python) [Seleccionar]
l = 1
while True:
try:
var = eval('Player'+str(l)+'Speed')
exec('Turn'+str(l)+' = '+str(var))
l += 1
except:
l -= 1
break


Por esto:

Código (python) [Seleccionar]

l = 1
continuarBucle = True
while continuarBucle:
    try:
        var = eval('Player'+str(l)+'Speed')
        exec('Turn'+str(l)+' = '+str(var))
        l += 1
    except:
        l -= 1
        continuarBucle = False


de esa manera se estaría usando semáforos y no se detendría el bucle tan bruscamente con break.


Saludos
¡Regresando como cual Fenix! ~
Bomber Code © 2021 https://www.bombercode.net/foro/

Ayudas - Aportes - Tutoriales - Y mucho mas!!!

3n31ch

#7
Si correcto, muchas gracias Daniel. Una forma de no usar break es poner el condicional en el while. Ahora, para mi es mas facil de entender un código con break "Si pasa esto me salgo del ciclo en el que estoy" a con una condición while "Si pasa esto cambio el booleano a falso, luego pueden o no pasar cosas, en la siguiente iteración me salgo.". Fuera de eso, no sé si hay algún problema a nivel de ejecución (velocidades o cosas) pero en caso de no haberlo prefiero el break.

Nota: Esto que digo solo aplica si hay una condicional booleana que se altere en medio del código, en caso contrario, en efecto puede ser mejor la condición en el while. Supongo que es tema de preferencias. No estoy seguro si Clean Code habla de esto.

Aunque en tu caso en Macro Flash tengo entendido que tienes el do-while (si al terminar pasa esto me salgo), puede que lo prefieras.

De todas formas si el tema es hacerlo lo mas reducido y correcto posible (con bubble) quizás la opción correcta sea algo como esto:

Código (python) [Seleccionar]

# Seteo de variables
Player1Speed = 2
Player2Speed = 3
Player3Speed = 1
Player4Speed = 4

# Calculo la cantidad de jugadores y seteo y orden de turnos.
l = 0
while f"Player{l+1}Speed" in globals(): #verifico si la variable i+1 existe (ahora no hay error de try except)
l+=1
exec(f'Turn{l} = "Player{l}"') #seteo Turn1 directamente con el nombre del player
j = l
while 1 < j: #ordenamiento burbuja "inverso" directamente en la definición de variables
if(eval(eval(f'Turn{j-1}') + str('Speed')) < eval(eval(f'Turn{j}') + str('Speed'))): #si el player actual es mas rapido que el anterior entonces ejecuto lo siguiente
exec(f'Turn{j}, Turn{j-1} = Turn{j-1}, Turn{j}') #intercambio el player actual con el anterior
else: #en caso contrario
break #me salgo de este ciclo, ya que los anteriores estan ordenados
j-= 1 #resto a j-1

#imprimir resultados
i = 1
while i <= l:
print(f'Turn{i} = {eval("Turn" + str(i))}')
i += 1

Tachikomaia

No me da el cerebro para entender el código. ¿Podría alguien decirme los outputs de las 3 últimas partes? Gracias.

3n31ch

Te envíe un mensaje privado para ver si te lo puedo explicar por otro medio. No obstante no te entiendo. Te refieres a explicarte a detalle lo que pasa en la sección 3. bubble sort, 4. remplazo de velocidad y 5. impresión de resultados?