Python codility课程:堆栈和队列鱼bug

时间:2018-02-05 17:03:00

标签: python stack

我的代码似乎回答了一个关于codility的测试用例的错误答案。(其他测试用例都是正确的)

测试用例: large_random

大型随机试验,N = ~100,000 我得到了一个

得到868预期840

问题链接: https://app.codility.com/programmers/lessons/7-stacks_and_queues/fish/

def solution(A, B): #declare stacks for fish traveling downstrea, upstream dstrm = [] ustrm = [] #set counter to zero for fish traveling upstream UNHINDERED #by fish traveling downstream, needed because iteration starts upstream counter = 0 n = len(A) #iterate over input, starting from upstream for i in range(n): if B[i] == 0: ustrm.append(A[i]) elif B[i] == 1: dstrm.append(A[i])

# clear upstream stack of fish known to be UNHINDERED, increase counter if len(ustrm) > 0 and len(dstrm) == 0: counter += len(ustrm) ustrm.clear() #compare what's bigger and decrease stack of fish that is eaten while len(dstrm) > 0 and len(ustrm) > 0: if dstrm[-1] > ustrm[-1]: ustrm.pop() elif ustrm[-1] > dstrm[-1]: dstrm.pop() return len(dstrm) + len(ustrm) + counter

5 个答案:

答案 0 :(得分:1)

Python 3

对于那些正在寻找易于理解的分步说明的人,这里是我的 100% 解决方案。

它通过附加和弹出来使用队列/堆栈,正如课程所建议的那样。

您可以在底部添加各种测试。提交前不要忘记删除打印输出!

def solution(A, B):
    N = len(A)
    print('START')
    print('Fish sizes:      ' + str(A))
    print('Fish directions: ' +  str(B))
    print()
    
    upstream = 0
    downstream = []
    
    for n in range(N):
        fs = A[n]
        fd = B[n]
    
        print('Fish pos: ' + str(n) + ', fish dir: ' + str(fd)+ ', fish size: ' + str(fs))

        if fd == 0 and downstream == []:
            print('No fishes in the way')
            upstream += 1
            print('Fishes gone upstream: ' + str(upstream))

        elif fd == 1:
            downstream.append(fs)
            print('No fishes in the way')
            print('Fishes going downstream: ' + str(downstream))

        elif fd == 0 and downstream != []:
            print('Challenge!')

            while downstream:
                # pick the downstream head
                pfs = downstream.pop()

                # if it's bigger kills upstream, puts back downstream, move on
                if pfs > fs:
                    downstream.append(pfs)
                    print('Downward eats upward')
                    print('Fishes going downstream: ' + str(downstream))
                    break

                    # if it's smaller don't put it back and move on to next fish
                elif pfs < fs:
                    print('Upward eats downward')
                    print('Fishes going downstream: ' + str(downstream))
                    if downstream == []:
                        upstream += 1
                        print('Fishes gone upstream: ' + str(upstream))
                        break
                continue
        print()

    print('FINISH')
    print('Fishes gone upstream: ' + str(upstream))
    print('Fishes going downstream: ' + str(len(downstream)))
    fishes = upstream + len(downstream)
    print('Fishes alive: ' + str(fishes))

    return fishes

    
if __name__ == '__main__':
    assert solution([4,3,2,1,5], [0,1,0,0,0]) == 2
    print('Test 1 OK!')
    print()
    assert solution([1,2,3,4,5], [1,1,1,1,0]) == 1
    print('Test 2 OK!')
    print()
    assert solution([5,4,3,2,1], [1,0,0,0,0]) == 1
    print('Test 3 OK!')
    print()
    assert solution([1,2,3,4,5], [1,0,0,0,0]) == 4
    print('Test 4 OK!')
    print()
    assert solution([1,2,3,4,5], [1,1,1,1,1]) == 5
    print('Test 4 OK!')
    print()

这是一步一步清楚解释的输出:

START
Fish sizes:      [4, 3, 2, 1, 5]
Fish directions: [0, 1, 0, 0, 0]

Fish pos: 0, fish dir: 0, fish size: 4
No fishes in the way
Fishes gone upstream: 1

Fish pos: 1, fish dir: 1, fish size: 3
No fishes in the way
Fishes going downstream: [3]

Fish pos: 2, fish dir: 0, fish size: 2
Challenge!
Downward eats upward
Fishes going downstream: [3]

Fish pos: 3, fish dir: 0, fish size: 1
Challenge!
Downward eats upward
Fishes going downstream: [3]

Fish pos: 4, fish dir: 0, fish size: 5
Challenge!
Upward eats downward
Fishes going downstream: []
Fishes gone upstream: 2

FINISH
Fishes gone upstream: 2
Fishes going downstream: 0
Fishes alive: 2
Test 1 OK!

START
Fish sizes:      [1, 2, 3, 4, 5]
Fish directions: [1, 1, 1, 1, 0]

Fish pos: 0, fish dir: 1, fish size: 1
No fishes in the way
Fishes going downstream: [1]

Fish pos: 1, fish dir: 1, fish size: 2
No fishes in the way
Fishes going downstream: [1, 2]

Fish pos: 2, fish dir: 1, fish size: 3
No fishes in the way
Fishes going downstream: [1, 2, 3]

Fish pos: 3, fish dir: 1, fish size: 4
No fishes in the way
Fishes going downstream: [1, 2, 3, 4]

Fish pos: 4, fish dir: 0, fish size: 5
Challenge!
Upward eats downward
Fishes going downstream: [1, 2, 3]
Upward eats downward
Fishes going downstream: [1, 2]
Upward eats downward
Fishes going downstream: [1]
Upward eats downward
Fishes going downstream: []
Fishes gone upstream: 1

FINISH
Fishes gone upstream: 1
Fishes going downstream: 0
Fishes alive: 1
Test 2 OK!

START
Fish sizes:      [5, 4, 3, 2, 1]
Fish directions: [1, 0, 0, 0, 0]

Fish pos: 0, fish dir: 1, fish size: 5
No fishes in the way
Fishes going downstream: [5]

Fish pos: 1, fish dir: 0, fish size: 4
Challenge!
Downward eats upward
Fishes going downstream: [5]

Fish pos: 2, fish dir: 0, fish size: 3
Challenge!
Downward eats upward
Fishes going downstream: [5]

Fish pos: 3, fish dir: 0, fish size: 2
Challenge!
Downward eats upward
Fishes going downstream: [5]

Fish pos: 4, fish dir: 0, fish size: 1
Challenge!
Downward eats upward
Fishes going downstream: [5]

FINISH
Fishes gone upstream: 0
Fishes going downstream: 1
Fishes alive: 1
Test 3 OK!

START
Fish sizes:      [1, 2, 3, 4, 5]
Fish directions: [1, 0, 0, 0, 0]

Fish pos: 0, fish dir: 1, fish size: 1
No fishes in the way
Fishes going downstream: [1]

Fish pos: 1, fish dir: 0, fish size: 2
Challenge!
Upward eats downward
Fishes going downstream: []
Fishes gone upstream: 1

Fish pos: 2, fish dir: 0, fish size: 3
No fishes in the way
Fishes gone upstream: 2

Fish pos: 3, fish dir: 0, fish size: 4
No fishes in the way
Fishes gone upstream: 3

Fish pos: 4, fish dir: 0, fish size: 5
No fishes in the way
Fishes gone upstream: 4

FINISH
Fishes gone upstream: 4
Fishes going downstream: 0
Fishes alive: 4
Test 4 OK!

START
Fish sizes:      [1, 2, 3, 4, 5]
Fish directions: [1, 1, 1, 1, 1]

Fish pos: 0, fish dir: 1, fish size: 1
No fishes in the way
Fishes going downstream: [1]

Fish pos: 1, fish dir: 1, fish size: 2
No fishes in the way
Fishes going downstream: [1, 2]

Fish pos: 2, fish dir: 1, fish size: 3
No fishes in the way
Fishes going downstream: [1, 2, 3]

Fish pos: 3, fish dir: 1, fish size: 4
No fishes in the way
Fishes going downstream: [1, 2, 3, 4]

Fish pos: 4, fish dir: 1, fish size: 5
No fishes in the way
Fishes going downstream: [1, 2, 3, 4, 5]

FINISH
Fishes gone upstream: 0
Fishes going downstream: 5
Fishes alive: 5
Test 4 OK!

> 

答案 1 :(得分:0)

您的整体策略对我没有意义,而且我对大多数测试用例通过感到惊讶。这是一个非常简单的例子,你的代码出错:

A:[1,2] B:[0,1]

如果我正确地理解了这个符号,鱼0是最上游的鱼,它在上游游泳,鱼1是最下游的鱼,它在下游游泳。因此,鱼不会见面,答案是两个。

但是,您的代码输出1,因为它根本没有实际检查它们的相对位置。它只是将最上游的下游鱼类与最上游的上游鱼类进行比较,并声明一个人会吃掉另一个,无论他们是否相遇。

(如果我向后收到符号,只需反转数组B - 在这两种情况下你的代码输出1,这绝对不正确。)

正确的解决方案需要比较鱼的位置,而不仅仅是它们的大小。

答案 2 :(得分:0)

如果有人仍然对此问题的解决方案感兴趣,这是我使用Python的元组方法。我得到了100%。

def solution(A, B):

    fishes, stack = [], []

    for i in range(len(A)):
        fishes.append((B[i], A[i]))

    while fishes:
        if stack and not stack[-1][0] and fishes[-1][0]:
            if stack[-1][1] > fishes[-1][1]:
                fishes.pop()
            else:
                stack.pop()
        else:
            stack.append(fishes.pop())

    return len(stack)

答案 3 :(得分:0)

这是我的方法-也许有人可以理解-我是如何解决的 Codility Python

中的Codility 100%
  

代码

def solution(A, B):
"""
Codility 100%
https://app.codility.com/demo/results/trainingF5HTCA-YFV/

Idea is to use stack concept
For each iteration if current fish is of type 1 add it to stack 1 fish
Create stack 1 fish - it always holds the downstream ie 1 kind of fish
 and keep killing the smaller fish from the list if it is greater
  else killed by current fish.
Now if stack 1 fish has no fish it means current fish can be counted as remaining fish.


0 represents a fish flowing upstream - 0 fish
1 represents a fish flowing downstream - 1 fish

A[0] = 4    B[0] = 0 alive fish
A[1] = 3    B[1] = 1 downstream
A[2] = 2    B[2] = 0 eaten by A[1]
A[3] = 1    B[3] = 0 eaten by A[1]
A[4] = 5    B[4] = 0 eat to A[1] and remain alive

"""

count = 0
# stores the 1 fish in stack
stack_1_fish = []
print(A)
print(B)
for index in range(len(A)):
    if B[index] == 0:
        # until stack has some 1 fish
        while stack_1_fish:
            # get last fish from stack and check if it can die or not
            # the larger fish eats the smaller one.
            # two fish P and Q meet each other when P < Q, B[P] = 1 and B[Q] = 0, and there are no living fish between them
            if stack_1_fish[-1] > A[index]:
                # stack 1 fish kill to current fish
                # exit from while loop and else block also execute next top for loop
                # check for other fish fight
                print("Killed by " + str(stack_1_fish[-1]) + " Die " + str(A[index]))
                break
            else:
                # stack 1 fish is killed by current fish
                p = stack_1_fish.pop()
                print("Killed by " + str(A[index]) + " Die " + str(p))

        # this is the case when stack becomes empty ie. no fish of kind 1
        # it would never meet previous fish but can fight with downstream fish
        else:
            print("Count fish as remaining......." + str(A[index]))
            count += 1
    else:
        # fish 1 found add to stack
        stack_1_fish.append(A[index])
        print("1 fish found, add to stack, it can kill or killed by someone..." + str(A[index]))
        print(stack_1_fish)

print("Count: " + str(count))
print("Stack 1 fish: " + str(len(stack_1_fish)))
return count + len(stack_1_fish)
  

执行输出-

if __name__ == '__main__':
result = solution([4, 3, 2, 1, 5], [0, 1, 0, 0, 0])
# result = solution([4, 3, 2, 1, 5], [0, 0, 0, 0, 0])
# result = solution([4, 3, 2, 1, 5], [1, 1, 1, 1, 1])
print("")
print("Solution " + str(result))

[4, 3, 2, 1, 5]
[0, 1, 0, 0, 0]
Count fish as remaining.......4
1 fish found, add to stack, it can kill or killed by someone...3
[3]
Killed by 3 Die 2
Killed by 3 Die 1
Killed by 5 Die 3
Count fish as remaining.......5
Count: 2
Stack 1 fish: 0

Solution 2

[4, 3, 2, 1, 5]
[0, 0, 0, 0, 0]
Count fish as remaining.......4
Count fish as remaining.......3
Count fish as remaining.......2
Count fish as remaining.......1
Count fish as remaining.......5
Count: 5
Stack 1 fish: 0

Solution 5

[4, 3, 2, 1, 5]
[1, 1, 1, 1, 1]
1 fish found, add to stack, it can kill or killed by someone...4
[4]
1 fish found, add to stack, it can kill or killed by someone...3
[4, 3]
1 fish found, add to stack, it can kill or killed by someone...2
[4, 3, 2]
1 fish found, add to stack, it can kill or killed by someone...1
[4, 3, 2, 1]
1 fish found, add to stack, it can kill or killed by someone...5
[4, 3, 2, 1, 5]
Count: 0
Stack 1 fish: 5

Solution 5

答案 4 :(得分:0)

我发现最优雅的Codility fish solution可以在这里找到。 它正在使用堆栈:

def solution(a, b):
    l = 0 # left
    s = [] # stack
    for i in range(len(a)):
        if b[i]==1: # fish moving upwards
            s.append(a[i]) # to the stack
        else: # eat fish mowing downwards.
            while len(s)>0:
                if s[-1]<a[i]:
                    s.pop() # eat from the stack
                else:
                    break
            else:
                l+=1
    l+=len(s)
    return l