From: Jakob Cornell Date: Sat, 22 Jun 2019 05:16:00 +0000 (-0500) Subject: Various X-Git-Url: https://jcornell.net/gitweb/gitweb.cgi?a=commitdiff_plain;h=7683eda87a14c4f7ed7013a078fd1a2b836c3349;p=zoombinis-solve.git Various --- diff --git a/common.py b/common.py index ce0cf44..8195c0a 100644 --- a/common.py +++ b/common.py @@ -24,7 +24,7 @@ class Zoombini: self.attrs = frozenset(attrs) def __str__(self): - return str({type(a).__name__: a.value for a in self.attrs.values()}) + return str({type(a).__name__: a.value for a in self.attrs}) ALL_ATTRS = frozenset(attr for prop in Zoombini.PROPERTIES for attr in prop) @@ -40,4 +40,4 @@ def save(troupe, path): def random_zoombini(): import random - return Zoombini({random.choice(list(t)) for t in ALL_ATTRS}) + return Zoombini({random.choice(list(t)) for t in Zoombini.PROPERTIES}) diff --git a/puzzles/allergic_cliffs/4-2.py b/puzzles/allergic_cliffs/4-2.py new file mode 100644 index 0000000..33fdade --- /dev/null +++ b/puzzles/allergic_cliffs/4-2.py @@ -0,0 +1,53 @@ +import sys + +from zoombinis import common, ui +from zoombinis.puzzles.allergic_cliffs.common import * + +import pathlib +import random + +try: + [file_name] = sys.argv[1:] + troupe = common.load(pathlib.Path(file_name)) +except: + print("args: ", file = sys.stderr) + raise + +class Instance: + def __init__(self, zoombinis, io_agent): + self.io_agent = io_agent + self.waiting = set(zoombinis) + self.across = {cliff: set() for cliff in Cliff} + + def next_pair(self): + import itertools + def key(pair): + cliff, zoombini = pair + pool = self.across[cliff] if self.across[cliff] else self.waiting - {zoombini} + sim_score = sum(len(zoombini.attrs & z.attrs) for z in pool) / len(pool) + free_ratio = (8 - len(self.across[cliff])) / (8 - len(self.across[cliff.other()])) + return sim_score * free_ratio ** (1/10) + return max(itertools.product(Cliff, self.waiting), key = key) + + def send(self, zoombini, cliff): + send_fmt = "Send {} across the {} cliff." + self.io_agent.print(send_fmt.format(zoombini, cliff.name.lower())) + ans = self.io_agent.choose("Did it work?", ["y", "n"]) + if ans == 'n': + cliff = cliff.other() + self.io_agent.print(send_fmt.format(zoombini, cliff.name.lower())) + self.io_agent.wait() + self.across[cliff].add(zoombini) + self.waiting.remove(zoombini) + + def run(self): + first = max(self.waiting, key = lambda z: sum(len(z.attrs & oz.attrs) for oz in self.waiting) / len(self.waiting)) + self.send(first, random.choice(list(Cliff))) + while not any(len(s) == 8 for s in self.across.values()): + (c, z) = self.next_pair() + self.send(z, c) + [full] = [c for c in Cliff if len(self.across[c]) == 8] + for z in list(self.waiting): + self.send(z, full.other()) + +Instance(troupe, ui.Agent(sys.stdin, sys.stderr)).run() diff --git a/puzzles/allergic_cliffs/4.py b/puzzles/allergic_cliffs/4.py index 80de256..3da700d 100644 --- a/puzzles/allergic_cliffs/4.py +++ b/puzzles/allergic_cliffs/4.py @@ -1,7 +1,6 @@ import sys -import zoombinis.common as common -import zoombinis.ui as ui +from zoombinis import common, ui from zoombinis.puzzles.allergic_cliffs.common import * import pathlib @@ -12,7 +11,7 @@ try: troupe = common.load(pathlib.Path(file_name)) except: print("args: ", file = sys.stderr) - sys.exit(1) + raise class Instance: def __init__(self, zoombinis, io_agent): @@ -59,7 +58,7 @@ class Instance: elif len(self.pos_cand_rules) == 3: self.pos_rules = frozenset(self.pos_cand_rules) - def send(zoombini, cliff): + def send(self, zoombini, cliff): send_fmt = "Send {} across the {} cliff." self.io_agent.print(send_fmt.format(zoombini, cliff.name.lower())) ans = self.io_agent.choose("Did it work?", ["y", "n"]) @@ -67,7 +66,6 @@ class Instance: cliff = cliff.other() self.io_agent.print(send_fmt.format(zoombini, cliff.name.lower())) self.io_agent.wait() - self.waiting.remove(zoombini) self.across[cliff].add(zoombini) if self.pos_cliff is None: for attr in zoombini.attrs: @@ -79,8 +77,10 @@ class Instance: def run(self): while self.waiting: z = self.choose_zoombini() - c = self.choose_cliff() + c = self.choose_cliff(z) self.send(z, c) self.waiting.remove(z) + print(self.cand_rules) + print(self.pos_cliff) Instance(troupe, ui.Agent(sys.stdin, sys.stderr)).run() diff --git a/puzzles/allergic_cliffs/common.py b/puzzles/allergic_cliffs/common.py index d8f8d75..4ae751b 100644 --- a/puzzles/allergic_cliffs/common.py +++ b/puzzles/allergic_cliffs/common.py @@ -1,15 +1,8 @@ -import sys -sys.path.append('../../..') import zoombinis.common as comm from enum import Enum +Zoombini = comm.Zoombini # for pickle issue workaround + Cliff = Enum('Cliff', ['UPPER', 'LOWER']) Cliff.other = lambda self: {Cliff.UPPER: Cliff.LOWER, Cliff.LOWER: Cliff.UPPER}[self] - -ALL_RULES = frozenset( - (cliff, attr) - for cliff in Cliff - for prop in comm.Zoombini.Property - for attr in prop -) diff --git a/rand_troupe.py b/rand_troupe.py new file mode 100644 index 0000000..7b8e07f --- /dev/null +++ b/rand_troupe.py @@ -0,0 +1,6 @@ +import sys +import pickle +from zoombinis import common + +zs = {common.random_zoombini() for _ in range(16)} +pickle.dump(zs, sys.stdout.buffer) diff --git a/troupe.py b/troupe.py index dff8e6b..b79b62d 100644 --- a/troupe.py +++ b/troupe.py @@ -20,15 +20,19 @@ try: print(template.format('feet', get_options(Z.Feet)), file = sys.stderr, end = '') feet = input() - zs.append( - Zoombini({ - Z.Hair[hair.upper()], - Z.Eyes[eyes.upper()], - Z.Nose[nose.upper()], - Z.Feet[feet.upper()], - }) - ) - print("added", file = sys.stderr) + try: + zs.append( + Zoombini({ + Z.Hair[hair.upper()], + Z.Eyes[eyes.upper()], + Z.Nose[nose.upper()], + Z.Feet[feet.upper()], + }) + ) + except KeyError: + print("not added!", file = sys.stderr) + else: + print("added", file = sys.stderr) except EOFError: pass diff --git a/ui.py b/ui.py index 99a54f3..1e6ee59 100644 --- a/ui.py +++ b/ui.py @@ -9,6 +9,7 @@ class Agent: def choose(self, message, choices): def prompt(): self.out_stream.write("{} ({}) ".format(message, '/'.join(choices))) + self.out_stream.flush() return self.in_stream.readline().strip() resp = prompt() while resp not in choices: @@ -17,4 +18,5 @@ class Agent: def wait(self): self.out_stream.write("Ready? (Enter) ") + self.out_stream.flush() self.in_stream.readline()