Blame Demos/benchmarks/meteor_contest.py

Packit Service 99d393
# The Computer Language Benchmarks Game
Packit Service 99d393
# http://shootout.alioth.debian.org/
Packit Service 99d393
#
Packit Service 99d393
# contributed by Daniel Nanz, 2008-08-21
Packit Service 99d393
Packit Service 99d393
import optparse
Packit Service 99d393
import time
Packit Service 99d393
from bisect import bisect
Packit Service 99d393
Packit Service 99d393
import util
Packit Service 99d393
Packit Service 99d393
w, h = 5, 10
Packit Service 99d393
dir_no = 6
Packit Service 99d393
S, E = w * h, 2
Packit Service 99d393
SE = S + (E / 2)
Packit Service 99d393
SW = SE - E
Packit Service 99d393
W, NW, NE = -E, -SE, -SW
Packit Service 99d393
Packit Service 99d393
Packit Service 99d393
def rotate(ido, rd={E: NE, NE: NW, NW: W, W: SW, SW: SE, SE: E}):
Packit Service 99d393
    return [rd[o] for o in ido]
Packit Service 99d393
Packit Service 99d393
def flip(ido, fd={E: E, NE: SE, NW: SW, W: W, SW: NW, SE: NE}):
Packit Service 99d393
    return [fd[o] for o in ido]
Packit Service 99d393
Packit Service 99d393
Packit Service 99d393
def permute(ido, r_ido):
Packit Service 99d393
    ps = [ido]
Packit Service 99d393
    for r in range(dir_no - 1):
Packit Service 99d393
        ps.append(rotate(ps[-1]))
Packit Service 99d393
        if ido == r_ido:                 # C2-symmetry
Packit Service 99d393
            ps = ps[0:dir_no//2]
Packit Service 99d393
    for pp in ps[:]:
Packit Service 99d393
        ps.append(flip(pp))
Packit Service 99d393
    return ps
Packit Service 99d393
Packit Service 99d393
Packit Service 99d393
def convert(ido):
Packit Service 99d393
    '''incremental direction offsets -> "coordinate offsets" '''
Packit Service 99d393
    out = [0]
Packit Service 99d393
    for o in ido:
Packit Service 99d393
        out.append(out[-1] + o)
Packit Service 99d393
    return list(set(out))
Packit Service 99d393
Packit Service 99d393
Packit Service 99d393
def get_footprints(board, cti, pieces):
Packit Service 99d393
    fps = [[[] for p in range(len(pieces))] for ci in range(len(board))]
Packit Service 99d393
    for c in board:
Packit Service 99d393
        for pi, p in enumerate(pieces):
Packit Service 99d393
            for pp in p:
Packit Service 99d393
                fp = frozenset([cti[c + o] for o in pp if (c + o) in cti])
Packit Service 99d393
                if len(fp) == 5:
Packit Service 99d393
                    fps[min(fp)][pi].append(fp)
Packit Service 99d393
    return fps
Packit Service 99d393
Packit Service 99d393
Packit Service 99d393
def get_senh(board, cti):
Packit Service 99d393
    '''-> south-east neighborhood'''
Packit Service 99d393
    se_nh = []
Packit Service 99d393
    nh = [E, SW, SE]
Packit Service 99d393
    for c in board:
Packit Service 99d393
        se_nh.append(frozenset([cti[c + o] for o in nh if (c + o) in cti]))
Packit Service 99d393
    return se_nh
Packit Service 99d393
Packit Service 99d393
Packit Service 99d393
def get_puzzle(w=w, h=h):
Packit Service 99d393
    board = [E*x + S*y + (y%2) for y in range(h) for x in range(w)]
Packit Service 99d393
    cti = dict((board[i], i) for i in range(len(board)))
Packit Service 99d393
Packit Service 99d393
    idos = [[E, E, E, SE],         # incremental direction offsets
Packit Service 99d393
            [SE, SW, W, SW],
Packit Service 99d393
            [W, W, SW, SE],
Packit Service 99d393
            [E, E, SW, SE],
Packit Service 99d393
            [NW, W, NW, SE, SW],
Packit Service 99d393
            [E, E, NE, W],
Packit Service 99d393
            [NW, NE, NE, W],
Packit Service 99d393
            [NE, SE, E, NE],
Packit Service 99d393
            [SE, SE, E, SE],
Packit Service 99d393
            [E, NW, NW, NW]]
Packit Service 99d393
Packit Service 99d393
    perms = (permute(p, idos[3]) for p in idos)    # restrict piece 4
Packit Service 99d393
    pieces = [[convert(pp) for pp in p] for p in perms]
Packit Service 99d393
    return (board, cti, pieces)
Packit Service 99d393
Packit Service 99d393
Packit Service 99d393
def print_board(board, w=w, h=h):
Packit Service 99d393
    for y in range(h):
Packit Service 99d393
        for x in range(w):
Packit Service 99d393
            print(board[x + y * w])
Packit Service 99d393
        print('')
Packit Service 99d393
        if y % 2 == 0:
Packit Service 99d393
            print('')
Packit Service 99d393
    print()
Packit Service 99d393
Packit Service 99d393
Packit Service 99d393
board, cti, pieces = get_puzzle()
Packit Service 99d393
fps = get_footprints(board, cti, pieces)
Packit Service 99d393
se_nh = get_senh(board, cti)
Packit Service 99d393
Packit Service 99d393
Packit Service 99d393
def solve(n, i_min, free, curr_board, pieces_left, solutions,
Packit Service 99d393
          fps=fps, se_nh=se_nh, bisect=bisect):
Packit Service 99d393
    fp_i_cands = fps[i_min]
Packit Service 99d393
    for p in pieces_left:
Packit Service 99d393
        fp_cands = fp_i_cands[p]
Packit Service 99d393
        for fp in fp_cands:
Packit Service 99d393
            if fp <= free:
Packit Service 99d393
                n_curr_board = curr_board[:]
Packit Service 99d393
                for ci in fp:
Packit Service 99d393
                    n_curr_board[ci] = p
Packit Service 99d393
                if len(pieces_left) > 1:
Packit Service 99d393
                    n_free = free - fp
Packit Service 99d393
                    n_i_min = min(n_free)
Packit Service 99d393
                    if len(n_free & se_nh[n_i_min]) > 0:
Packit Service 99d393
                        n_pieces_left = pieces_left[:]
Packit Service 99d393
                        n_pieces_left.remove(p)
Packit Service 99d393
                        solve(n, n_i_min, n_free, n_curr_board,
Packit Service 99d393
                              n_pieces_left, solutions)
Packit Service 99d393
                else:
Packit Service 99d393
                    s = ''.join(map(str, n_curr_board))
Packit Service 99d393
                    solutions.insert(bisect(solutions, s), s)
Packit Service 99d393
                    rs = s[::-1]
Packit Service 99d393
                    solutions.insert(bisect(solutions, rs), rs)
Packit Service 99d393
                    if len(solutions) >= n:
Packit Service 99d393
                        return
Packit Service 99d393
        if len(solutions) >= n:
Packit Service 99d393
            return
Packit Service 99d393
    return
Packit Service 99d393
Packit Service 99d393
SOLVE_ARG = 60
Packit Service 99d393
Packit Service 99d393
def main(n):
Packit Service 99d393
    times = []
Packit Service 99d393
    for i in range(n):
Packit Service 99d393
        t0 = time.time()
Packit Service 99d393
        free = frozenset(range(len(board)))
Packit Service 99d393
        curr_board = [-1] * len(board)
Packit Service 99d393
        pieces_left = list(range(len(pieces)))
Packit Service 99d393
        solutions = []
Packit Service 99d393
        solve(SOLVE_ARG, 0, free, curr_board, pieces_left, solutions)
Packit Service 99d393
        #print len(solutions),  'solutions found\n'
Packit Service 99d393
        #for i in (0, -1): print_board(solutions[i])
Packit Service 99d393
        tk = time.time()
Packit Service 99d393
        times.append(tk - t0)
Packit Service 99d393
    return times
Packit Service 99d393
Packit Service 99d393
if __name__ == "__main__":
Packit Service 99d393
    parser = optparse.OptionParser(
Packit Service 99d393
        usage="%prog [options]",
Packit Service 99d393
        description="Test the performance of the Float benchmark")
Packit Service 99d393
    util.add_standard_options_to(parser)
Packit Service 99d393
    options, args = parser.parse_args()
Packit Service 99d393
Packit Service 99d393
    util.run_benchmark(options, options.num_runs, main)
Packit Service 99d393