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)
Related
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])
I'm a beginner programmer and I wanted to make my own binary search algorithm from scratch without any help. It's safe to say it's not going well. I was hoping someone could find the error in my code. I fixed a few issues, but now I've ran into the issue where if can't find values greater than the middle index, and it is not ending once it reaches a single value not equal to the target.
import random
userInput = 100
numbers = []
for i in range(100):
numbers.append(random.randint(0, 100))
#Adding 100 to use as a test
numbers.append(100)
numbers.sort()
print(numbers)
def binarySearch(list, target):
midIndex = int(len(list)/2)
midValue = list[midIndex]
if midValue == target:
print("We found " + str(target))
elif target > midValue:
newList = numbers[midIndex:]
binarySearch(newList, target)
elif target < midValue:
newList = numbers[:midIndex]
binarySearch(newList, target)
elif len(list) == 1 and list[0] != target:
print(target + " is not in the list")
else:
print("It's not in the list")
binarySearch(numbers, userInput)
There are two main issues with your code:
mid is being used to represent both an index and a value.
The end of binarySearch() is never reached.
Issue #1: mid
When creating newList using a slice of list, you are using mid as an index:
elif target > mid:
newList = numbers[mid:]
However, mid is not an index. It is the value in the middle of list:
mid = list[int(len(list)/2)]
Try using two variables:
midIndex = int(len(list)/2)
midValue = list[midIndex]
Issue #2: binarySearch()
binarySearch() never reaches the final elif to see if target is not in the list.
The final elif is only reached after checking the following conditions:
if midValue == target:
...
elif target > midValue:
...
elif target < midValue:
...
Clearly, if midValue and target are two numbers, one of these comparisons must return True.
Because of the order of the checks performed, binarySearch() never ends up getting to this section:
elif len(list) == 1 and list[0] != target:
...
To fix this issue, try rearranging your if statements so that binarySearch() reaches this part of the code.
I'm struggling to understand where the error is in this code:
def arr_sort_binsearch(ar):
ar.sort()
first = 0
last = len(ar)-1
found = False
item = 8
for num in ar:
while first<=last and not found:
midpoint = (first + last)//2
if ar[midpoint] + num == item:
found = True
else:
if item < ar[midpoint]:
last = midpoint-1
else:
first = midpoint+1
print("{} and {} is: {}".format(num, ar[num], item))
ar = [1,3,5,7]
arr_sort_binsearch(ar)
I'm getting an exception that says my index is out of range. I understand the theory of what an index overflow is it's just that I can't find it in my code.
the error is in this statement i think:
print("{} and {} is: {}".format(num, ar[num], item))
num should not be an argument in ar
cheers
If you try to write a binary search, your code is incorrect.
1, answer your question, why IndexError: list index out of range:
the code for loop over the input list ar as num, and at last print, the element will be the index of ar[num], this raise the error, eg:
you have ar=[1,2,3,4,5,8,9,11,6], when loop to 9, the printtry to use ar[9], but there is only 9 element in the list ar, exceed the maximum index 8, this will raise IndexError: list index out of range.
2, your binary search can be amended like this:
def arr_sort_binsearch(ar,item):
ar.sort()
first = 0
last = len(ar)-1
found = False
while first<=last and not found:
midpoint = (first + last)//2
if ar[midpoint] == item:
found = True
else:
if item < ar[midpoint]:
last = midpoint-1
else:
first = midpoint+1
return found
This will return the True or False, if you call function:
arr_sort_binsearch([1,2,3,4,5,8,9,11,6],12) Return False
arr_sort_binsearch([1,2,3,4,5,8,9,11,6],8) Return True
I am new to python and we were given an assignment to create a linear search program that does not use "in" or index. The program compiles but says that every number I input is not in the list. I also have to do the same thing for a binary search but I'm doing things one at a time ha. Any help is appreciated!
PS: How could I show what index it is in without using the "index" function?
def linearSearch(intList,target):
found = False
position = 0
while position < len(intList) and not found:
if intList[position] == target:
found = True
position = position + 1
return found
linearList = [3,5,9,7,6,12,15,9,1]
numInput = input("What number are you looking for? ")
numFound = linearSearch(linearList, numInput)
if numFound:
print("The number is in index: ")
else:
print("The number is not in the list")
1) Start position = -1
2) return position
3) You want to position+=1 before if intList[position] == target: and you want to break when you do find the element. You then don't need found
Something is found when linearSearch(linearList, numInput) > 0
Then, your code just doesn't work because the list contains ints whereas input will always return a string. You must use int(input(".."))
This method uses list comprehension, and it will account for any duplicates in the list as well. It assigns a list of index/indices where the key occurs in the list. Read more about list comprehension here.
l = [1, 2, 3, 4, 4, 6]
el = 4
search = [i for i in range(len(l)) if el==l[i]]
print(search)
output:
[3, 4]
alternatively,
def LinSearch(target, intList):
search = [i for i in range(len(intList)) if target==intList[i]]
return search
def linearSearch(intList,target):
#print (target)
found = False
position = 0
while position < len(intList):
#print(intList[position])
if intList[position] == target:
found = True
break
position = position + 1
return found
linearList = [3,5,9,7,6,12,15,9,1]
numInput = int(input("What number are you looking for? "))
numFound = linearSearch(linearList,numInput)
if numFound:
print("The number is in index: ")
else:
print("The number is not in the list")
Please take care of type conversion...
Linear Search :
// funtion which rturns true if item found inside list.
def linearSearch(list, value):
for i in range(len(list)):
if i == value:
return True
// Call above function pass list of values and item to search
list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
item = 10
print(linearSearch(list, item)) // item to search
def target(list,num):
for x in list:
if x == str(num):
print("match found:"+x)
break
else:
print('no match found')
list1 = ['6','4','7','9','0','2','3','1']
inp = input('Enter number to search:')
target(list1,inp)
def linear_search(list, key):
for i, item in enumerate(list):
if item == key:
return i
return -1
print(linear_search([4,5,2,7,1,8],7))
#If key is in the list returns its position in the list, otherwise returns -1.
n=int(input("Enter the number:"))
list,n=[10,11,12,13,14,15],n
if n in list:
print("Element found at",list.index(n))
else:
print("Not Found")
Advice: In python index starts from 0. To start from 1 format the code like this: list.index(n)+1
def linearSearch(array,k):
flag = False
position = 0
while position < len(intList) and not flag:
if array[position] == k:
flag = True
else:
position += 1
return position
array = [3,5,9,7,6,12,15,9,1]
numInput = int(input("What number are you looking for? "))
numFound = linearSearch(linearList,numInput)
if numFound:
print("The number is in index: ")
else:
print("The number is not in the list")
I am trying to perform a binary search on a list in python. List is created using command line arguments. User inputs the number he wants to look for in the array and he is returned the index of the element. For some reason, the program only outputs 1 and None. Code is below.
Any help is extremely appreciated.
import sys
def search(list, target):
min = 0
max = len(list)-1
avg = (min+max)/2
while (min < max):
if (list[avg] == target):
return avg
elif (list[avg] < target):
return search(list[avg+1:], target)
else:
return search(list[:avg-1], target)
print "The location of the number in the array is", avg
# The command line argument will create a list of strings
# This list cannot be used for numeric comparisions
# This list has to be converted into a list of ints
def main():
number = input("Please enter a number you want to search in the array !")
index = int(number)
list = []
for x in sys.argv[1:]:
list.append(int(x))
print "The list to search from", list
print(search(list, index))
if __name__ == '__main__':
main()
CL :
Anuvrats-MacBook-Air:Python anuvrattiku$ python binary_search.py 1 3 4 6 8 9 12 14 16 17 27 33 45 51 53 63 69 70
Please enter a number you want to search in the array !69
The list to search from [1, 3, 4, 6, 8, 9, 12, 14, 16, 17, 27, 33, 45, 51, 53, 63, 69, 70]
0
Anuvrats-MacBook-Air:Python anuvrattiku$
In Python2 and Python3 you can use bisect as written in the comments.
Replace your search with the following
from bisect import bisect_left
def search(alist, item):
'Locate the leftmost value exactly equal to item'
i = bisect_left(alist, item)
if i != len(alist) and alist[i] == item:
return i
raise ValueError
alist = [1,2,7,8,234,5,9,45,65,34,23,12]
x = 5
alist.sort() # bisect only works on sorted lists
print(search(alist, x)) # prints 2 as 5 is on position 2 in the sorted list
Also, the AS SortedCollection (Python recipe) could be useful.
The following code (from here) performs the binary search and returns position and if the item was found at all.
def binarySearch(alist, item):
first = 0
last = len(alist)-1
found = False
while first<=last and not found:
pos = 0
midpoint = (first + last)//2
if alist[midpoint] == item:
pos = midpoint
found = True
else:
if item < alist[midpoint]:
last = midpoint-1
else:
first = midpoint+1
return (pos, found)
Will return (2, True) if used in the example above.
Well, there are some little mistakes in your code. To find them, you should either use a debugger, or at least add traces to understand what happens. Here is your original code with traces that make the problems self evident:
def search(list, target):
min = 0
max = len(list)-1
avg = (min+max)/2
print list, target, avg
...
You can immediately see that:
you search in a sub array that skips avg-1 when you are below avg
as you search in a sub array you will get the index in that subarray
The fixes are now trivial:
elif (list[avg] < target):
return avg + 1 + search(list[avg+1:], target) # add the offset
else:
return search(list[:avg], target) # sublist ends below the upper limit
That's not all, when you end the loop with min == max, you do not return anything (meaning you return None). And last but not least never use a name from the standard Python library for your own variables.
So here is the fixed code:
def search(lst, target):
min = 0
max = len(lst)-1
avg = (min+max)/2
# uncomment next line for traces
# print lst, target, avg
while (min < max):
if (lst[avg] == target):
return avg
elif (lst[avg] < target):
return avg + 1 + search(lst[avg+1:], target)
else:
return search(lst[:avg], target)
# avg may be a partial offset so no need to print it here
# print "The location of the number in the array is", avg
return avg
Recursive:
def in_list(l, x):
if len(l) < 2:
if l[0] == x:
return True
else:
return False
mid = len(l) // 2
if x < l[mid]:
return in_list(l[:mid], x)
else:
return in_list(l[mid:], x)
or iterative:
def in_list2(l, x):
low = 0
high = len(l) - 1
while low <= high:
mid = (low + high) // 2
if l[mid] == x:
return True
if x < l[mid]:
high = mid - 1
else:
low = mid + 1
return False
#Serge Ballesta 's solution is undoubtly the correct answer to this question.
I am just going to add another way of solving this:
def search(arr, item, start, end):
if end-start == 1:
if arr[start] == item:
return start
else:
return -1;
halfWay = int( (end-start) / 2)
if arr[start+halfWay] > item:
return search(arr, item, start, end-halfWay)
else:
return search(arr, item, start+halfWay, end)
def binarysearch(arr, item):
return search(arr, item, 0, len(arr))
arr = [1, 3, 4, 6, 8, 9, 12, 14, 16, 17, 27, 33, 45, 51, 53, 63, 69, 70]
print("Index of 69: " + str(binarysearch(arr, 69))) # Outputs: 16
The reason you aren't getting correct result is because in every recursive call your code is sending sliced array. So the array length keeps reducing. Ideally you should work out a way to send original array and work with only start, end indices.