Finding the index of a list - python

My function gives the error ("IndexError: list index out of range"), and I'm not to sure why, even first putting i = 0. My code is to print the index of the first element that is equal to the target value and if it doesn't equal anything in the list then index = -1. (Using While loop)
Function
def yareyare(list_g, list_size, target):
found = False
i = 0
while i < list_size or not found:
if target == list_g[i]:
found = True
result = i
else:
i += 1
if not found:
result = -1
print("The index is {}".format(result))
Main
# Imports
from index import yareyare
# Inputs
list_g = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list_size = len(list_g)
target = str(input("What is the target value(1-10): "))
#
yareyare(list_g, list_size, target)

There are two simple errors in the code.
First, the boolean logic of the while loop should be and not or because it allows it to loop forever since found doesn't become True until the target is found.
Second, you need to convert target to an int not an str
It should work after that.

while i < list_size or not found: is the culprit. As long as found is false, the loop continues even if it ran out of list entries. That said, the entire code seems very clumsy; a Python approach would normally use list.index, or for more verbosity, a for loop with enumerate and an else clause.

There are several problems with this code. I am going to try and fix your errors while changing as little of your original code as possible. There are some things that you are doing that will work that I would advise against, like passing the list length as a parameter rather than using len and using a while loop for this at all.
Your first issue is that target is a string while the goals you compare it to are ints. That means this:
target == list_g[i]
Will never be true. It must be changed to:
int(target) == list_g[i]
Your second problem is that you are looping while i < list_size OR found is false. When you find a match, you set found to false but you never increment i. This means that i will always stay at the same value and therefore it will always equal list_g[i] so you will never increment it. Since i is always less than the list length i < list_size or not found will always be true and you will be trapped in an infinite loop. You should change the or to an and.
Here is your function with the fixes:
def yareyare(list_g, list_size, target):
found = False
i = 0
while i < list_size and not found:
if int(target) == list_g[i]:
found = True
result = i
else:
i += 1
if not found:
result = -1
print("The index is {}".format(result))

Related

Subset Sum using Sets (Python)

I'm trying to solve the Subset Sum problem using Set and recursion in python.
I've found a lot of solutions with an array, but none with a set.
Here is my code:
def checkForSubSet(set, sum):
if len(set) == 0 or sum < 0:
return False
e = set.pop()
if sum == e:
return True
return checkForSubSet(set, sum - e) or checkForSubSet(set, sum)
if __name__ == '__main__':
set = {3, 34, 4, 12, 5, 2}
sum = 17
if (checkForSubSet(set, sum) == True) :
print("Found a subset with given sum")
else :
print("No subset with given sum")
sometimes its works and sometimes not... any idea?
ty for any help!
Your basic error is that you pop() a value from the input set. This means that in all subsequent calls you will not have that value available. This is easily seen with a print statement, where I've replaced sum and set with names that don't clash with builtins:
def checkForSubSet(components, target):
print(f"{components=} {target=}")
if len(components) == 0 or target< 0:
return False
e = components.pop()
if target == e:
return True
return checkForSubSet(components, target - e) or checkForSubSet(components, target)
>>> checkForSubSet({3,2,1}, 4)
components={1, 2, 3} target=4
components={2, 3} target=3
components={3} target=1
components=set() target=-2
components=set() target=1
components=set() target=3
components=set() target=4
False
We see that the set gets ordered. 1 is tested first, and then popped off. And so on until 3 is popped off and then, hitting the base case, the function returns False. It tries the alternative cases - but the set (which persists throughout) no longer has items in it. Thus, as it goes back up the tree it is testing against an empty set.
Recursion is always about a base case and an iterative case:
def has_subset(components: Set[int], target: int) -> bool:
print(f"{components=} {target=}")
# Base Case: check for truth once the set is empty
if 0 == target:
return True
# Iterative Case: iterate through each option you have for reducing the size of the set by one
else:
return any(has_subset(components - {item}, target - item) for item in components)
Here, we check the base case of an empty set. If we have an empty set and the target is 0, we return true. Otherwise, we return false.
The iterative case is (almost always) more interesting. Here, we simply iterate through all elements of the set, and check what has_subset() returns if we remove one item and reduce our target by that item. any() lets us return the first result we get that is True, or False if we exhaust all options. Note, however, that we are using the construct components - {item} which takes your initial set and returns a new set that includes all the elements except those in the set {item}. Since this is a new set, it does not fall prey to the previous problem when we recurse with it.
There are optimizations that can happen (what happens if your choice makes target a negative number?), but this should still work.

how can I get the function to return index of 2 numbers that add up to a target value

I am writing a function to take a list of integers and an integer called target and return the indices of the two numbers in the list such that they add up to target. But my code doesn't work the way it should. The function ends up not printing anything at all. How can I fix this? I am a beginner and I can't figure out what's wrong :(
def solution(list, target):
firstindex = 0
secondindex = -1
while(firstindex <= len(list)-1):
if list[firstindex] + list[secondindex] == target:
print(f"The sum was found at index {firstindex} and {secondindex}")
break
else:
firstindex = firstindex + 1
secondindex = secondindex - 1
#I am calling the function here
solution([1,2,3,4,5, 6], 5)
You can use this way to solve the problem.
def solution(list, target):
n = len(list)
for firstindex in range(n - 1):
for secondindex in range(firstindex + 1, n):
if list[firstindex] + list[secondindex] == target:
print(f"The sum was found at index {firstindex} and {secondindex}")
solution([1,2,3,4,5, 6], 5)
Not so sure about the approach in general to the task you are trying to solve, depending on the algorithm you implement and the starting parameters you may receive multiple results and not one single value.
Looking at your example list and target value, the pairs (1,4) (2,3) would both solve for the target value.
In principle, in case you're not using any IDE that keeps track of the variable values or don't want to use any library to keep things very lightweight, I'd recommend to use pen and paper and walk through the variable values of your loop or have printouts in the code itself as a simple means to debug, like this:
def solution(list, target):
firstindex = 0
secondindex = -1
while(firstindex <= len(list)-1):
print(firstindex)
print(secondindex)
if list[firstindex] + list[secondindex] == target:
print(f"The sum was found at index {firstindex} and {secondindex}")
break
else:
firstindex = firstindex + 1
secondindex = secondindex - 1
#I am calling the function here
solution([1,2,3,4,5, 6], 5)
What you will find is that your second index starting at -1 will decrement simultaneously to the first index, while it does not stay fixed while iterating through the first index. Hope that helps a bit in the debugging.
Really, try to solve this question algorithmically on paper first.
Cheers,
Let me know how it goes
Edit: I utterly messed up my thinking, as Python does indeed use negative indices for starting with the last item of the list and walking back. Need to stop thinking C...
Don't use list as the variable name for the first list the function is taking, it is a keyword in python.
edit:
you are refering to the keyword list in your function which represents a type object in python. You are basically referring to the classification of the object. Instead assign your variable to another name such as def solution(original, target):

can't quite figure out what's not working (checkio excersise "Even the Last")

You are given an array of integers. You should find the sum of the integers with even indexes (0th, 2nd, 4th...). Then multiply this summed number and the final element of the array together. Don't forget that the first element has an index of 0.
For an empty array, the result will always be 0 (zero).
Input: A list of integers.
Output: The number as an integer.
Precondition: 0 ≤ len(array) ≤ 20
all(isinstance(x, int) for x in array)
all(-100 < x < 100 for x in array
result = 0
if array:
for element in array:
i = array.index(element)
if i%2 == 0:
result += element
else:
pass
else:
return 0
return result
Last_digit = array[-1]
final_result = result*Last_digit
return final_result
print(final_result)```
I've figured out the problem, that you've shared the array you're having problem with. Since you have this array :
[-37,-36,-19,-99,29,20,3,-7,-64,84,36,62,26,-76,55,-24,84,49,-65,41]
If you notice here, 84 appears twice, first at index 9 and then 16. The method you're using to get index of elements, .index returns the index of the first instance the element is found in the list.Therefore for the value of 84, the index is taken as 9 and not 16 which is an odd value, this does not add 84 to your sum. You should rather use enumerate for your code:
for idx, element in enumerate(array):
if idx %2 == 0:
result += element
First, I recommend reading the stackexchange guides on posting a well-formed question. You need to state what your goal is, what you've tried, what errors get thrown, and what the output should look like -- along with code examples and a minimal reproducible example as needed.
However, I'll help you out anyway.
You have a dangling return at line 11:
else:
return 0
return result
This makes no sense, as you've already returned 0. This is also apparently a snippet from a function, no? Post the whole function. But based on the instructions, you could try this:
import random
array = random.sample(range(-100, 100), 20)
def etl_func(arr):
arrsum = 0
for i, val in enumerate(arr):
if i%2 == 0: arrsum += val
return (arrsum * arr[-1])
answer = etl_func(array)
print(answer)
Note that importing random and using array = random.sample(range(-100, 100), 20) are not necessary if you're already GIVEN an array to work with. They're included here just as an example.
Also note that it's unnecessary to use an else: pass. If the condition evaluates to true (i.e. i%2 == 0), the if block will be executed. If i%2 != 0, the loop will short circuit automatically and move to the next iteration. Adding else: pass is like telling someone sitting in your chair to sit in your chair. You're telling the program to do what it's already going to do anyway. There's nothing necessarily wrong with including the else: pass, if it really want to... but it's just adding lines of meaningless code, which nobody wants to deal with.
EDIT: I don't know whether you were supposed to write a function or just some code (back to the "ask a well-formed question" issue...), so I went with a function. It should be trivial to turn the function into just plain code -- but you want to get into the habit of writing good functions for reusability and modularity. Makes everything run more smoothly and elegantly, and makes troubleshooting much easier.
This function also works for the array mentioned in the comments to your original post.
In addition, if you need a direct replacement for your code (rather than a function... I'm not familiar with checkio or how your answers are supposed to be formatted), and you already have the array of integers stored in the variable array, try this:
arrsum = 0
for i, val in enumerate(array):
if i%2 == 0: arrsum += val
print(arrsum * array[-1])
Since your question didn't say anything about using or defining functions, return statements shouldn't appear anywhere. There's nothing to return unless you're writing a function.

Stuck at Python Solution for AlmostIncreasingSequence (CodeSignal)

I was working on this particular task given by CodeSignal which had the purpose of creating a program that would go through a given list with numbers and check if the numbers were increasing and/or "almost increasing". What this means is that, for example, if the list was (1, 3, 2, 1) then the program should return false due to the fact that, while it does appear to increase, it also takes a dip back to 1, returning false. Getting true on the output would require the list incrementing up normally, or almost incrementing up like (1, 3, 2, 4).
I created a code for this through research and Youtube videos, and I actually understood how the code worked and tried it out on Python, however only getting 12/19 correct. I did think this code would go through and ace all the 19 tests but it turns out it had an issue within it and would like to know how I could fix this. The code:
def almostIncreasingSequence(sequence):
count = 0
for i in range(0, len(sequence)-1):
if sequence[i] <= sequence[i-1]:
count +=1
if sequence[i] <= sequence[i-2] and sequence[i+1] <= sequence[i-1]:
return False
return count <= 1
The outputs:
I have tried to give the best solution possible with me but unfortunately ended up with time limit exceeded for last 4 test cases.
Explanation
each time I tried with excepting one element from an array and checked if it is in sorted order or not and thus i continued it until last if i did not found any such possible arrays i returned false
def solution(sequence):
if sorted(set(sequence)) == sequence :
return True
for i in range(len(sequence)):
temp = sequence[:i]+sequence[i+1:]
if sorted(set(temp)) == temp :
return True
return False
def isIncreasing(sequence):
return sorted(set(sequence)) == sequence
def isAlmostIncreasing(sequence):
#(optional)
#if isIncreasing(sequence) :
# return True
for i in range(len(sequence) - 1):
if sequence[i] >= sequence[i+1]:
temp, temp2 = sequence[:], sequence[:]
del temp[i]
del temp2[i+1]
return isIncreasing(temp) or isIncreasing(temp2)
return True
First, if sequence is already IncreasingSequence then no need to check individual data.(optional)
but if it's not:
find first wrong pair at index i & i+1. (if no wrong pair found, then sequence has no issue.)
if we remove one of them, check will we get proper result in remaining sequence?

How to keep track the amount of even integers when looking through randomized list using recursion

Sorta newbie here. So in trying to wrap my head around using recursive functions I wanted to try to make a program that:
1: Generates a list containing 10 random integers ranging from 0 - 20
2: Using a recursive function goes trough the list and finds out what elements of the list are even integers
3: Prints out only the aformentioned even numbers
Where I have gotten stuck is in how to print out the result. I can't seem to figure out what value i want to put inside the function when calling it ( F(?) )
I tried to integrate a counter that kept track on how many times the program found a even number but it always resulted in an error that the variable is not defined no matter how hard I tried to make it global.
How could I go about this? Am I totally in the wrong?
import random
numL = []
for i in range(10):
x = random.randint(0,20)
numL.append(x)
print(numL)
def F(x):
if numL[x] % 2 == 0:
return numL[x]
else:
return F(x+1)
print(F( ??? ))
First question asked on this forum, hopefully I did okay, appreciate any help!
Assuming you want to return a list of the even numbers then you have 4 cases to consider
This is the last number in the list and its even so return this number
This is the last number in the list and its odd dont retrun this number
There are more numbers to check and this number is even so return
this plus the function result
There are more numbers to check and this number is odd to return
only the function result and not this num
So we can code this as
import random
def get_even_nums(nums):
num = nums[0]
#This is our terminating case we definitivly return a value here
if len(nums) == 1:
return [num] if num % 2 == 0 else []
else:
#If we got here we will be recursivly calling the function
#If its even number return that number plus the result of the function
#it its not even then just return the reult of the function and not this num
if num % 2 == 0:
return [num] + get_even_nums(nums[1:])
else:
return get_even_nums(nums[1:])
numL = [random.randint(0, 20) for _ in range(10)]
print(numL)
print(get_even_nums(numL))
OUTPUT
[3, 6, 5, 10, 20, 18, 5, 0, 3, 9]
[6, 10, 20, 18, 0]
So I took your function and changed it up slightly (using a slightly different approach). There's no need to a global list, though you could do that as well, if you wanted. The problem that you have is the lack of a base case or rather an incorrect one.
If you run your original function with an argument 0, which basically is the first element of your generated array, the fucntion will run until it hits one even number. At that point it'll exit recursion, because the base case basically stops recursive calls once you hit an even number.
Now, to fix this, you have to approach the problem differently. I would put your generated array as the input argument to your function, then ask myself "What would be a good base case?" Probably one that stops your recursive calls once you reach the end of the input list.
if len(numL) == 0:
return ...
Also, we need a way to return the even numbers that we found during our search through the list. For that reason I'd introduce a new acc list, where we would append the even numbers that we found. Thus the function input arguments would be
def F(numL, acc):
...
Now, in the recursive call we should check wether the current element is even or not. If it is, great, we add it to the acc list and continue into the recursive call. If it's not, we don't add anything to the acc but just continue with recursion.
if numL[0] % 2 == 0:
acc.append(numL[0])
return F(numL[1:], acc)
Putting it all together, we get:
def F(numL, acc):
if len(numL) == 0:
return acc
else:
if numL[0] % 2 == 0:
acc.append(numL[0])
return F(numL[1:], acc)
where numL represents your generated list and acc represents the resulting list we'll return after we traverse the list.
This is your function (as I understand it, you wanted this):
import random
def F(i):
r = random.randint(0,20)
if r % 2 == 0:
print(r)
i += 1
if i != 10:
F(i)
F(0)

Categories

Resources