Coverage for src\aoc2022\days\day5.py: 100%

47 statements  

« prev     ^ index     » next       coverage.py v7.0.0, created at 2022-12-23 05:19 +0000

1from typing import List, Tuple 

2 

3from src.aoc2022 import utils 

4 

5stacks_type = Tuple[List[str], ...] 

6moves_type = List[Tuple[int, int, int]] 

7 

8 

9def parse_data(raw_data: str) -> Tuple[stacks_type, moves_type]: 

10 """ 

11 Parses the raw text input into the initial configuration and the move list 

12 

13 :param raw_data: Raw text data to be parsed 

14 :type raw_data: str 

15 

16 :return: Initial Configuration and move list 

17 :rtype: List[Tuple[int]] 

18 """ 

19 configuration_data, move_data = raw_data.split("\n\n") 

20 

21 stack_rows = configuration_data.split("\n") 

22 reversed_rows = stack_rows[::-1] 

23 num_stacks = int(reversed_rows[0].split(" ")[-2]) 

24 

25 stacks: Tuple[List[str], ...] = tuple([] for _ in range(num_stacks)) 

26 

27 for row in reversed_rows[1:]: 

28 values = row[1::4] 

29 for idx, value in enumerate(values): 

30 if value != " ": 

31 stacks[idx].append(value) 

32 

33 moves = [] 

34 move_lines = move_data.split("\n") 

35 for move_line in move_lines: 

36 split_move = move_line.split(" ") 

37 num_transfer = int(split_move[1]) 

38 start_stack = int(split_move[3]) 

39 end_stack = int(split_move[5]) 

40 

41 moves.append((num_transfer, start_stack, end_stack)) 

42 

43 return stacks, moves 

44 

45 

46def transfer_items(stacks: stacks_type, moves: moves_type) -> str: 

47 """ 

48 Computes the final state of the stacks after applying the moves 

49 

50 :param stacks: Tuple of lists representing each stack 

51 :type stacks: Tuple[List[str]] 

52 

53 :param moves: List of tuples for each move 

54 :type moves: List[Tuple[int]] 

55 

56 :return: value at the top of each stack after moves 

57 :rtype: str 

58 """ 

59 

60 for n, start, stop in moves: 

61 for _ in range(n): 

62 v = stacks[start - 1].pop() 

63 stacks[stop - 1].append(v) 

64 

65 top_boxes = [] 

66 for s in stacks: 

67 if len(s) > 0: 

68 top_boxes.append(s[-1]) 

69 else: 

70 top_boxes.append(" ") 

71 

72 return "".join(top_boxes) 

73 

74 

75def transfer_multiple_items(stacks: stacks_type, moves: moves_type) -> str: 

76 """ 

77 Computes the final state of the stacks after applying the moves 

78 moving multiple boxes in a single move 

79 

80 :param stacks: Tuple of lists representing each stack 

81 :type stacks: Tuple[List[str]] 

82 

83 :param moves: List of tuples for each move 

84 :type moves: List[Tuple[int]] 

85 

86 :return: value at the top of each stack after moves 

87 :rtype: str 

88 """ 

89 

90 for n, start, stop in moves: 

91 

92 v = stacks[start - 1][-n:] 

93 for _ in range(n): 

94 stacks[start - 1].pop() 

95 stacks[stop - 1].extend(v) 

96 

97 top_boxes = [] 

98 for s in stacks: 

99 if len(s) > 0: 

100 top_boxes.append(s[-1]) 

101 else: 

102 top_boxes.append(" ") 

103 

104 return "".join(top_boxes) 

105 

106 

107if __name__ == "__main__": # pragma: no cover 

108 data = utils.get_raw_data("./src/aoc2022/data/day5.txt") 

109 stacks, moves = parse_data(data) 

110 result = transfer_items(stacks, moves) 

111 print(f"The final state of the stacks is {result}") 

112 

113 stacks, moves = parse_data(data) 

114 result = transfer_multiple_items(stacks, moves) 

115 print(f"The final state of the stacks is {result}")