Google Code Jam 2014 ... con obstáculos - Qualification Round
Preparando el concurso
Dado que la entrada y salida de datos es siempre exactamente igual he hecho una plantilla que usaré en todos los retos:
# -*- coding: utf-8 -*-
#!/usr/bin/python
import sys
import time
def getValue(inputFile, dataType="string"):
line = ""
value = 0
while len(line) < 1:
line = inputFile.readline()
if dataType == "string":
value = line.split()[0]
elif dataType == "integer":
value = int(line.split()[0])
elif dataType == "float":
value = float(line.split()[0])
return value
def getList(inputFile, dataType="string", separator="space"):
# dataType could be string, integer and float
# separator can be space or none
datalist = []
line = ""
while len(line) < 1:
line = inputFile.readline()
if separator == "space":
datalist = line.split()
elif separator == "none":
line = line.rstrip('\n')
for i in range(len(line)):
datalist.append(line[i])
#if dataType=="string": ... already a string
if dataType == "integer":
i = 0
while (i < len(datalist)):
datalist[i] = int(datalist[i])
i = i + 1
elif dataType == "float":
i = 0
while (i < len(datalist)):
datalist[i] = float(datalist[i])
i = i + 1
return datalist
def getBoard(inputFile, dimX, dimY, dataType="string", separator="none"):
board = []
for y in range(dimY):
board.append(getList(inputFile, dataType, separator))
return board
def printBoard(board, array="0"):
#print board
for i in range(len(board)):
for j in range(len(board[i])):
if array == "1":
sys.stdout.write("[\"" + str(board[i][j]) + "\"]")
else:
sys.stdout.write(str(board[i][j]))
print ("")
### solve it! ###
def solveIt(inputs, values, board):
# time.sleep(1)
# print ""
# print inputs
# print values
# print board
res = []
i = 0
j = 1
res.append(i)
res.append(j)
return res
if __name__ == '__main__':
# Open input and output files
inputFile = open(sys.argv[1], 'r')
outputFile = open(sys.argv[2], 'w')
# Get number of cases
NoC = int(getValue(inputFile))
# for each case
for i in range(NoC):
# get case data
inputs = getValue(inputFile, "integer")
values = getList(inputFile, "integer")
board = getBoard(inputFile, "integer")
# solve problem
res = solveIt(inputs, values, board)
# write data
outputFile.write("Case #" + str(i + 1) + ": " + str(res[0] + 1) + " " + str(res[1] + 1) + "\n")
# print "Case #"+str(i+1)+": "+str(res[0]+1)+" "+str(res[1]+1)
# Close input and output files
inputFile.close()
outputFile.close()
Y pensarás ¿no puedes hacer eso el día del concurso? Pues no porque tengo los minutos contados. 10 minutos pueden suponer la diferencia entre que de tiempo a resolver un problema o no.
Insomnio provocado
4:00Aprovecho una subida de fiebre del niño para despertarme del todo y valorar la dificultad de los problemas.
Esta vez me voy directo al "Contest scoreboard" donde veo que los mejores tardan 15 minutos en resolver el primero, otros 15 el segundo y alrededor de una hora el tercero y el cuarto así que supongo que los fáciles son el primero y el segundo.
Tras leer el primero, parece más una broma que un problema. El segundo también parece fácil pero necesita de una lectura más profunda del problema y con menos sueño.
Mañana será otro día. Bueno, hoy dentro de un rato será otro día.
Problem A. Magic Trick
7:30Este problema es facilísimo. Nos dan dos arrays distintos en los que los números cambian de posición y nos piden que busquemos los números de una fila del primer array en otra fila del segundo array.
- Si se encuentran 2 -> Case #x: Bad magician!
- Si no se encuentran -> Volunteer cheated!
- Si se encuentra 1 -> Case #x: x
Tras un "tengo pis" y un "dale el antibiótico al niño" la solución, utilizando la plantilla como librería es la siguiente contenida en la función solveIt:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import time
import sys
import gcjtemplate
### solve it! ###
def solveIt(row1,board1,row2,board2):
res=[]
for i in board2[row2-1]:
if i in board1[row1-1]:
res.append(i)
return res
if __name__=='__main__':
# Open input and output files
inputFile=open(sys.argv[1],'r')
outputFile=open(sys.argv[2],'w')
# Get number of cases
NoC=int(gcjtemplate.getValue(inputFile))
# for each case
for i in range(NoC):
# get case data
row1=gcjtemplate.getValue(inputFile,"integer")
board1=gcjtemplate.getBoard(inputFile,4,4,"integer","space")
row2=gcjtemplate.getValue(inputFile,"integer")
board2=gcjtemplate.getBoard(inputFile,4,4,"integer","space")
# solve problem
res=solveIt(row1, board1, row2, board2)
# write data
if len(res)==0:
outputFile.write("Case #"+str(i+1)+": Volunteer cheated!\n")
print ("Case #"+str(i+1)+": Volunteer cheated!")
elif len(res)==1:
outputFile.write("Case #"+str(i+1)+": "+str(res[0])+"\n")
print ("Case #"+str(i+1)+": "+str(res[0]))
elif len(res)>1:
outputFile.write("Case #"+str(i+1)+": Bad magician!\n")
print ("Case #"+str(i+1)+": Bad magician!")
else:
time.sleep(5)
print "HELP, HELP!"
# Close input and output files
inputFile.close()
outputFile.close()
Problem B. Cookie Clicker Alpha
8:45En este problema la dificultad está más en comprenderlo que en resolverlo.
Tu objetivo es llegar a tener un número de galletas en el menor tiempo posible. Empiezas con una fábrica de galletas y que te ha costado x galletas. Cuando llegas a esas x galletas puedes elegir entre comprar una fábrica para doblar la capacidad de producción o seguir produciendo como hasta ahora.
Se trata de elegir la mejor estrategia para decir cual es el menor número de segundos que se tarda en llegar a conseguir el número de galletas que queremos.
Hay que tener en cuenta que nos dan unos límites que, aunque en python nos dan igual, en otros lenguajes nos vienen bien para elegir el tipo de datos.
9:09Se levanta la tropa, les llevo al parque, reunión familiar, comilona, ...
23:43Estoy a 1:15 de decidir si paso a la siguiente fase o no. En teoría es factible pero no me gusta ir tan corto de tiempo.
00:35El que nos den 8 minutos para entregar el resultado de nuestro programa en vez de los 4 habituales es un indicador de que puede ser bastante costoso en términos computacionales.
Este problema es de naturaleza recursiva ya que para decidir entre comprar o no comprar otra fábrica de galletas hay que saber qué es lo que pasaría si no se comprara otra o qué pasaría si se comprara otra, en cuyo caso habría que volver a saber qué es lo que pasaría si no se comprara otra o qué pasaría si se comprara otra, ... hasta que viéramos que deja de salir a cuenta comprar otra fábrica.
Sin embargo el problema se puede enfocar desde un punto de vista más lineal si pensamos en qué vamos a basar la decisión final: si con la capacidad de producción que tengo ahora tardo menos en producir las galletas que aumentando la producción en una fábrica más es que no debo comprar más fábricas.
Ignorando el resto de la plantilla que he puesto arriba del todo, la solución es la siguiente:
### solve it! ###
def solveIt(c,f,x):
res=0.0
speed=2
cookies=0.0
spentSeconds=0
finish=0
while finish==0:
withoutMoreFarms=x/speed
secondsToBuyFarm=c/speed
newSpeed=speed+f
withOneMoreFarm=secondsToBuyFarm+x/newSpeed
if withOneMoreFarm< withoutMoreFarms:
spentSeconds=spentSeconds+secondsToBuyFarm
speed=newSpeed
else:
spentSeconds=spentSeconds+withoutMoreFarms
finish=1
# print "spentSeconds: "+str(spentSeconds)
res=spentSeconds
return res
if __name__=='__main__':
# Open input and output files
inputFile=open(sys.argv[1],'r')
outputFile=open(sys.argv[2],'w')
# Get number of cases
NoC=int(getValue(inputFile))
# for each case
for i in range(NoC):
# get case data
c,f,x=getList(inputFile,"float")
# solve problem
res=solveIt(c,f,x)
# write data
outputFile.write("Case #"+str(i+1)+": "+str(round(res,7))+"\n")
#print "Case #"+str(i+1)+": "+str(round(res,7))
# Close input and output files
inputFile.close()
outputFile.close()
Una vez enviada la respuesta al Large Set te indican que:
You have already tried this input set. (Judged at the end of the contest.)
Así que no hay forma de saber si ya tengo los 25 puntos que necesito o no.
¿Mas?
1:00Pues va a ser que a estas horas lo que me apetece es dormir. Mañana publicaré este post y el resultado del concurso.
9:20¡He pasado!
Lo que no entiendo muy bien es cómo puede haber gente que lo haya hecho peor todavía que yo y haber pasado también, pero ahí están los resultados.
Para la próxima a mirar la librería multiprocessing que me hará falta para utilizar todos los cores de mi máquina.
