Reputation: 27
I have written a simple function in Python which aims to find, if from two elements a
and b
, one can be obtained from another by swapping at most one pair of elements in one of the arrays.
This is my function:
def areSimilar(a, b):
test = 0
for i in range(len(b)):
for j in range(len(b)):
b2 = b
b2[i] = b[j]
b2[j] = b[i]
if a == b2:
test = 1
return(test==1)
The issue is that upon inspecting b
, it has changed even though I don't actually perform any calculations on b
- what's going on!!??
Upvotes: 0
Views: 52
Reputation: 26896
(EDITED: to better address the second point)
There are two issues with your code:
b2 = b
this just creates another reference to the underlying object. If b
is mutable, any change made to b2
will be reflected in b
too.i
and j
swapped, so test
condition is hit either never or (at least -- depending on the amount of duplicates) twice. While this would not lead to incorrect results, it would normally be regarded as an error in the logic.To fix your code, you could just create a copy of b
. Assuming that by Python arrays you actually mean Python list
s one way of doing it would be to create a new list
every time by replacing b2 = b
with b2 = list(b)
. A more efficient approach is to perform the swapping on b
itself (and swap back):
def are_similar(a, b):
for i in range(len(b)):
for j in range(len(b)):
b[i], b[j] = b[j], b[i]
if a == b:
b[i], b[j] = b[j], b[i] # swap back
return True
else:
b[i], b[j] = b[j], b[i] # swap back
return False
print(are_similar([1, 1, 2, 3], [1, 2, 1, 3]))
# True
print(are_similar([1, 1, 2, 3], [3, 2, 1, 1]))
# False
By contrast, you can see how inefficient (while correct) the copying-based approach is:
def are_similar2(a, b):
for i in range(len(b)):
for j in range(len(b)):
b2 = list(b)
b2[i] = b[j]
b2[j] = b[i]
if a == b2:
return True
return False
print(are_similar2([1, 1, 2, 3], [1, 2, 1, 3]))
# True
print(are_similar2([1, 1, 2, 3], [3, 2, 1, 1]))
# False
with much worse timings, even on relatively small inputs:
a = [1, 1, 2, 3] + list(range(100))
b = [1, 2, 1, 3] + list(range(100))
%timeit are_similar(a, b)
# 10000 loops, best of 3: 22.9 µs per loop
%timeit are_similar2(a, b)
# 10000 loops, best of 3: 73.9 µs per loop
Upvotes: 1
Reputation: 2699
I would got with Sadap's code, but if you want to copy, use :
import copy
def areSimilar(a, b):
test = 0
for i in range(len(b)):
for j in range(len(b)):
b2 = copy.deepcopy(b)
b2[i] = copy.deepcopy(b[j])
b2[j] = copy.deepcopy(b[i])
if a == b2:
test = 1
if test == 1:
return True
else:
return False
Upvotes: 0