Subtraction(list) recursively in Python 3 - python-3.x

I know how to add the numbers in a list recursively
def mysum(L):
if not L:
return 0
else:
return L[0] + mysum(L[1:])
Can you help me to build the subtraction recursively in the same manner(only one input - List).
mydiff([10,1,2,3])
Many thanks

if the sequence is (3,2,1), the result is 0. But subtraction is going in reverse direction, i.e. 2 -1 than 3 - (2-1) if you use return L[0] - mysum(L[1:]).
So we have to use an accumulator which keeps the difference of first and second element of a sequence.
def mydiff(L, acc=None):
if not L:
return acc
else:
if acc is None:
acc = L[0] - L[1]
L = L[2:]
else:
acc -= L[0]
L = L[1:]
return mydiff(L, acc)
More simpler one;
def mysub(seq, acc=None):
seq = iter(seq)
if acc is None:
item = next(seq, None)
if item is None:
return acc
acc = item
item = next(seq, None)
if item is None:
return acc
return mysub(seq, acc - item)

The calculation to be done is
>>> 10-(1+(2+(3+0)))
4
so the first operation is a subtraction, but the rest of the operations remain additions. I think you need to use an inner function if you're not allowed to add a second parameter to the main function:
def mydiff(L):
def sub(L, first=False):
if not L:
return 0
else:
if first:
return L[0] - sub(L[1:])
else:
return L[0] + sub(L[1:])
return sub(L, True)
Testing:
>>> mydiff([10,1,2,3])
4

Related

How to sort a list into even then odd numbers using recursion when the function can only call itself and use basic list manipulations

The function takes in a list of integers and returns a list of the same elements sorted into the order of even integers then odd ones. Im struggling with implementing a recursive function to complete it even though I am able to solve this using a for loop.
def sort(lst: list[int]) -> list[int]:
l1 = []
l2 = []
for i in lst:
if i % 2 == 0:
l1.append(i)
else:
l2.append(i)
x = l1 + l2
return x
def eto(lst: list[int]) -> list[int]:
if len(lst) == 1
return lst
else:
y = lst[0]
x = lst[1:]
return(eto(x))
I'm not sure how to proceed from here.
I suppose we are allowed to reorder the odd numbers, as long as they are in the second part of the list. I completed your proposition:
def eto(lst: list[int]) -> list[int]:
if len(lst) <= 1:
return lst
head = lst[0]
tail = lst[1:]
if head % 2 == 0:
return [head] + eto(tail)
return eto(tail) + [head]

Python Recursive calls not updating global variable

I'm trying to implement a partial brute force approach in python for Leetcode Beautiful Arrangements. I'm struggling to update my "counter" variable during the recursive calls.
I've tried multiple approaches with global variables and passing it in as a function parameter, no matter what I've done, I'm not getting the correct return value even though the if L == len(numbers) condition is met.
class Solution:
def countArrangement(self, n: int) -> int:
def count_beautiful_arranges(N: int, counter):
numbers = [0]*N
# start index at 1
# loop creates the array of 1 to N for initial list
for i in range(1, N+1):
numbers[(i-1)] = i
# call recursive permutation function
permutation(numbers, 0, counter)
return counter
def permutation(numbers: list, L: int, counter):
# check each recursive call
#print(L)
#print(len(numbers))
if L == len(numbers):
counter = counter + 1
for j in range(L, len(numbers)):
swap(numbers, j, L)
if numbers[L] % (L+1) == 0 or (L+1) % numbers[L] == 0:
permutation(numbers, L+1, counter)
swap(numbers, j, L)
def swap(numbers: list, x: int, y: int):
#pythonic code
numbers[x], numbers[y] = numbers[y], numbers[x]
count_beautiful_arranges(n, 0)
I fixed it by using Python's ability to attach a variable to a function. with
<Function_Name>. method I was able to attach a counter and increment it in the recursive stack.
I declared permutation.countser before calling the recursive functions then returned the value after the calls were completed.
This StackOverflow answer helped me.
def count_beautiful_arranges(N: int, counter):
numbers = [0]*N
# start index at 1
# loop creates the array of 1 to N for initial list
for i in range(1, N+1):
numbers[(i-1)] = i
permutation(numbers, 0)
def permutation(numbers: list, L: int):
if L == len(numbers):
permutation.countser += 1
for j in range(L, len(numbers)):
swap(numbers, j, L)
if numbers[L] % (L+1) == 0 or (L+1) % numbers[L] == 0:
permutation(numbers, L+1)
swap(numbers, j, L)
def swap(numbers: list, x: int, y: int):
#pythonic code
numbers[x], numbers[y] = numbers[y], numbers[x]
permutation.countser = 0
count_beautiful_arranges(n, 0)
return permutation.countser

I want to return the sum of all indexes in n via recursion. How do I do this?

def final_sum(n):
n = str(n)
if int(n) == 0:
return 0
else:
x = int(n[0])
return x + int(final_sum(n[1:]))
print(final_sum(123))
For example, if my n is 123, I should be getting 6. But I am having an error in this code. Can anyone help? I have to use recursive function. So tell me what's wrong with the code.
in return x + int(final_sum(n[1:])), n[1:] is str type
in the beginning of the function, with n = str(n), you assume the input is an int
Besides, you did not consider the case that n[1:] can be empty in return x + int(final_sum(n[1:])).
Here is an anwser based on your code
def final_sum(n):
if n == 0:
return 0
n = str(n)
x = int(n[0])
if len(n)==1:
return x
else:
return x + final_sum(int(n[1:]))
Here is another version using % operation
def final_sum(n):
if n < 10:
return n
return n % 10 + final_sum(n // 10)
First of all, at the beggining I would do this instead of casting back and forth:
def final_sum(n):
if n<10:
return n
You see, the problem is, in the last recursive iteration, you are passing this to the function:
final_sum("")
When you should be passing an int. I think this is happening because your last cast is backwards and you never check how many digits the number has. So the code should look like this:
def final_sum(n):
if n<10:
return n
n = str(n)
x = int(n[0])
return x + final_sum(int(n[1:]))
print(final_sum(123))

Quick sort counting

Python questions again.
I want to count the number of comparison operations performed by quick sort. Because I use a recursive function, I do not think that assigning count = 0 to the beginning of the function body is inappropriate, so I made it as follows.
def QuickSort(lst, count = 0):
if len(lst) > 1:
pivot_idx = len(lst) // 2
smaller_nums, larger_nums = [], []
for idx, num in enumerate(lst):
if idx != pivot_idx:
if num < lst[pivot_idx]:
smaller_nums.append(num)
else:
larger_nums.append(num)
count = QuickSort(smaller_nums, count + 1)[1]
count = QuickSort(larger_nums, count + 1)[1]
lst[:] = smaller_nums + [lst[pivot_idx]] + larger_nums
return lst, count
However, after counting, I confirmed the count which is much lower than my expectation. According to big o, the quick sort would have to show the calculation of n * log (n), but it showed a much lower count. For example, when sorting a list with 1000 random elements, we expected to see a count of 1000 * log (1000) = 6907, but actually only 1164 counts. I am wondering if I am misusing the count in the function or misunderstanding it.
Thank you.
Your post is mistaken on several points:
Big-O is allows arbitrary constant factors and also ignoring the values for "small" values of n, where "small" can be arbitrarily large for any given analysis. So your computations are meaningless.
Your counts are wrong. There's one comparison per loop iteration. You're counting something else.
This is a strange way to code the count. Just use a global variable.
Try this. Note really you're using twice as many comparisons as this reports. The check that the loop index isn't the pivot could be eliminated with a smarter implementation.
c = 0
def QuickSort(lst):
if len(lst) <= 1:
return lst
pivot_idx = len(lst) // 2
smaller, larger = [], []
for idx, num in enumerate(lst):
if idx != pivot_idx:
global c
c += 1
(larger, smaller)[num < lst[pivot_idx]].append(num)
return QuickSort(smaller) + [lst[pivot_idx]] + QuickSort(larger)
def Run(n):
lst = [random.randint(0,1000) for r in xrange(n)]
QuickSort(lst)
print c
Run(1000)
If you're aghast at the prospect of using a global variable, then you can just wrap the sort in a class:
import random
class QuickSort:
def __init__(self):
self.comparisons = 0
def sort(self, lst):
if len(lst) <= 1:
return lst
pivot_idx = len(lst) // 2
smaller, larger = [], []
for idx, num in enumerate(lst):
if idx != pivot_idx:
self.comparisons += 1
(larger, smaller)[num < lst[pivot_idx]].append(num)
return self.sort(smaller) + [lst[pivot_idx]] + self.sort(larger)
def Run(n):
lst = [random.randint(0,1000) for r in xrange(n)]
quicksort = QuickSort()
print quicksort.sort(lst)
print quicksort.comparisons
Run(100)
Building on the answer provided by Gene by adding print statements and a sort "error" range, his example was very helpful to my understanding of quicksort and an error term on the big O impact of operations performance comparison.
class QuickSort:
def __init__(self):
self.comparisons = 0
def sort(self, lst):
k_err = 0 # k << n, the value the sort array can be in error
if len(lst) <= 1:
return lst
pivot_idx = len(lst) // 2
smaller, larger = [], []
for idx, num in enumerate(lst):
if idx != (pivot_idx) :
self.comparisons += 1
try:
(larger, smaller)[(num - k_err) < lst[pivot_idx]].append(num)
except:
(larger, smaller)[(num + k_err) < lst[pivot_idx]].append(num)
print(pivot_idx,"larger", self.comparisons, larger)
print(pivot_idx, "smaller", self.comparisons, smaller, )
return self.sort(smaller) + [lst[pivot_idx]] + self.sort(larger)
def Run(n):
random.seed(100)
lst = [random.randint(0,round(100,0)) for r in range(n)]
quicksort = QuickSort()
print(len(lst), lst)
print(quicksort.sort(lst))
print(quicksort.comparisons, quicksort.comparisons/n, ((quicksort.comparisons/n)/math.log(n,10)), math.log(n,10) )

permutation of a list of numbers done recursively in python

So basically I'm trying to take a list of numbers and write a recursive function that outputs all possible outputs in a list of lists.
My code:
def permutations(lst):
if len(lst) <= 1:
return lst
l = []
for i in range(len(lst)):
m = lst[i]
remlst = lst[:i] + lst[i+1:]
for p in permutations(remlst):
l.append([m] + p)
return l
I'm getting a few errors about not being able to append int.
Simple output:
>>>permutations([1,2])
[[1,2],[2,1]]
There is an implementation for that in itertools:
import itertools
for p in itertools.permutations(list):
# do stuff
Also, to fix your own function, notice that in your "base case" len(lst) <= 1 your returning a list, instead of a list-of-lists. Also, the second return statement should be moved out of the loop;
def permutations(lst):
if len(lst) <= 1:
return [lst]
l = []
for i in range(len(lst)):
m = lst[i]
remlst = lst[:i] + lst[i+1:]
for p in permutations(remlst):
l.append([m] + p)
return l
Because you iterate through result of permutations
for p in permutations(remlst):
your base case needs to return a list of lists like your recursive case does, otherwise you get the error TypeError: can only concatenate list (not "int") to list
You also need to return after the outer for loop.
def permutations(lst):
if len(lst) <= 1:
return [lst] # [[X]]
l = []
for i in range(len(lst)):
m = lst[i]
remlst = lst[:i] + lst[i+1:]
for p in permutations(remlst):
l.append([m] + p)
return l # return at end of outer for loop

Resources