megasort/main.py

136 lines
3.0 KiB
Python
Raw Permalink Normal View History

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()