a.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import os, argparse, re
  2. def solve_task(lines):
  3. # Extract the initial stacks and instructions from the input
  4. (stacks, raw_instructions) = load_stacks(lines)
  5. #print(f"Stacks: {stacks}\n")
  6. #print(f"Instructions: {raw_instructions}")
  7. #display_stacks(stacks)
  8. # Parse the instructions into a list of tuples
  9. packed_instructions = pack_instructions(raw_instructions)
  10. #print(f"Packed: {packed_instructions}")
  11. # Perform all instructions
  12. for instruction in packed_instructions:
  13. perform_instruction(stacks, instruction)
  14. #display_stacks(stacks)
  15. # Get the answer by getting the uppermost (last) element of
  16. # each stack. This way has side effects, but we won't need
  17. # to preserve the stacks past this line.
  18. print("Final answer: " + ''.join([s.pop() for s in stacks]))
  19. def display_stacks(stacks):
  20. print("Current stacks:")
  21. for stack in stacks:
  22. print(''.join(stack))
  23. def perform_instruction(stacks, instruction):
  24. quantity = int(instruction[0])
  25. source = int(instruction[1]) - 1
  26. destination = int(instruction[2]) - 1
  27. # Since lists are mutable, we can manipulate the supplied lists
  28. # instead of returning new ones
  29. for _ in range(quantity):
  30. stacks[destination].append(stacks[source].pop())
  31. def pack_instructions(instr):
  32. # Return a list of instruction-tuples
  33. return [get_instruction_tuple(i) for i in instr]
  34. def get_instruction_tuple(intr_line):
  35. # Returns a tuple with three values (quantity, source, destination)
  36. m = re.match("move (\d+) from (\d+) to (\d+)", intr_line)
  37. return (m.group(1), m.group(2), m.group(3))
  38. def load_stacks(lines):
  39. number_of_piles = (len(lines[0])+1)//4
  40. piles = [[] for x in range(number_of_piles)]
  41. instructions_start_line = 0
  42. for linum in range(len(lines)):
  43. line = lines[linum]
  44. for col in range(len(line)):
  45. c = line[col]
  46. if col % 4 != 1 or c == ' ':
  47. continue
  48. if c == '1':
  49. instructions_start_line = linum+2
  50. break
  51. pile = col // 4
  52. piles[pile].insert(0, c)
  53. if instructions_start_line != 0:
  54. break
  55. return (piles, lines[instructions_start_line:])
  56. def read_lines(filename):
  57. lines = []
  58. with open(filename) as infile:
  59. for raw_line in infile:
  60. line = raw_line.replace('\n', '')
  61. line = line.replace('\r', '')
  62. #line = raw_line.rstrip() # Usefull to keep space in this task
  63. lines.append(line)
  64. return lines
  65. def parse_arguments():
  66. parser = argparse.ArgumentParser(description="Script that solves the case",epilog="Have a nice day!")
  67. parser.add_argument('filename', nargs='?', default="example.txt", help='Input file')
  68. args = parser.parse_args()
  69. return args
  70. def main():
  71. args = parse_arguments()
  72. lines = read_lines(args.filename)
  73. solve_task(lines)
  74. if __name__ == "__main__":
  75. main()