两个永远不会完成的python2.7 rand.shuffle程序

时间:2014-12-11 15:22:09

标签: python

我对Python(以及一般的编程)相对较新,但需要解决这个问题。我试图用不同的规则随机化csv文件中的信息(这不是作业,而是用于工作)。我之前已经有了这个脚本的版本,所以我知道基本没问题。但是,对于当前的两个版本,它们永远不会成功。我将在下面包含相关的代码。

    import os
import sys
import random
import csv

# Opens the file supplied in the first argument in the command line.
# Then, sets up each row as its own entity for later randomization
with open(os.path.join(os.getcwd(),sys.argv[1]),'rU') as csvfile:
    orderimport = csv.reader(csvfile, dialect=csv.excel_tab, delimiter=',')
    orderdata = []

    next(orderimport,None)
    for row in orderimport:
        orderdata.append(row)

done = False
attempt = 1
max_i = 0

while not done:
    random.shuffle(orderdata)
    done = True; # maybe

# prints the attempts in hundreds of thousands, as well as the max number of lines completed before starting over (however many rows are in the sheet is the max)

    if attempt % 100000 == 0:
        print attempt,max_i
    for i in range(len(orderdata)-3):

# This is where you supply the rules!
# This is useful if you want to prevent blocks of trials. You can change these values to whatever you need sorted. 
        if (orderdata[i][11]==orderdata[i+1][11] and orderdata[i][11]==orderdata[i+2][11] and orderdata[i][11]==orderdata[i+3][11]) or \
        (orderdata[i][6]==orderdata[i+1][6]):
            if i>max_i:
                max_i = i
            done = False
            break
        else:           
            continue
    attempt += 1
# This is where it will saves the file. Do not change this part! 
# Just supply the full desired filename (with file type) as the second argument when running the script.
with open(os.path.join(os.getcwd(),sys.argv[2]),'wb') as csvfile:
    orderexport = csv.writer(csvfile, dialect=csv.excel_tab, delimiter=',')
    for row in orderdata:
        orderexport.writerow(row)

和略有不同的程序,只列出了不同的部分:

    if abs(int(orderdata[i][5]) - int(orderdata[i+1][5])) < 2 and abs(int(orderdata[i][6]) - int(orderdata[i+1][6])) < 2:
        if i>max_i:
            max_i = i
        done = False
        break
    else:           
        continue
attempt += 1

两者都有效但只是继续前进并且永远不会成功找到包含这些规则的随机列表。我做的事情愚蠢,还是只是不可能?谢谢!

1 个答案:

答案 0 :(得分:0)

这是一种通过修剪和回溯探索行的所有可能排序的方法。在这种情况下,我们感兴趣的是a[i][2] <> a[i+1][2]所有i的订购。

def sols(a,avail,avoid):
  if not avail:
    yield []
  for i in avail:
    r = a[i]
    if not (avoid and r[2] == avoid):   -- to see all orderings, change to "if True:"
      avail1 = avail - set([i])
      for s in sols(a, avail1, r[2]):
        yield [r]+s

def solutions(a):
  inds = range(0, len(a))
  return sols(a, set(inds), None)

arr = [ [1,1,10,1,1], [2,2,30,2,2], [3,3,10,3,3], [4,4,30,4,4] ]
for s in solutions(arr):
  print s

输出结果为:

[[1, 1, 10, 1, 1], [2, 2, 30, 2, 2], [3, 3, 10, 3, 3], [4, 4, 30, 4, 4]]
[[1, 1, 10, 1, 1], [4, 4, 30, 4, 4], [3, 3, 10, 3, 3], [2, 2, 30, 2, 2]]
[[2, 2, 30, 2, 2], [1, 1, 10, 1, 1], [4, 4, 30, 4, 4], [3, 3, 10, 3, 3]]
[[2, 2, 30, 2, 2], [3, 3, 10, 3, 3], [4, 4, 30, 4, 4], [1, 1, 10, 1, 1]]
[[3, 3, 10, 3, 3], [2, 2, 30, 2, 2], [1, 1, 10, 1, 1], [4, 4, 30, 4, 4]]
[[3, 3, 10, 3, 3], [4, 4, 30, 4, 4], [1, 1, 10, 1, 1], [2, 2, 30, 2, 2]]
[[4, 4, 30, 4, 4], [1, 1, 10, 1, 1], [2, 2, 30, 2, 2], [3, 3, 10, 3, 3]]
[[4, 4, 30, 4, 4], [3, 3, 10, 3, 3], [2, 2, 30, 2, 2], [1, 1, 10, 1, 1]]

请注意,在4行的24种可能的排列中,只打印了8行。 您可以通过将sols()中的第二个if语句更改为&#34;如果为True&#34;来验证它是否探索了所有可能的排列。而且你将获得所有24个。

要选择一个随机的,只需将输入数组洗牌并采用第一个解决方案:

random.shuffle(arr)
print "a random ordering:", solutions(arr).next()

注意:我认为可以调整算法以更有效地使用内存 - 我会调查一下。

更新:这是(我确定)一个更有效的解决方案,它使用元组来共享内存。 在这种情况下,我已实施了您的第一个排除规则。

def sols(a,avail,avoid,x1,x2,x3):
  if not avail:
    yield None
  for i in avail:
    r = a[i]
    bad = (avoid and r[6]) or (x1 and x2 and x3 and x1 == x2 and x2 == x3 and x3 == r[11])
    if not bad:
      avail1 = avail - set([i])
      for s in sols(a, avail1, r[6], x2, x3, r[11]):
        yield (r,s)

def fromTuples(t):
  arr = []
  while isinstance(t, tuple):
    arr.append( t[0] )
    t = t[1]
  return arr

def solutions(a):
  for s in sols(a, set(range(len(a))), None, None, None, None):
    yield fromTuples(s)

def randomSolution(a):
  solutions(random.shuffle(a)).next()

您可以通过修改sols来实施您的其他排除规则,如下所示:

def sols(a, avail, x5, x6):
  ...
    bad = (x5 && abs(x5 - r[5]) < 2) and (x6 && abs(x6 - r[6]) < 2)
    ...
      for s in sols(a, avail1, r[5], r[6]):
        ...

当然,可能没有任何排列符合您的排除规则,在这种情况下,您将获得StopIteration例外。