两个从未完成的python2.7 rand.shuffle程序

两个从未完成的python2.7 rand.shuffle程序,python,Python,我对Python(以及一般的编程)比较陌生,但需要解决这个问题。我试图用不同的规则将csv文件中的信息随机化(这不是家庭作业,是为了工作)。我以前有一个版本的脚本可以运行,所以我知道基本的都可以。然而,对于当前的两个版本,它们永远不会成功。我将在下面包含相关的代码位 import os import sys import random import csv # Opens the file supplied in the first argument in the command li

我对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
如果abs(int(orderdata[i][5])-int(orderdata[i+1][5])<2和abs(int(orderdata[i][6])-int(orderdata[i+1][6])<2:
如果i>max_i:
max_i=i
完成=错误
打破
其他:
持续
尝试次数+=1

这两种方法都有效,但只是不停地进行,永远无法成功地找到具有这些规则的随机列表。我是在做傻事,还是根本不可能?谢谢

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

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语句更改为“if True”来验证它是否探索了所有可能的排列,您将得到全部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]):
        ...
def sols(a、avail、x5、x6):
...
坏=(x5和abs(x5-r[5])<2)和(x6和abs(x6-r[6])<2)
...
对于溶胶中的s(a,1,r[5],r[6]):
...

当然,可能没有满足排除规则的任何排列,在这种情况下,您将得到StopIteration异常。

您的orderdata列表有多大?您拥有的元素越多,任何特定的洗牌都不太可能满足您的“不运行”标准。请注意,您的输入可以更简单地使用
orderdata=csvfile.readlines()
[1:]完成。问得好。它们都在150-200行之间。我让两个脚本通宵运行,一个达到了101行(IIRC),另一个到了90年代。谢谢你,holdenweb!那种东西很有用!用更少的行数运行测试,然后继续增加行数。要么您会发现运行时间呈指数增长(或者更糟!),要么有一条特定的线路使得条件无法满足。