Find time needed for vertices to stop disappearing - python

I am given undirected graph that consists of N vertices numbered from 0 to N-1 connected with M edges.The graph is described by two arrays, A and B both of length M. A pair ([A[k],B[k]) describes edge between A[k] and B[k] for k from 0 to M-1.
Each second every vertex with at most 1 edge connected to disappears.Every edge which is connected to one of disappearing vertices also disappears.
After how many seconds will the vertices stop disappearing.
For N=7, ((0,1),(1,2),(2,0),(1,4),(4,5),(4,6)) answer should be 2.
def solution(N,A,B):
d2 = dict.fromkeys(range(N), 0)
count = 0
arr = []
for i in range(len(A)):
arr.append((A[i],B[i]))
while True:
for i in range(len(A)+1):
for c in arr:
if i in c:
d2[i] += 1
arr1 = arr
for i in range(len(A)+1):
if d2[i] <= 1:
arr = list(filter(lambda x: x[1] != i and x[0] != i, arr))
if len(arr) == len(arr1):
return count + 1
break
count += 1
Here is my code.For this test case (4, [0, 1, 2, 3], [1, 2, 3, 0]) it outputs Keyerror: 4. Can you help me to solve the problem.Thank you.

Try this (I inserted a couple of print() to let you see what's going on):
def solution(N, A, B):
linked = defaultdict(list)
for i in range(len(A)):
linked[A[i]].append(B[i])
linked[B[i]].append(A[i])
changed = True
seconds = 0
removing = []
while changed:
changed = False
seconds += 1
print(f'second {seconds}')
for i in list(linked.keys())[:]:
if len(linked[i]) > 1:
continue
if len(linked[i]) == 1:
removing.append((linked[i][0],i))
del linked[i]
changed = True
for i,j in removing:
print(f'remove {j} from {i}')
linked[i].remove(j)
removing = []
return seconds - 1

Related

Given an array of N integers, and an integer K, find the number of pairs of elements in the array whose sum is equal to K

Problem Statement:- Given an array of N integers, and an integer K, find the number of pairs of elements in the array whose sum is equal to K.
**def countpairs(x,length,sum):
count = 0
for i in range(0,length):
for j in range(i+1,length):
print(x[i],x[j])
if(x[i]+x[j]==sum):
count+=1
print(count)
x = [1, 1, 1, 1]
sum = 2
length=len(x)
countpairs(x,length,sum)
Output:= 6**
This is My solution used in VS code.
My Question:- whenever I am running the same code in gfg it is not accepting the code giving me this error. I even have tried the same code in the online compiler there also it is running correctly.
This Is the gfg code which i have written
class Solution:
def getPairsCount(self, arr, K, N):
count = 0
for i in range(0,N):
for j in range(i+1,N):
if(arr[i]+arr[j]==K):
count+=1
return count
#Initial Template for Python 3
if __name__ == '__main__':
tc = int(input())
while tc > 0:
n, k = list(map(int, input().strip().split()))
arr = list(map(int, input().strip().split()))
ob = Solution()
ans = ob.getPairsCount(arr, n, k)
print(ans)
tc -= 1
Error
if(arr[i]+arr[j]==K):
IndexError: list index out of range
There's no added value in using a class for this. You just need:-
def getPairsCount(arr, K):
count = 0
for i in range(len(arr)-1):
if arr[i] + arr[i+1] == K:
count += 1
return count
EDIT:
Previous answer assumed that only adjacent elements were to be considered. If that's not the case then try this:-
import itertools
def getPairsCount(arr, K):
count = 0
for c in itertools.combinations(sorted(arr), 2):
if c[0] + c[1] == K:
count += 1
return count
data = [1, 2, 1, 4, -1]
print(getPairsCount(data, 3))
We do not need two loops for this question. Here is something that runs in O(n):
def countpairs(list_,K):
count = 0
set_ = set(list_)
pairs_ = []
for val in list_:
if K - val in set_:
# we ensure that pairs are unordered by using min and max
pairs_.append ( (min(val, K-val), max(val, K-val)) )
count+=1
set_pairs = set(pairs_)
print ("Pairs which sum up to ",K," are: ", set_pairs)
return len(set_pairs)
x = [1,4,5,8,2,0,24,7,6]
sum_ = 13
print ("Total count of pairs summming up to ", sum_, " = ", countpairs(x, sum_))
Output:
Pairs which sum up to 13 are: {(6, 7), (5, 8)}
Total count of pairs summming up to 13 = 2
The idea is that if two values should sum to a value K, we can iterate through the array and check if there is another element in the array which when paired with the current element, sums up to K. The inner loop in your solution can be replaced with a search using the in. Now, we need this search to be fast (O(1) per element), so we create a set out of our input array (set_ in my example).
def solve(a,K):
freq = {}
for v in a:
if v in freq:
freq[v] += 1
else:
freq[v] = 1
for i in range(len(set(a))):
res += freq[a[i]] * freq[K - a[i]]
return res
a = [int(v) for v in input().split()]
K = int(input())
print(solve(a,K))
# Time Complexity : O(N)
# Space Complexity : O(1)
def solve(a,K):
freq = {}
for v in a:
if v in freq:
freq[v] += 1
else:
freq[v] = 1
for i in range(len(set(a))):
res += freq[a[i]] * freq[K - a[i]]
return res
a = [int(v) for v in input().split()]
K = int(input())
print(solve(a,K))

Choosing k out of N numbers from 2 arrays with highest total value

Let A, B and C be three arrays, each containing N numbers:
A = a[0], a[1], a[2], ..., a[N-1]
B = b[0], b[1], b[2], ..., b[N-1]
C = c[0], c[1], c[3], ..., c[N-1]
I want to select the best k < N elements from A and the best k < N elements from B so that the total sum of their values is maximized. The interesting twist is: If element i is chosen from both A and B (where i in {0, ..., N-1} is the index), then instead of these elements contributing a[i] + b[i], they will contribute c[i] where c[i] >= a[i] + b[i].
At first glance this looked deceptively straightforward to me, but the more I think about the more involved it gets.
I am ultimately looking for an implementation in Python, but at this stage I am just trying to get a sense of what would be an efficient algorithm here.
Example
To clarify, inputs to the algorithm are the 3 N x 1 arrays A, B and C and an integer value for k. The expected output are two k x 1 lists of indices, defining the value-maximizing combination of elements from A and B (and C).
For example, suppose k = 2, N = 4 and let
A = a[0], a[1], a[2], a[3] = 3, 1, 1, 0
B = b[0], b[1], b[2], b[3] = 1, 3, 0, 1
C = c[0], c[1], c[2], c[3] = 4, 4, 3, 2
Even in this simple example, there are many possible combinations. For instance, if elements i = 0, 2 are chosen from A and elements j = 1, 3 are chosen from B, then the total value would be a[0] + a[2] + b[1] + b[3] = 8.
If on the other hand elements i = 0, 1 and j = 0, 1 would be chosen from both A and B, then the special twist applies: Instead of yielding a[0] + a[1] + b[0] + b[1], the total value is given by c[0] + c[1] = 8.
In this example, the combination of elements that maximizes the total value is given by i = 0, 2 from A and elements j = 1, 2 from B. This yields a total value of a[0] + b[1] + c[2] = 9, which can be verified is more than any other combination.
Comparison of answers
Here's a quick comparison of the 3 submitted solutions. First, I checked all of them, and they all give the intended results. As a side comment, none of them requires the elements of C to be weakly larger than the sum of the corresponding elements in A and B, so I dropped this assumption in my performance review.
Here's what I run:
import numpy as np
from utils import tic, toc # simple wrapper to time.perf_counter()
k, N = 10, 1000
A = list(np.random.random_sample([N]))
B = list(np.random.random_sample([N]))
C = list(np.random.random_sample([N]))
tic()
print(optimal_choices(k, A, B, C)) # solution by btilly
toc()
tic()
print(maxPicks(A.copy(), B.copy(), C.copy(), k)) # solution by Eric T-M
toc()
tic()
print(maxSum(A, B, C, k)) # solution by Alain T.
toc()
I tested for various combinations of k and N. It seems that #btilly's algorithm scales well in N as long as k is small. #Alain-T.'s algorithm does the opposite, doing well when k is large relative to N. Across the board, #Eric-T-M's algorithm does best, scaling well in both k and N.
Small problem: k = 10 and N = 500
btilly's algorithm: 0.49s
Eric T-M's algorithm: 0.00s
Alain T.'s algorithm: 0.52s
Small-k, large-N: k = 10 and N = 1000
btilly's algorithm: 0.89s
Eric T-M's algorithm: 0.00s
Alain T.'s algorithm: 1.99s
Large-k, small-N: k = 80 and N = 100
btilly's algorithm: 1.54s
Eric T-M's algorithm: 0.00s
Alain T.'s algorithm: 0.09s
Medium problem: k = 50 and N = 1000
btilly's algorithm: 13.01ss
Eric T-M's algorithm: 0.00s
Alain T.'s algorithm: 8.55s
Large problem 1: k = 10 and N = 1_000_000
Eric T-M's algorithm: 1.03s
Large problem 2: k = 1_000 and N = 100_000
Eric T-M's algorithm: 10.22s
(For the benchmarks, I removed the sorting in Alain T.'s code, to make it comparable.)
Try this. It takes O(N^2) time and it is fairly simple.
def maxPicks(A,B,C,k):
# returns the tuple (list of entries picked in A, list of entries picked in B, total value)
# BASE CASE
if k == 0:
return ([], [], 0)
aMax = max(A)
bMax = max(B)
cMax = max(C)
if (aMax + bMax) > cMax:
aIdx = A.index(aMax)
bIdx = B.index(bMax)
B[aIdx] = C[aIdx] - A[aIdx]
A[aIdx] = -2
C[aIdx] = -1
A[bIdx] = C[bIdx] - B[bIdx]
B[bIdx] = -2
C[bIdx] = -1
nextPicks = maxPicks(A,B,C,k-1)
return (nextPicks[0] + [aIdx], nextPicks[1] + [bIdx], nextPicks[2] + aMax + bMax)
else:
cIdx = C.index(cMax)
A[cIdx] = -1
B[cIdx] = -1
C[cIdx] = -1
nextPicks = maxPicks(A,B,C,k-1)
return (nextPicks[0] + [cIdx], nextPicks[1] + [cIdx], nextPicks[2] + cMax)
Here's how it works:
The base case should be self explanatory. Otherwise we will compare the sum of the maximum of all entries in A and the maximum of all entries in B to the maximum of all entries in C. If this sum is larger than it is safe to pick these entries from A and B, but before making more picks we will need to set the entries we picked as well as their corresponding entries in C to a negative value. As a side note I do assume that all values in A, B and C are originally nonnegative so by setting them negative we forbid our algorithm from picking them again. If this assumption is wrong you might want to set these values to something extremely negative to prohibit double picks. We also see that if we picked A[i] the value of B[i] is now whatever C[i]-A[i] was, because picking B[i] will lose us the value in A[i] and give us the value in C[i] same for the entry A[j] if we pick B[j].
If on the other hand, the greatest entry in C was greater than or equal to aMax+bMax we want to pick it (by picking the corresponding entries in both A and B, because no other picks of entries in A and B or just C alone would be more valuable. At this point we know we don't want to re-pick A[i],B[i], or C[i] again, so we set them all negative.
This can be solved with dynamic programming.
# Helper function to get out of the data structure.
def get_nested_array (data, path):
for x in path:
if data is None or len(data) <= x:
return None
else:
data = data[x]
return data
# Helper function to set data in the data structure.
def set_nested_array (data, path, value):
# Navigate there
for x in path[0:len(path)-1]:
while len(data) <= x:
data.append([])
if data[x] is None:
data[x] = []
data = data[x]
while len(data) <= path[-1]:
data.append(None)
data[path[-1]] = value
# Is this option better than what is there? If so, then add it.
def possibly_add_choice (best_choice, pos, i, j, current_sum, last_i, last_j):
best_prev = get_nested_array(best_choice, [pos, i, j])
if best_prev is None or best_prev[0] < current_sum:
set_nested_array(best_choice, [pos, i, j], (current_sum, last_i, last_j))
# Our program.
def optimal_choices (k, A, B, C):
# best_choice[pos][i][j] = (max_sum, last_a, last_b)
# where:
# We have made all choices in the range 0..pos-1
# We chose i out of A
# We chose j out of B
# and
# max_sum is the best possible sum
# last_a is the last index chosen from a
# last_b is the last index chosen from b
# then we can find the answer working backwards from
# best_choice[len(A)][k][k]
#
best_choice = []
# Enter the empty set answer
set_nested_array(best_choice, [0, 0, 0], (0, None, None))
for pos in range(len(A)):
best_choice.append([])
best_choice_for_pos = best_choice[pos]
for i in range(k+1):
if len(best_choice_for_pos) <= i:
break
best_choice_for_i = best_choice_for_pos[i]
for j in range(k+1):
if len(best_choice_for_i) <= j:
break
last_sum, last_i, last_j = best_choice_for_i[j]
# Try all 4 things we can choose here. Nothing, or A or B or both.
possibly_add_choice(best_choice, pos+1, i, j, last_sum, last_i, last_j)
possibly_add_choice(best_choice, pos+1, i+1, j, last_sum + A[pos], pos, last_j)
possibly_add_choice(best_choice, pos+1, i, j+1, last_sum + B[pos], last_i, pos)
possibly_add_choice(best_choice, pos+1, i+1, j+1, last_sum + C[pos], pos, pos)
# Now we have the answer, it is just a question of decoding it.
if get_nested_array(best_choice, [len(A), k, k]) is None:
return (None, None)
else:
choose_a = []
choose_b = []
best_spot = [len(A), k, k]
max_sum, last_i, last_j = get_nested_array(best_choice, best_spot)
while last_i is not None or last_j is not None:
# Figure out where we last had a choice and what was chosen.
if last_i is None:
last_pos = last_j
i_dec = 0
j_dec = 1
elif last_j is None:
last_pos = last_i
i_dec = 1
j_dec = 0
else:
last_pos = max(last_i, last_j)
i_dec = 0
j_dec = 0
if last_pos == last_i:
i_dec = 1
if last_pos == last_j:
j_dec = 1
# record the choice.
if 1 == i_dec:
choose_a.append(last_pos)
if 1 == j_dec:
choose_b.append(last_pos)
# Go back to that spot
max_sum, last_i, last_j = get_nested_array(best_choice, [last_pos, k-len(choose_a), k-len(choose_b)])
# We walked backwards to generate these lists. So they are currently reversed.
return (list(reversed(choose_a)), list(reversed(choose_b)))
print(optimal_choices(2, [3, 1, 1, 0 ], [1, 3, 0, 1], [4, 4, 3, 2]))
If you expand A and B into a list of index pairs with their respective sums (applying exceptions from C), you can iteratively take the maximum sum and exclude the corresponding pairs at each step. This will select the highest possible totals from the remaining pairs at each iteration:
def maxSum(A,B,C,K):
S = [ ([a+b,C[i]][i==j],i,j) for i,a in enumerate(A)
for j,b in enumerate(B)]
usedA,usedB = set(),set()
for _ in range(K):
_,i,j = max(s for s in S if not(s[1] in usedA or s[2] in usedB))
usedA.add(i)
usedB.add(j)
return sorted(usedA),sorted(usedB)
output:
A = [3, 1, 1, 0]
B = [1, 3, 0, 1]
C = [4, 4, 3, 2]
print(maxSum(A,B,C,2)) # ([0, 2], [1, 2]) total is 9
A = [1,2,3,4]
B = [4,5,6,2]
C = [5,9,9,6]
print(maxSum(A,B,C,2)) # ([1, 3], [1, 2]) total is 19
print(maxSum(A,B,C,3)) # ([1, 2, 3], [0, 1, 2]) total is 26

Find n integers in list that after multiplying equal to m

I need to print out n indexes of elements of list that after multiplying equal to some given integer. It's guaranteed that the combination exists in a list. For example, for the following input(number of elements in array, multiplication wanted number, number of elements in wanted sublist and given array):
7 60 4
30 1 1 3 10 6 4
I should get in any order
1 2 4 5
Because 1*1*10*6==60. If there are more than 1 solution I need to print any of them.
My solution works but pretty slow, how can I make it work faster?
from itertools import chain, combinations
arr = list(map(int, input().split()))
numbers = list(map(int, input().split()))
s = sorted(numbers)
def filtered_sublists(input_list, length):
return (
l for l in all_sublists(input_list)
if len(l) == length
)
def all_sublists(l):
return chain(*(combinations(l, i) for i in range(len(l) + 1)))
def multiply(arr):
result = 1
for x in arr:
result = result * x
return result
def get_indexes(data):
indexes = []
for i in range(len(data)):
if arr[1] == multiply(data[i]):
for el in data[i]:
if numbers.index(el) in indexes:
all_ind = [i for i, x in enumerate(numbers) if x == el]
for ind in all_ind:
if ind not in indexes:
indexes.append(ind)
break
else:
indexes.append(numbers.index(el))
break
return indexes
sublists = list(filtered_sublists(numbers, arr[2]))
print(*get_indexes(sublists))
The key is don't test every combination.
def combo(l, n=4, target=60, current_indices=[], current_mul=1):
if current_mul > target and target > 0:
return
elif len(current_indices) == n and current_mul == target:
yield current_indices
return
for i, val in enumerate(l):
if (not current_indices) or (i > current_indices[-1] and val * current_mul <= target):
yield from combo(l, n, target, current_indices + [i], val * current_mul)
l = [30,1,1,3,10,6,4]
for indices in combo(l, n=4, target=60):
print(*indices)
Prints:
1 2 4 5
More testcases:
l = [1,1,1,2,3,3,9]
for c, indices in combo(l, n=4, target=9):
print(*indices)
Prints:
0 1 2 6
0 1 4 5
0 2 4 5
1 2 4 5
We can use a memoized recursion for an O(n * k * num_factors), solution, where num_factors depends on how many factors of the target product we can create. The recurrence should be fairly clear from the code. (Zeros aren't handled but those should be pretty simple to add extra handling for.)
Pythonesque JavaScript code:
function f(A, prod, k, i=0, map={}){
if (i == A.length || k == 0)
return []
if (map[[prod, k]])
return map[[prod, k]]
if (prod == A[i] && k == 1)
return [i]
if (prod % A[i] == 0){
const factors = f(A, prod / A[i], k - 1, i + 1, map)
if (factors.length){
map[[prod, k]] = [i].concat(factors)
return map[[prod, k]]
}
}
return f(A, prod, k, i + 1, map)
}
var A = [30, 1, 1, 3, 10, 6, 4]
console.log(JSON.stringify(f(A, 60, 4)))
console.log(JSON.stringify(f(A, 60, 3)))
console.log(JSON.stringify(f(A, 60, 1)))
You could start from the target product and recursively divide by factors in the remaining list until you get down to 1 and after using the specified number of factors. This has the advantage of quickly eliminating whole branches of recursion under numbers that are not a factor of the target product.
Handling zero values in the list and a target product of zero requires a couple of special conditions at the start and while traversing factors.
For example:
def findFactors(product, count, factors, offset=0):
if product == 0: return sorted((factors.index(0)+i)%len(factors) for i in range(count))
if not count: return [] if product == 1 else None
if not factors: return None
for i,factor in enumerate(factors,1):
if factor == 0 or product%factor != 0: continue
subProd = findFactors(product//factor,count-1,factors[i:],i+offset)
if subProd is not None: return [i+offset-1]+subProd
r = findFactors(60, 4, [30,1,1,3,10,6,4])
print(r) # [1, 2, 4, 5]
r = findFactors(60, 4, [30,1,1,0,3,10,6,4])
print(r) # [1, 2, 5, 6]
r = findFactors(0, 4, [30,1,1,3,10,6,0,4])
print(r) # [0, 1, 6, 7]

Finding the number of paths in a maze with obstacles

I've been working on this leetcode problem, which is essentially finding the number of valid paths in a maze given some obstacleGrid matrix. If obstacleGrid[i][j] == 1, then we have an obstacle at (i,j) and we have zero otherwise, which a valid spot. We can only move down and right with the goal of starting from the upper left to the bottom right.
I have written the code below:
def uniquePathsWithObstacles(self, obstacleGrid):
# obstruction at the start
if (obstacleGrid[0][0] == 1): return 0
# obstruction at the end
if (obstacleGrid[-1][-1] == 1): return 0
m, n = len(obstacleGrid), len(obstacleGrid[0])
memo = [[0] * n] * m
# starting move
memo[0][0] = 1
# now check the first row
for j in range(1, n):
memo[0][j] = 1 if (obstacleGrid[0][j] == 0 and memo[0][j-1] != 0) else 0
# now check the first column
for i in range(1, m):
memo[i][0] = 1 if (obstacleGrid[i][0] == 0 and memo[i-1][0] != 0) else 0
# now check everything else
for i in range(1, m):
for j in range(1, n):
if (obstacleGrid[i][j] == 1): memo[i][j] = 0
else: memo[i][j] = memo[i-1][j] + memo[i][j-1]
return memo[-1][-1]
I took the obvious DP approach and I know the idea works but something is wrong with the code; for some reason I don't think my memo matrix is being updated properly? I feel like the problem is staring at me in the face but for some reason I can't see it. Any help appreciated!
Edit: For obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]] and if I had a print(memo) right before the return statement, I get [[1, 1, 2], [1, 1, 2], [1, 1, 2]]. This happens to give me the right answer, but the memo matrix is wrong!
One problem lies in the line memo = [[0] * n] * m.
This does not really create mcopies of the same list, but instead, it only creates the [0] * n list once and then creates memo as a list of m references to this list. Any change to any of these lists therefore modifies all other lists!
You can try this yourself:
memo = [[0] * 3] * 4
memo[0][1] = 1
print(memo)
This gives [[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0]].
Instead, you have to initialize each list on their own, e.g.,
memo = []
for i in range(m):
memo.append([0] * n)
I just tried to do this with recursion as an comparison rather than an answer.
import numpy as np
def number_of_paths(obstacles):
"""
Calculate the number of paths available in a maze with obstacles, with only right and down moves, from top left
to bottom right.
Args:
obstacles (ndarray): binary matrix with 1 representing obstacle
Returns:
int: the number of paths
"""
if obstacles[0,0] == 1:
raise ValueError # cannot start on an obstacle
count = 0
if obstacles.shape == (2,1):
return 1
if obstacles.shape == (1,2):
return 1
if obstacles.shape[1] > 1 and obstacles[0,1] == 0:
count += number_of_paths(obstacles[:,1:])
if obstacles.shape[0] > 1 and obstacles[1,0] == 0:
count += number_of_paths(obstacles[1:,:])
return count
your code is correct and 1 line must be updated per the below:
def uniquePathsWithObstacles(self, obstacleGrid):
# obstruction at the start
if (obstacleGrid[0][0] == 1): return 0
# obstruction at the end
if (obstacleGrid[-1][-1] == 1): return 0
m, n = len(obstacleGrid), len(obstacleGrid[0])
memo = [[0] * n for i in range(m)]
# starting move
memo[0][0] = 1
# now check the first row
for j in range(1, n):
#memo[0][j] = 1 if (obstacleGrid[0][j] == 0 and memo[0][j-1] != 0) else 0
memo[0][j] = 1 if (obstacleGrid[0][j] == 0 and memo[0][j-1] != 0) else 0
# now check the first column
for i in range(1, m):
memo[i][0] = 1 if (obstacleGrid[i][0] == 0 and memo[i-1][0] != 0) else 0
# now check everything else
for i in range(1, m):
for j in range(1, n):
if (obstacleGrid[i][j] == 1): memo[i][j] = 0
else: memo[i][j] = memo[i-1][j] + memo[i][j-1]
return memo[-1][-1]

What is the minimum number of swaps required to bubble sort an array?

I'm trying to solve the Hackerrank problem New Year Chaos:
Further explanation can be found on the page. For example, denoting the 'swapped' queue as q, if q = [2, 1, 5, 3, 4], then the required number of swaps is 3:
According to the first answer of https://www.quora.com/How-can-I-efficiently-compute-the-number-of-swaps-required-by-slow-sorting-methods-like-insertion-sort-and-bubble-sort-to-sort-a-given-array, the number of swaps required by bubble sort is equal to the number of inversions in the array. I tried to test this with the following Hackerrank submission:
#!/bin/python
import sys
T = int(raw_input().strip())
for a0 in xrange(T):
n = int(raw_input().strip())
q = map(int,raw_input().strip().split(' '))
# your code goes here
diff = [x - y for x, y in zip(q, range(1,n+1))]
if any([abs(el) > 2 for el in diff]):
print "Too chaotic"
else:
all_pairs = [(q[i], q[j]) for i in range(n) for j in range(i+1, n)]
inversions = [pair[0] > pair[1] for pair in all_pairs]
print inversions.count(True)
Here is also a version of the code to run locally:
n = 5
q = [2, 1, 5, 3, 4]
diff = [x - y for x, y in zip(q, range(1,n+1))]
if any([abs(el) > 2 for el in diff]):
print "Too chaotic"
else:
all_pairs = [(q[i], q[j]) for i in range(n) for j in range(i+1, n)]
inversion_or_not = [pair[0] > pair[1] for pair in all_pairs]
print inversion_or_not.count(True)
For the given test case, the script correctly prints the number 3. However, for all the other 'hidden' test cases, it gives the wrong answer:
I've also tried a submission which implements bubble sort:
#!/bin/python
import sys
def swaps_bubble_sort(q):
q = list(q) # Make a shallow copy
swaps = 0
swapped = True
while swapped:
swapped = False
for i in range(n-1):
if q[i] > q[i+1]:
q[i], q[i+1] = q[i+1], q[i]
swaps += 1
swapped = True
return swaps
T = int(raw_input().strip())
for a0 in xrange(T):
n = int(raw_input().strip())
q = map(int,raw_input().strip().split(' '))
# your code goes here
diff = [x - y for x, y in zip(q, range(1,n+1))]
if any([abs(el) > 2 for el in diff]):
print "Too chaotic"
else:
print swaps_bubble_sort(q)
but with the same (failed) result. Is the minimum number of swaps not equal to the number of inversions or that attained by bubble sort?
You just have to count the number of necessary swaps in bubble sort. Here is my code that got accepted.
T = input()
for test in range(T):
n = input()
l = map(int, raw_input().split())
for i,x in enumerate(l):
if x-(i+1) > 2:
print "Too chaotic"
break
else:
counter = 0
while 1:
flag = True
for i in range(len(l)-1):
if l[i] > l[i+1]:
l[i],l[i+1] = l[i+1],l[i]
counter += 1
flag = False
if flag:
break
print counter
In your first code your approach is O(n^2) which is not appropriate for n = 10^5. In this line
all_pairs = [(q[i], q[j]) for i in range(n) for j in range(i+1, n)]
you are trying to store 10^10 tuples in your RAM.
The problem with your second code is you are using the abs of elements of diff to make sure the array is not chaotic. However one person can go to the end of the line only by getting bribed and it doesn't violates the rules. So you just have to make sure a person doesn't come forward more than two positions not the other way around.
Swift 4 version:
func minimumBribes(queue: [Int]) -> Int? {
for (index, value) in queue.enumerated() {
if value - (index + 1) > 2 { // `+ 1` needed because index starts from `0`, not from `1`.
return nil
}
}
var counter = 0
var queue = queue // Just a mutable copy of input value.
while true {
var isSorted = true
for i in 0 ..< queue.count - 1 {
if queue[i] > queue[i + 1] {
queue.swapAt(i, i + 1)
counter += 1
isSorted = false
}
}
if isSorted {
break
}
}
return counter
}
// Complete the minimumBribes function below.
func minimumBribes(q: [Int]) -> Void {
if let value = minimumBribes(queue: q) {
print("\(value)")
} else {
print("Too chaotic")
}
}
clean python solution:
def minimumBribes(q):
b = 0
for i, x in enumerate(q):
if x - i > 3:
print('Too chaotic')
return
for y in q[max(0, x - 2):i]:
if y > x:
b += 1
print(b)

Categories

Resources