File size: 2,812 Bytes
a4da721
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
def parse_input(s):
    # Convert the input string into alternating lengths of files and spaces
    lengths = [int(c) for c in s]
    
    # Convert to blocks representation
    blocks = []
    file_id = 0
    pos = 0
    for i, length in enumerate(lengths):
        if i % 2 == 0:  # File
            blocks.extend([file_id] * length)
            file_id += 1
        else:  # Space
            blocks.extend([-1] * length)  # -1 represents free space
    return blocks

def calculate_checksum(blocks):
    checksum = 0
    for pos, block in enumerate(blocks):
        if block != -1:  # Skip free space
            checksum += pos * block
    return checksum

def compact_blocks_part1(blocks):
    result = blocks.copy()
    
    while True:
        # Find rightmost file block
        right = len(result) - 1
        while right >= 0 and result[right] == -1:
            right -= 1
        if right < 0:
            break
            
        # Find leftmost free space
        left = 0
        while left < len(result) and result[left] != -1:
            left += 1
        if left >= right:
            break
            
        # Move one block
        result[left] = result[right]
        result[right] = -1
        
    return result

def compact_blocks_part2(blocks):
    result = blocks.copy()
    
    # Get unique file IDs in descending order
    file_ids = sorted(set(x for x in result if x != -1), reverse=True)
    
    for file_id in file_ids:
        # Find all blocks of this file
        file_blocks = []
        start = None
        for i, block in enumerate(result):
            if block == file_id:
                if start is None:
                    start = i
                file_blocks.append(block)
            elif start is not None and block != file_id:
                break
                
        if not file_blocks:
            continue
            
        # Remove the file from its current position
        for i in range(start, start + len(file_blocks)):
            result[i] = -1
            
        # Find leftmost position where file can fit
        pos = 0
        while pos < len(result):
            if all(result[i] == -1 for i in range(pos, pos + len(file_blocks)) if i < len(result)):
                # Place file here
                for i in range(len(file_blocks)):
                    result[pos + i] = file_id
                break
            pos += 1
            
    return result

# Read input
with open("input.txt", "r") as f:
    input_data = f.read().strip()

# Part 1
blocks = parse_input(input_data)
compacted = compact_blocks_part1(blocks)
checksum = calculate_checksum(compacted)
print(str(checksum))

# Part 2
blocks = parse_input(input_data)
compacted = compact_blocks_part2(blocks)
checksum = calculate_checksum(compacted)
print(str(checksum))