Added defragmentation-related stuff
This commit is contained in:
parent
fca55f589b
commit
c5edaabaff
|
@ -0,0 +1,83 @@
|
||||||
|
import random, math
|
||||||
|
|
||||||
|
def mk_initial_balances(accts, coins):
|
||||||
|
o = []
|
||||||
|
for i in range(accts):
|
||||||
|
o.extend([i] * random.randrange((coins - len(o)) * 2 // (accts - i)))
|
||||||
|
o.extend([accts-1] * (coins - len(o)))
|
||||||
|
return o
|
||||||
|
|
||||||
|
def fragments(coins):
|
||||||
|
o = 0
|
||||||
|
for i in range(1, len(coins)):
|
||||||
|
if coins[i] != coins[i-1]:
|
||||||
|
o += 1
|
||||||
|
return o
|
||||||
|
|
||||||
|
def xfer(coins, frm, to, value):
|
||||||
|
coins = coins[::]
|
||||||
|
pos = 0
|
||||||
|
while pos < len(coins) and value > 0:
|
||||||
|
if coins[pos] == frm:
|
||||||
|
coins[pos] = to
|
||||||
|
value -= 1
|
||||||
|
pos += 1
|
||||||
|
return coins
|
||||||
|
|
||||||
|
def unscramble(coins, c1, c2):
|
||||||
|
coins = coins[::]
|
||||||
|
k1 = coins.count(c1)
|
||||||
|
pos = 0
|
||||||
|
while pos < len(coins):
|
||||||
|
if coins[pos] in (c1, c2):
|
||||||
|
coins[pos] = c1 if k1 > 0 else c2
|
||||||
|
if coins[pos] == c1:
|
||||||
|
k1 -= 1
|
||||||
|
pos += 1
|
||||||
|
return coins
|
||||||
|
|
||||||
|
def multi_unscramble(coins, addrs):
|
||||||
|
coins = coins[::]
|
||||||
|
ks = [coins.count(c) for c in addrs]
|
||||||
|
pos = 0
|
||||||
|
at = 0
|
||||||
|
while pos < len(coins):
|
||||||
|
if coins[pos] in addrs:
|
||||||
|
coins[pos] = addrs[at]
|
||||||
|
ks[at] -= 1
|
||||||
|
if ks[at] == 0:
|
||||||
|
at += 1
|
||||||
|
pos += 1
|
||||||
|
return coins
|
||||||
|
|
||||||
|
def unscramble_swap_strategy(coins, rounds):
|
||||||
|
for i in range(rounds):
|
||||||
|
c1, c2 = sorted([random.randrange(max(coins)+1) for _ in range(2)])
|
||||||
|
coins = unscramble(coins, c1, c2)
|
||||||
|
return coins
|
||||||
|
|
||||||
|
def run_with_unscrambling(coins, rounds):
|
||||||
|
M = max(coins) + 1
|
||||||
|
for i in range(rounds):
|
||||||
|
c1, c2 = [random.randrange(M) for _ in range(2)]
|
||||||
|
value = int(coins.count(c1) ** random.random())
|
||||||
|
coins = xfer(coins, c1, c2, value)
|
||||||
|
coins = unscramble(coins, min(c1, c2), max(c1, c2))
|
||||||
|
return coins
|
||||||
|
|
||||||
|
def run_with_unscramble_online(coins, rounds):
|
||||||
|
M = max(coins) + 1
|
||||||
|
for i in range(rounds):
|
||||||
|
c1, c2 = [random.randrange(M) for _ in range(2)]
|
||||||
|
value = int(coins.count(c1) ** random.random())
|
||||||
|
coins = xfer(coins, c1, c2, value)
|
||||||
|
if random.random() < 1:
|
||||||
|
cx = sorted([random.randrange(M) for _ in range(5)])
|
||||||
|
coins = multi_unscramble(coins, cx)
|
||||||
|
return coins
|
||||||
|
|
||||||
|
c = mk_initial_balances(200, 10000)
|
||||||
|
# random.shuffle(c)
|
||||||
|
# c = unscramble_swap_strategy(c, 20000)
|
||||||
|
c = run_with_unscramble_online(c, 10000)
|
||||||
|
print(fragments(c))
|
|
@ -0,0 +1,49 @@
|
||||||
|
import random
|
||||||
|
|
||||||
|
def mk_shuffle(n):
|
||||||
|
L = list(range(n))
|
||||||
|
random.shuffle(L)
|
||||||
|
return L
|
||||||
|
|
||||||
|
def mk_fragmented_shuffle(n, shuffs):
|
||||||
|
L = list(range(n))
|
||||||
|
for i in range(shuffs):
|
||||||
|
x1 = random.randrange(n)
|
||||||
|
x2 = random.randrange(n)
|
||||||
|
value = int(min(n - x1, n - x2, abs(x2 - x1)) ** random.random())
|
||||||
|
L[x1:x1+value], L[x2:x2+value] = L[x2:x2+value], L[x1:x1+value]
|
||||||
|
return L
|
||||||
|
|
||||||
|
def fragments(vals):
|
||||||
|
tot = 1
|
||||||
|
for i in range(1, len(vals)):
|
||||||
|
if vals[i] != vals[i-1] + 1:
|
||||||
|
tot += 1
|
||||||
|
return tot
|
||||||
|
|
||||||
|
def apply_perm(vals, perm):
|
||||||
|
o = [0 for x in vals]
|
||||||
|
for i in range(len(perm)):
|
||||||
|
o[i] = vals[perm[i]]
|
||||||
|
return o
|
||||||
|
|
||||||
|
def attempt_fix(vals):
|
||||||
|
perm = list(range(len(vals)))
|
||||||
|
indices = {}
|
||||||
|
for i, x in enumerate(vals):
|
||||||
|
indices[x] = i
|
||||||
|
for i in range(len(vals)):
|
||||||
|
if perm[i] == i and vals[i] != i:
|
||||||
|
poz = indices[i]
|
||||||
|
if perm[poz] == poz:
|
||||||
|
perm[i], perm[poz] = perm[poz], perm[i]
|
||||||
|
assert apply_perm(perm, perm) == list(range(len(vals)))
|
||||||
|
return perm
|
||||||
|
|
||||||
|
def fix(vals):
|
||||||
|
goal = list(range(len(vals)))
|
||||||
|
path = []
|
||||||
|
while vals != goal:
|
||||||
|
vals = apply_perm(vals, attempt_fix(vals))
|
||||||
|
path.append(vals)
|
||||||
|
return path
|
|
@ -0,0 +1,65 @@
|
||||||
|
import heapq, random
|
||||||
|
|
||||||
|
def distance_score(state):
|
||||||
|
state = [int(x) for x in state.split(',')]
|
||||||
|
tot = 0
|
||||||
|
for i, s in enumerate(state):
|
||||||
|
xorval = (i+1) ^ s
|
||||||
|
indexmask = 1
|
||||||
|
while indexmask < len(state):
|
||||||
|
if xorval & indexmask:
|
||||||
|
tot += 1
|
||||||
|
indexmask <<= 1
|
||||||
|
return tot
|
||||||
|
|
||||||
|
def generate_legal_moves_for_bit(state, bit):
|
||||||
|
o = set()
|
||||||
|
xormask = 2**bit
|
||||||
|
state = [int(x) for x in state.split(',')]
|
||||||
|
for i in range(2**(len(state)-1)):
|
||||||
|
new_state = state[::]
|
||||||
|
indexmask = 1
|
||||||
|
for j in range(len(state)):
|
||||||
|
if j > (j ^ xormask):
|
||||||
|
if i & indexmask:
|
||||||
|
new_state[j], new_state[j ^ xormask] = new_state[j ^ xormask], new_state[j]
|
||||||
|
indexmask <<= 1
|
||||||
|
o.add(','.join([str(x) for x in new_state]))
|
||||||
|
return o
|
||||||
|
|
||||||
|
def generate_legal_moves(state):
|
||||||
|
o = set()
|
||||||
|
b = 0
|
||||||
|
while 2**b < len(state):
|
||||||
|
o = o.union(generate_legal_moves_for_bit(state, b))
|
||||||
|
b += 1
|
||||||
|
return o
|
||||||
|
|
||||||
|
def mk_shuffle(n):
|
||||||
|
L = list(range(1, n+1))
|
||||||
|
random.shuffle(L)
|
||||||
|
return ','.join([str(x) for x in L])
|
||||||
|
|
||||||
|
def find_path(start):
|
||||||
|
parents = {}
|
||||||
|
scores = {start: 0}
|
||||||
|
queue = [(distance_score(start), start)]
|
||||||
|
goal = ','.join([str(x) for x in sorted([int(x) for x in start.split(',')])])
|
||||||
|
totvs = 0
|
||||||
|
while len(queue):
|
||||||
|
qval = heapq.heappop(queue)[1]
|
||||||
|
newvals = [x for x in generate_legal_moves(qval) if x not in scores]
|
||||||
|
for v in newvals:
|
||||||
|
if scores.get(v, 99999) > scores[qval] + 1:
|
||||||
|
scores[v] = scores[qval] + 1
|
||||||
|
parents[v] = qval
|
||||||
|
totvs += 1
|
||||||
|
if v == goal:
|
||||||
|
path = [v]
|
||||||
|
while path[-1] != start:
|
||||||
|
parent = parents[path[-1]]
|
||||||
|
path.append(parent)
|
||||||
|
return path
|
||||||
|
for v in newvals:
|
||||||
|
heapq.heappush(queue, (distance_score(v), v))
|
||||||
|
raise Exception("huh")
|
Loading…
Reference in New Issue