| 1 | #! /usr/bin/python |
| 2 | ### -*-python-*- |
| 3 | ### |
| 4 | ### Generate input script and expected output for hash tables. |
| 5 | |
| 6 | import sys as SYS |
| 7 | import random as R |
| 8 | |
| 9 | ###-------------------------------------------------------------------------- |
| 10 | ### Command-line parsing. |
| 11 | |
| 12 | SYS.argv[0:1] = [] |
| 13 | def arg(default = None): |
| 14 | if len(SYS.argv): |
| 15 | r = SYS.argv[0] |
| 16 | SYS.argv[0:1] = [] |
| 17 | return r |
| 18 | else: |
| 19 | return default |
| 20 | |
| 21 | R.seed(None) |
| 22 | SEED = int(arg(str(R.randrange(0, 1 << 32))), 0) |
| 23 | R.seed(SEED) |
| 24 | |
| 25 | LINES = int(arg(1000)) |
| 26 | |
| 27 | ###-------------------------------------------------------------------------- |
| 28 | ### Word list. |
| 29 | |
| 30 | def word(): |
| 31 | def char(): return 'abcdefghijklmnopqrstuvwxyz'[R.randrange(0, 26)] |
| 32 | word = char() + char() + char() |
| 33 | while R.randrange(0, 6) != 0: word += char() |
| 34 | return word |
| 35 | |
| 36 | ## for i in ['/usr/share/dict/words', '/usr/dict/words']: |
| 37 | ## try: |
| 38 | ## WORDS = [line[:-1] for line in open(i)] |
| 39 | ## raise Exception |
| 40 | ## except: |
| 41 | ## pass |
| 42 | ## else: |
| 43 | ## def word(): |
| 44 | ## return WORDS[R.randrange(0, len(WORDS))] |
| 45 | ## break |
| 46 | |
| 47 | ###-------------------------------------------------------------------------- |
| 48 | ### Initialization. |
| 49 | |
| 50 | SERIAL = 1 |
| 51 | MAP = {} |
| 52 | |
| 53 | SCRIPT = open('sym.script', 'w') |
| 54 | WIN = open('expout', 'w') |
| 55 | |
| 56 | ###-------------------------------------------------------------------------- |
| 57 | ### Utility functions. |
| 58 | |
| 59 | OPS = [] |
| 60 | def op(weight): |
| 61 | """ |
| 62 | Operation decorator. Add the following function to the operations table, |
| 63 | with the given probability WEIGHT. This works as follows: if TOTAL is the |
| 64 | total of all the WEIGHTs, then this operation has a probability of |
| 65 | WEIGHT/TOTAL of being selected. |
| 66 | """ |
| 67 | def _(cls): |
| 68 | OPS.append((weight, cls)) |
| 69 | return cls |
| 70 | return _ |
| 71 | |
| 72 | def serial(): |
| 73 | """Return the next number in a simple sequence.""" |
| 74 | global SERIAL |
| 75 | SERIAL += 1 |
| 76 | return SERIAL - 1 |
| 77 | |
| 78 | ###-------------------------------------------------------------------------- |
| 79 | ### The actual operations. |
| 80 | |
| 81 | @op(10) |
| 82 | def op_set(): |
| 83 | w = word() |
| 84 | n = serial() |
| 85 | SCRIPT.write('set %s %d\n' % (w, n)) |
| 86 | MAP[w] = n |
| 87 | |
| 88 | @op(10) |
| 89 | def op_get(): |
| 90 | w = word() |
| 91 | try: |
| 92 | WIN.write('%d\n' % MAP[w]) |
| 93 | except KeyError: |
| 94 | if R.randrange(8): return |
| 95 | WIN.write('*MISSING*\n') |
| 96 | SCRIPT.write('get %s\n' % (w)) |
| 97 | |
| 98 | @op(10) |
| 99 | def op_del(): |
| 100 | w = word() |
| 101 | try: |
| 102 | del MAP[w] |
| 103 | except KeyError: |
| 104 | if R.randrange(8): return |
| 105 | WIN.write('*MISSING*\n') |
| 106 | SCRIPT.write('del %s\n' % (w)) |
| 107 | |
| 108 | @op(4) |
| 109 | def op_count(): |
| 110 | SCRIPT.write('count\n') |
| 111 | WIN.write('%d\n' % len(MAP)) |
| 112 | |
| 113 | @op(1) |
| 114 | def op_show(): |
| 115 | SCRIPT.write('show\n') |
| 116 | if not MAP: |
| 117 | WIN.write('*EMPTY*\n') |
| 118 | else: |
| 119 | kk = MAP.keys() |
| 120 | kk.sort() |
| 121 | WIN.write(' '.join(['%s:%d' % (k, MAP[k]) for k in kk]) + '\n') |
| 122 | |
| 123 | ###-------------------------------------------------------------------------- |
| 124 | ### Generate the output. |
| 125 | |
| 126 | OPTAB = [] |
| 127 | for p, func in OPS: |
| 128 | OPTAB += [func] * p |
| 129 | for i in xrange(LINES): |
| 130 | OPTAB[R.randrange(0, len(OPTAB))]() |
| 131 | op_show() |
| 132 | |
| 133 | SCRIPT.close() |
| 134 | WIN.close() |
| 135 | open('sym.seed', 'w').write('sym-gtest seed = %08x\n' % SEED) |
| 136 | |
| 137 | ###----- That's all, folks -------------------------------------------------- |