python中的随机选择,意外工作

python中的随机选择,意外工作,python,algorithm,Python,Algorithm,我正在尝试实现我刚在课堂上学到的rselect算法。然而,我似乎无法找出我在实现中的错误所在。这是我的密码*编辑* :我试着使用David在回答中提供的信息,但我的代码仍然很奇怪。以下是修订后的代码: def rselect(seq,length,i):# i is the i'th order statistic. if len(seq)<=1:return seq lo,pi,hi,loc_pi= random_partition(seq if loc_pi==

我正在尝试实现我刚在课堂上学到的rselect算法。然而,我似乎无法找出我在实现中的错误所在。这是我的密码*编辑* :我试着使用David在回答中提供的信息,但我的代码仍然很奇怪。以下是修订后的代码:

def rselect(seq,length,i):# i is the i'th order statistic.
    if len(seq)<=1:return seq
    lo,pi,hi,loc_pi= random_partition(seq
    if loc_pi==i:return pi 
    if loc_pi>i:return rselect(lo,loc_pi-1,i) 
    elif loc_pi<i:return rselect(hi,length-loc_pi,i-loc_pi)#
from random import choice  
def random_partition(seq):
    pi =choice(seq)
    #print 'pi',pi
    loc_pi=seq.index(pi)
    print 'Location',loc_pi
    lo=[x for x in seq if x<=pi]
    hi=[x for x in seq if x>pi]
    return lo,pi,hi,len(lo)+1   #--A

def test_rselect(seq,i):
    print 'Sequence',seq
    l=len(seq)
    print 'Statistic', rselect(seq,l,i)
预期输出:我希望在这里找到第i个顺序统计信息

因此

test\r选择([54,-11000565,64,2,5],2)
应始终返回
5
作为统计数据

任何关于我在这个实现中遇到的问题的帮助都会很有帮助。。谢谢
编辑2:尝试分析算法时,我认为错误在于如何返回标记A行中的轴位置(loc_pi)。考虑到上述程序的以下事件序列

test_rselect( [ 55, 900, -1,10, 545, 250], 3) // call to input array 

calls rselect ([ 55, 900, -1,10, 545, 250],6,3)

    1st  call to random_partition:
        pi=545 and loc_pi=4
        lo=[55,-1,10,250,545]
        hi=[900]
    return to rselect function (lo,545,hi,6)
    here loc_pi>i: so rselect(lo,5,3)// and discard the hi part

    2nd recursive call to rselect:
    2nd recursive call to random_partition:
        call random_partition on (lo) // as 'hi' is discarded
        pi=55 loc_pi=0
        lo=[-1,10,55]
        hi=[250,545]
        return to rselect(lo,55,hi,4)
        here loc_pi>i: rselect(lo,3,3)// The pivot element is lost already as it is in 'hi' here!!

关于如何返回枢轴元素位置以获得正确的o/p的任何帮助都会很有帮助。设置悬赏,以获得一个明确解释我做错了什么以及如何纠正的答案(由于我期待学习,欢迎提供好的提示:)。期待伟大的答案

您的算法的问题是您对
loc\u pi
的确定。例如,在“代码”> LoopyPi= Seq.Index(PI)< /代码>中选择1000个是第一个<代码>π<代码>的情况。在这种情况下,
loc_pi
将等于2,因为1000位于序列的索引2,函数将返回1000,我们知道这绝对不是顺序统计2

因此,我们知道我们不能根据随机选择的
pi
的索引来确定
loc\u pi
。毕竟,这个列表的顺序是任意的——它的位置毫无意义。对于该
loc\u pi
值,您实际想要得到的是该子列表中低于所选pi的元素数。谢天谢地,这很容易得到!换句话:

    return lo,pi,hi,loc_pi

您会发现它的性能正确且始终如一

dynamic-oit-vapornet-c-913:test dgrtwo$ python test21.py
Sequence [54, -1, 1000, 565, 64, 2, 5]
Statistic pi 565
Location 3
pi 5
Location 5
pi -1
Location 0
pi 2
Location 0
2
dynamic-oit-vapornet-c-913:test dgrtwo$ python test21.py
Sequence [54, -1, 1000, 565, 64, 2, 5]
Statistic pi -1
Location 1
pi 54
Location 0
pi 5
Location 2
pi 2
Location 0
2
ETA:请注意,如果输入序列中存在关联,那么您编写的算法将不会始终有效。试几个例子,你就会明白我的意思。有一些简单的方法可以解决这个问题,我相信你能找到。

如果你改变:

return lo,pi,hi,len(lo)+1
致:

并添加一个结束括号
,以便纠正语法错误,如下所示:

lo,pi,hi,loc_pi= random_partition(seq)
对于无重复输入的序列,它将可靠地工作:

for i in xrange(1,8):
    print rselect([54,-1,1000,565,64,2,5],7,i),
#Output:
-1 2 5 54 64 565 [1000]
from random import choice, shuffle

def rselect(seq, i):
    lo, hi, pi, loc_pi = random_partition(seq)
    if loc_pi == i or (min(lo) == max(lo) and not hi):
        return pi
    elif loc_pi > i:
        return rselect(lo, i)
    elif loc_pi < i:
        return rselect(hi, i - loc_pi)

def random_partition(seq):
    pi = choice(seq)
    lo = [x for x in seq if x <= pi]
    hi = [x for x in seq if x > pi]
    return lo, hi, pi, len(lo)

#this is a nice way to test it:
cat = range(1,21)
for i in xrange(1,21):
    shuffle(cat)
    print rselect(cat,i),

#Output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
这是预期的输出

我想我的主要建议是尝试按照您的代码编写代码,这是一个很难一目了然阅读的问题

参数
length
是冗余的,因此可以完全删除。有时最后一个条目会以单值列表的形式返回,所以我改变了这一点(尽管如果你给它一个空列表,它会知道fall over,可能没什么大不了的)。以下是可读性稍高的代码格式,并进行了更正以允许重复输入:

for i in xrange(1,8):
    print rselect([54,-1,1000,565,64,2,5],7,i),
#Output:
-1 2 5 54 64 565 [1000]
from random import choice, shuffle

def rselect(seq, i):
    lo, hi, pi, loc_pi = random_partition(seq)
    if loc_pi == i or (min(lo) == max(lo) and not hi):
        return pi
    elif loc_pi > i:
        return rselect(lo, i)
    elif loc_pi < i:
        return rselect(hi, i - loc_pi)

def random_partition(seq):
    pi = choice(seq)
    lo = [x for x in seq if x <= pi]
    hi = [x for x in seq if x > pi]
    return lo, hi, pi, len(lo)

#this is a nice way to test it:
cat = range(1,21)
for i in xrange(1,21):
    shuffle(cat)
    print rselect(cat,i),

#Output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
从随机导入选择中,洗牌
def R选择(序号i):
lo,hi,pi,loc_pi=随机分区(seq)
如果loc_pi==i或(最小(lo)=最大(lo)且不高):
返回pi
elif loc_pi>i:
返回rselect(lo,i)
elif loc_pi
我不认为有任何主要错误(在如何返回轴或其他方面),只是一个(甚至两个)混乱造成了很大的偏差,而且我认为您的意思是在rselect的第一行与I进行比较,而不是1

以下是我对它的看法,尽可能少的改变:

def rselect(seq,length,i):# i is the i'th order statistic.
    if len(seq)<=i:return seq
    lo,pi,hi,loc_pi= random_partition(seq)
    if loc_pi==i:return pi 
    if loc_pi>i:return rselect(lo,loc_pi,i) 
    elif loc_pi<i:return rselect(hi,length-(loc_pi+1),i-(loc_pi+1))
from random import choice  
def random_partition(seq):
    pi =choice(seq)
    lo=[x for x in seq if x<=pi]
    hi=[x for x in seq if x>pi]
    return lo,pi,hi,len(lo)-1
def rselect(seq,length,i):#i是第i阶统计量。
if len(seq)i:返回rselect(lo,loc_pi,i)

elif loc_Piu这有什么问题?正确的操作是什么样的?如果是随机的,理论上结果应该总是不同的。我想,在问题完成之前,我已经发布了。我的问题是程序返回第i个顺序的不同值statistic@Woot4Moo:有很多随机算法可以产生确定性的结果(随机性可以用来减少预期的运行时间或内存需求)。我缺少什么?每次输出都是不同的(除了“序列”之外,它应该是相同的,因为它是在对它做任何事情之前打印出来的-参见
print'Sequence',seq
。那么它是以什么方式确定的呢?我还没能测试你的建议,但出于好奇,我们不应该返回len(lo)+1而不是len吗(lo),也包括pivot元素?完全正确;出于某种原因,我考虑使用1进行索引。修复(虽然现在它将提供不同的输出,但我没有机会更改):我尝试根据您的建议运行代码,但我得到了一个完全奇怪的输出,例如输入`testrselect([54,-11000565,64,2,5],2)`我得到:
@ubuntu:~/py scripts$python Dselect.py序列[54,-1,1000,565,64,2,5]统计pi 54位置0 pi-1位置1-1
。这真的不起作用。你能帮忙吗?我真的不认为它解决了问题。我看不到结果打印的统计数据。你能详细说明你的解决方案是什么吗?我用输入序列尝试过,例如,解决方案在某些情况下有效,在其他情况下无效
test_rselect([54,-11000,56,5,64,2,5],3)
如果loc_pi>i:return rselect(lo,loc_pi+1,i)
,则返回一个在线索引器
。请改进您的答案。谢谢!@KodeSeeker-我已更新以允许输入序列中的重复元素(这就是
def rselect(seq,length,i):# i is the i'th order statistic.
    if len(seq)<=i:return seq
    lo,pi,hi,loc_pi= random_partition(seq)
    if loc_pi==i:return pi 
    if loc_pi>i:return rselect(lo,loc_pi,i) 
    elif loc_pi<i:return rselect(hi,length-(loc_pi+1),i-(loc_pi+1))
from random import choice  
def random_partition(seq):
    pi =choice(seq)
    lo=[x for x in seq if x<=pi]
    hi=[x for x in seq if x>pi]
    return lo,pi,hi,len(lo)-1
def rselect(seq,i):# i is the i'th order statistic.
    if len(seq)<=i:return seq
    lo,pi,hi= random_partition(seq)
    if i < len(lo):return rselect(lo,i) 
    if i < len(seq)-len(hi): return pi 
    return rselect(hi,i-(len(seq)-len(hi)))
from random import choice
def random_partition(seq):
    pi =choice(seq)
    lo=[x for x in seq if x<pi]
    hi=[x for x in seq if x>pi]
    return lo,pi,hi

def test_rselect(seq,i):
    print 'Sequence',seq
    stat=rselect(seq,i)
    print 'Statistic', stat