instrucciones ▶ representar las posiciones y direcciones ▶ aplicar las instrucciones ▶ calcular la distancia Manhattan input = """ L2, L5, L5, R5, L2, L4, R1, R1, L4, R2, R1, … """ (0, 0) hacia el Norte N S W E 2 5 5 (3, -5) → dist=8
mismo sitio, terminamos def solve(input): input = [s.strip() for s in input.split(',')] direction = N pos = Vector(0, 0) already_visited = {pos} for step in input: instruction = Instruction(LEFT if step[0] == 'L' else RIGHT, int(step[1:])) direction = turn(direction, instruction.side) for _ in range(0, instruction.advance): pos = advance(pos, direction) if pos in already_visited: return pos already_visited.add(pos) return pos # no se ha repetido ninguna posición
s in input.split(',')] direction = 0+1j # (0,1) pos = 0+0j # (0,0) already_visited = {pos} for step in input: side, advance = step[0], int(step[1:]) direction *= 1j if side == 'L' else -1j for _ in range(advance): pos += direction if pos in already_visited: return pos already_visited.add(pos) return pos if __name__ == '__main__': input = """ … """ pos = solve(input) dist = abs(pos.real) + abs(pos.imag) print "distance to (0,0) = %d" % (dist,) http://mathworld.wolfram.com/Rotation.html N S W E eje real eje imaginario números complejos operaciones con números complejos • suma: 3+5j + 2-4j = 5+1j • rotación: • 90º izquierda = mult por 0+1j • 90º derecha = mult por 0-1j (2,4) = 2+4j
raavrd atevrs tsrnev sdttsa rasrtv nssdts ntnada … """ ▶ https://adventofcode.com/2016/day/6 ▶ convertir las columnas en listas → transponer ▶ contar la frecuencia de las letras ▶ quedarse con el máximo de cada columna
assert all(len(message) == ncolumns for message in messages) # columns = [[]] * ncolumns # bad!! columns = [[] for i in range(ncolumns)] for i in range(ncolumns): for message in messages: columns[i].append(message[i]) # o también for i, column in enumerate(columns): for message in messages: column.append(message[i]) messages = """ eedadn drvtee eandsr … """ # o también for message in messages: for char, column in zip(message, columns): column.append(char) # o también for i, column in enumerate(columns): column = [message[i] for message in messages] # o también columns = [[message[i] for message in messages] for i in range(ncolumns)] # o también columns = zip(*messages)
''.join(Counter(c).most_common()[0][0] for c in columns) print solution zip(), enumerate(), defaultdict() comprensiones collections.Counter split() y join()
current = queue.pop(0) if is_solution(current): return depth if current not in visited: visited.add(current) <add possible states to queue> return None optimización? BFS
flip(S, i): top_pankakes = ['+' if p == '-' else '-' for p in reversed(S[0:i])] return ''.join(top_pankakes) + S[i:] def solve(S): visited, queue = set(), [(0, shorten(S))] while queue: depth, current = queue.pop(0) if current.count('+') == len(current): return depth if current not in visited: visited.add(current) for i in range(1, len(current)+1): flipped = shorten(flip(current, i)) if flipped not in visited: queue.append((depth+1, flipped)) return None implementación BFS
▶ namedtuple, Counter, defaultdict ▶ itertools ▶ groupby ▶ product, permutations ▶ slicing [:], join, split ▶ assert ▶ regex python es MUY expresivo tiene su propio “acento” nunca paras de aprender practicar, practicar, practicar
de funciones de uso común ▶ vectores ▶ lectura de la entrada ▶ strip(), split() ▶ pensar/escribir/pintar antes de escribir código ▶ casos de prueba pequeños ▶ assert ▶ fuerza bruta, no suele funcionar ▶ pero da ideas de cómo resolverlo bien