Skip to content

Instantly share code, notes, and snippets.

@ckhung
Last active April 4, 2023 05:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ckhung/7e027f54dddd0e223da23f5efe59be76 to your computer and use it in GitHub Desktop.
Save ckhung/7e027f54dddd0e223da23f5efe59be76 to your computer and use it in GitHub Desktop.
knight's tour
#!/usr/bin/python3
import argparse, sys, os, atexit
from ansi import cursor
from ansi.color import fg, bg, fx
from time import sleep
# manual fix for ansi.cursor.erase
from ansi.sequence import sequence
cursor.erase = sequence('2J')
parser = argparse.ArgumentParser(
description='knight''s tour',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-w', '--width', type=int, default=5,
help='width of board')
parser.add_argument('-a', '--height', type=int, default=0,
help='height (altitude) of board; 0 means same as width')
parser.add_argument('-x', type=int, default=0,
help='initial x position, 0 to width-1')
parser.add_argument('-y', type=int, default=0,
help='initial y position, 0 to height-1')
parser.add_argument('-s', '--speed', type=int, default=12,
help='speed; exponential effect; meaningful value roughly 0 to 18')
args = parser.parse_args()
if args.height <= 0:
args.height = args.width
if args.x < 0 or args.x >= args.width:
print('initial x position should be 0 to width-1')
if args.y < 0 or args.y >= args.height:
print('initial y position should be 0 to height-1')
term = os.get_terminal_size()
def xy2rc(x, y):
return (
(term.lines - args.height*2)//2 + (args.height - y)*2,
(term.columns - args.width*4)//2 + x*4
)
def show_at(x, y, s, style=''):
sys.stdout.write(str(style) + str(cursor.goto(*xy2rc(x, y))) + s + str(fx.reset))
sys.stdout.flush()
board = [ [ 0 for y in range(args.height) ] for x in range(args.width) ]
move = ( (2,1), (1,2), (-1,2), (-2,1), (-2,-1), (-1,-2), (1,-2), (2,-1) )
def step(k, x, y):
if x<0 or y<0 or x>=args.width or y>=args.height or board[x][y]>0:
return False
board[x][y] = k
show_at(x, y, '{:3}'.format(k), style=fg.cyan+fx.negative)
sleep(1.0/(1<<args.speed))
show_at(x, y, '{:3}'.format(k))
if k >= args.width*args.height: return True
for d in range(8):
if step(k+1, x+move[d][0], y+move[d][1]):
return True
board[x][y] = 0
show_at(x, y, '{:3}'.format(k), style=fg.red+fx.negative)
sleep(1.0/(1<<args.speed))
show_at(x, y, ' '*3)
return False
atexit.register(
lambda: sys.stdout.write(cursor.show()+cursor.goto(term.lines, 1))
)
sys.stdout.write(cursor.erase()+cursor.hide())
step(1, args.x, args.y)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment