b.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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. answer = []
  19. for s in stacks:
  20. if len(s) != 0:
  21. answer.append(s[-1])
  22. print("Final answer: " + ''.join(answer))
  23. def display_stacks(stacks):
  24. print("Current stacks:")
  25. for stack in stacks:
  26. print(''.join(stack))
  27. def perform_instruction(stacks, instruction):
  28. quantity = int(instruction[0])
  29. source = int(instruction[1]) - 1
  30. destination = int(instruction[2]) - 1
  31. # Since lists are mutable, we can manipulate the supplied lists
  32. # instead of returning new ones
  33. stacks[destination].extend(stacks[source][-quantity:])
  34. del stacks[source][-quantity:]
  35. def pack_instructions(instr):
  36. # Return a list of instruction-tuples
  37. return [get_instruction_tuple(i) for i in instr]
  38. def get_instruction_tuple(intr_line):
  39. # Returns a tuple with three values (quantity, source, destination)
  40. m = re.match("move (\d+) from (\d+) to (\d+)", intr_line)
  41. return (m.group(1), m.group(2), m.group(3))
  42. def load_stacks(lines):
  43. number_of_piles = (len(lines[0])+1)//4
  44. piles = [[] for x in range(number_of_piles)]
  45. instructions_start_line = 0
  46. for linum in range(len(lines)):
  47. line = lines[linum]
  48. for col in range(len(line)):
  49. c = line[col]
  50. if col % 4 != 1 or c == ' ':
  51. continue
  52. if c == '1':
  53. instructions_start_line = linum+2
  54. break
  55. pile = col // 4
  56. piles[pile].insert(0, c)
  57. if instructions_start_line != 0:
  58. break
  59. return (piles, lines[instructions_start_line:])
  60. def read_lines(filename):
  61. lines = []
  62. with open(filename) as infile:
  63. for raw_line in infile:
  64. line = raw_line.replace('\n', '')
  65. line = line.replace('\r', '')
  66. #line = raw_line.rstrip() # Usefull to keep space in this task
  67. lines.append(line)
  68. return lines
  69. def parse_arguments():
  70. parser = argparse.ArgumentParser(description="Script that solves the case",epilog="Have a nice day!")
  71. parser.add_argument('filename', nargs='?', default="example.txt", help='Input file')
  72. args = parser.parse_args()
  73. return args
  74. def main():
  75. args = parse_arguments()
  76. lines = read_lines(args.filename)
  77. solve_task(lines)
  78. if __name__ == "__main__":
  79. main()