Troubleshooting creating a function to swap elements in Python 3 - python-3.x

I am having trouble understanding the for loop needed to create a function that swaps elements in a Python list.
I am trying to create the function using one for loop but apparently more than one is required
Inputs:
n = int(input().strip())
a = list(map(int, input().strip().split(' ')))
My method:
def count_swaps(a):
total_swaps = 0
i = 0
if a[i + 1] > a[i]:
total_swaps += 1
temp = a[i+1]
a[i+1] = a[i]
a[i] = temp
return total_swaps
Correct solution:
def count_swaps(a):
total_swaps = 0
for i in range(n):
swaps = 0
for j in range(n-1):
if a[j] > a[j+1]:
temp = a[j+1]
a[j+1] = a[j]
a[j] = temp
swaps += 1
total_swaps += swaps
return total_swaps
My question is, why is there need of two for loops, i.e. the j in range(n-1) and i in range(n)? In addition, should the range not be the same in both?

Related

What am I doing wrong with this code for hackerrank?

I have been coding this problem for HackerRank and I ran into so many problems. The problem is called "Plus Minus" and I am doing it in Python 3. The directions are on https://www.hackerrank.com/challenges/plus-minus/problem. I tried so many things and it says that "there is no response on stdout". I guess a none-type is being returned. Here is the code.:
def plusMinus(arr):
p = 0
neg = 0
z = arr.count(0)
no = 0
for num in range(n):
if arr[num] < 0:
neg+=1
if arr[num] > 0:
p+=1
else:
no += 1
continue
return p/n
The following are the issues:
1) variable n, which represents length of the array, needs to be passed to the function plusMinus
2) No need to maintain the extra variable no, as you have already calculated the zero count. Therefore, we can eliminate the extra else condition.
3) No need to use continue statement, as there is no code after the statement.
4) The function needs to print the values instead of returning.
Have a look at the following code with proper naming of variables for easy understanding:
def plusMinus(arr, n):
positive_count = 0
negative_count = 0
zero_count = arr.count(0)
for num in range(n):
if arr[num] < 0:
negative_count += 1
if arr[num] > 0:
positive_count += 1
print(positive_count/n)
print(negative_count/n)
print(zero_count/n)
if __name__ == '__main__':
n = int(input())
arr = list(map(int, input().rstrip().split()))
plusMinus(arr, n)
The 6 decimals at the end are needed too :
Positive_Values = 0
Zeros = 0
Negative_Values = 0
n = int(input())
array = list(map(int,input().split()))
if len(array) != n:
print(f"Error, the list only has {len(array)} numbers out of {n}")
else:
for i in range(0,n):
if array[i] == 0:
Zeros +=1
elif array[i] > 0:
Positive_Values += 1
else:
Negative_Values += 1
Proportion_Positive_Values = Positive_Values / n
Proportion_Of_Zeros = Zeros / n
Proportion_Negative_Values = Negative_Values / n
print('{:.6f}'.format(Proportion_Positive_Values))
print('{:.6f}'.format(Proportion_Negative_Values))
print('{:.6f}'.format(Proportion_Of_Zeros))

You are given an array A of N integers. Your task is to find the maximum number of times an odd number is repeated in the array

You are given an array A of N integers. Your task is to find the maximum number of times an odd number is repeated in the array.
Sample Input:
12
1 1 1 1 2 2 2 2 2 1 1 1
Sample Output:
4
n = int(input())
arr = list(map(int, input().split()))
c = 0
fc = 0
for i in range(n):
if arr[i] % 2 != 0:
temp = arr[i]
c += 1
for j in range(i + 1, n):
if arr[j] == temp:
c += 1
else:
print(c)
c = 0
break
if c > fc:
fc = c
print(fc)
I have tried the above approach, but it returns 6 for the input case
You are resetting count in the else clause which is wrong since you need to reset count everytime you see a new odd number. Moreover, you need to check if c > fc after you have computed c everytime, not just in the end.
Here is your code fixed.
c = 0
fc = 0
for i in range(n):
if arr[i] % 2 != 0:
c = 0
temp = arr[i]
c += 1
for j in range(i + 1, n):
if arr[j] == temp:
c += 1
else:
print(c)
break
if c > fc:
fc = c
print(fc)
Here is a better approach, which traverses the list of numbers only once.
index = 0
maxCount = 0
currCount = 0
while index < len(arr):
if arr[index]%2 == 1:
currCount = 0
currCount += 1
index += 1
while index < len(arr) and arr[index]%2 == 1:
currCount += 1
index+=1
if currCount > maxCount:
maxCount = currCount
index+=1
print(maxCount)

Buggy merge sort implementation

My merge sort implementation is buggy since i am not getting two sorted list before calling merge.I am not sure what is wrong with it.
def mergeSort(arr):
if len(arr) == 1 : return arr
mid = len(arr) // 2
left_half = arr[:mid]
right_half = arr[mid:]
mergeSort(left_half)
mergeSort(right_half)
return merge(left_half,right_half)
def merge(list1,list2):
res = []
i = 0
j = 0
while i < len(list1) and j < len(list2):
if list1[i] < list2[j]:
res.append(list1[i])
i += 1
elif list1[i] > list2[j]:
res.append(list2[j])
j += 1
#Add remaining to res if any
while i < len(list1):
res.append(list1[i])
i += 1
while j < len(list2):
res.append(list2[j])
j += 1
return res
A = [5,1,2,15]
print(mergeSort(A))
My understanding of merge sort is that the space complexity is O(n) since n items in memory (in the final merge).Is quick sort preferred over merge sort just because quick sort is in-place?
I not python expert, but you should write
left_half = arr[:mid]
right_half = arr[mid:]
left_half = mergeSort(left_half)
right_half = mergeSort(right_half)
Because your mergeSort return copy of sorted array.
You have 3 mistakes in your code.
The first is that you don't handle the empty list. You need a <= instead of an == in your second line.
The second is that by simply calling mergeSort(left_half) you suppose that it will sort left_half “by reference”, which it doesn't (same with right_half).
The third is that you aren't doing anything in the case list1[i] == list2[j]. Actually you don't need that elif, you simply need an else. It doesn't matter whether you append list1[i] or list2[j] if they are equal, but you must append one of the two.
Your code should rather be:
def mergeSort(arr):
if len(arr) <= 1 : return arr
mid = len(arr) // 2
left_half = mergeSort(arr[:mid])
right_half = mergeSort(arr[mid:])
return merge(left_half, right_half)
def merge(list1, list2):
res = []
i = 0
j = 0
while i < len(list1) and j < len(list2):
if list1[i] < list2[j]:
res.append(list1[i])
i += 1
else:
res.append(list2[j])
j += 1
#Add remaining to res if any
...
As for your questions about space complexity and comparison with quicksort, there are already answers here on StackOverflow (here and here).

Is it possible to merge these two functions as one calls on another

Would like to know if it is possible to merge these two functions together it seems like it could be a singular function through recursion but i'm not sure. I don't really do a lot of programming but this works as intended i just thought it would be nice to have it as a single function. Just not sure how to program recursion any advice would be great thanks
def sieve(A, n):
for i in A:
if i % n == 0 and i > n:
A.remove(i)
return A
def primelist(N):
A = [i for i in range(2, N + 1)]
for i in A:
A = (sieve(A, i))
print(A)
Decided on a new approach and solved:
def primelist(N):
k = 0
A = [i for i in range(2, N + 1)]
while k < len(A):
for i in A:
if i % A[k] == 0 and i > A[k]:
A.remove(i)
k += 1
return(A)
Decided on a new approach and solved:
We can do better -- your solution, and that of #ikuamike, have the same issue. These lines in particular are inefficient:
for i in A:
if i % A[k] == 0 and i > A[k]:
First, when possible, we should do an easier test before a harder test, so the if should really be:
for i in A:
if i > A[k] and i % A[k] == 0:
to do the comparison (subtraction) test ahead of the modulus (division) test. (Why do all those divisions when you don't need too?)
The next issue is that all the numbers from A[0] to A[k] don't need to be tested as they're eliminated by the comparison, so why not leave them out in the first place:
for i in A[k + 1:]:
if i % A[k] == 0:
Revised code:
def primelist(N):
k = 0
A = [i for i in range(2, N + 1)]
while k < len(A):
for i in A[k + 1:]:
if i % A[k] == 0:
A.remove(i)
k += 1
return A
With N set to 10,000, you can measure the time improvement.
def primelist(N):
A = [i for i in range(2, N + 1)]
new_a = A
for i in A:
for n in new_a:
if n % i == 0 and n > i:
new_a.remove(n)
print(new_a)
This should work well for you, I just replaced the for loop in seive onto the primelist function.

Puzzler solver program: How many different solutions are there to (1/a)+(1/b)+(1/c)+(1/d)+(1/e)+(1/f)+(1/g) = 1?

I wrote the python code below that solves and prints each possible solution for anything under 6 unit fractions, but given how I programmed it, it takes infinitely long to check for 7 fractions. Any ideas on how to modify the code to find all the possible solutions more efficienty?
import sys
from fractions import Fraction
import os
#myfile = open('7fractions.txt', 'w')
max = 7 #>2 #THIS VARIABLE DECIDES HOW MANY FRACTIONS ARE ALLOWED
A = [0] * max
A[0] = 1
def printList(A):
return str(A).strip('[]')
def sumList(A):
sum = 0
for i in A:
if i != 0:
sum += Fraction(1, i)
return sum
def sumTest(A):
sum = 0
v = 0
for i in range(0, len(A)):
if A[i] == 0 and v == 0:
v = Fraction(1,A[i-1])
if v != 0:
sum += v
else:
sum += Fraction(1, A[i])
return sum
def solve(n, A):
if n == max - 2:
while (sumTest(A) > 1):
print(A)
if sumList(A) < 1:
e = 1 - sumList(A)
if e.numerator == 1 and e.denominator>A[n-1]:
A[n+1] = e.denominator
#myfile.write(printList(A) + '\n')
print(A)
A[n+1] = 0
A[n] += 1
else:
while (sumTest(A) > 1):
if sumList(A) < 1:
A[n+1] = A[n] + 1
solve(n+1, A)
A[n+1] = 0
A[n] += 1
#execute
solve(0, A)

Resources