2024-03-10 07:29:13 +00:00
|
|
|
from functools import partial
|
2024-03-10 06:30:03 +00:00
|
|
|
import random
|
|
|
|
|
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
class Cell(object):
|
|
|
|
def __init__(self):
|
|
|
|
self.is_set = False
|
|
|
|
self.value = None
|
|
|
|
|
|
|
|
def set(self, x):
|
|
|
|
self.is_set = True
|
|
|
|
self.value = x
|
|
|
|
|
|
|
|
|
|
|
|
class Merge(object):
|
|
|
|
def __init__(self, xs, ys, on_complete):
|
|
|
|
self.xs = xs[:]
|
|
|
|
self.ys = ys[:]
|
|
|
|
self.output = []
|
|
|
|
self.on_complete = on_complete
|
|
|
|
self.running = True
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
self.settle()
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
def touch(self):
|
|
|
|
# print(f"Touching: {self}")
|
|
|
|
if ask(self.xs[0], self.ys[0]):
|
|
|
|
self.output.append(self.xs.pop(0))
|
|
|
|
else:
|
|
|
|
self.output.append(self.ys.pop(0))
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
self.settle()
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
def settle(self):
|
|
|
|
if len(self.xs) == 0:
|
|
|
|
self.output += self.ys
|
|
|
|
self.ys = []
|
|
|
|
self.complete()
|
|
|
|
return
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
if len(self.ys) == 0:
|
|
|
|
self.output += self.xs
|
|
|
|
self.xs = []
|
|
|
|
self.complete()
|
|
|
|
return
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
def complete(self):
|
|
|
|
self.on_complete(self.output)
|
|
|
|
self.running = False
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
def __repr__(self):
|
|
|
|
return f"Merge({self.xs}, {self.ys}, {self.output})"
|
2024-03-10 06:30:03 +00:00
|
|
|
|
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
def _sort(xs, merges, on_complete):
|
|
|
|
if len(xs) < 2:
|
|
|
|
on_complete(xs[:])
|
|
|
|
return
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
half = len(xs) // 2
|
|
|
|
fst = xs[:half]
|
|
|
|
snd = xs[half:]
|
|
|
|
sorted_fst = Cell()
|
|
|
|
sorted_snd = Cell()
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
def cb(setter, value):
|
|
|
|
setter(value)
|
|
|
|
if sorted_fst.is_set and sorted_snd.is_set:
|
|
|
|
new_merge = Merge(sorted_fst.value, sorted_snd.value, on_complete)
|
|
|
|
merges.append(new_merge)
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
_sort(fst, merges, partial(cb, sorted_fst.set))
|
|
|
|
_sort(snd, merges, partial(cb, sorted_snd.set))
|
2024-03-10 06:30:03 +00:00
|
|
|
|
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
def merge_sort(xs):
|
|
|
|
merges = []
|
|
|
|
result = Cell()
|
|
|
|
_sort(xs, merges, result.set)
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
while True:
|
|
|
|
# replace in place
|
|
|
|
for i in reversed(range(len(merges))):
|
|
|
|
if not merges[i].running:
|
|
|
|
merges.pop(i)
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
if len(merges) == 0:
|
|
|
|
break
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
# print(f"Number of ongoing merges: {merges}")
|
|
|
|
# print(f"Number of ongoing merges: {len(merges)}")
|
|
|
|
random.shuffle(merges)
|
|
|
|
for m in merges[:]:
|
|
|
|
m.touch()
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
assert result.is_set
|
|
|
|
return result.value
|
|
|
|
|
|
|
|
|
|
|
|
TRUTHY = "y yes 1 t true aye left up top first p".split()
|
|
|
|
FALSEY = "n no 0 2 f false nay right down bottom second nil".split()
|
2024-03-10 06:30:03 +00:00
|
|
|
|
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
def ask(x, y):
|
|
|
|
if random.choice([False, True]):
|
|
|
|
yes_result = True
|
|
|
|
a, b = x, y
|
|
|
|
else:
|
|
|
|
yes_result = False
|
|
|
|
a, b = y, x
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
while True:
|
|
|
|
choice = input(f"Is {a} better than {b}? ")
|
|
|
|
if choice in TRUTHY:
|
|
|
|
return yes_result
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
if choice in FALSEY:
|
|
|
|
return not yes_result
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 07:29:13 +00:00
|
|
|
print(f"Huh? I didn't understand {choice}. Answer \"y\" or \"n\".")
|
2024-03-10 06:30:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
with open("input.txt", "rt") as f_in:
|
2024-03-10 06:31:13 +00:00
|
|
|
lines_in = [i.strip() for i in f_in.read().split("\n") if i.strip()]
|
2024-03-10 06:30:03 +00:00
|
|
|
|
2024-03-10 06:31:13 +00:00
|
|
|
random.shuffle(lines_in)
|
2024-03-10 07:29:13 +00:00
|
|
|
results = merge_sort(lines_in)
|
2024-03-10 06:30:03 +00:00
|
|
|
|
|
|
|
with open("output.txt", "wt") as f_out:
|
2024-03-10 07:29:13 +00:00
|
|
|
f_out.write("\n".join(results))
|
2024-03-10 06:30:03 +00:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|