In [30]:
given = """
E N T E R L A S E R L A S E R R E S A L
L A S E R O B S I D I A N L A S E R G W
E R E S A L L A S E R L M R R E S A L A
L A S E R R E S A L A O E R L A S E R L
L L E M I T T E R S O S E L R E S A L L
A A M R E S A L E N A S L A L A S E R R
S S R E S A L R S L A R A S R E S A L E
E E L A S E R T R L L E S E L A S E R S
R R W A L L O E R R A S E R R E S A L A
L A S E R N S E L E S A R E B E R Y L L
L R L M E A S L A S E L N L L A S E R J
A E A O L A R A S A R O L R E S A L A E
S S S O L L E S E L T A L A S E R D S M
E A E N R A S E R S W R E S A L E L R I
R L R S E S A R D R L A S E R O W A E T
L R R T S E L O E T R E S A L N A S S T
A E E O A R O S O N L A S E R Y L E A E
S S S N L L A B A R R E S A L X L R L R
E A A E B L R E S A L L A S E R E X I T
R L L L A S E R E S L A S E R L A S E R
""".strip().replace(' ', '\t')
print(given)


E	N	T	E	R	L	A	S	E	R	L	A	S	E	R	R	E	S	A	L
L	A	S	E	R	O	B	S	I	D	I	A	N	L	A	S	E	R	G	W
E	R	E	S	A	L	L	A	S	E	R	L	M	R	R	E	S	A	L	A
L	A	S	E	R	R	E	S	A	L	A	O	E	R	L	A	S	E	R	L
L	L	E	M	I	T	T	E	R	S	O	S	E	L	R	E	S	A	L	L
A	A	M	R	E	S	A	L	E	N	A	S	L	A	L	A	S	E	R	R
S	S	R	E	S	A	L	R	S	L	A	R	A	S	R	E	S	A	L	E
E	E	L	A	S	E	R	T	R	L	L	E	S	E	L	A	S	E	R	S
R	R	W	A	L	L	O	E	R	R	A	S	E	R	R	E	S	A	L	A
L	A	S	E	R	N	S	E	L	E	S	A	R	E	B	E	R	Y	L	L
L	R	L	M	E	A	S	L	A	S	E	L	N	L	L	A	S	E	R	J
A	E	A	O	L	A	R	A	S	A	R	O	L	R	E	S	A	L	A	E
S	S	S	O	L	L	E	S	E	L	T	A	L	A	S	E	R	D	S	M
E	A	E	N	R	A	S	E	R	S	W	R	E	S	A	L	E	L	R	I
R	L	R	S	E	S	A	R	D	R	L	A	S	E	R	O	W	A	E	T
L	R	R	T	S	E	L	O	E	T	R	E	S	A	L	N	A	S	S	T
A	E	E	O	A	R	O	S	O	N	L	A	S	E	R	Y	L	E	A	E
S	S	S	N	L	L	A	B	A	R	R	E	S	A	L	X	L	R	L	R
E	A	A	E	B	L	R	E	S	A	L	L	A	S	E	R	E	X	I	T
R	L	L	L	A	S	E	R	E	S	L	A	S	E	R	L	A	S	E	R

In [3]:
print("""
Artisan
Bass	speaker
Count	(on)
Deprived	(of)
Enjoyed	together
False	teeth
French	cap
Gram	or	pound
Inform	(of)
Like	a	birthday
Moon	feature
More	confident
Not	capable
Place	a	value	on
Put	in	danger
Race in	stages
Recycle	alternative
Regal	
Renders undrinkable
Rip	up
Suitor
Trash
Undo	a	wedding
Wave	rider
""".replace('\t', ' '))


Artisan
Bass speaker
Count (on)
Deprived (of)
Enjoyed together
False teeth
French cap
Gram or pound
Inform (of)
Like a birthday
Moon feature
More confident
Not capable
Place a value on
Put in danger
Race in stages
Recycle alternative
Regal 
Renders undrinkable
Rip up
Suitor
Trash
Undo a wedding
Wave rider


In [5]:
import forge
from puzzle.puzzlepedia import puzzlepedia

puzzle = puzzlepedia.parse("""
@ 6 9 7 11 3 1 8 4 10 5 12 2
* APPRAISE
* DENATURE
* IMPERIAL
* ?
* RELAY
* ?
* BEREFT
* CRAFTER
* REFUSE
* SURFER
* UNFIT
* WOOFER
""".lower())


WARNING
Max fringe size was: 2158
WARNING
Max fringe size was: 2298
WARNING
Max fringe size was: 2257
WARNING
Max fringe size was: 2293
WARNING
Max fringe size was: 2030
WARNING
Max fringe size was: 1959

In [22]:
import Numberjack

given = """
1	0	1	0	0
0	0	0	1	1
0	0	1	0	1
0	1	1	1	0
1	0	1	0	1
0	1	0	1	1
0	0	1	0	0
1	0	1	1	1
1	0	0	0	0
1	1	0	0	1
""".strip()

G = Numberjack.Matrix(5, 5, 'x')
model = Numberjack.Model()

options = G.row + G.col

def constrain(bits):
  model.add(Numberjack.Disjunction([
    Numberjack.Conjunction([bits_bit == option_bit for bits_bit, option_bit in zip(bits, option)])
    for option in options
  ]))

for soln in given.split('\n'):
  bits = [bit == '1' for bit in soln.split('\t')]
  constrain(bits)

solver = model.load('Mistral')
solver.solve()
print(str(model))

print("is_sat", solver.is_sat())
print("is_unsat", solver.is_unsat())


for r in range(5):
  row = []
  for c in range(5):
    row.append('%2d' % G[r][c].get_value())
  print('\t'.join(row))


assign:
  x0.0 in {0}
  x0.1 in {1}
  x0.2 in {1}
  x0.3 in {1}
  x0.4 in {0}
  x1.0 in {0}
  x1.1 in {0}
  x1.2 in {1}
  x1.3 in {0}
  x1.4 in {0}
  x2.0 in {0}
  x2.1 in {1}
  x2.2 in {0}
  x2.3 in {1}
  x2.4 in {1}
  x3.0 in {1}
  x3.1 in {0}
  x3.2 in {0}
  x3.3 in {0}
  x3.4 in {0}
  x4.0 in {1}
  x4.1 in {0}
  x4.2 in {1}
  x4.3 in {1}
  x4.4 in {1}
  
subject to:
  OR(AND((x0.0 == True), (x0.1 == False), (x0.2 == True), (x0.3 == False), (x0.4 == False)), AND((x1.0 == True), (x1.1 == False), (x1.2 == True), (x1.3 == False), (x1.4 == False)), AND((x2.0 == True), (x2.1 == False), (x2.2 == True), (x2.3 == False), (x2.4 == False)), AND((x3.0 == True), (x3.1 == False), (x3.2 == True), (x3.3 == False), (x3.4 == False)), AND((x4.0 == True), (x4.1 == False), (x4.2 == True), (x4.3 == False), (x4.4 == False)), AND((x0.0 == True), (x1.0 == False), (x2.0 == True), (x3.0 == False), (x4.0 == False)), AND((x0.1 == True), (x1.1 == False), (x2.1 == True), (x3.1 == False), (x4.1 == False)), AND((x0.2 == True), (x1.2 == False), (x2.2 == True), (x3.2 == False), (x4.2 == False)), AND((x0.3 == True), (x1.3 == False), (x2.3 == True), (x3.3 == False), (x4.3 == False)), AND((x0.4 == True), (x1.4 == False), (x2.4 == True), (x3.4 == False), (x4.4 == False)))
  OR(AND((x0.0 == False), (x0.1 == False), (x0.2 == False), (x0.3 == True), (x0.4 == True)), AND((x1.0 == False), (x1.1 == False), (x1.2 == False), (x1.3 == True), (x1.4 == True)), AND((x2.0 == False), (x2.1 == False), (x2.2 == False), (x2.3 == True), (x2.4 == True)), AND((x3.0 == False), (x3.1 == False), (x3.2 == False), (x3.3 == True), (x3.4 == True)), AND((x4.0 == False), (x4.1 == False), (x4.2 == False), (x4.3 == True), (x4.4 == True)), AND((x0.0 == False), (x1.0 == False), (x2.0 == False), (x3.0 == True), (x4.0 == True)), AND((x0.1 == False), (x1.1 == False), (x2.1 == False), (x3.1 == True), (x4.1 == True)), AND((x0.2 == False), (x1.2 == False), (x2.2 == False), (x3.2 == True), (x4.2 == True)), AND((x0.3 == False), (x1.3 == False), (x2.3 == False), (x3.3 == True), (x4.3 == True)), AND((x0.4 == False), (x1.4 == False), (x2.4 == False), (x3.4 == True), (x4.4 == True)))
  OR(AND((x0.0 == False), (x0.1 == False), (x0.2 == True), (x0.3 == False), (x0.4 == True)), AND((x1.0 == False), (x1.1 == False), (x1.2 == True), (x1.3 == False), (x1.4 == True)), AND((x2.0 == False), (x2.1 == False), (x2.2 == True), (x2.3 == False), (x2.4 == True)), AND((x3.0 == False), (x3.1 == False), (x3.2 == True), (x3.3 == False), (x3.4 == True)), AND((x4.0 == False), (x4.1 == False), (x4.2 == True), (x4.3 == False), (x4.4 == True)), AND((x0.0 == False), (x1.0 == False), (x2.0 == True), (x3.0 == False), (x4.0 == True)), AND((x0.1 == False), (x1.1 == False), (x2.1 == True), (x3.1 == False), (x4.1 == True)), AND((x0.2 == False), (x1.2 == False), (x2.2 == True), (x3.2 == False), (x4.2 == True)), AND((x0.3 == False), (x1.3 == False), (x2.3 == True), (x3.3 == False), (x4.3 == True)), AND((x0.4 == False), (x1.4 == False), (x2.4 == True), (x3.4 == False), (x4.4 == True)))
  OR(AND((x0.0 == False), (x0.1 == True), (x0.2 == True), (x0.3 == True), (x0.4 == False)), AND((x1.0 == False), (x1.1 == True), (x1.2 == True), (x1.3 == True), (x1.4 == False)), AND((x2.0 == False), (x2.1 == True), (x2.2 == True), (x2.3 == True), (x2.4 == False)), AND((x3.0 == False), (x3.1 == True), (x3.2 == True), (x3.3 == True), (x3.4 == False)), AND((x4.0 == False), (x4.1 == True), (x4.2 == True), (x4.3 == True), (x4.4 == False)), AND((x0.0 == False), (x1.0 == True), (x2.0 == True), (x3.0 == True), (x4.0 == False)), AND((x0.1 == False), (x1.1 == True), (x2.1 == True), (x3.1 == True), (x4.1 == False)), AND((x0.2 == False), (x1.2 == True), (x2.2 == True), (x3.2 == True), (x4.2 == False)), AND((x0.3 == False), (x1.3 == True), (x2.3 == True), (x3.3 == True), (x4.3 == False)), AND((x0.4 == False), (x1.4 == True), (x2.4 == True), (x3.4 == True), (x4.4 == False)))
  OR(AND((x0.0 == True), (x0.1 == False), (x0.2 == True), (x0.3 == False), (x0.4 == True)), AND((x1.0 == True), (x1.1 == False), (x1.2 == True), (x1.3 == False), (x1.4 == True)), AND((x2.0 == True), (x2.1 == False), (x2.2 == True), (x2.3 == False), (x2.4 == True)), AND((x3.0 == True), (x3.1 == False), (x3.2 == True), (x3.3 == False), (x3.4 == True)), AND((x4.0 == True), (x4.1 == False), (x4.2 == True), (x4.3 == False), (x4.4 == True)), AND((x0.0 == True), (x1.0 == False), (x2.0 == True), (x3.0 == False), (x4.0 == True)), AND((x0.1 == True), (x1.1 == False), (x2.1 == True), (x3.1 == False), (x4.1 == True)), AND((x0.2 == True), (x1.2 == False), (x2.2 == True), (x3.2 == False), (x4.2 == True)), AND((x0.3 == True), (x1.3 == False), (x2.3 == True), (x3.3 == False), (x4.3 == True)), AND((x0.4 == True), (x1.4 == False), (x2.4 == True), (x3.4 == False), (x4.4 == True)))
  OR(AND((x0.0 == False), (x0.1 == True), (x0.2 == False), (x0.3 == True), (x0.4 == True)), AND((x1.0 == False), (x1.1 == True), (x1.2 == False), (x1.3 == True), (x1.4 == True)), AND((x2.0 == False), (x2.1 == True), (x2.2 == False), (x2.3 == True), (x2.4 == True)), AND((x3.0 == False), (x3.1 == True), (x3.2 == False), (x3.3 == True), (x3.4 == True)), AND((x4.0 == False), (x4.1 == True), (x4.2 == False), (x4.3 == True), (x4.4 == True)), AND((x0.0 == False), (x1.0 == True), (x2.0 == False), (x3.0 == True), (x4.0 == True)), AND((x0.1 == False), (x1.1 == True), (x2.1 == False), (x3.1 == True), (x4.1 == True)), AND((x0.2 == False), (x1.2 == True), (x2.2 == False), (x3.2 == True), (x4.2 == True)), AND((x0.3 == False), (x1.3 == True), (x2.3 == False), (x3.3 == True), (x4.3 == True)), AND((x0.4 == False), (x1.4 == True), (x2.4 == False), (x3.4 == True), (x4.4 == True)))
  OR(AND((x0.0 == False), (x0.1 == False), (x0.2 == True), (x0.3 == False), (x0.4 == False)), AND((x1.0 == False), (x1.1 == False), (x1.2 == True), (x1.3 == False), (x1.4 == False)), AND((x2.0 == False), (x2.1 == False), (x2.2 == True), (x2.3 == False), (x2.4 == False)), AND((x3.0 == False), (x3.1 == False), (x3.2 == True), (x3.3 == False), (x3.4 == False)), AND((x4.0 == False), (x4.1 == False), (x4.2 == True), (x4.3 == False), (x4.4 == False)), AND((x0.0 == False), (x1.0 == False), (x2.0 == True), (x3.0 == False), (x4.0 == False)), AND((x0.1 == False), (x1.1 == False), (x2.1 == True), (x3.1 == False), (x4.1 == False)), AND((x0.2 == False), (x1.2 == False), (x2.2 == True), (x3.2 == False), (x4.2 == False)), AND((x0.3 == False), (x1.3 == False), (x2.3 == True), (x3.3 == False), (x4.3 == False)), AND((x0.4 == False), (x1.4 == False), (x2.4 == True), (x3.4 == False), (x4.4 == False)))
  OR(AND((x0.0 == True), (x0.1 == False), (x0.2 == True), (x0.3 == True), (x0.4 == True)), AND((x1.0 == True), (x1.1 == False), (x1.2 == True), (x1.3 == True), (x1.4 == True)), AND((x2.0 == True), (x2.1 == False), (x2.2 == True), (x2.3 == True), (x2.4 == True)), AND((x3.0 == True), (x3.1 == False), (x3.2 == True), (x3.3 == True), (x3.4 == True)), AND((x4.0 == True), (x4.1 == False), (x4.2 == True), (x4.3 == True), (x4.4 == True)), AND((x0.0 == True), (x1.0 == False), (x2.0 == True), (x3.0 == True), (x4.0 == True)), AND((x0.1 == True), (x1.1 == False), (x2.1 == True), (x3.1 == True), (x4.1 == True)), AND((x0.2 == True), (x1.2 == False), (x2.2 == True), (x3.2 == True), (x4.2 == True)), AND((x0.3 == True), (x1.3 == False), (x2.3 == True), (x3.3 == True), (x4.3 == True)), AND((x0.4 == True), (x1.4 == False), (x2.4 == True), (x3.4 == True), (x4.4 == True)))
  OR(AND((x0.0 == True), (x0.1 == False), (x0.2 == False), (x0.3 == False), (x0.4 == False)), AND((x1.0 == True), (x1.1 == False), (x1.2 == False), (x1.3 == False), (x1.4 == False)), AND((x2.0 == True), (x2.1 == False), (x2.2 == False), (x2.3 == False), (x2.4 == False)), AND((x3.0 == True), (x3.1 == False), (x3.2 == False), (x3.3 == False), (x3.4 == False)), AND((x4.0 == True), (x4.1 == False), (x4.2 == False), (x4.3 == False), (x4.4 == False)), AND((x0.0 == True), (x1.0 == False), (x2.0 == False), (x3.0 == False), (x4.0 == False)), AND((x0.1 == True), (x1.1 == False), (x2.1 == False), (x3.1 == False), (x4.1 == False)), AND((x0.2 == True), (x1.2 == False), (x2.2 == False), (x3.2 == False), (x4.2 == False)), AND((x0.3 == True), (x1.3 == False), (x2.3 == False), (x3.3 == False), (x4.3 == False)), AND((x0.4 == True), (x1.4 == False), (x2.4 == False), (x3.4 == False), (x4.4 == False)))
  OR(AND((x0.0 == True), (x0.1 == True), (x0.2 == False), (x0.3 == False), (x0.4 == True)), AND((x1.0 == True), (x1.1 == True), (x1.2 == False), (x1.3 == False), (x1.4 == True)), AND((x2.0 == True), (x2.1 == True), (x2.2 == False), (x2.3 == False), (x2.4 == True)), AND((x3.0 == True), (x3.1 == True), (x3.2 == False), (x3.3 == False), (x3.4 == True)), AND((x4.0 == True), (x4.1 == True), (x4.2 == False), (x4.3 == False), (x4.4 == True)), AND((x0.0 == True), (x1.0 == True), (x2.0 == False), (x3.0 == False), (x4.0 == True)), AND((x0.1 == True), (x1.1 == True), (x2.1 == False), (x3.1 == False), (x4.1 == True)), AND((x0.2 == True), (x1.2 == True), (x2.2 == False), (x3.2 == False), (x4.2 == True)), AND((x0.3 == True), (x1.3 == True), (x2.3 == False), (x3.3 == False), (x4.3 == True)), AND((x0.4 == True), (x1.4 == True), (x2.4 == False), (x3.4 == False), (x4.4 == True)))
  
is_sat True
is_unsat False
 0	 1	 1	 1	 0
 0	 0	 1	 0	 0
 0	 1	 0	 1	 1
 1	 0	 0	 0	 0
 1	 0	 1	 1	 1

In [23]:
''.join("""
QLSRUXWGGSFCSUSLFWLSDAFHWFIXTEYYCMVT
OLTGUGHVHMVIXOUBWEZFTHYPTXCGPWGIKOLW
BFIIRBYXTOGQYFPYOZZXGMQJNUUGHNWNWATH
MYZFRGMSYUUFVYEDPTPHLJOOQLFTXARTWKOG
YNJSTTHPXNCRHOSHLKJYWVBTDCYNRGLVKMWN
HIURUSGNCIFNJWXWCPCTROYRQGELVRFWEAGT
RHTFGEWNRJGYGYKFVYEYMSPQDWKFEXUDPJRZ
EMDDUGUCGTGRGMFGRPVYIMVQUWVBGOAPKRGN
GHJTUTNYGWYWWKVTKRTRUNULGYFUYEXQRUCF
CNXJKUFKHYJVCITWIBGMGIIFRIARRIXAWJKI
SUNERQRUTFGRGFDPMJUWNBWDJWKCZJJYFVKN
WJSHPGNPLPLTULJHRSMKMAXNVZYRMYGHWNDU
ENUIWQDDLSATXFJQSZSTNPZIVERLCTLXKGTD
WZIQXWCYTGERRLFWMQMJSXILJAVGSTCRVQHW
VFJPUQNUFHEYMHNYNNLRJGJRQKXGFPRENLWR
GHDDFLLNUZHTXQRFTCXQMAJNYGILDPIZXUGK
""".strip().split('\n'))


Out[23]:
'QLSRUXWGGSFCSUSLFWLSDAFHWFIXTEYYCMVTOLTGUGHVHMVIXOUBWEZFTHYPTXCGPWGIKOLWBFIIRBYXTOGQYFPYOZZXGMQJNUUGHNWNWATHMYZFRGMSYUUFVYEDPTPHLJOOQLFTXARTWKOGYNJSTTHPXNCRHOSHLKJYWVBTDCYNRGLVKMWNHIURUSGNCIFNJWXWCPCTROYRQGELVRFWEAGTRHTFGEWNRJGYGYKFVYEYMSPQDWKFEXUDPJRZEMDDUGUCGTGRGMFGRPVYIMVQUWVBGOAPKRGNGHJTUTNYGWYWWKVTKRTRUNULGYFUYEXQRUCFCNXJKUFKHYJVCITWIBGMGIIFRIARRIXAWJKISUNERQRUTFGRGFDPMJUWNBWDJWKCZJJYFVKNWJSHPGNPLPLTULJHRSMKMAXNVZYRMYGHWNDUENUIWQDDLSATXFJQSZSTNPZIVERLCTLXKGTDWZIQXWCYTGERRLFWMQMJSXILJAVGSTCRVQHWVFJPUQNUFHEYMHNYNNLRJGJRQKXGFPRENLWRGHDDFLLNUZHTXQRFTCXQMAJNYGILDPIZXUGK'

In [24]:
example = {"ver":[[1,2,3],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0]],"hor":[[12,3],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0],[0]]}

In [26]:
ver_str = """
5 1 1 5
4 3 3 1 3 4 3 4
4 4 1 1 1 1 1 1 4 3
3 4 3 1 1 1 1 2 4 3
2 4 1 1 1 1 1 1 1 5 2
1 2 2 3 4 3 4 2 2 1
1 2 2 2 2 1
2 2 2 2
2 2 4 4 4 4 4 1 1 2 2
2 2 1 1 1 1 1 1 1 1 2 2 2 2
2 2 3 4 4 1 1 1 1 1 1 1 2 2
2 2 1 1 1 1 1 1 1 1 1 1 1 2 2
2 4 4 4 1 2 4 4 1 1 2 2
2 4 2 2
2 6 2 2
2 6 1 1 4 4 4 2 4
2 7 1 1 1 1 1 1 1 2 4
2 4 2 4 1 1 1 1 4 2 5
2 8 1 1 1 1 1 1 4 5
2 5 3 1 4 4 4 5 5
2 6 3 6 6
2 5 3 6 5
2 6 4 4 8 6
2 6 24 3 3 2
9 23 3 2 2
2 1 5 4 3 3 2 2
1 3 5 4 4 4 2 2 1
1 3 4 15 4 2 2 1
2 3 4 9 5 2 2 2
3 3 5 5 2 2 3
3 3 6 7 2 2 3
4 3 18 4 4
5 4 14 4 5
6 4 8 4 6
8 4 5 8
10 5 6 9
12 19 11
14 14 13
""".strip()
hor_str = """
00 00 0 0 00 00 00 00 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1
00 00 0 0 00 00 00 00 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 1 1
00 00 0 0 00 00 00 00 0 0 0 0 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 0 0 0 5 1 1
00 00 0 0 00 00 00 00 0 2 1 1 0 0 0 1 1 1 0 0 0 5 1 1 0 0 5 1 1 3 0 0 1 1 5 1
00 00 0 0 00 00 00 00 0 1 1 1 0 0 5 1 1 1 0 0 5 1 1 3 3 0 5 1 1 5 0 0 1 1 1 3
00 00 0 3 01 00 00 00 6 1 1 1 5 0 5 1 1 3 0 0 5 1 1 5 1 0 5 1 1 5 0 5 3 1 1 1 0 1 1 0 2 06 15 3 0 1 2
00 00 4 3 02 00 03 16 5 4 3 3 3 4 3 1 1 5 2 2 2 2 2 3 3 3 3 2 2 2 2 2 1 1 1 3 5 3 4 1 5 10 03 8 3 3 3 04
07 05 5 7 13 03 19 08 7 5 4 4 4 3 4 5 5 5 2 1 2 2 2 2 2 2 2 2 2 2 2 1 4 3 4 3 3 4 4 9 9 03 04 5 5 7 8 05 05 7
09 15 5 3 03 18 04 03 3 2 2 2 2 2 3 2 3 2 3 3 2 3 3 3 3 3 3 3 3 3 3 3 3 4 3 4 4 2 3 4 4 02 02 2 3 3 3 11 15 9
12 10 9 7 06 05 04 04 3 3 2 2 1 1 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 3 2 2 3 2 3 1 1 2 2 03 04 4 5 6 7 09 10 12
""".strip()
ver = [[int(s) for s in line.split()] for line in ver_str.split('\n')]
hor_rows = [[int(s) for s in line.split()] for line in hor_str.split('\n')]
hor = []
for col_idx in range(max(map(len, hor_rows))):
  col = []
  hor.append(col)
  for row in hor_rows:
    if col_idx < len(row) and row[col_idx]:
      col.append(row[col_idx])
print(ver)
print(hor)


[[5, 1, 1, 5], [4, 3, 3, 1, 3, 4, 3, 4], [4, 4, 1, 1, 1, 1, 1, 1, 4, 3], [3, 4, 3, 1, 1, 1, 1, 2, 4, 3], [2, 4, 1, 1, 1, 1, 1, 1, 1, 5, 2], [1, 2, 2, 3, 4, 3, 4, 2, 2, 1], [1, 2, 2, 2, 2, 1], [2, 2, 2, 2], [2, 2, 4, 4, 4, 4, 4, 1, 1, 2, 2], [2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2], [2, 2, 3, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2, 2], [2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2], [2, 4, 4, 4, 1, 2, 4, 4, 1, 1, 2, 2], [2, 4, 2, 2], [2, 6, 2, 2], [2, 6, 1, 1, 4, 4, 4, 2, 4], [2, 7, 1, 1, 1, 1, 1, 1, 1, 2, 4], [2, 4, 2, 4, 1, 1, 1, 1, 4, 2, 5], [2, 8, 1, 1, 1, 1, 1, 1, 4, 5], [2, 5, 3, 1, 4, 4, 4, 5, 5], [2, 6, 3, 6, 6], [2, 5, 3, 6, 5], [2, 6, 4, 4, 8, 6], [2, 6, 24, 3, 3, 2], [9, 23, 3, 2, 2], [2, 1, 5, 4, 3, 3, 2, 2], [1, 3, 5, 4, 4, 4, 2, 2, 1], [1, 3, 4, 15, 4, 2, 2, 1], [2, 3, 4, 9, 5, 2, 2, 2], [3, 3, 5, 5, 2, 2, 3], [3, 3, 6, 7, 2, 2, 3], [4, 3, 18, 4, 4], [5, 4, 14, 4, 5], [6, 4, 8, 4, 6], [8, 4, 5, 8], [10, 5, 6, 9], [12, 19, 11], [14, 14, 13]]
[[7, 9, 12], [5, 15, 10], [4, 5, 5, 9], [3, 3, 7, 3, 7], [1, 2, 13, 3, 6], [3, 18, 5], [3, 19, 4, 4], [16, 8, 3, 4], [6, 5, 7, 3, 3], [2, 1, 1, 4, 5, 2, 3], [1, 1, 1, 3, 4, 2, 2], [1, 1, 1, 3, 4, 2, 2], [5, 3, 4, 2, 1], [4, 3, 2, 1], [5, 5, 3, 4, 3, 2], [1, 1, 1, 1, 1, 1, 1, 5, 2, 2], [1, 1, 1, 1, 1, 1, 1, 5, 3, 2], [1, 1, 1, 3, 5, 5, 2, 2], [2, 2, 3, 3], [2, 1, 3, 2], [5, 5, 2, 2, 2, 2], [1, 5, 1, 1, 2, 2, 3, 2], [1, 1, 1, 1, 1, 2, 2, 3, 2], [1, 1, 3, 5, 3, 2, 3, 2], [3, 1, 3, 2, 3, 2], [3, 2, 3, 2], [5, 5, 5, 3, 2, 3, 2], [1, 1, 1, 1, 1, 1, 2, 2, 3, 2], [1, 1, 1, 1, 1, 1, 2, 2, 3, 2], [3, 5, 5, 2, 2, 3, 2], [2, 2, 3, 2], [5, 2, 1, 3, 3], [5, 1, 1, 3, 1, 4, 3, 2], [1, 1, 1, 1, 1, 1, 1, 3, 4, 2], [1, 1, 1, 5, 1, 1, 1, 4, 3, 3], [1, 3, 1, 3, 3, 4, 2], [5, 3, 4, 3], [1, 3, 4, 2, 1], [1, 4, 4, 3, 1], [1, 9, 4, 2], [2, 5, 9, 4, 2], [6, 10, 3, 2, 3], [15, 3, 4, 2, 4], [3, 8, 5, 2, 4], [3, 5, 3, 5], [1, 3, 7, 3, 6], [2, 3, 8, 3, 7], [4, 5, 11, 9], [5, 15, 10], [7, 9, 12]]

In [27]:
import json
json.dumps({'ver': ver, 'hor': hor})


Out[27]:
'{"ver": [[5, 1, 1, 5], [4, 3, 3, 1, 3, 4, 3, 4], [4, 4, 1, 1, 1, 1, 1, 1, 4, 3], [3, 4, 3, 1, 1, 1, 1, 2, 4, 3], [2, 4, 1, 1, 1, 1, 1, 1, 1, 5, 2], [1, 2, 2, 3, 4, 3, 4, 2, 2, 1], [1, 2, 2, 2, 2, 1], [2, 2, 2, 2], [2, 2, 4, 4, 4, 4, 4, 1, 1, 2, 2], [2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2], [2, 2, 3, 4, 4, 1, 1, 1, 1, 1, 1, 1, 2, 2], [2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2], [2, 4, 4, 4, 1, 2, 4, 4, 1, 1, 2, 2], [2, 4, 2, 2], [2, 6, 2, 2], [2, 6, 1, 1, 4, 4, 4, 2, 4], [2, 7, 1, 1, 1, 1, 1, 1, 1, 2, 4], [2, 4, 2, 4, 1, 1, 1, 1, 4, 2, 5], [2, 8, 1, 1, 1, 1, 1, 1, 4, 5], [2, 5, 3, 1, 4, 4, 4, 5, 5], [2, 6, 3, 6, 6], [2, 5, 3, 6, 5], [2, 6, 4, 4, 8, 6], [2, 6, 24, 3, 3, 2], [9, 23, 3, 2, 2], [2, 1, 5, 4, 3, 3, 2, 2], [1, 3, 5, 4, 4, 4, 2, 2, 1], [1, 3, 4, 15, 4, 2, 2, 1], [2, 3, 4, 9, 5, 2, 2, 2], [3, 3, 5, 5, 2, 2, 3], [3, 3, 6, 7, 2, 2, 3], [4, 3, 18, 4, 4], [5, 4, 14, 4, 5], [6, 4, 8, 4, 6], [8, 4, 5, 8], [10, 5, 6, 9], [12, 19, 11], [14, 14, 13]], "hor": [[7, 9, 12], [5, 15, 10], [4, 5, 5, 9], [3, 3, 7, 3, 7], [1, 2, 13, 3, 6], [3, 18, 5], [3, 19, 4, 4], [16, 8, 3, 4], [6, 5, 7, 3, 3], [2, 1, 1, 4, 5, 2, 3], [1, 1, 1, 3, 4, 2, 2], [1, 1, 1, 3, 4, 2, 2], [5, 3, 4, 2, 1], [4, 3, 2, 1], [5, 5, 3, 4, 3, 2], [1, 1, 1, 1, 1, 1, 1, 5, 2, 2], [1, 1, 1, 1, 1, 1, 1, 5, 3, 2], [1, 1, 1, 3, 5, 5, 2, 2], [2, 2, 3, 3], [2, 1, 3, 2], [5, 5, 2, 2, 2, 2], [1, 5, 1, 1, 2, 2, 3, 2], [1, 1, 1, 1, 1, 2, 2, 3, 2], [1, 1, 3, 5, 3, 2, 3, 2], [3, 1, 3, 2, 3, 2], [3, 2, 3, 2], [5, 5, 5, 3, 2, 3, 2], [1, 1, 1, 1, 1, 1, 2, 2, 3, 2], [1, 1, 1, 1, 1, 1, 2, 2, 3, 2], [3, 5, 5, 2, 2, 3, 2], [2, 2, 3, 2], [5, 2, 1, 3, 3], [5, 1, 1, 3, 1, 4, 3, 2], [1, 1, 1, 1, 1, 1, 1, 3, 4, 2], [1, 1, 1, 5, 1, 1, 1, 4, 3, 3], [1, 3, 1, 3, 3, 4, 2], [5, 3, 4, 3], [1, 3, 4, 2, 1], [1, 4, 4, 3, 1], [1, 9, 4, 2], [2, 5, 9, 4, 2], [6, 10, 3, 2, 3], [15, 3, 4, 2, 4], [3, 8, 5, 2, 4], [3, 5, 3, 5], [1, 3, 7, 3, 6], [2, 3, 8, 3, 7], [4, 5, 11, 9], [5, 15, 10], [7, 9, 12]]}'

In [31]:
import forge
from puzzle.puzzlepedia import puzzlepedia

puzzle = puzzlepedia.parse("""
@ 1 2 3 4 5 6 7 8 9 10
* BigOldBell
* BootyJuker
* CorkChoker
* FacePinner
* FakeTurtle
* LemurPoker
* PixieProng
* SheepStick
* SqueezeToy
* TinyStools
""".lower())


ERROR:root:An unexpected error occurred while tokenizing input
The following traceback may be corrupted or invalid
The error message is: ('EOF in multi-line string', (1, 0))

---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-31-ee22142fabb0> in <module>()
     14 * SqueezeToy
     15 * TinyStools
---> 16 """.lower())

/Users/philharnish/Projects/forge/src/puzzle/puzzlepedia/puzzlepedia.py in parse(source, hint, threshold)
      9   _init()
     10   result = puzzle.Puzzle('first stage', source, hint=hint, threshold=threshold)
---> 11   interact_with(result)
     12   return result
     13 

/Users/philharnish/Projects/forge/src/puzzle/puzzlepedia/puzzlepedia.py in interact_with(puzzle)
     15 def interact_with(puzzle):
     16   _init()
---> 17   display.display(puzzle_widget.PuzzleWidget(puzzle))
     18 
     19 

/Users/philharnish/Projects/forge/src/puzzle/puzzlepedia/puzzle_widget.py in PuzzleWidget(puzzle)
      8   widget_children = []
      9   for problem in puzzle._meta_problems:
---> 10     widget_children.append(problem_widget.ProblemWidget(problem))
     11   accordion = widgets.Accordion(children=widget_children)
     12   for i, problem in enumerate(puzzle._meta_problems):

/Users/philharnish/Projects/forge/src/puzzle/puzzlepedia/problem_widget.py in ProblemWidget(meta_problem)
     34   if meta_problem.peek():
     35     _update_solutions_for_problem(
---> 36         solutions_table, best_solution, meta_problem.peek())
     37   return widgets.VBox([widgets.HBox(items), solutions_table])
     38 

/Users/philharnish/Projects/forge/src/puzzle/puzzlepedia/problem_widget.py in _update_solutions_for_problem(table, best_solution, problem)
     39 
     40 def _update_solutions_for_problem(table, best_solution, problem):
---> 41   solutions = problem.solutions()
     42   if solutions.peek():
     43     best_solution.value = solutions.peek()

/Users/philharnish/Projects/forge/src/puzzle/problems/problem.py in solutions(self)
     42 
     43   def solutions(self):
---> 44     for _ in self._filtered_solutions_iterator:
     45       # Exhaust the _filtered_solutions_iterator.
     46       pass

/Users/philharnish/Projects/forge/src/puzzle/problems/problem.py in _filter_solutions_iter(self)
     65     # the Problem's constraints changed mid-solve.
     66     for k, v in itertools.chain(
---> 67         self._all_solutions.items(), self._solutions_iterator):
     68       constrained = all(fn(k, v) for fn in self._constraints)
     69       if constrained:

/Users/philharnish/Projects/forge/src/puzzle/problems/problem.py in _take_solutions_iter(self)
     57 
     58   def _take_solutions_iter(self):
---> 59     for k, v in self._solve_iter():
     60       self._all_solutions[k] = v
     61       yield k, v

/Users/philharnish/Projects/forge/src/puzzle/problems/acrostic_problem.py in _solve_iter(self)
     42 
     43   def _solve_iter(self):
---> 44     for solution, weight in self._acrostic.items():
     45       if weight < self._threshold:
     46         return

/Users/philharnish/Projects/forge/src/puzzle/heuristics/acrostics/_acrostic_iter.py in items(self)
     41 
     42   def items(self):
---> 43     for phrase, weight in self._walk_phrase_graph_from(0, [], 0):
     44       yield phrase, weight
     45 

/Users/philharnish/Projects/forge/src/puzzle/heuristics/acrostics/_acrostic_search.py in _walk_phrase_graph_from(self, pos, acc, acc_weight)
     32         best_phrase = heap.pop()
     33         yield from self._recurse_with(
---> 34             pos, acc, acc_weight, target, best_phrase, best_weight)
     35         best_weight = heap.best_weight()
     36     while len(heap):

/Users/philharnish/Projects/forge/src/puzzle/heuristics/acrostics/_acrostic_iter.py in _recurse_with(self, pos, acc, acc_weight, target, phrase, weight)
     59       interesting = (acc_len < 3) or (pos / acc_len >= _TARGET_WORD_LEN)
     60       if interesting:
---> 61         for result in self._walk_phrase_graph_from(pos, acc, acc_weight):
     62           # Forward any findings from recursive calls up the trampoline.
     63           yield result

/Users/philharnish/Projects/forge/src/puzzle/heuristics/acrostics/_acrostic_search.py in _walk_phrase_graph_from(self, pos, acc, acc_weight)
     32         best_phrase = heap.pop()
     33         yield from self._recurse_with(
---> 34             pos, acc, acc_weight, target, best_phrase, best_weight)
     35         best_weight = heap.best_weight()
     36     while len(heap):

/Users/philharnish/Projects/forge/src/puzzle/heuristics/acrostics/_acrostic_iter.py in _recurse_with(self, pos, acc, acc_weight, target, phrase, weight)
     59       interesting = (acc_len < 3) or (pos / acc_len >= _TARGET_WORD_LEN)
     60       if interesting:
---> 61         for result in self._walk_phrase_graph_from(pos, acc, acc_weight):
     62           # Forward any findings from recursive calls up the trampoline.
     63           yield result

/Users/philharnish/Projects/forge/src/puzzle/heuristics/acrostics/_acrostic_search.py in _walk_phrase_graph_from(self, pos, acc, acc_weight)
     32         best_phrase = heap.pop()
     33         yield from self._recurse_with(
---> 34             pos, acc, acc_weight, target, best_phrase, best_weight)
     35         best_weight = heap.best_weight()
     36     while len(heap):

/Users/philharnish/Projects/forge/src/puzzle/heuristics/acrostics/_acrostic_iter.py in _recurse_with(self, pos, acc, acc_weight, target, phrase, weight)
     59       interesting = (acc_len < 3) or (pos / acc_len >= _TARGET_WORD_LEN)
     60       if interesting:
---> 61         for result in self._walk_phrase_graph_from(pos, acc, acc_weight):
     62           # Forward any findings from recursive calls up the trampoline.
     63           yield result

/Users/philharnish/Projects/forge/src/puzzle/heuristics/acrostics/_acrostic_search.py in _walk_phrase_graph_from(self, pos, acc, acc_weight)
     20     interval_size = 1 / remaining_distance
     21     heap = max_heap.MaxHeap()
---> 22     for phrase, weight in self._phrases_at(pos, acc):
     23       phrase_len = len(phrase)
     24       normalized_weight = min(1, weight / self._trie.interesting_threshold())

/Users/philharnish/Projects/forge/src/puzzle/heuristics/acrostics/_acrostic_iter.py in _phrases_at(self, pos, acc)
     78     yield from self._iter_phrases(phrases_at)
     79     # Then find more.
---> 80     yield from self._walk(pos, acc)
     81 
     82   def _start_walk(self, pos, acc):

/Users/philharnish/Projects/forge/src/puzzle/heuristics/acrostics/_acrostic_iter.py in _walk(self, pos, acc)
     99     if not walk:
    100       return
--> 101     for phrase, weight in walk:
    102       if phrases_at is not None:
    103         l = len(phrase)

/Users/philharnish/Projects/forge/src/data/trie.py in walk(self, seek_sets, exact_match)
     81       exact_matches.add(word)
     82       yield word, weight
---> 83     for word, weight in self._walk(seek_sets, False):
     84       if word in exact_matches:
     85         continue

/Users/philharnish/Projects/forge/src/data/trie.py in _walk(self, seek_sets, exact_match)
    102       pos = len(acc)
    103       if seek_set_mode:
--> 104         seeking = seek_sets.seek(acc)
    105       else:
    106         seeking = seek_sets[pos]

/Users/philharnish/Projects/forge/src/data/seek_sets/seek_set.py in seek(self, seek)
     73       _visit(
     74           result, [False] * l, self._sets, self._set_index,
---> 75           self._indexes, seek, 0, False)
     76     except StopIteration:
     77       pass

/Users/philharnish/Projects/forge/src/data/seek_sets/seek_set.py in _visit(result, visited, sets, set_index, indexes, seek, pos, stop)
    163       continue
    164     visited[next_visit] = True
--> 165     _visit(result, visited, sets, set_index, indexes, seek, pos + 1, stop)
    166     visited[next_visit] = False

/Users/philharnish/Projects/forge/src/data/seek_sets/seek_set.py in _visit(result, visited, sets, set_index, indexes, seek, pos, stop)
    163       continue
    164     visited[next_visit] = True
--> 165     _visit(result, visited, sets, set_index, indexes, seek, pos + 1, stop)
    166     visited[next_visit] = False

/Users/philharnish/Projects/forge/src/data/seek_sets/seek_set.py in _visit(result, visited, sets, set_index, indexes, seek, pos, stop)
    163       continue
    164     visited[next_visit] = True
--> 165     _visit(result, visited, sets, set_index, indexes, seek, pos + 1, stop)
    166     visited[next_visit] = False

/Users/philharnish/Projects/forge/src/data/seek_sets/seek_set.py in _visit(result, visited, sets, set_index, indexes, seek, pos, stop)
    163       continue
    164     visited[next_visit] = True
--> 165     _visit(result, visited, sets, set_index, indexes, seek, pos + 1, stop)
    166     visited[next_visit] = False

/Users/philharnish/Projects/forge/src/data/seek_sets/seek_set.py in _visit(result, visited, sets, set_index, indexes, seek, pos, stop)
    139     index = None
    140   else:
--> 141     index = indexes[pos] - 1
    142   if pos == len(seek):
    143     for i, set in enumerate(sets):

KeyboardInterrupt: 

In [8]:
import Numberjack

model = Numberjack.Model()

x = {}
for name in 'abcd':
  x[name] = Numberjack.Variable([4, 5, 6, 8], name)

model.add(Numberjack.AllDiff(x.values()))

model.add(Numberjack.Sum([x[n] for n in 'abcd']) == 23)
base = 1
for n in 'efgh':
  base = x[n] * base
model.add(base == 42)

solver = model.load('Mistral')
solver.solve()

print("is_sat", solver.is_sat())
print("is_unsat", solver.is_unsat())

print(model)

for name in 'abcdefgh':
  print(x[name], x[name].get_value())


is_sat False
is_unsat True
assign:
  a in {1..8}
  b in {1..8}
  c in {1..8}
  d in {1..8}
  e in {1..8}
  f in {1..8}
  g in {1..8}
  h in {1..8}
  
subject to:
  AllDiff(a, b, c, d, e, f, g, h)
  ((a + b + c + d) == 23)
  ((h * (g * (f * (e * 1)))) == 42)
  
a in {1..8} None
b in {1..8} None
c in {1..8} None
d in {1..8} None
e in {1..8} None
f in {1..8} None
g in {1..8} None
h in {1..8} None

In [ ]: