I wonder why range slice is not working properly in python - python

I made code as follows to execute binary search in sorted list for my study.
Code to find which number of values 'x' are in the list 'ss'.
Problem is, it should execute as reducing range of list, but it doesn't work.
def bin_search(ss, x):
return bin_search_range( ss, x, range(len(ss)) )
def bin_search_range(ss, x, r):
print(r)
print("len(r)", len(r))
if len(r) > 0:
mid = ((r.start) + (r.stop)) // 2
print("start", r.start)
print("stop", r.stop)
print("mid", mid)
print("x", x," ss[mid]", ss[mid])
if x == ss[mid]:
print("----[x = ss[mid]----")
return print("answer", mid)
elif x < ss[mid]:
print("----[x < ss[mid]]----")
return bin_search_range(ss, x, r[:mid])
else:
print("----[x > ss[mid]]----")
return bin_search_range(ss, x, r[mid+1:])
else: # len(r) == 0
return None
#Except "return print("answer", mid)", I just wrote down the rest of the output to know the progress.
In the manner of recursion, I repeated slicing the list through mid(which is median of list).
Until the median and 'x' match.
Below median, in other words left of median. There was no problem finding the value in.
There was a problem when finding the value on the right side of the median.
Below are the results of the execution of bin_search ([1, 2, 3, 4, 5, 6, 7], 5).
[Execution Result]
bin_search ([1, 2, 3, 4, 5, 6, 7], 5)
range(0, 7)
len(r) 7
start 0
stop 7
mid 3
x 5 ss[mid] 4
----[x > ss[mid]]----
range(4, 7)
len(r) 3
start 4
stop 7
mid 5
x 5 ss[mid] 6
----[x < ss[mid]]----
range(4, 7)
len(r) 3
start 4
stop 7
mid 5
x 5 ss[mid] 6
.
.
.
#RecursionError: maximum recursion depth exceeded while calling a Python object
Since x = 5, ss[mid] = 6, shouldn't the range of range be reduced to (4,5)?
Just like my prediction below
[Expected Result]
range(0, 7)
len(r) 7
start 0
stop 7
mid 3
x 5 ss[mid] 4
----[x > ss[mid]]----
range(4, 7)
len(r) 3
start 4
stop 7
mid 5
x 5 ss[mid] 6
----[x < ss[mid]]----
range(4, 5)
len(r) 3
start 4
stop 5
mid 4
x 5 ss[mid] 5
----[x = ss[mid]----
answer 4
Besides, when len(r) becomes 0, I thought I would print None, but I can't get any output.
Doesn't None print out when all the runs are over? I thought None would be printed because there was no range to search anymore, but I don't know why it couldn't be printed.
No matter how hard I think about it, I don't know if there's a problem with the code. If you know anything about it, I'd appreciate it if you could help me.

Related

smallest difference of a sequence of a list

I am new to python. I am working on program to find the smallest difference of sequence of element. for example I have a input A=[7,8,9],M=3. Difference of all elements of sequence should be in this form S=(|7-7|,|7-8|,|7-9|,|8-7|,|8-8|,|8-9|,|9-7|,|9-8|,|9-9|).S=[0,1,2,1,0,1,2,1,0]. we get 9 different element in list. So the output of M smallest element of s is 0. since 0 is 3 smallest element. Does anyone know what I am doing wrong
enter code here
F=[]
A = [7, 8, 9]
M = 3
S=0
for i in range(len(A)):
for j in range(len(A)):
S = S + (abs(A[i] - A[j]))
t = F.append(S)
t.sort()
for k in range(len(t)):
if k == M:
break
print(t[k])
The right code is here:
A = [7, 8, 9]
M = 3
S=[] #
for i in range(len(A)):
for j in range(len(A)):
S.append(abs(A[i] - A[j]))
# t = F.append(S) # t is not defined before
S.sort()
print(S[M-1]) # S is sorted
Ask me if you have any questions.
Here, you can try this:
x=[7,8,9]
y=[abs(j-k) for j in x for k in x]
print(y)
What you are doing is basically a nested loop.
Here is how it goes:
for i in x:
for j in x:
#==== This is what your program needs =====
i=7
|__j=7
|__j=8
|__j=9
i=8
|__j=7
|__j=8
|__j=9
i=9
|__j=7
|__j=8
|__j=9
Now if you print the how it looks like:
x=[7,8,9]
for i in x:
print(f'The main number is {i}.')
for j in x:
print(f"{i} - {j} = {abs(i-j)}")
And that does exactly what you need
The main number is 7.
7 - 7 = 0
7 - 8 = 1
7 - 9 = 2
The main number is 8.
8 - 7 = 1
8 - 8 = 0
8 - 9 = 1
The main number is 9.
9 - 7 = 2
9 - 8 = 1
9 - 9 = 0

How do I get the left diagonal elements of a matrix/grid from a specific element?

I have an 8x8 grid of different numbers, and I want to get the elements of the diagonal that contains a given starting position. Here is an example
l = [[str(randint(1,9)) for i in range(8)] for n in range(8)]
>> [
[1 5 2 8 6 9 6 8]
[2 2 2 2 8 2 2 1]
[9 5 9 6 8 2 7 2]
[2 8 8 6 4 1 8 1]
[2 5 5 5 4 4 7 9]
[3 9 8 8 9 4 1 1]
[8 9 2 4 2 8 4 3]
[4 4 7 8 7 5 3 6]
]
How would I go about getting the left diagonal from the position x=4 and y=3 (so 4th list and 5th element in that list)? So The diagonal I would want would be [8,2,2,4,5,8,9,4].
I essentially asked this question yesterday, and a user was able to help me with getting the right diagonal with this code:
def rdiagonal(m, x, y):
#x
row = max((y - x, 0))
#y
col = max((x - y, 0))
while row < len(m) and col < len(m[row]):
yield m[row][col]
row += 1
col += 1
I tried to change that code to get the left diagonal also, but could not figure it out. What changes would I need to make to get the left diagonal?
First of all, note that in the right diagonal, i=j, so you don't need two variables for row and col, as they'll always be equal along the main diagonal.
For the left one, notice that in this case j=l-i, where l=length(arr) is the length of your rows. Thus the following code will do:
def leftdiagonal(arr):
k =[]
dim = len(arr)-1
for i in range(dim+1):
k.append(arr[i][dim-i])
return(k)
If you think about it like a graph on 2D plane. Row is the y and column is the x. However, python definition of row index increases downward, so 'y' is flipped. This means the origin is on upper left corner and 'y' increases as it goes down.
This means 2 things:
You can flip the rows of your list and you can use the function you already have
Or you can build a new function without touching the list. Logic is below.
'y' being flipped means the diagonal you want is essentially the following function
y = c - x
And finding c would allow you to find the diagonal. Naturally,
c = x + y
So to find the rightmost col or col with largest index,
rightmost_row = min(len(m)-1, c)
To find the lowest row, observe
x = c - y
So
lowest_row = c - rightmost_row
Then, you can navigate from top right to bottom left. Your current code moves from top left corner toward bottom right.
The code below gets you left diagonal.
def ldiagonal(m, x, y):
#c
c = x + y
#x
col = min((c, len(m)-1))
#y
row = c - col
while col >= 0 and row < len(m[row]):
yield m[row][col]
col -= 1
row += 1
Hope these can get you started.
To start from any point:
def ldiagonal(m, x, y):
while y >= 0 and x < len(m):
yield m[x][y]
x += 1
y -= 1
print(list(ldiagonal(m, 0, 0))) #=> [1]
print(list(ldiagonal(m, 0, 7))) #=> [8, 2, 2, 4, 5, 8, 9, 4] # it's the main
print(list(ldiagonal(m, 4, 4))) #=> [4, 8, 2, 4]
print(list(ldiagonal(m, 7, 7))) #=> [6]

Compute the last (decimal) digit of x1 ^ (x2 ^ (x3 ^ (... ^ xn))) [duplicate]

This question already has answers here:
Last digit of power list
(2 answers)
Closed 4 years ago.
I need to find the unit digit of x1 ^ (x2 ^ (x3 ^ (... ^ xn))) from integers passed into the function as a list.
For example the input [3, 4, 2] would return 1 because 3 ^ (4 ^ 2) = 3 ^ 16 = 43046721 the last digit of which is 1.
The function needs to be efficient as possible because obviously trying to calculate 767456 ^ 981242 is not very quick.
I have tried a few methods but I think the best way to solve this is using sequences. For example any number ending in a 1, when raised to a power, will always end in 1. For 2, the resulting number will end in either 2, 4, 6 or 8.
If a number is raised to a power, the last digit of the resulting number will follow a pattern based on the last digit of the exponent:
1: Sequence is 1
2: Sequence is 2, 4, 8, 6
3: Sequence is 3, 9, 7, 1
4: Sequence is 4, 6
5: Sequence is 5
6: Sequence is 6
7: Sequence is 7, 9, 3, 1
8: Sequence is 8, 4, 2, 6
9: Sequence is 9, 1
0: Sequence is 0
I think the easiest way to calculate the overall last digit is to work backwards through the list and calculate the last digit of each calculation one at a time until I get back to the start but I am not sure how to do this?
If anyone could help or suggest another method that is equally or more efficient than that would be appreciated.
I have this code so far but it does not work for very large numbers
def last_digit(lst):
if lst == []:
return 1
total = lst[len(lst)-2] ** lst[len(lst)-1]
for n in reversed(range(len(lst)-2)):
total = pow(lst[n], total)
return total%10
Edit: 0 ^ 0 should be assumed to be 1
x^n = x^(n%4) because the last digit always has a period of 4.
x ^2 ^3 ^4 ^5
1 1 1 1 1
2 4 8 6 2
3 9 7 1 3
4 6 4 6 4
5 5 5 5 5
6 6 6 6 6
7 9 3 1 7
8 4 2 6 8
9 1 9 1 9
As you can see, all 9 digits have a period of 4 so we can use %4 to make calculations easier.
There's also a pattern if we do this %4.
x ^0 ^1 ^2 ^3 ^4 ^5 ^6 ^7 ^8 ^9
1 1 1 1 1 1 1 1 1 1 1
2 1 2 0 0 0 0 0 0 0 0
3 1 3 1 3 1 3 1 3 1 3
4 1 0 0 0 0 0 0 0 0 0
5 1 1 1 1 1 1 1 1 1 1 (all %4)
6 1 2 0 0 0 0 0 0 0 0
7 1 3 1 3 1 3 1 3 1 3
8 1 0 0 0 0 0 0 0 0 0
9 1 1 1 1 1 1 1 1 1 1
As shown, there is a pattern for each x when n>1. Therefore, you can see that (x^n)%4 = (x^(n+4k))%4 when n>1. We can then prevent the issues that arises from n=0 and n=1 by adding 4 to n. This is because, if (x^n)%4 = (x^(n+4k))%4, then (x^n)%4 = (x^(n%4+4))%4 as well.
powers = [3, 9, 7, 1]
lastDigit = 1
for i in range(len(powers) - 1, -1, -1):
if lastDigit == 0:
lastDigit = 1
elif lastDigit == 1:
lastDigit = powers[i]
else:
lastDigit = powers[i]**(lastDigit%4+4)
print(lastDigit%10)
This is more math than programming. Notice that all the sequences you listed has length either 1, 2, or 4. More precisely, x^4 always ends with either 0, 1, 5, 6, as does x^(4k). So if you know x^(m mod 4) mod 10, you know x^m mod 10.
Now, to compute x2^(x3^(...^xn)) mod 4. The story is very similar, x^2 mod 4 is ether 0 if x=2k or 1 if x=2k+1 (why?). So
is 0 if x2 == 0
is 1 if x2 > 0 and x3 == 0
if x2 is even, then it is either 2 or 0 with 2 occurs only when x2 mod 4 == 2 and (x3==1 or (any x4,...xn == 0) ).
if x2 is odd, then x2^2 mod 4 == 1, so we get 1 if x3 is even else x2 mod 4.
Enough math, let's talk coding. There might be corner cases that I haven't cover, but it's should work for most cases.
def last_digit(lst):
if len(lst) == 0:
return 1
x = lst[0] % 10
if len(lst) == 1:
return x
# these number never change
if x in [0,1,5,6]:
return x
# now we care for x[1] ^ 4:
x1 = x[1] % 4
# only x[0] and x[1]
if len(lst) == 2 or x1==0:
return x[0] ** x1 % 10
# now that x[2] comes to the picture
if x1 % 2: # == 1
x1_pow_x2 = x1 if (x[2]%2) else 1
else:
x1_pow_x2 = 2 if (x1==2 and x[2]%2 == 1) else 0
# we almost done:
ret = x ** x1_pow_x2 % 10
# now, there's a catch here, if x[1]^(x[2]^...^x[n-1]) >= 4,
# we need to multiply ret with the last digit of x ** 4
if x[1] >=4 or (x[1] > 1 and x[2] > 1):
ret = (ret * x**4) % 10
return ret
Working off of your sequences idea and fleshing it out, you'd want to create a dictionary that can map all relevant sequences.
mapping = {}
for i in range(1, 10):
mapping[i] = [i]
last_digit = i
while True:
last_digit *= i
last_digit = last_digit%10
if last_digit in mapping[i]:
break
else:
mapping[i].append(last_digit)
print(mapping)
This produces Output: mapping
{1: [1],
2: [2, 4, 8, 6],
3: [3, 9, 7, 1],
4: [4, 6],
5: [5],
6: [6],
7: [7, 9, 3, 1],
8: [8, 4, 2, 6],
9: [9, 1]}
Now the real logic can start, The key takeaway is that the pattern repeats itself after the sequence is completed. So, it does not matter how big the power is, if you just use a modulo and figure out which position of the sequence it should occupy.
def last_digit_func(lst, mapping):
if lst == []: #taken from OP
return 1
last_digit = lst[0] % 10
if 0 in lst[1:]: #edge case 0 as a power
return 1
if last_digit == 0: #edge case 0 at start
return last_digit
for current_power in lst[1:]:
if len(mapping[last_digit]) == 1:
return last_digit
ind = current_power % len(mapping[last_digit])
ind -= 1 #zero indexing, but powers start from 1.
last_digit = mapping[last_digit][ind]
return last_digit
test1 = [3, 4, 2]
print(last_digit_func(test1, mapping)) #prints 1
I verified this by calculating the powers in python.
test2 = [767456 , 981242]
print(last_digit_func(test2, mapping)) #prints 6
And i tried to verify this by running it in python....i now have instant regrets and my program is still trying to solve it out. Oh well :)

Array Of Number And Finding SubArray

Input = 5 4 5 5 6 7 8 8 8 7 6
In This Input, The longest subarray is [6, 10] where maximum=8 and minimum are 7 and difference is 1. Difference Should be Less And Equal To 1.
a subarray such that the difference between the minimum and the maximum value in that range is at most 1
Output Should Be 7 8 8 8 7
Please Suggest Me How To Code?
#THIS IS MY CODE
n = int(input())
data = []
for _ in range(n):
data.append(int(input()))
for i in range(0,n):
maxi = max(data[i+1:])
mini = min(data[i+1:])
diff = maxi - mini
if diff <= 1:
print(data[i:])
l = len(data[i:])
print(l)
break
Here is a naive solution. Make every possible sub-list and filter out those that meet your condition.
import numpy as np
a = [5,4,5,5,6,7,8,8,8,7,6]
max_diff = 1
sub_arrays = [x for x in [a[i:j] for i in range(len(a)) for j in range(i+1, len(a))] if (max(x)-min(x) <= max_diff)]
max_sub_array = sub_arrays[np.argmax([len(sa) for sa in sub_arrays])]
On your sample input, the output is:
[7, 8, 8, 8, 7]

Python Looping Random numbers

What I've got to do is get to print out as 5 4 3 2 1
then 4 3 2 1 under that then 3 2 1 and so on, right now all I have is the first line so i'll get 5 4 3 2 1 or 6 5 4 3 2 1 but I can't seem to get it right when trying to get it to continue until it reaches 1
from random import choice
i=choice([5,6,7,8,9,10])
while i:
print(i, end=" ")
i -= 1
if(i <1):
break
A compact approach:
import random as rnd
length = rnd.choice([5, 6, 7, 8, 9, 10])
lst = [str(x) for x in range(length, 0, -1)]
while lst:
print(" ".join(lst))
lst.pop(0)
Replace range with xrange if you are using Python 2.7.
You need two loops, one to do the initial countdown (5, 4, 3, 2, 1), the other to loop through each of the lists you need to produce. For example:
from random import choice
i=choice([5,6,7,8,9,10])
for j in [*range(i,0,-1)]:
for k in [*range(j,0,-1)]:
print(k, end=" ")
print('')
You can try this.
from random import choice
x = choice([5,6,7,8,9,10])
while x > 0:
y = x
while y > 0:
print y,
y = y-1
print "\n"
x = x-1

Categories

Resources