#!/usr/bin/python
ROWS = 2
COLS = 3
## different cell representations
def cell( r, c) :
## exercise for the reader: _gues_ which of the following is the fastest
## ...
## then profile it :)
index = COLS*( r) + c
# return [ r,c ]
# return ( r,c )
# return index
# return "(%i,%i)" % (r,c)
def baseN( num, b, numerals= "abcdefghijklmnopqrstuvwxyz" ) :
return ( ( num == 0 ) and numerals[ 0 ] ) or ( baseN( num // b, b, numerals) .lstrip ( numerals[ 0 ] ) + numerals[ num % b] )
return baseN( index, 26 )
ORIGIN = cell( 0 , 0 )
def debug( t) : pass ; #print t
def dump( grid) : print ( "\n " .join ( map ( str , grid) ) )
def print_path( path) :
## Note: to 'normalize' to start at (1,1) node:
# while ORIGIN != path[0]: path = path[1:] + path[:1]
print " -> " .join ( map ( str , path) )
def bruteforce_hamiltonians( grid, whenfound) :
def inner( grid, whenfound, partial) :
cols = len ( grid[ -1 ] ) # number of columns remaining in last rank
if cols< 1 :
# assert 1 == len(set([ len(r) for r in grid ])) # for debug only
whenfound( partial) # disable when benchmarking
pass
else :
#debug(" ------ cols: %i ------- " % cols)
for i, rank in enumerate ( grid) :
if len ( rank) < cols: continue
#debug("debug: %i, %s (partial: %s%s)" % (i,rank, "... " if len(partial)>3 else "", partial[-3:]))
for ci, cell in enumerate ( rank) :
partial.append ( cell)
grid[ i] = rank[ :ci] +rank[ ci+1 :] # modify grid in-place, keeps rank
inner( grid, whenfound, partial)
grid[ i] = rank # restore in-place
partial.pop ( )
break
pass
# start of recursion
inner( grid, whenfound, [ ] )
grid = [ [ cell( c, r) for r in range ( COLS) ] for c in range ( ROWS) ]
dump( grid)
bruteforce_hamiltonians( grid, print_path)
IyEvdXNyL2Jpbi9weXRob24KUk9XUyA9IDIKQ09MUyA9IDMKCiMjIGRpZmZlcmVudCBjZWxsIHJlcHJlc2VudGF0aW9ucwpkZWYgY2VsbChyLGMpOiAKICAgICMjIGV4ZXJjaXNlIGZvciB0aGUgcmVhZGVyOiBfZ3Vlc18gd2hpY2ggb2YgdGhlIGZvbGxvd2luZyBpcyB0aGUgZmFzdGVzdAogICAgIyMgLi4uCiAgICAjIyB0aGVuIHByb2ZpbGUgaXQgOikKICAgIGluZGV4ID0gQ09MUyoocikgKyBjCiAgICAjIHJldHVybiBbIHIsYyBdCiAgICAjIHJldHVybiAoIHIsYyApCiAgICAjIHJldHVybiBpbmRleAogICAgIyByZXR1cm4gIiglaSwlaSkiICUgKHIsYykKCiAgICBkZWYgYmFzZU4obnVtLGIsbnVtZXJhbHM9ImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6Iik6CiAgICAgICAgcmV0dXJuICgobnVtID09IDApIGFuZCBudW1lcmFsc1swXSkgb3IgKGJhc2VOKG51bSAvLyBiLCBiLCBudW1lcmFscykubHN0cmlwKG51bWVyYWxzWzBdKSArIG51bWVyYWxzW251bSAlIGJdKQoKICAgIHJldHVybiBiYXNlTihpbmRleCwgMjYpCgpPUklHSU4gPSBjZWxsKDAsMCkKCmRlZiBkZWJ1Zyh0KTogcGFzczsgI3ByaW50IHQKZGVmIGR1bXAoZ3JpZCk6IHByaW50KCJcbiIuam9pbihtYXAoc3RyLCBncmlkKSkpCgpkZWYgcHJpbnRfcGF0aChwYXRoKToKICAgICMjIE5vdGU6IHRvICdub3JtYWxpemUnIHRvIHN0YXJ0IGF0ICgxLDEpIG5vZGU6CiAgICAjIHdoaWxlIE9SSUdJTiAhPSBwYXRoWzBdOiBwYXRoID0gcGF0aFsxOl0gKyBwYXRoWzoxXSAKICAgIHByaW50ICIgLT4gIi5qb2luKG1hcChzdHIsIHBhdGgpKQoKZGVmIGJydXRlZm9yY2VfaGFtaWx0b25pYW5zKGdyaWQsIHdoZW5mb3VuZCk6CiAgICBkZWYgaW5uZXIoZ3JpZCwgd2hlbmZvdW5kLCBwYXJ0aWFsKToKCiAgICAgICAgY29scyA9IGxlbihncmlkWy0xXSkgIyBudW1iZXIgb2YgY29sdW1ucyByZW1haW5pbmcgaW4gbGFzdCByYW5rCiAgICAgICAgaWYgY29sczwxOgogICAgICAgICAgICAjIGFzc2VydCAxID09IGxlbihzZXQoWyBsZW4ocikgZm9yIHIgaW4gZ3JpZCBdKSkgIyBmb3IgZGVidWcgb25seQogICAgICAgICAgICB3aGVuZm91bmQocGFydGlhbCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgZGlzYWJsZSB3aGVuIGJlbmNobWFya2luZwogICAgICAgICAgICBwYXNzCiAgICAgICAgZWxzZToKICAgICAgICAgICAgI2RlYnVnKCIgLS0tLS0tIGNvbHM6ICVpIC0tLS0tLS0gIiAlIGNvbHMpCgogICAgICAgICAgICBmb3IgaSxyYW5rIGluIGVudW1lcmF0ZShncmlkKToKICAgICAgICAgICAgICAgIGlmIGxlbihyYW5rKTxjb2xzOiBjb250aW51ZQogICAgICAgICAgICAgICAgI2RlYnVnKCJkZWJ1ZzogJWksICVzIChwYXJ0aWFsOiAlcyVzKSIgJSAoaSxyYW5rLCAiLi4uICIgaWYgbGVuKHBhcnRpYWwpPjMgZWxzZSAiIiwgcGFydGlhbFstMzpdKSkKICAgICAgICAgICAgICAgIGZvciBjaSxjZWxsIGluIGVudW1lcmF0ZShyYW5rKToKICAgICAgICAgICAgICAgICAgICBwYXJ0aWFsLmFwcGVuZChjZWxsKQogICAgICAgICAgICAgICAgICAgIGdyaWRbaV0gPSByYW5rWzpjaV0rcmFua1tjaSsxOl0gIyBtb2RpZnkgZ3JpZCBpbi1wbGFjZSwga2VlcHMgcmFuawoKICAgICAgICAgICAgICAgICAgICBpbm5lcihncmlkLCB3aGVuZm91bmQsIHBhcnRpYWwpCgogICAgICAgICAgICAgICAgICAgIGdyaWRbaV0gPSByYW5rICMgcmVzdG9yZSBpbi1wbGFjZQogICAgICAgICAgICAgICAgICAgIHBhcnRpYWwucG9wKCkKICAgICAgICAgICAgICAgIGJyZWFrCiAgICAgICAgcGFzcwogICAgIyBzdGFydCBvZiByZWN1cnNpb24KICAgIGlubmVyKGdyaWQsIHdoZW5mb3VuZCwgW10pCgpncmlkID0gWyBbIGNlbGwoYyxyKSBmb3IgciBpbiByYW5nZShDT0xTKSBdIGZvciBjIGluIHJhbmdlKFJPV1MpIF0KCmR1bXAoZ3JpZCkKCmJydXRlZm9yY2VfaGFtaWx0b25pYW5zKGdyaWQsIHByaW50X3BhdGgpCg==