Files

122 lines
3.2 KiB
Python
Raw Permalink Normal View History

2024-12-29 15:21:53 +03:00
import sys
sys.path.append('../aoclib')
from aoclib import Input
class FS(object):
def __init__(self, s: str):
self._initial = s
counter = 0
self.blocks = []
for i in range(0, len(s), 2):
file_len = int(s[i])
self.blocks.extend([counter for _ in range(file_len)])
if i+1 >= len(s):
break
space_len = int(s[i+1])
self.blocks.extend(['.' for _ in range(space_len)])
counter += 1
self.free = 0
def __str__(self):
return ''.join([str(n) for n in self.blocks])
def reset(self):
self.__init__(self._initial)
def defragment(self):
for i in range(len(self.blocks)-1, -1, -1):
if self.blocks[i] == '.':
continue
next = self._next_free()
if not next or next >= i:
break
# swap
self.blocks[next], self.blocks[i] = self.blocks[i], self.blocks[next]
def smart_defragment(self):
files = self._get_files()
for file in files:
for span in self._get_spans():
file_len = file[2] - file[1]
span_len = span[1] - span[0]
if (span[1] - 1) >= file[1]:
break
if file_len <= span_len:
self.blocks[span[0]:span[0]+file_len] = [file[0] for _ in range(file_len)]
self.blocks[file[1]:file[2]] = ['.' for _ in range(file_len)]
break
def solve1(self):
self.reset()
self.defragment()
return sum([x[0] * int(x[1]) if x[1] != '.' else 0 for x in enumerate(self.blocks)])
def solve2(self):
self.reset()
self.smart_defragment()
return sum([x[0] * int(x[1]) if x[1] != '.' else 0 for x in enumerate(self.blocks)])
def _next_free(self, start=0) -> int:
try:
i = self.blocks.index('.', start)
return i
except Exception:
return None
def _get_files(self):
files = []
end, start = 0, 0
i = len(self.blocks)-1
while i > 0:
if self.blocks[i] == '.':
i -= 1
continue
end = i+1
start = i
for j in range(i, -1, -1):
if self.blocks[j] != self.blocks[i]:
break
start = j
files.append((self.blocks[i], start, end))
i = start-1
return files
def _get_spans(self):
spans = []
start = self._next_free()
while start:
end = start
for i in range(start+1, len(self.blocks)):
if self.blocks[i] != '.':
break
end = i
spans.append((start, end+1))
start = self._next_free(end+1)
return spans
if __name__ == '__main__':
#s = Input('input_test.txt').raw()
s = Input('input.txt').raw()
fs = FS(s)
#part 1
#print('part 1:', fs.solve1())
#part 2
print('part 2:', fs.solve2())