Output error in this simple code for ArrayRotation? - python

Wrote a simple code for left array rotation, getting the same array without any Rotation done to it as the wrong output.
def leftRotate(arr, d, n):
while (d-1) > 0:
leftRotatebyOne(arr, n)
def leftRotatebyOne(arr, n):
temp = arr[0]
for i in range(n-1):
arr[i] = arr[i + 1]
arr[n - 1] = temp
def PrintArray(arr, size):
for i in range(size):
print("%d" % arr[i], end=" ")
arr = []
l = int(input("Enter the number of elements: "))
for i in range(0, l):
ele = int(input())
arr.append(ele)
d = int(input("Enter the number of rotations: "))
n = len(arr)
leftRotate(arr, d, n)
PrintArray(arr, n)
and here's an example of the output i've got,
Enter the number of elements: 3
1
2
3
Enter the number of rotations: 1
1 2 3
I expected an output of 2 3 1 after one rotation.

I would suggest using array slicing, then adding the slices together, to perform rotation.
def left_rotate(data, num):
return data[num:] + data[:num]
def right_rotate(data, num):
return data[-num:] + data[:-num]
For example
>>> a = [1,2,3,4,5,6,7]
>>> left_rotate(a, 2)
[3, 4, 5, 6, 7, 1, 2]
>>> right_rotate(a, 2)
[6, 7, 1, 2, 3, 4, 5]
Also note that collections.deque has this behavior available already
>>> from collections import deque
>>> d = deque([1,2,3,4,5,6,7])
>>> d.rotate(2)
>>> d
deque([6, 7, 1, 2, 3, 4, 5])
>>> d.rotate(-2)
>>> d
deque([1, 2, 3, 4, 5, 6, 7])

In the function leftRotate,
there is an error in while loop.
Replace
while (d-1) > 0:
leftRotatebyOne(arr, n)
with
while d > 0:
leftRotatebyOne(arr, n)
d -= 1

When d == 1, while (d-1) > 0: will not be executed any time. Also, you never decrement d. The easiest way to solve is by using a for _ in range(d) loop:
def leftRotate(arr, d, n):
for _ in range(d):
leftRotatebyOne(arr, n)
NOTE: Python has way better ways to do rotations than this. This code seems to be C more than Python. Passing the array length makes no sense in Python for example. And the rotation can be done all in one assignation.
def leftRotate(arr, d):
d %= len(arr)
for _ in range(d):
arr[-1], arr[:-1] = arr[0], arr[1:]
Cory Kramer's answer is even more pythonic. But it has a bug and a difference with your question's methods. The bug is that it doesn't work when the number of rotations requested are higher than the length of the list. The difference is that they are returning a new list instead of modifying it. These two issues could be addresed like this:
def left_rotate(data, num):
num %= len(data)
data[:] = data[num:] + data[:num]
def right_rotate(data, num):
num %= len(data)
data[:] = data[-num:] + data[:-num]

Related

how to count the number divisible by N in given range (A to B) for multiple cases (C) in python

So basically, there are multiple cases that need to be solve by counting the number that divisible by N in given range A to B.
for example, there are 2 cases.
case 1 has A=1, B=10, N=3
case 2 has A=8, B=20, N=4
but on one condition that the input must be like this:
2 #<-- number of cases
1 #<-- A
10 #<-- B
3 #<-- N
8 #<-- A
20 #<-- B
4 #<-- N
the output will be like:
Case 1: 3 #because between 1 until 10, only 3,6,9 that divisible by 3
Case 2: 4 #because between 8 until 20, only 8,12,16,20 that divisible by 4
I have this function for reference:
def CountDiv(A,B,N):
count = 0
for i in range(A, B+1):
if i % N == 0:
count = count + 1
return count
My explanation is bad but I just don't know how to make it more clearer. I hope someone will understand and enlightened me about this problem. Thank you
The CountDiv function works. So, I'm assuming that you are asking how to properly slice your input list. If you have your input sequence in a list, this should work
seq = [ 2, #<-- number of cases
1, #<-- A
10, #<-- B
3, #<-- N
8, #<-- A
20, #<-- B
4, #<-- N
]
def slices(lst, n):
number_of_cases = lst.pop(0)
for i in range(0, n * number_of_cases, n):
yield lst[i:i + n]
def CountDiv(A,B,N):
count = 0
for i in range(A, B+1):
if i % N == 0:
count = count + 1
return count
print([CountDiv(*sub) for sub in [*slices(seq, n=3)]])
# [3, 4]
If you want the exact output you described, you can do this
for idx, sub in enumerate([*slices(seq, n=3)]):
print(f"Case {idx}: {CountDiv(*sub)}")
# Case 0: 3
# Case 1: 4
You should also combine #mozway's and my answer, like so.
def slices(lst, n):
number_of_cases = lst.pop(0)
for i in range(0, n * number_of_cases, n):
yield lst[i:i + n]
def ndiv(A, B, N):
return (B+N-(A+N-1)//N*N)//N if B>=A else 0
for idx, sub in enumerate([*slices(seq, n=3)]):
print(f"Case {idx}: {ndiv(*sub)}")
Edit on request: The * operator is used twice above to unpack elements from an iterable. For example, in the statement above, ndiv(*sub) could be replaced by ndiv(sub[0], sub[1], sub[2]). If we wanted to make it very verbose, we could write it like this
result_of_slicing = list(slices(seq, n= 3))
# [[1, 10, 3], [8, 20, 4]]
for index, a_slice in enumerate(result_of_slicing):
A, B, N = a_slice
result_of_ndiv = ndiv(A=A, B=B, N=N)
print(f"Case {index}: {result_of_ndiv}")
# Case 0: 3
# Case 1: 4
You don't need to loop over all values. You can only generate the multiple from the smallest starting point ((A+N-1)//N*N):
def ndiv(A, B, N):
return len(list((A+N-1)//N*N, B+1, N)))
Even better, calculate directly the number of values using:
def ndiv(A, B, N):
if B<A:
return 0
return (B+N-(A+N-1)//N*N)//N
example:
>>> ndiv(8,20,4)
4
>>> ndiv(1,10,3)
3
>>> ndiv(1,1,3)
0

Array task. Finding last two negative numbers in array

Search for the numbers of the last two consecutive negative elements in an array. The length of the array is entered from the keyboard. Float type.
my code is:
import math
import numpy
import random
#i = (random.uniform(-1000, 1000))
o = []
a = []
n = int(input())
n += 1
l = 0
sh = 1
m2 = n
m = n-1
m=int(m)
for i in range(n):
x = (random.uniform(-1000, 1000))
a.append(x)
for i in range(m):
otric = a.pop(m)
otric = int(otric)
a.insert(otric,int(m+1))
if otric < 0:
o.append(otric)
m -= 1
if len(o) > 2: break
print(a)
print(o)
and this doesn't work, idk how to fix it.. please help
Use zip to get all consecutive negative numbers and return the last element of the resulting list:
a = [random.uniform(-1000, 1000) for _ in range(n)]
>>> [(x,y) for x,y in zip(a, a[1:]) if x<0 and y<0][-1]
(-696.9270891497699, -612.4999984966855)
Iterate the list in reverse and when a value is negative also grab the next one and see if it is the pair we're looking for:
lst = [1, -7, -8, 1, 1, -1, 1, -2, -3, 1, -4, 1, -5, 1, 1]
it = reversed(lst)
for a in it:
if a < 0:
b = next(it, 0)
if b < 0:
print(b, a)
break

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]

Get the absolute difference between elements of a circular array

Let's say I have a array like l = [1, 3, 4, 5, 6, 8]
where the nth element represents the distance between the nth and n+1th object.
I want to find the distance between any two objects, and I used this code for this:
def dis(l_list, index1, index2, mylist):
m = mylist.index(index1)
n = mylist.index(index2)
i=0
j=0
if n > m:
while n >= m:
i = i + mylist[m]
m = m + 1
elif n < m:
while n <= m:
i = i + mylist[n]
n = n + 1
else:
return(0)
j = mylist[n] % l_mylist
print(abs(i - j))
l_mylist = input()
l_mylist = int(l_mylist)
mylist = []
mylist = list(map(int, input().split()))
i,j = input().split()
i, j=int(i), int(j)
dis(l_mylist, i, j, mylist)
but I am still getting the wrong output. Can anyone please point out where I am wrong?
If you want to sum around a potentially circular list. You can use a collections.deque() to rotate the list, e.g.:
from collections import deque
def dist(l, i1, i2):
d = deque(l)
d.rotate(-i1)
return sum(list(d)[:i2-i1]))
In []:
l = [1,2,3,4,5,6,7,8]
dist(l, 3-1, 6-1) # 3, 4, 5
Out[]:
12
In []:
dist(l, 6-1, 3-1) # 6, 7, 8, 1, 2
Out[]:
24
def distance(first_index, second_index, my_list):
temp_list = my_list + my_list
if (first_index > second_index):
first_index += len(my_list)
requested_sum = sum(my_list[second_index-1:first_index-1])
else:
requested_sum = sum(my_list[first_index-1:second_index-1])
return requested_sum
If I understood you correctly, then this should do the trick.
There are much more compact and efficient ways to do this, but this is the simplest and easiest to understand in my opinion.

I don't know what is wrong in my algorithm in code for Google Code Jam 2018 1B-B

Now the contest is over, so I want to ask my algorithmic fails on my code.
This is the problem. If anyone interested, you can see it at here
def solve():
S = int(input())
D, A, B, M, N = [], [], [], [], []
for i in range(S):
d, a, b = [int(c) for c in input().split(" ")]
D.append(d); A.append(a); B.append(b)
M.append(d+a); N.append(d-b)
straightMstart, straightNstart = [0]*(S), [0]*(S)
crossedMstart, crossedNstart = [0]*(S), [0]*(S) # cross over
for i in range(1, S):
if M[i] == M[i-1]:
straightMstart[i] = straightMstart[i-1]
crossedNstart[i] = crossedNstart[i-1]
else:
straightMstart[i] = i
if N[i] == N[i-1]:
straightNstart[i] = straightNstart[i-1]
crossedMstart[i] = crossedMstart[i-1]
else:
straightNstart[i] = i
if M[i] != M[i-1]:
crossedNstart[i] = straightNstart[i-1]
if N[i] != N[i-1]:
crossedMstart[i] = straightMstart[i-1]
maxlen = 1
maxlensubsets = 1
for i in range(1, S):
thislen = i - min(crossedMstart[i], crossedNstart[i]) + 1
if maxlen < thislen:
maxlen = thislen
maxlensubsets = 1
elif maxlen == thislen:
maxlensubsets += 1
# print(crossedNstart)
# print(crossedMstart)
return "%d %d" % (maxlen, maxlensubsets)
testcase = int(input())
for tc in range(1, testcase+1):
print("Case %d: %s" % (tc, solve()))
I used crossed max length to find the maximum size of set.(for M and Ns)
I will give you the following example to make easier to understand my logic:
# Let's suppose that the M and N is:
M (=D[i]+A[i]) = [ 9, 9, 18, 22, 22]
N (=D[i]-B[i]) = [-10, -5, 7, -1, -1]
# Straight Start means starting index for same value.
# M=9 starts from index 0, M=18 starts from index 2, M=22 starts from index 3
straightMstart = [0, 0, 2, 3, 3]
# Same logic applied to straightNstart
straightNstart = [0, 1, 2, 3, 3]
# Crossed Start means cross-starting index of opponent array.
# For crossedMstart, you start from N[i] and climb N then cross to climb M
# The reason why I swapped order of cNs and cMs is that both arrays are based on opponent arrays
crossedNstart = [0, 0, 1, 2, 2]
crossedMstart = [0, 0, 0, 2, 2]
I'm really confusing, I don't really understand what is the point of my fault. Please help me to correct my logic.
Your algorithm has multiple ways it could fail. The simplest of them is entering a string in any of the inputs. Then I do see a problem with straightNstart[i] which is always zero for the current iteration if N[i] or M[i] match N[i-1] or M[i-1]. This sets the crossedMstart[i] and crossedNstart[i] values to 0. Another problem is when S <= 1 which ignores both loops.
The first problem is easy to solve which potentially covers the problems for d, a, b, testcase where d, a, b, testcase should raise only a TypeError:
S = input("[description]")
if S.isdigit():
S = int(S)
if S <= 1:
raise ValueError("Value must be greater then 1")
else:
raise TypeError("Value must be numeric")
For the other problem it could be possible to iterate twice so that the straightNstart[i], straightMstart[i] assignments have any effect on the outcome ( at least not when M[i] or N[i] are not equal to M[i-1] or N[i-1] ).
I found that my algorithm does not handling multiple crossover.

Categories

Resources