txt
con la lista de números aleatorios y la solución por los procedimientos Primero y Segundo¶# FUNCIONES
from random import sample, seed
seed()
def lista_ordenada(lis, orden_inverso=False): # la función da True si ponemos lista_ordenada([4,3,2,1], orden_inverso=True)
ordenada = False
aux = lis[:]
aux.sort(reverse=orden_inverso)
if aux == lis:
ordenada = True
return ordenada
def sa(a,b):
if len(a) > 1: a[0],a[1] = a[1],a[0]
return a,b
def sb(a,b):
if len(b) > 1: b[0],b[1] = b[1],b[0]
return a,b
def ss(a,b):
sa(a,b)
sb(a,b)
return a,b
def pa(a,b):
if len(b) > 0:
a.insert(0, b[0])
b.pop(0)
return a,b
def pb(a,b):
if len(a) > 0:
b.insert(0, a[0])
a.pop(0)
return a,b
def ra(a,b):
if len(a) > 1: a.append(a.pop(0))
return a,b
def rb(a,b):
if len(b) > 1: b.append(b.pop(0))
return a,b
def rr(a,b):
ra(a,b)
rb(a,b)
return a,b
def rra(a,b):
if len(a) > 1: a.insert(0, a.pop())
return a,b
def rrb(a,b):
if len(b) > 1: b.insert(0, b.pop())
return a,b
def rrr(a,b):
rra(a,b)
rrb(a,b)
return a,b
def separa(tramo, n, s, a, b): # se llevan de la pila A a la B los números del tramo que toca
contador = 0
ancho = int(n/s)
fin = tramo * ancho # fin del tramo
inicio = (tramo-1)*ancho+1 # inicio del tramo
pasados = 0 # cuenta cuantos números se han pasado de la pila A a la B
while pasados < fin-inicio+1: # recorremos los elementos de la plia A hasta que pasemos todos los números de este tramo
if inicio <= a[0] <= fin:
pb(a,b)
contador += 1
pasados += 1
else:
ra(a,b)
contador += 1
return a, b, contador
def ordena(tramo, n, s, a, b): # Pasamos de B a A los del tramo que toca, comenzando por el nº mayor, que para el tramo 1 es 5.
# ordena los números recientemente separados y llevados a B
# el objetivo es que esos números queden en B ordenados de forma decreciente: 5,4,3,2,1
contador = 0
ancho = int(n/s)
fin = tramo * ancho # fin del tramo
inicio = (tramo-1)*ancho+1 # inicio del tramo
while not lista_ordenada(b, orden_inverso=True): # se repite hasta que B quede ordenada decrecientemente. Si solo queda un elemento en B es que está ordenada
while max(b) != b[0]: # buscamos el máximo y vamos haciendo ra o rra hasta que quede el primero
if b.index(max(b)) <= int(len(b)/2):
rb(a,b)
else:
rrb(a,b)
contador += 1
if not lista_ordenada(b, orden_inverso=True):
pa(a,b); contador += 1
while len(a) > n-fin: # llevamos de A a B los números del tramo que toca
pb(a,b); contador += 1
return a, b, contador
def ordena_final(tramo, n, s, a, b): # ordena los números del úlitmo tramo que están en "A" y el objetivo es que queden crecientes: ...,18,19,20.
contador = 0
ancho = int(n/s)
fin = n # en el último tramo se ajusta para que el último nº sea igual a n
inicio = (tramo-1)*ancho+1 # inicio del tramo
while not lista_ordenada(a): # se repite hasta que A quede ordenada en orden creciente. Si solo queda un elemento en A es que está ordenada
while min(a) != a[0]:
if a.index(min(a)) <= int(len(a)/2):
ra(a,b)
else:
rra(a,b)
contador += 1
if not lista_ordenada(a):
pb(a,b); contador += 1
while len(b) > 0: # llevamos de B a A todos los números que hay en B
pa(a,b); contador += 1
return a, b, contador
for n in [20000]:
print("n:", n)
# Generación de la pila A
#n = 500 # n=número de elementos de la pila
s_optimo = 0 # inicializamos el valor óptimo de s
while True: # evita que se genere justo la lista A con los números ya ordenados
a = sample(range(1, n+1), n)
if not lista_ordenada(a):
break
a_original = a[:]
b = []
###### PROCEDIMIENTO PRIMERO ######
'''
contador = 0
while not lista_ordenada(a): # se repite hasta que A quede ordenada. Si solo queda un elemento en A es que está ordenada
while min(a) != a[0]: # buscamos el mínimo y vamos haciendo ra o rra hasta que quede el primero
if a.index(min(a)) <= int(len(a)/2):
ra(a,b)
else:
rra(a,b)
contador += 1
if not lista_ordenada(a):
pb(a,b); contador += 1 #print(a,b) # luego hacemos pb
while len(b) > 0: # luego se hace pa pa pa pa hasta que no quede nadie en la pila b
pa(a,b); contador += 1
primero = contador
print("PRIMERO:", primero)
'''
#### procedimiento SEGUNDO para varios valores de s en un cierto rango
lista_pasos = [0,0] # en esta lista recogemos cuántos pasos (ordenes) se necesitan por el procedimiento SEGUNDO para cada s, ponemos dos cero pq s comienz en 2
inicio_s = 60 # inicio_s es 2 para valores pequeños, hasta n=90
fin_s = 95
for s in range(inicio_s, fin_s):
###### PROCEDIMIENTO SEGUNDO ######
a = a_original[:]
n = len(a)
b = []
contador = 0
for tramo in range(1, s): # tramo=1,2,...,s-1. El último tramo se trata de forma diferente
a, b, contador_separa = separa(tramo,n,s,a,b) # lleva de A a B los números correspondientes a ese tramo
contador += contador_separa
a, b, contador_ordena = ordena(tramo,n,s,a,b) # ordena los números recientemente separados y llevados a B
contador += contador_ordena
# tramo final donde los números de A ya se ordenan en A, ya no se usa la función separa
# la pila de trabajo es "A" y el objetivo es que sea creciente: ...,18,19,20.
a, b, contador_ordena_final = ordena_final(tramo,n,s,a,b)
contador += contador_ordena_final
segundo = contador
lista_pasos.append(segundo)
print("s:", s, "SEGUNDO:", segundo)
optimo_segundo = min(lista_pasos[2:])
s_optimo = lista_pasos.index(optimo_segundo) + (inicio_s-2)# valor óptimo de s, por ejemplo el óptimo se alzanza en s=5
### ESCRIBIR ARCHIVO txt ###
texto = ''
for i in a_original:
if i==1: valor = -2**32//2 # el mínimo int en C es -2147483648
elif i==2: valor = -32768
elif i==3: valor = 0
elif i==4: valor = 32767
elif i==5: valor = 2**32//2-1 # el máximo int en C es 2147483647
else: valor = i
texto += ''.join(str(valor)) + ' '
texto = texto[:-1]
primero = 0
with open('/content/sample_data/'+ str(n) + '_' + str(primero) + '_' + str(optimo_segundo) + '_' + str(s_optimo) + '.txt', 'w') as writefile:
writefile.write(texto)
n: 20000 s: 50 SEGUNDO: 1897534 s: 51 SEGUNDO: 1881800 s: 52 SEGUNDO: 1860620 s: 53 SEGUNDO: 1846975 s: 54 SEGUNDO: 1838064 s: 55 SEGUNDO: 1825757 s: 56 SEGUNDO: 1815955 s: 57 SEGUNDO: 1804842 s: 58 SEGUNDO: 1789726 s: 59 SEGUNDO: 1780909 s: 60 SEGUNDO: 1771676 s: 61 SEGUNDO: 1763111 s: 62 SEGUNDO: 1754555 s: 63 SEGUNDO: 1753958 s: 64 SEGUNDO: 1751075 s: 65 SEGUNDO: 1746238 s: 66 SEGUNDO: 1732761 s: 67 SEGUNDO: 1727379 s: 68 SEGUNDO: 1721616 s: 69 SEGUNDO: 1717974 s: 70 SEGUNDO: 1715755 s: 71 SEGUNDO: 1709268 s: 72 SEGUNDO: 1719015 s: 73 SEGUNDO: 1716419 s: 74 SEGUNDO: 1708077 s: 75 SEGUNDO: 1707089 s: 76 SEGUNDO: 1707764 s: 77 SEGUNDO: 1715409 s: 78 SEGUNDO: 1702141 s: 79 SEGUNDO: 1699896 s: 80 SEGUNDO: 1701886 s: 81 SEGUNDO: 1707786 s: 82 SEGUNDO: 1699309 s: 83 SEGUNDO: 1704034 s: 84 SEGUNDO: 1709128 s: 85 SEGUNDO: 1703836 s: 86 SEGUNDO: 1706841 s: 87 SEGUNDO: 1706652 s: 88 SEGUNDO: 1703335 s: 89 SEGUNDO: 1703660 s: 90 SEGUNDO: 1712126 s: 91 SEGUNDO: 1710044 s: 92 SEGUNDO: 1709844 s: 93 SEGUNDO: 1715752 s: 94 SEGUNDO: 1718782 s: 95 SEGUNDO: 1721078 s: 96 SEGUNDO: 1722592 s: 97 SEGUNDO: 1722750 s: 98 SEGUNDO: 1726514 s: 99 SEGUNDO: 1732867
!zip -r /content/sample_data/casos.zip /content/sample_data/*.txt