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)
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})
--- /dev/null
+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: <troupe-file>", 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()
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
troupe = common.load(pathlib.Path(file_name))
except:
print("args: <troupe-file>", file = sys.stderr)
- sys.exit(1)
+ raise
class Instance:
def __init__(self, zoombinis, io_agent):
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"])
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:
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()
-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
-)
--- /dev/null
+import sys
+import pickle
+from zoombinis import common
+
+zs = {common.random_zoombini() for _ in range(16)}
+pickle.dump(zs, sys.stdout.buffer)
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
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:
def wait(self):
self.out_stream.write("Ready? (Enter) ")
+ self.out_stream.flush()
self.in_stream.readline()