Python - how does the variable affect the loop - python

I am wondering why there is a different result when I change from arr[n] in version 1 to n in version 2:
Version 1
def summer_69(arr):
list_sum2 = 0
n = 0
for arr[n] in range(arr[n] == 6, (arr[n]== 9) + 1):
list_sum2 += arr[n]
print(list_sum2)
summer_69([1, 3, 5])
summer_69([4, 5, 6, 7, 8, 9])
Result for Version 1
0
0
Version 2
def summer_69(arr):
list_sum2 = 0
n = 0
for n in range(arr[n] == 6, (arr[n]== 9) + 1):
list_sum2 += arr[n]
print(list_sum2)
summer_69([1, 3, 5])
summer_69([4, 5, 6, 7, 8, 9])
Result for Version 2
1
4

that's not how range works.
in this line:
for n in range(arr[n] == 6, (arr[n]== 9) + 1):
arr[n] == 6 and (arr[n]== 9) + 1 are returning truth values because == is a comparison operator so n here at best takes values 0 or 1.
you want
for n in range(6, 10):
so that the value of n iterates from 6 to 9, range() being inclusive to the left and exclusive to the right

Related

Write a function sum13(nums)

Write a function sum13(nums) that takes a list of ints nums and returns the sum of the numbers in the list, returning 0 for an empty list. Except the number 13 is very unlucky, so it does not count and numbers that come immediately after a 13 also do not count.
Test Result
print(sum13([1, 2, 2, 1, 13]))
6
print(sum13([13, 2, 2, 1]))
3
print(sum13([13, 13, 2, 13, 1, 5, 6, 13]))
11(EXPECTED)
13(GOT)
here is my program I don't know why the last test code is not running
def sum13(nums):
"""jdhdjkls"""
if len(nums) == 0:
return 0
for i in range(0, len(nums)):
if nums[i] == 13:
nums[i] = 0
if i+1 < len(nums):
nums[i+1] = 0
return sum(nums)
You can use the built-in zip() method to zip two lists skewed like:
[1, 2, 3, 4]
[1, 2, 3, 4]
to
[1, 2, 3, 4]
[2, 3, 4, None]
and check to see if any of the pairs have 13 in them.
Here is how:
def sum13(nums):
s = 0 if nums[0] == 13 else nums[0]
for p in zip(nums, nums[1:]):
if all(n != 13 for n in p):
s += p[1]
return s
print(sum13([1, 2, 2, 1, 13]))
print(sum13([13, 2, 2, 1]))
print(sum13([13, 13, 2, 13, 1, 5, 6, 13]))
Output:
6
3
11
You can also unpack the pairs:
def sum13(nums):
s = 0 if nums[0] == 13 else nums[0]
for i, j in zip(nums, nums[1:]):
if i != 13 != j:
s += j
return s
print(sum13([1, 2, 2, 1, 13]))
print(sum13([13, 2, 2, 1]))
print(sum13([13, 13, 2, 13, 1, 5, 6, 13]))
This will solve your problem:
def sum13(nums):
"""jdhdjkls"""
if len(nums) == 0:
return 0
for i in range(0, len(nums)):
if nums[i] == 13:
nums[i] = 0
# problem arises when there are 2 consecutive 13 this if statement will rectify it.
if (i+1 < len(nums)) and (nums[i+1]!=13):
nums[i+1] = 0
return sum(nums)
We could try using recursion to solve this problem:
def sum13(numbers):
if not numbers: # base case
return 0
first, *rest = numbers
if first == 13:
first = 0
if rest and rest[0] != 13:
rest.pop(0)
return first + sum13(rest)
print(sum13([1, 2, 2, 1, 13]))
print(sum13([13, 2, 2, 1]))
print(sum13([13, 13, 2, 13, 1, 5, 6, 13]))
Though not the style of answer you likely want, we can also coerce itertools.groupby to do the work for us:
from itertools import groupby
def sum13(numbers):
previous13 = False
def is_tainted(number):
nonlocal previous13
tainted = previous13
previous13 = number == 13
return True if tainted else previous13
total = 0
for tainted, subset in groupby(numbers, is_tainted):
if not tainted:
total += sum(subset)
return total
Your scripts can't correspond to 13 13 2 because they are made 0 0 2 in first step.
for and continue is effective for your goal.
def sum13(nums):
sums=0
after13=False
for num in nums:
if num == 13:
after13=True
continue
if not after13:
sums+=num
after13=False
return sums

How do I make this Merge Sort function a generator (Python)?

So I understand how to make the merge sort algorithm in Python 3, and this is my code below for implementing the function:
def x(arr):
for i in mergeSort(arr):
yield from i
def mergeSort(arr):
if len(arr) > 1:
middle = len(arr) // 2
left = arr[:middle]
right = arr[middle:]
mergeSort(left)
mergeSort(right)
a = 0
b = 0
c = 0
while a < len(left) and b < len(right):
if left[a] < right[b]:
arr[c] = left[a]
a += 1
else:
arr[c] = right[b]
b += 1
c += 1
while a < len(left):
arr[c] = left[a]
a += 1
c += 1
while b < len(right):
arr[c] = right[b]
b += 1
c += 1
for i in mergeSort([6,3,8,7,4,1,2,9,5,0]):
print(i)
The gist of it is that the function returns the array sorted at the end. However, I am trying to build a sorting visualiser, and to do so, I need to make this function yield the array whenever a change is made so you can see the bars switch - so I need to make it a generator, but all attempts I've made to do so haven't worked. How could I modify my code to make this function a generator?
Thanks.
First you will need to make sure that a deeply recursive execution can actually report about the state of the whole list. With your current set up that is not possible, since the recursive function only gets to see a small slice of the array.
So, in order to fix that situation, don't pass slices with the recursive call, but pass start/end indices instead, giving access to the same arr to all function execution contexts.
Then you can yield arr after each merge. The code that makes the recursive call should use yield from.
I adapted your code only to apply the above idea:
def mergeSort(arr):
# arr is a unique list that all levels in the recursion tree can access:
def mergeSortRec(start, end): # separate function that can take start/end indices
if end - start > 1:
middle = (start + end) // 2
yield from mergeSortRec(start, middle) # don't provide slice, but index range
yield from mergeSortRec(middle, end)
left = arr[start:middle]
right = arr[middle:end]
a = 0
b = 0
c = start
while a < len(left) and b < len(right):
if left[a] < right[b]:
arr[c] = left[a]
a += 1
else:
arr[c] = right[b]
b += 1
c += 1
while a < len(left):
arr[c] = left[a]
a += 1
c += 1
while b < len(right):
arr[c] = right[b]
b += 1
c += 1
yield arr
yield from mergeSortRec(0, len(arr)) # call inner function with start/end arguments
for i in mergeSort([6,3,8,7,4,1,2,9,5,0]):
print(i)
For the example list, the output is the following:
[3, 6, 8, 7, 4, 1, 2, 9, 5, 0]
[3, 6, 8, 4, 7, 1, 2, 9, 5, 0]
[3, 6, 4, 7, 8, 1, 2, 9, 5, 0]
[3, 4, 6, 7, 8, 1, 2, 9, 5, 0]
[3, 4, 6, 7, 8, 1, 2, 9, 5, 0]
[3, 4, 6, 7, 8, 1, 2, 9, 0, 5]
[3, 4, 6, 7, 8, 1, 2, 0, 5, 9]
[3, 4, 6, 7, 8, 0, 1, 2, 5, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
You could decide to yield also the start/end indices, so that the consumer of the iterator knows where exactly the algorithm was manipulating the list. So then change:
yield arr
to:
yield arr, start, end
With that change, the output becomes:
([3, 6, 8, 7, 4, 1, 2, 9, 5, 0], 0, 2)
([3, 6, 8, 4, 7, 1, 2, 9, 5, 0], 3, 5)
([3, 6, 4, 7, 8, 1, 2, 9, 5, 0], 2, 5)
([3, 4, 6, 7, 8, 1, 2, 9, 5, 0], 0, 5)
([3, 4, 6, 7, 8, 1, 2, 9, 5, 0], 5, 7)
([3, 4, 6, 7, 8, 1, 2, 9, 0, 5], 8, 10)
([3, 4, 6, 7, 8, 1, 2, 0, 5, 9], 7, 10)
([3, 4, 6, 7, 8, 0, 1, 2, 5, 9], 5, 10)
([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 0, 10)
Maybe something like this:
def x(arr):
for i in mergeSort(arr):
yield i
def mergeSort(arr):
if len(arr) > 1:
middle = len(arr) // 2
left = arr[:middle]
right = arr[middle:]
mergeSort(left)
mergeSort(right)
a = 0
b = 0
c = 0
while a < len(left) and b < len(right):
if left[a] < right[b]:
arr[c] = left[a]
a += 1
else:
arr[c] = right[b]
b += 1
c += 1
while a < len(left):
arr[c] = left[a]
a += 1
c += 1
while b < len(right):
arr[c] = right[b]
b += 1
c += 1
return arr
# Entry point
generator = x([6,3,8,7,4,1,2,9,5,0])
print(next(generator)) # prints 0
print(next(generator)) # prints 1
# print the remaining elements
for i in generator:
print(i)
Output:
0
1
2
3
4
5
6
7
8
9
Note that a shorter recursive implementation of merge sort you could use could be the following:
def merge_sort(mylist):
if len(mylist) < 2:
return mylist
less = []
equal = []
greater = []
n = int(len(mylist)/2)
pivot = mylist[n]
for x in mylist:
if x < pivot:
less.append(x)
elif x == pivot:
equal.append(x)
elif x > pivot:
greater.append(x)
return merge_sort(less) + equal + merge_sort(greater)

building a simple Sudoku print in python

What i'm trying to do is write a code in python which will print a simple Sudoku (solved for now).
I started with a 4 on 4, but planing on 9 on 9 after that.
I managed to make the numbers to not repeat other numbers horizontal and vertical, the problem is how to make them not repeat other numbers within their "box".
Example:
4 3 2 1
3 2 1 4
1 4 3 2
2 1 4 3
Expected:
4 3 2 1
2 1 4 3
1 4 3 2
3 2 1 4
Code:
import random
# preforming 1st check if the giving number already exist in the list sq
# which is created in main
def chk1(num):
while num in sq:
num = random.randint(1,4)
return num
# preforming 2nd check if the giving number already exist in the current index
# of each list that is in sud which is created in main
def chk2(num, i, y):
x = 0
curr = 0
while x != i:
if num != sud[curr][y]:
x +=1
curr +=1
else:
num = random.randint(1,4)
x = 0
curr = 0
return num
# creating the structure of 4 lists in the list sud using the 1st & 2nd check
# each round a unique list is created and is appended to anther list.
def main():
global sq, sud
curry = 0
currx = 0
sq = []
sud = []
for i in range(4):
for y in range(4):
num = random.randint(1,4)
num = chk1(num)
if curry == 1 & currx == 1:
num = chk2(num, i, y)
sq.append(num)
if curry == 0:
curry +=1
sud.append(sq)
if currx == 0:
currx +=1
sq = []
return sud
# printing the final output of main function by line
for line in main():
print(line)
Thanks in advance
Your code may get stuck if it generates a partial set of incompatible numbers. Try this one - it uses recursion and steps back if fails to place another digit:
import numpy as np
def build_sudoku(sudoku=None, i=None):
if sudoku is None:
sudoku = np.zeros((9, 9), dtype=int)
i = 80
if i < 0:
return sudoku
s = sudoku.copy()
r, c = i // 9, i % 9
row, col = s[r, :], s[:, c]
square = g[r//3 * 3:r//3 * 3+3, c//3 * 3:c//3 * 3+3].flatten()
valid = [v for v in np.arange(1, 10) if v not in set([*row, *col, *square])]
np.random.shuffle(valid)
for v in valid:
s[r, c] = v
result = fill_one(s, i-1)
if result is not None:
return result
return None
build_sudoku()
array([[3, 1, 5, 8, 4, 2, 9, 7, 6],
[2, 8, 7, 5, 9, 6, 3, 4, 1],
[9, 4, 6, 1, 7, 3, 2, 8, 5],
[5, 6, 4, 7, 2, 8, 1, 9, 3],
[7, 9, 1, 3, 5, 4, 8, 6, 2],
[8, 2, 3, 6, 1, 9, 4, 5, 7],
[6, 3, 2, 9, 8, 7, 5, 1, 4],
[1, 7, 8, 4, 3, 5, 6, 2, 9],
[4, 5, 9, 2, 6, 1, 7, 3, 8]])
The problem you've presented is much nearer to the Magic Square problem then the actual sudoku (sum of rows, sum of columns + sum in small squares). Therefore, I am providing you example of magic square implementation example from GeeksforGeeks:
def generateSquare(n):
# 2-D array with all
# slots set to 0
magicSquare = [[0 for x in range(n)]
for y in range(n)]
# initialize position of 1
i = n / 2
j = n - 1
# Fill the magic square
# by placing values
num = 1
while num <= (n * n):
if i == -1 and j == n: # 3rd condition
j = n - 2
i = 0
else:
# next number goes out of
# right side of square
if j == n:
j = 0
# next number goes
# out of upper side
if i < 0:
i = n - 1
if magicSquare[int(i)][int(j)]: # 2nd condition
j = j - 2
i = i + 1
continue
else:
magicSquare[int(i)][int(j)] = num
num = num + 1
j = j + 1
i = i - 1 # 1st condition
# Printing magic square
print ("Magic Squre for n =", n)
print ("Sum of each row or column",
n * (n * n + 1) / 2, "\n")
for i in range(0, n):
for j in range(0, n):
print('%2d ' % (magicSquare[i][j]),
end = '')
# To display output
# in matrix form
if j == n - 1:
print()
n = 7
generateSquare(n)

how do i do round-robin in python 3

i have to do a rotation of a list. I get a sorted list and i have to get minimum of pairs and maximum of tree numbers in a permutation of this sorted list as an answear. It has to have different numbers sorted from lowest to highest. For example:
MyList=[1, 1, 1, 2, 2, 2, 3, 3, 3, 3]
and the output must be:
1 2 3
1 2 3
1 3
2 3
and for :
MyList=[1, 1, 1, 1, 1, 2, 3, 4, 5, 6]
and the output must be:
1 2
1 3
1 4
1 5
1 6
I saw i can do it with a method called round-robin but i don't know how.
Thank you for your help!
from itertools import cycle
A = [[1,2,3],[4,5,6],[7]]
B = [[8],[9,10,11],[12,13]]
for p in A:
max1 = len(p) if max1 <len(p) else max1
for p in B:
max1 = len(p) if max1 <len(p) else max1
i = len(A)
j = 0
C = []
list_num = cycle(k for k in range(i))
for x in list_num:
j += 1
if j == i*3:
break
if A[x]:
C.append(A[x].pop(0))
if B[x]:
C.append(B[x].pop(0))
Output:
[1, 8, 4, 9, 7, 12, 2, 5, 10, 13, 3, 6, 11]

How to replace K-values of list by skipping 9 from startend

I have a number lets make it a list s = [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
and I have k = 4
What I want is to replace 4-values of list s with number 9 which dont have number 9.
means at position 2 ,we have 9,so skip that and replace next one.
Output should be like: [9,9,9,9,9,2,7,3,6,8,4,1,9,0,0,3,6,8]
With this code I am unable to skip 9's in it:
x= [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
k = 4
def elements_replaced(lst, new_element, indices):
return [new_element if i in indices else e for i, e in enumerate(lst)]
output = elements_replaced(x,9,range(k))
print output
you can try:
>>> s = [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
>>> k = 4
>>> for index,number in enumerate(s):
if k > 0:
if number != 9:
s[index] = 9
k = k-1
else :
break
>>> s
[9, 9, 9, 9, 9, 2, 7, 3, 6, 8, 4, 1, 9, 0, 0, 3, 6, 8]
You can also use list comprehensions. This will get inefficient if your input list is large relative to the number of nines.
from itertools import chain, repeat
s = [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
nines = chain([9] * 4, repeat(None))
result = [x if x == 9 else next(nines) or x for x in s]
print(result)
# [9, 9, 9, 9, 9, 2, 7, 3, 6, 8, 4, 1, 9, 0, 0, 3, 6, 8]
x = [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
k = 4
a = 0
while k and a < len(x):
if x[a] != 9:
x[a] = 9
k -= 1
a += 1
x= [1,6,9,2,3,2,7,3,6,8,4,1,9,0,0,3,6,8]
k = 4
def elements_replaced(lst, new_element, indices):
for index, value in enumerate(lst):
if index in indices and value != new_element:
lst[index] = new_element
return lst
output = elements_replaced(x,9,range(k+1))
print (output)

Categories

Resources