How compare variable to Array[i] in Python - python

I am learning python, one the the question I have is how can check if variable x is equal to array[i]. I am trying to use divide and conquer to find element in array
x = 12
arr = [12,31,33]
middle = len(arr)//2
print ("Find",x)
print ("Middle ", arr[middle])
print ("Middle Left",arr[middle] +1)
print ("Middle Right", arr[middle] -1)
if x == arr[middle]:
print ("found it")
elif x == arr[middle] - 1 :
print ("found on left")
elif x == arr[middle] + 1:
print ("found on right")
else:
print("Not found")

if you want to find element at left/right based on index, you need to minus/add on index.
x = 12
arr = [12,31,33]
middle = len(arr)//2
print ("Find",x)
print ("Middle ", arr[middle])
print ("Middle Left",arr[middle + 1] )
print ("Middle Right", arr[middle -1])
if x == arr[middle]:
print ("found it")
elif x == arr[middle - 1] :
print ("found on left")
elif x == arr[middle + 1]:
print ("found on right")
else:

Unless your problem specifically says that you must use divide and conquer to do this, you could just use .index(x) to get its index - i.
So for your example:
x = 12
arr = [12,31,33]
then:
arr.index(x)
gives 0 for i (the index). This is much neater and unless you have a massive list, will be perfectly fast enough.
If it turns out you must write your own divide and conquer for this, then the place you are going wrong is when indexing from arr with arr[middle] and then adding and subtracting from that value. What you want to do instead, is index one further or one before with arr[middle - 1] or arr[middle + 1].
Hopefully you can implement these changes to your code yourself if you don't want to use the much easier .index().

How about creating a function like this?
arr = [12,31,33,31]
def position(array,key):
# find all entries
positions = [ind for ind,i in enumerate(array) if i==key]
# return No match if nothing is found
if not positions:
return "No match!"
# set mid to middle of array
mid = len(arr) / 2
# loop through all found elements and print
for i in positions:
if i < mid:
where = "left"
elif i > mid:
where = "right"
else:
where = "mid"
print("found {} on {}".format(key,where))
print(position(arr,31)) # 'found 31 on left \n found 31 on right'
print(position(arr,19)) # 'No match!'

Related

Neighbours of same sign exercise in Python - help needed

I have the following exercise.
Neighbours of same sign
Given a sequence of numbers, find and print the first adjacent elements which have the same sign. If there is no such pair, print NONE.
Please note that the output must be the same as indicated in the example.
Example
Input:
-1 2 -3 -4 -5 1 2
Output:
-3 -4
this is my code, but it does not work when I try to catch the case when the pairs are not the same sign, can someone help?
The code works fine, but when i add the ELSE things break down.
s = input()
my_list_str = s.split()
my_list = []
for beta in my_list_str:
my_list.append(int(beta))
for i in range(len(my_list)-1):
if my_list[i]>0 and my_list[i+1] >0:
print (my_list[i], end =' ')
print (my_list[i+1])
break
elif my_list[i]<0 and my_list[i+1] <0:
print (my_list[i], end =' ')
print (my_list[i+1])
break
else:
print ('NONE')
just add a found flag
s = input()
my_list_str = s.split()
my_list = []
for beta in my_list_str:
my_list.append(int(beta))
found=False
for i in range(len(my_list)-1):
if my_list[i]>0 and my_list[i+1] >0:
print (my_list[i], end =' ')
print (my_list[i+1])
found=True
break
elif my_list[i]<0 and my_list[i+1] <0:
print (my_list[i], end =' ')
print (my_list[i+1])
found=True
break
if not found:
print ('NONE')
you should check the else part once
I would suggest keeping track of the sign of the previous and current numbers and a found flag. For example like this:
list = [-1, 2, -3, 4, -5, 1]
prev_sign = -1
found = 0
for i in range(len(list)):
this_sign = list[i] < 0
if this_sign == prev_sign:
print("{} {}".format(list[i - 1], list[i]))
found = 1
break
prev_sign = this_sign
if not found:
print("NONE")
Or even more concise, the for loop could look like this:
for i in range(1, len(list)):
if (list[i] < 0) == (list[i - 1] < 0):
print("{} {}".format(list[i - 1], list[i]))
found = 1
break
One error I see with the code is the placement of the else statement inside the for-loop. In the existing code, if the first two elements have mismatched sign, then it will immediately print 'NONE' because it reaches that else statement, and will continue printing 'NONE' until it does find matching neighbors. I would rewrite your for-loop as follows:
found_pair = False
for i in range(len(my_list)-1):
if my_list[i] * my_list[i+1] > 0: # matching sign
found_pair = (my_list[i], my_list[i+1])
break
if found_pair:
print(found_pair[0], found_pair[1])
else:
print('NONE')
In the above code, the result must necessarily only print once after it's already finished the for-loop. If a pair is found, it is stored and we break, otherwise we exhaust the loop without ever assigning found_pair, leading 'NONE' to be printed only once at the end. Let me know if this doesn't work or if you have any questions!
David
Lots of suggestions for a found flag, but you don't need one. This is where the else on a for loop comes in:
lst = [-1, 2, -3, 4, -5, 1]
# zip lst with a slice of itself to get corresponding
# elements offset by 1 position
for a, b in zip(lst, lst[1:]):
if a * b > 0:
print(f"Found pair {a} {b}")
break
else:
print("NONE")
The else will only trigger if the for loop completes (isn't ended early by break)

list out of range in python adjacent numbers question

I have a question which is asking to compare 2 numbers in a list, specifically if the adjacent numbers are positive or negatives
However I am stuck on the first part of the question. My idea is to compare the first number using its index with the second number so i+1, but inevitably is goes out of range.
I am missing something here, help is appreciated.
my_list=[-1,2,-3,-4,-5,1,2]
for i in range(len(my_list)):
print (my_list[i])
print (my_list[i+1])
I have been working on it and this is the full questions
Given a sequence of numbers, find and print the first pair of adjacent elements which have the same sign. If there is no such pair, print NONE.
I'm not allowed to use zip in this case.
However I cannot do the last bit where it ask pro print none if no pairs are there
s = input()
my_list_str = s.split()
my_list = []
for beta in my_list_str:
my_list.append(int(beta))
for i in range(len(my_list)-1):
if my_list[i]>0 and my_list[i+1] >0:
print (my_list[i], end =' ')
print (my_list[i+1])
break
elif my_list[i]<0 and my_list[i+1] <0:
print (my_list[i], end =' ')
print (my_list[i+1])
break
Two points:
Most of the time it is considered "unpythonic" to use indices to iterate over a list
The for-loop has the option to close with an else-condition: The code in the else condition is only executed if the for-loop isn't left via a break
So, you could try the following:
for first, second in zip(my_list[:-1], my_list[1:]):
if (first < 0 and second < 0) or (first > 0 and second > 0):
print(first, second)
break
else:
print("NONE")
EDIT: If you need to use indices, then you could do:
for i in range(len(my_list) - 1):
first, second = my_list[i], my_list[i+1]
if (first < 0 and second < 0) or (first > 0 and second > 0):
print(first, second)
break
else:
print("NONE")
If you are not allowed to use the else-option of the for-loop, then you could try:
found = False
for i in range(len(my_list) - 1):
first, second = my_list[i], my_list[i+1]
if (first < 0 and second < 0) or (first > 0 and second > 0):
print(first, second)
found = True
break
if not found:
print("NONE")
Because you want to print (my_list[i+1])
Your list size is 7 -> when i = 6 -> [i+1] = 7
=> my_list[7] <- out of range
You can do it like below:
my_list=[-1,2,-3,-4,-5,1,2]
list_len = len(my_list)
for i in range(list_len-1):
print(f'comparison {i+1}')
print (my_list[i])
print (my_list[i+1])
my_list=[-1,2,-3,-4,-5,1,2]
list_len = len(my_list)
x = 7 # any positive number
for i in range(x):
if i < list_len:
print (my_list[i])
if i+1 < list_len:
print (my_list[i+1])

How to obtain the closest, lowest palindrome of a given number

I am trying to modify the answer to give me the closest lowest palindrome number.
I have tried modifying the answer to this:
def lowest(n):
s = str(n + 1)
l = len(s)
if s[:l//2][::-1] < s[(l+1)//2:]:
head = str(int(s[:(l+1)//2]))
else:
head = s[:(l+1)//2]
print int(head + head[:l//2][::-1])
But for the number 1000, it still returns 1001. What am i doing wrong?
In case you are looking for the previous palindrome, you have invert a couple of signals in the linked answer and add an edge-case exception (for 10^k+1, for all even k>0)
def prev_palindrome(n):
s = str(n - 1)
l = len(s)
if s[:l//2][::-1] > s[(l+1)//2:]:
head = str(int(s[:(l+1)//2])-1)
else:
head = s[:(l+1)//2]
if len(head) < l/2:
return int(head + '9' + head[:l//2][::-1]) #edge case
else:
return int(head + head[:l//2][::-1])
If you want the closest you can try:
nxt = next_palindrome(n)
prv = prev_palindrome(n)
if abs(prv-n) <= abs(nxt-n):
print prv
else:
print nxt
Please note that both next_palindrome and prev_palindrome returns are strictly higher/lower than n.

Binary Search python 3.5

I'm trying to write binary search in python 3.5 but it wont work I'm not sure why.
def binarySearch(alist, value):
first = 0
last = len(alist)-1
midpoint = (last//2)
while binarySearch:
if value == alist[midpoint]:
return True and print ("found")
else:
if value < midpoint:
last = midpoint-1
else:
if value > midpoint:
first = midpoint+1
binarySearch([1,2,3,4,5,6,7,8],3)
if I put value as 4 it displays found, if I put anything else nothing happens and its stuck running doing nothing.
Thanks for your help.
User1915011 beat me to my answer. In line with his answer and #wim's comment, I have made the following changes your binarySearch method.
Changed the loop to use the found variable
Added an additional assignment to midpoint inside the loop
Ensure the loop terminates by adding first<=last
Return found after the while loop to indicate success or failure.
def binarySearch(alist, value):
first = 0
last = len(alist)-1
found = False
while first<=last and not found:
midpoint = (first + last)//2
if value == alist[midpoint]:
found = True
else:
if value < alist[midpoint]:
last = midpoint-1
else:
if value > midpoint:
first = midpoint+1
return found
if binarySearch([1,2,3,4,5,6,7,8],3):
print "found"
Your looping condition is just wrong while binarySearch?
You change value of midpoint only once instead you should be changing it every loop iteration.
You compare value with index (midpoint) and should be comparing with
list value (alist[midpoint])
This is wrong: return True and print ("found") it will always return None.
Here is a detailed explanation how it works:
def binarySearch(array, i):
## Binary search is the algorithm which is used to search an element in a sorted array
## The time complexity of the binary search is O(log n)
## Which means that in an array of length(2^(n-1)) elements we need to look at only n elements
## That is why we say that binary search algorithm runs in logarithmic time, which is much faster than linear time
start = 0
last = len(array)-1
result = False
count = 0 ## to debug
print("\n******************************************************************\n")
while(start <= last and not result):
## Debugger Begin
mid = 0
print("Loop number: ", count)
print("Start element: ", array[start], " Position of Start Element: ", start)
print("Last element: ", array[last], " Position of Last Element: ", last)
## Debugger End
mid = (start + last)//2 ## '//' indicates the floor division(ignores the value after the period)
if(array[mid] == i):
print("***Mid***")
result = True;
else:
if(i < array[mid]):
print("***The value of the item:",i," we are searching for is LESS than the current middle element***")
last = mid - 1
else:
print("***The value of the item:",i," we are searching for is GREATER than the current middle element***")
start = mid + 1
## Debugger
count = count+1
print("Mid element: ", array[mid], " Position of Mid Element: ", mid, "\n")
## Debugger
print("******************************************************************")
if(result == True):
print("\nThe element:",i ,"is in the array")
else:
print("\nItem is not in the array")
return result
## Array you want to search
array = [9, 11, 12, 21, 23, 34, 45, 49, 65, 98]
## Item you want to search in the array
i = 21
print("Searching the element: ",i , "\nIn the Array: ", array)
print("Length of the array is: ", len(array))
## Binary Search
binarySearch(array, i)
binary converters are also cool
num = int(input('please enter your number: '))
list = []
for i in (128, 64, 32, 16, 8, 4, 2, 1):
if num >= i:
list.append(1)
num = num-i
else:
list.append(0)
print(list)

Python random horserace

I'm trying to create a function where it takes in a list I give it of my predicted out come of the race and my bet. So for example, i could predict the outcome [1,3,4,2] where horse 1 would be in 1st, horse 3, in 2nd etc... This prediction would be compared to a randomized/ shuffled list a. I have set up a couple of if statements to try and compare both items in each list to each other but it ends up giving me all my placements were correct even if they were not. I am stuck!!!
def horseRace(gList,bet):
import random
a = [1,2,3,4]
random.shuffle(a,random.random)
i = 0
x = 0
while i < len(gList):
if gList[i] == a[0]:
x = x + 1
if gList[i] == a[1]:
x = x + 1
if gList[i] == a[2]:
x = x + 1
if gList[i] == a[3]:
x = x + 1
else:
x = x
i = i + 1
print(x)
print(a)
print(gList)
if x == 4:
money = bet*2
print("You guessed 4 position(s) correctly and won $ %d !"%money)
if x == 0:
money = 0.00
print("You guessed no position(s) correctly and won $ %d !"%money)
if x == 1:
money = bet
print("You guessed 1 position(s) correctly and won $ %d !"%money)
if x == 2:
money = bet
print("You guessed 2 position(s) correctly and won $ %d !"%money)
if x == 3:
money = bet
print("You guessed 3 position(s) correctly and won $ %d !"%money)
your while loop should look more like this
while i < len(gList):
if gList[i] == a[i]:
x = x + 1
else:
x = x
i = i + 1
That way, you're comparing the value in cell position i in gList to the value in the same cell position in a. Right now, your code essentially says to add one to x as long as the value gList[i] is equal to any of:
a[1], a[2], a[3], a[4]
which of course it wil be
Consider using a for loop to count the number of correct guess. Assuming gList and a are the same size:
for (gList_i, a_i) in zip(gList, a):
if g_List_i == a_i:
x += 1
Also, maybe a function for the message, that would take the number of positions guessed correctly as an input.
def win_message(nwins):
if nwins == 0:
money = 0
elif nwins == 4:
money = 2*bet
else: # For nwins equals 2 or 3
money = bet
if nwins > 1:
plural = "s"
else:
plural = ""
print("You guessed %d position%s correctly and won $ %d !" % (nwins, plural, money))
You can do it in more Pythonic way, and count the number of correct guess in one line:
nCorrect = len(filter(lambda x: x[0]==x[1], zip(randomized,gList)))
Here is the full code, I'll explain in the bottom:
import random
def horseRace(gList,bet):
randomized = [1,2,3,4]
random.shuffle(randomized,random.random)
nCorrect = len(filter(lambda x: x[0]==x[1], zip(randomized,gList)))
def getResult(bet,nCorrect):
if nCorrect==0:
return 0
elif nCorrect==4:
return 2*bet
else:
return bet
outcome = getResult(bet,nCorrect)
print 'Randomized order: ' + randomized
print 'Your guess: ' + bet
print 'You guessed %d position(s) correctly and won $%d!' % (nCorrect,outcome)
You should change the getResult method depending on how you want to calculate your outcome.
I'll explain this line:
nCorrect = len(filter(lambda x: x[0]==x[1], zip(randomized,gList)))
So, first, it'll combine the randomized and gList into a list of tuples:
gList = [1,2,3,4]
randomized = [1,3,2,4]
print zip(randomized,gList)
[(1,1), (2,3), (3,2), (4,4)]
Then the filter will take only elements that match the condition. In this case the condition is that the first element of the tuple equals the second element of the tuple (x[0]==x[1])
print filter(lambda x: x[0]==x[1], zip(randomized,gList))
[(1,1), (4,4)]
Then we return the length of the array, which is the number of correct guess.

Categories

Resources