# FUNCIONES
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
# PASOS NECESARIOS PARA COLOCAR CADA ELEMENTO DE A EN SU SITIO EN B total = pasosA + pasosB (esta suma es solo una idea, se ha de sumar de una forma peculiar)
def necesariosA(a, b): # array pasosA calcula los pasos necesarios para colocar cada elemento de A como el primero de su pila
for v in a:
if a.index(v) < len(a)/2:
pasosA.append(a.index(v))
else:
pasosA.append(-(len(a)- a.index(v)))
def necesariosB(a,b): # array pasosB calcula los pasos de B necesarios para colocar cada elemento de A dentro de su sitio en B
for i in range(len(a)): # objetivo_primero es el número que se ha de poner en la primera posición de la pila B
if a[i] < min(b): # si el elemento de A considerado es menor que el mayor de B entonces
objetivo_primero = max(b) # el objetivo_primero será el mayor de B
else: # objetivo_primero en este caso será el maximo de los inferiores en B al valor iésimo de A
objetivo_primero = min(b) #se inicializa en el valor mínimo de la pila B
for j in range(len(b)):
if b[j] < a[i] and b[j] > objetivo_primero:
objetivo_primero = b[j]
# el objetivo_primero se ha de situar el primero de la pila B
if b.index(objetivo_primero) < len(b)/2:
pasosB.append(b.index(objetivo_primero))
else:
pasosB.append(-(len(b)- b.index(objetivo_primero)))
def totaliza(a,b): # totalizar pasos
global total
for i in range(len(pasosA)):
if pasosA[i] * pasosB[i] < 0: # si son de distinto signo, uno positivo y otro negativo
total.append(abs(pasosA[i]) + abs(pasosB[i])) # no hay sinergia
else: # si son de igual signo o alguno cero
total.append(max(abs(pasosA[i]), abs(pasosB[i]))) # si son de igual signo hay sinergia
def calculaIndexPasosMinimos():
global pasosA, pasosB, total
pasosA = [] # [0,1,2, ...,41,-41,... , -2,-1] vector donde cada index está asociado con el valor del mismo index en A
pasosB = [] # [-3,2,-5, ..., -5,0] estos dos arrays se han de recalcular cada vez que realmente se mueva algún elemento de A a B
total = []
necesariosA(a, b)
necesariosB(a, b)
totaliza(a,b)
return total.index(min(total)) # retorna el índice del elemento de la pila A que menos pasos totales necesita
def giraA(a, b, indice, pasos):
global contador
for i in range(abs(pasos)):
if pasos > 0:
ra(a,b); contador += 1
elif pasos < 0:
rra(a,b); contador += 1
def giraB(a, b, indice, pasos):
global contador
for i in range(abs(pasos)):
if pasos > 0:
rb(a,b); contador += 1
elif pasos < 0:
rrb(a,b); contador += 1
# girando pilas A y B
def giraPilas(a,b,indice): # indice es el index del valor en la pila A que deseamos poner el primero
global contador
if pasosA[indice] * pasosB[indice] > 0: # Existe sinergia, nos podemos ahorrar pasos
pasos_comunes = min(abs(pasosA[indice]), abs(pasosB[indice]))
for i in range(pasos_comunes):
if pasosA[indice] > 0: # si el signo de ambos es positivo, ya que ambos tienen el mismo signo
rr(a,b); contador += 1
elif pasosA[indice] < 0: # si el signo de ambos es negativo
rrr(a,b); contador += 1
exceso_pasosA = abs(pasosA[indice]) - pasos_comunes
exceso_pasosB = abs(pasosB[indice]) - pasos_comunes
giraA(a, b, indice, ((pasosA[indice] > 0) - (pasosA[indice] < 0)) * exceso_pasosA) # (a > 0) - (a < 0) da el signo de a
giraB(a, b, indice, ((pasosB[indice] > 0) - (pasosB[indice] < 0)) * exceso_pasosB) # Python no tiene función sign
else: # No existe sinergia
giraA(a ,b, indice, pasosA[indice]) # gira A
giraB(a, b, indice, pasosB[indice]) # gira B
def crecientesA(a,b): # función que comprueba que en A están crecientes estrictos y sino lo consigue
global contador
if len(a) != 3:
print("ERROR: en A no hay tres números")
elif a[0] < a[1] > a[2] and a[0] < a[2]: # caso: 1 3 2
ra(a,b); contador += 1
sa(a,b); contador += 1
rra(a,b); contador += 1
elif a[0] > a[1] < a[2] and a[0] < a[2]: # caso: 2 1 3
sa(a,b); contador += 1
elif a[0] < a[1] > a[2] and a[0] > a[2]: # caso: 2 3 1
rra(a,b); contador += 1
elif a[0] > a[1] < a[2] and a[0] > a[2]: # caso: 3 1 2
ra(a,b); contador += 1
elif a[0] > a[1] > a[2]: # caso: 3 2 1
sa(a,b); contador += 1
rra(a,b); contador += 1
return # caso: 1 2 3 en este caso no se hace nada pq ya están ordenados
def situarMax_en_B(): # situa el valor máximo de B en la primera posición de B
indice = b.index(max(b))
if indice < len(a)/2:
pasos = indice
else:
pasos = -(len(b)- indice)
giraB(a, b, indice, pasos)
def cremallera(a,b): # función que va pasando los números de B a A en forma de cremallera, intercalándolos con los que ya hay en A
global contador
aux = [a[-3], a[-2], a[-1]] # los tres últimos valores de A se copian a una array auxiliar
for i in range(3):
while b[0] > max(aux):
pa(a,b); contador += 1
rra(a,b); contador += 1
aux.pop()
while len(b) > 0:
pa(a,b); contador += 1
if __name__ == "__main__":
from random import seed, shuffle
seed()
n = 500 # número de elementos de la pila
contadores = []
fracasos = 0 # cuenta las muestras que al resolverlas no mejoran el límite
for muestra in range(1000):
a = list(range(1, n+1)); shuffle(a) # generación aleatoria de la pila A
#a = [474, 188, 52, 468, 132, 334, 412, 434, 141, 212, 420, 143, 80, 60, 218, 329, 376, 109, 485, 213, 230, 65, 461, 257, 106, 282, 440, 190, 322, 358, 231, 209, 49, 281, 202, 245, 333, 239, 354, 352, 445, 388, 146, 298, 21, 54, 233, 304, 289, 470, 56, 272, 90, 22, 127, 119, 208, 136, 174, 236, 273, 130, 347, 293, 424, 157, 43, 310, 118, 266, 197, 95, 493, 31, 326, 53, 235, 185, 463, 379, 242, 287, 256, 264, 394, 71, 346, 292, 79, 345, 277, 477, 211, 162, 398, 362, 126, 274, 45, 34, 370, 300, 339, 97, 234, 240, 448, 37, 87, 9, 330, 489, 343, 222, 204, 124, 207, 238, 491, 267, 414, 288, 480, 166, 351, 50, 184, 152, 367, 258, 8, 260, 153, 286, 454, 133, 285, 104, 500, 254, 361, 129, 389, 380, 299, 117, 372, 303, 223, 279, 432, 422, 32, 386, 262, 122, 228, 395, 460, 28, 59, 108, 308, 495, 203, 349, 302, 441, 382, 224, 155, 205, 237, 101, 121, 449, 210, 48, 317, 413, 336, 366, 451, 476, 67, 13, 88, 364, 219, 436, 147, 139, 195, 148, 360, 423, 30, 408, 416, 296, 85, 473, 453, 225, 456, 271, 496, 39, 250, 275, 487, 455, 447, 27, 261, 335, 110, 353, 374, 430, 409, 269, 312, 247, 115, 253, 206, 483, 149, 259, 472, 280, 168, 309, 406, 221, 145, 392, 357, 75, 444, 419, 16, 69, 481, 435, 373, 484, 446, 467, 113, 399, 15, 41, 29, 268, 490, 215, 189, 63, 47, 102, 62, 438, 307, 128, 443, 402, 83, 325, 290, 36, 193, 381, 25, 70, 58, 393, 278, 73, 452, 131, 156, 111, 26, 163, 431, 305, 276, 154, 138, 478, 142, 38, 150, 457, 4, 342, 363, 92, 401, 311, 385, 319, 378, 220, 265, 159, 340, 2, 137, 471, 355, 180, 251, 494, 103, 6, 301, 86, 397, 10, 306, 14, 192, 426, 246, 116, 125, 323, 151, 321, 295, 263, 123, 294, 368, 249, 20, 465, 158, 112, 338, 391, 405, 18, 429, 475, 383, 421, 199, 344, 479, 61, 194, 359, 17, 499, 164, 324, 120, 375, 229, 365, 320, 179, 403, 64, 196, 270, 191, 466, 19, 183, 200, 488, 283, 410, 400, 76, 23, 172, 415, 160, 315, 140, 350, 337, 165, 462, 437, 78, 482, 227, 169, 186, 105, 313, 40, 328, 433, 144, 217, 459, 134, 89, 93, 458, 201, 464, 369, 135, 46, 82, 291, 96, 5, 216, 114, 3, 243, 469, 486, 241, 98, 442, 407, 77, 492, 427, 175, 498, 100, 284, 84, 11, 35, 371, 244, 161, 167, 396, 214, 181, 390, 418, 232, 182, 384, 66, 94, 341, 331, 377, 91, 450, 318, 44, 176, 497, 55, 1, 411, 226, 404, 255, 198, 297, 81, 173, 356, 170, 178, 187, 74, 428, 12, 51, 387, 327, 332, 248, 425, 417, 348, 252, 68, 314, 33, 439, 171, 24, 316, 99, 72, 57, 7, 177, 107, 42]
#a = [499, 318, 486, 482, 125, 54, 386, 447, 317, 232, 299, 483, 67, 147, 409, 228, 439, 311, 21, 252, 231, 337, 441, 205, 120, 98, 75, 151, 414, 407, 353, 113, 497, 197, 160, 451, 280, 204, 412, 71, 236, 336, 431, 306, 29, 418, 316, 283, 37, 194, 462, 454, 489, 73, 271, 442, 400, 296, 411, 422, 153, 217, 220, 485, 212, 339, 246, 265, 186, 56, 22, 455, 91, 420, 452, 206, 43, 345, 330, 107, 356, 364, 349, 208, 367, 289, 300, 351, 285, 254, 158, 223, 426, 184, 327, 200, 152, 27, 109, 210, 188, 218, 168, 275, 61, 500, 341, 102, 189, 68, 423, 148, 179, 494, 449, 93, 185, 165, 150, 347, 124, 215, 259, 471, 38, 277, 473, 161, 121, 154, 480, 332, 382, 496, 256, 476, 293, 273, 202, 58, 80, 103, 466, 77, 141, 230, 183, 144, 270, 225, 257, 478, 392, 470, 35, 19, 66, 131, 450, 16, 23, 135, 350, 481, 380, 139, 292, 26, 394, 342, 390, 415, 417, 31, 116, 361, 45, 448, 402, 432, 453, 436, 133, 313, 46, 360, 111, 10, 467, 366, 88, 41, 282, 383, 425, 251, 437, 3, 51, 324, 268, 157, 40, 315, 8, 177, 314, 427, 308, 322, 130, 456, 334, 303, 260, 195, 59, 464, 104, 445, 97, 44, 488, 335, 433, 76, 127, 372, 323, 229, 468, 138, 362, 279, 137, 182, 90, 354, 274, 140, 385, 281, 94, 309, 122, 465, 128, 132, 284, 410, 126, 457, 72, 9, 96, 474, 106, 421, 310, 325, 384, 32, 211, 413, 297, 312, 187, 172, 201, 20, 65, 18, 49, 435, 84, 352, 348, 301, 47, 146, 1, 440, 69, 207, 74, 243, 267, 286, 53, 64, 30, 42, 83, 430, 112, 25, 226, 438, 234, 175, 365, 319, 145, 178, 355, 11, 479, 240, 475, 477, 459, 248, 85, 70, 62, 235, 406, 224, 461, 405, 79, 290, 50, 4, 163, 114, 444, 416, 320, 368, 213, 214, 249, 307, 434, 24, 241, 460, 60, 171, 173, 222, 397, 48, 358, 117, 82, 2, 346, 12, 373, 87, 370, 193, 269, 278, 379, 378, 377, 401, 264, 247, 287, 393, 295, 134, 484, 338, 396, 180, 408, 216, 13, 387, 357, 305, 167, 227, 191, 472, 304, 424, 321, 190, 331, 398, 276, 174, 490, 403, 329, 458, 302, 250, 118, 192, 203, 374, 298, 492, 63, 105, 221, 242, 255, 196, 463, 493, 469, 39, 340, 261, 487, 272, 391, 326, 149, 5, 36, 143, 55, 328, 369, 233, 92, 115, 266, 388, 253, 155, 129, 288, 262, 142, 159, 15, 78, 123, 344, 244, 7, 164, 446, 495, 95, 239, 294, 263, 6, 110, 136, 57, 363, 101, 199, 169, 119, 209, 429, 375, 491, 198, 395, 181, 17, 162, 389, 86, 371, 428, 100, 258, 498, 28, 359, 33, 99, 219, 108, 291, 238, 52, 81, 89, 156, 399, 443, 381, 14, 245, 419, 166, 237, 404, 343, 170, 376, 176, 34, 333]
#a = [130, 456, 274, 302, 112, 15, 145, 258, 392, 223, 271, 121, 63, 139, 261, 443, 454, 398, 169, 113, 481, 357, 89, 235, 189, 137, 19, 221, 299, 179, 380, 286, 39, 135, 384, 490, 414, 317, 208, 260, 109, 471, 199, 81, 239, 342, 362, 18, 34, 106, 58, 192, 440, 97, 347, 418, 395, 88, 497, 238, 365, 183, 394, 71, 309, 378, 275, 155, 452, 346, 164, 319, 131, 247, 119, 241, 233, 266, 182, 415, 405, 37, 273, 449, 21, 105, 292, 170, 6, 227, 448, 178, 325, 180, 460, 185, 305, 334, 498, 150, 437, 320, 489, 359, 285, 115, 422, 50, 249, 222, 29, 375, 46, 404, 290, 219, 306, 134, 374, 26, 430, 262, 328, 122, 85, 494, 234, 4, 156, 376, 107, 323, 246, 32, 232, 110, 5, 428, 441, 253, 284, 90, 370, 31, 73, 464, 175, 160, 420, 64, 43, 158, 432, 388, 315, 25, 203, 461, 254, 53, 9, 322, 442, 243, 382, 195, 294, 487, 467, 493, 439, 217, 270, 488, 202, 13, 176, 24, 312, 499, 141, 447, 483, 78, 87, 101, 291, 209, 371, 174, 251, 72, 213, 462, 484, 240, 49, 127, 455, 353, 76, 52, 161, 366, 339, 410, 445, 476, 267, 311, 344, 196, 321, 403, 473, 350, 167, 255, 333, 67, 30, 118, 406, 336, 154, 263, 100, 99, 138, 236, 408, 478, 75, 287, 153, 463, 225, 324, 184, 205, 230, 193, 326, 303, 220, 466, 272, 417, 293, 116, 197, 425, 349, 393, 48, 348, 479, 340, 57, 33, 431, 16, 194, 474, 140, 450, 256, 103, 446, 429, 358, 91, 69, 104, 114, 424, 228, 277, 84, 332, 128, 438, 373, 396, 318, 399, 401, 206, 191, 372, 279, 264, 136, 20, 40, 177, 68, 45, 51, 2, 201, 492, 368, 14, 3, 10, 148, 36, 83, 295, 337, 281, 278, 495, 35, 23, 468, 65, 351, 92, 444, 343, 152, 402, 423, 56, 198, 289, 459, 120, 226, 126, 129, 61, 55, 296, 132, 330, 218, 204, 207, 390, 95, 407, 389, 491, 257, 331, 8, 96, 316, 22, 62, 242, 7, 469, 363, 47, 400, 345, 159, 327, 111, 133, 265, 27, 66, 165, 369, 54, 470, 149, 248, 163, 94, 397, 237, 383, 361, 250, 308, 172, 313, 11, 475, 412, 151, 338, 377, 244, 457, 434, 252, 59, 379, 187, 38, 280, 360, 453, 485, 215, 352, 356, 297, 409, 168, 367, 162, 188, 387, 44, 472, 1, 108, 465, 146, 144, 482, 173, 426, 283, 166, 314, 310, 413, 298, 435, 364, 181, 42, 143, 433, 451, 421, 157, 142, 304, 329, 86, 276, 210, 300, 231, 147, 335, 216, 301, 354, 212, 268, 436, 211, 288, 17, 229, 307, 12, 419, 79, 500, 355, 496, 486, 123, 74, 171, 341, 41, 77, 124, 259, 427, 411, 480, 28, 82, 269, 282, 200, 385, 60, 125, 386, 102, 224, 190, 93, 391, 214, 80, 117, 186, 477, 458, 416, 70, 98, 245, 381]
a_original = a[:]
b = []
contador = 0 # contador de pasos
pb(a,b); contador += 1 # bajamos el primer número de A a B
pb(a,b); contador += 1 # bajamos el segundo número de A a B
while len(a)>3:
index_minimosPasos = calculaIndexPasosMinimos()
giraPilas(a, b, index_minimosPasos)
pb(a,b); contador += 1 # lo pasa de A a B haciendo pb
crecientesA(a,b) # función que comprueba que en A están crecientes estrictos y sino lo consigue
situarMax_en_B() # situa el valor máximo de B en la primera posición de B
cremallera(a,b) # función que va pasando los números de B a A en forma de cremallera, intercalándolos con los que ya hay en A
contadores.append(contador)
if contador >= 5500:
fracasos += 1
print(contador, round(fracasos/muestra*100,1), "%", fracasos, "/", muestra)
print("maximo contadores: ", max(contadores))
5516 3.3 % 1 / 30 5522 4.4 % 2 / 45 5513 5.7 % 3 / 53 5741 6.7 % 4 / 60 5647 8.2 % 5 / 61 5529 6.0 % 6 / 100 5500 6.1 % 7 / 115 5624 6.8 % 8 / 118 5600 6.9 % 9 / 130 5512 7.5 % 10 / 133 5577 8.1 % 11 / 136 5649 8.5 % 12 / 141 5607 8.4 % 13 / 155 5508 8.4 % 14 / 166 5526 8.9 % 15 / 169 5520 9.2 % 16 / 174 5681 9.5 % 17 / 179 5553 9.5 % 18 / 190 5579 8.4 % 19 / 226 5503 8.5 % 20 / 234 5576 8.8 % 21 / 238 5505 9.1 % 22 / 242 5538 9.3 % 23 / 247 5552 9.4 % 24 / 254 5543 9.5 % 25 / 262 5535 9.4 % 26 / 278 5559 9.2 % 27 / 295 5556 9.4 % 28 / 297
--------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-6-fc11bce1eae5> in <module> 20 crecientesA(a,b) # función que comprueba que en A están crecientes estrictos y sino lo consigue 21 situarMax_en_B() # situa el valor máximo de B en la primera posición de B ---> 22 cremallera(a,b) # función que va pasando los números de B a A en forma de cremallera, intercalándolos con los que ya hay en A 23 contadores.append(contador) 24 if contador >= 5500: <ipython-input-5-caeeb6f693e5> in cremallera(a, b) 11 aux = [a[-3], a[-2], a[-1]] # los tres últimos valores de A se copian a una array auxiliar 12 for i in range(3): ---> 13 while b[0] > max(aux): 14 pa(a,b); contador += 1 15 rra(a,b); contador += 1 IndexError: list index out of range
print(a_original)
print()
[130, 456, 274, 302, 112, 15, 145, 258, 392, 223, 271, 121, 63, 139, 261, 443, 454, 398, 169, 113, 481, 357, 89, 235, 189, 137, 19, 221, 299, 179, 380, 286, 39, 135, 384, 490, 414, 317, 208, 260, 109, 471, 199, 81, 239, 342, 362, 18, 34, 106, 58, 192, 440, 97, 347, 418, 395, 88, 497, 238, 365, 183, 394, 71, 309, 378, 275, 155, 452, 346, 164, 319, 131, 247, 119, 241, 233, 266, 182, 415, 405, 37, 273, 449, 21, 105, 292, 170, 6, 227, 448, 178, 325, 180, 460, 185, 305, 334, 498, 150, 437, 320, 489, 359, 285, 115, 422, 50, 249, 222, 29, 375, 46, 404, 290, 219, 306, 134, 374, 26, 430, 262, 328, 122, 85, 494, 234, 4, 156, 376, 107, 323, 246, 32, 232, 110, 5, 428, 441, 253, 284, 90, 370, 31, 73, 464, 175, 160, 420, 64, 43, 158, 432, 388, 315, 25, 203, 461, 254, 53, 9, 322, 442, 243, 382, 195, 294, 487, 467, 493, 439, 217, 270, 488, 202, 13, 176, 24, 312, 499, 141, 447, 483, 78, 87, 101, 291, 209, 371, 174, 251, 72, 213, 462, 484, 240, 49, 127, 455, 353, 76, 52, 161, 366, 339, 410, 445, 476, 267, 311, 344, 196, 321, 403, 473, 350, 167, 255, 333, 67, 30, 118, 406, 336, 154, 263, 100, 99, 138, 236, 408, 478, 75, 287, 153, 463, 225, 324, 184, 205, 230, 193, 326, 303, 220, 466, 272, 417, 293, 116, 197, 425, 349, 393, 48, 348, 479, 340, 57, 33, 431, 16, 194, 474, 140, 450, 256, 103, 446, 429, 358, 91, 69, 104, 114, 424, 228, 277, 84, 332, 128, 438, 373, 396, 318, 399, 401, 206, 191, 372, 279, 264, 136, 20, 40, 177, 68, 45, 51, 2, 201, 492, 368, 14, 3, 10, 148, 36, 83, 295, 337, 281, 278, 495, 35, 23, 468, 65, 351, 92, 444, 343, 152, 402, 423, 56, 198, 289, 459, 120, 226, 126, 129, 61, 55, 296, 132, 330, 218, 204, 207, 390, 95, 407, 389, 491, 257, 331, 8, 96, 316, 22, 62, 242, 7, 469, 363, 47, 400, 345, 159, 327, 111, 133, 265, 27, 66, 165, 369, 54, 470, 149, 248, 163, 94, 397, 237, 383, 361, 250, 308, 172, 313, 11, 475, 412, 151, 338, 377, 244, 457, 434, 252, 59, 379, 187, 38, 280, 360, 453, 485, 215, 352, 356, 297, 409, 168, 367, 162, 188, 387, 44, 472, 1, 108, 465, 146, 144, 482, 173, 426, 283, 166, 314, 310, 413, 298, 435, 364, 181, 42, 143, 433, 451, 421, 157, 142, 304, 329, 86, 276, 210, 300, 231, 147, 335, 216, 301, 354, 212, 268, 436, 211, 288, 17, 229, 307, 12, 419, 79, 500, 355, 496, 486, 123, 74, 171, 341, 41, 77, 124, 259, 427, 411, 480, 28, 82, 269, 282, 200, 385, 60, 125, 386, 102, 224, 190, 93, 391, 214, 80, 117, 186, 477, 458, 416, 70, 98, 245, 381]
Idea 1
Idea 2