checking duplicates in list using while loop - python

I'm trying to check for duplicate numbers within a list using only while loops and if statements. For some reason it is returning True for the list [1, 2, 3, 4, 5, 6] and I can't figure out why.
def has_duplicates(xs):
count = 0
while count < len(xs) and len(xs) > 1:
check = 1
while check < len(xs):
if xs[check] == xs[count]:
return True
else:
check += 1
count += 1
return False

I get the correct output using your function. However, there are certainly easier ways to get the same result, as:
def has_duplic2(xs):
return len(set(xs)) != len(xs)

In your first algorithm you shouldn't assing to the check variable the value of 1.
Otherwise on the second cycle of the loop both count and check will be 1 and you'll be comparing the element [1] of your list with itself, which will always return true.
Instead you should set the check variable to check = count + 1. So that you never compare a value with itself.

Related

How to make python function start back over if conditions aren't met?

I am trying to create a function that spreads a rumor form one pixel in to other neighboring pixels as long as they == 1 (not a 0). I think the function I have now can spread it to the neighboring pixel one time, but I want it to loop again and again using the updated versions of the pixel map each time. How can I get it to loop back to the top when certain conditions aren't met?
def spread_rumor(array):
new_array = np.zeros_like(array) #make a copy of your city
for i in range(array.shape[0]): #for each index i for the number of rows:
for j in range(array.shape[1]): #for each index j for the number of columns
if array[i,j] == 0:
new_array[i,j] = 0
elif array[i,j] == 2:
new_array[i,j] = 2
elif array[i,j] == 1: #if the value of the city/board at [i,j] is a 1:
new_array[i,j] = 1 #we only do something if we find a person who can learn the rumor
neighbors = getNeighborValues(i,j, array) #get all of the values of their neighborhood cells
if np.any(np.array(neighbors) == 2) == True:
new_array[i,j] = 2
## there is more than one way to do this!
## You could use a loop to check all the neighbors and move one once you find one
## or you could check to see if there is a 2 in any of the neighbors
frac_empty = np.count_nonzero(array == 0)/array.size
frac_house = np.count_nonzero(array == 1)/array.size
frac_rumor = np.count_nonzero(array == 2)/array.size
if frac_empty + frac_rumor == 1.0: #the copy of our city is the same as city:
##our simulation isn't changing anymore,
##so making a copy and updating it isn't going to
##lead to further changes
spread_rumor = False
else:
##there are still changes going on
#this is where I would want it to start back over at the top again
return showCity(new_array) #this function creates a plt.imshow representation of the resulting array
There are a few loops you could apply to achieve something like this. Firstly, a while loop. while loops, as you may know, run until a condition is met. If you have many conditions, the while statement can get pretty ugly. Many choose to use while True if there are many conditions. Using break will exit the loop.
def rand_string():
while True:
string = "".join(random.sample("abcdefghijk", 7))
if string == "afedgcb":
break
elif string == "cdefgab":
break
elif string == "gbadcef":
break
else:
continue
return string
Above, we choose 7 random letters from the string abcdefghijk and check if the 7 random letters make either afedgcb, cdefgab, or gbadcef. If so, we break out of the loop and return the string. If not, we will restart the loop. The else/continue is not necessary, the loop will still start over if none of the conditions are met because we don't break out of the loop.
Another option is recursion. The example below simply chooses a random number from 0 and 10 and checks if it equals 5. If so, we return the number. If not, we just run the function again.
def rand_num_recursion():
num = random.randint(0,10)
if num == 5:
return num
else:
return rec()
Now, if you were to print(rec()), the answer would always be 5. Why? Because the function will continue to run until the random number chosen is 5. This recursive function can also easily be converted to a while loop:
def rand_num_while():
num = random.randint(0,10)
while num != 5:
num = random.randint(0,10)
return num
What if you have parameters?
With recursion this can be done easily. Of course, the below example is just for demonstration purposes - you would never really need a function to "empty" a list, it is just an example of how to pass updated parameters back to the beginning of the loop.
def empty_list(lst):
if len(lst) == 0:
return lst
else:
print(lst)
return empty_list(lst[:-1]) # return all members of the list except for the last one
When you write print(empty_list([1,2,3,4,5,6])) and keep the print(lst) in the function, the output is as follows:
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5]
[1, 2, 3, 4]
[1, 2, 3]
[1, 2]
[1]
[]
As you can see, every time the condition is not met, we pass an updated parameter back to the beginning of the loop. In this example, you can see that every time the loop occurs, it removes the last element from the list and passes it back to the beginning.

Count the number of times each element appears in a list. Then making a conditional statement from that

write a function that takes, as an argument, a list called aList. It returns a Boolean True if the list contains each of the integers between 1 and 6 exactly once, and False otherwise.
This is homework and I thought I had it right, but it is now telling me that it isn't right. Here is my code.
def isItAStraight(aList):
count = 0
for i in set(aList):
count += 1
return aList.count(i) == 1
for some reason even if a number appears more than once it still gives true and I can't figure out why it won't give me false unless the first or last number are changed.
Each number has to occur only one time otherwise it is false.
So like take [1,2,3,4,5,6]
would be true.
But [1,2,2,3,4,5]
would be false.
Also, I can't import things like Counter or collections (though it would be so much easier to do it isn't apart of the assignment.)
The list is randomly generated from 1 to 6.
With a return inside the loop, you are only checking one value. You need to check each value. Also, instead of looping through the items of the list, you should loop through the items you're actually looking for. It would also help to make sure there are the correct number of items in the list.
def isItAStraight(aList):
if len(aList) != 6:
return False
for i in range(1, 7):
if aList.count(i) != 1:
return False
return True
But the easiest way to do this is to simply sort the list and check if it's what you're looking for:
def isItAStraight(aList):
return sorted(aList) == list(range(1, 7))
You need to be careful about what's inside the list. What you've written is a basically the same as the pseudo-code below:
let count = 0
for every unique element in aList:
Add 1 to count
if count is now 1, return true.
This will always return true if there is at least one element in aList, since you're adding 1 to count and then returning immediately.
A couple approaches to consider:
Create a 6 element list of all zeros called flags. Iterate over aList and set the corresponding element in flags to 1. If flags is all ones, then you return true.
Sort the list, then check if the first six numbers are 1, 2, 3, 4, 5, 6.

Python: Does list contain 3 consecutive integers that sum to 7?

I am working through the prep materials for my application to a coding bootcamp. This is a practice problem I am struggling with (using Python):
"Write a function 'lucky_sevens(numbers)', which takes in a list of integers and print True if any three consecutive elements sum to 7.
Make sure your code correctly checks for the first and last elements of the array."
I know how to loop through an array one element at a time, but don't know how to "hold" one element while also assessing the second and third elements in relation to the first, as this prompt requires. As you can see from my attempt below, I'm not sure when/where/how to increment the index values to search the whole list.
def lucky_sevens(numbers):
index1 = 0 # For assessing 1st of 3 numbers
index2 = index1 + 1 # For assessing 2nd of 3 numbers
index3 = index2 + 1 # For assessing 3rd of 3 numbers
# If all index values are within the list...
if index1 <= (len(numbers) - 2) and index2 <= (len(numbers) - 1) and index3 <= len(numbers):
# If the values at those indices sum to 7...
if numbers[index1] + numbers[index2] + numbers[index3] == 7:
print True
else:
print False
# I think the increments below may be one of the places I am incorrect
index1 += 1
index2 += 1
index3 += 1
When I run
lucky_sevens([2, 1, 5, 1, 0])
It is printing False, I think because it is only considering elements in the 0th, 1st and 2nd positions (sums to 8, not 7, as required).
It should print True, because elements in the 1st, 2nd and 3rd positions sum to 7. (1 + 5 + 1 = 7).
Can anyone please provide a suggestion? I would be most appreciative.
Yes, for your case its only considering the first, second and third elements. This is because you do not have any loops in your function.
In Python loop constructs are for and while . So you would need to use either one.
I can give you some hints to the problem , not going to provide you the complete code (since otherwise how would you learn?) -
You need to loop through the indexes from first index (0) to the len(numbers) -2 . An easy function that can help you do this would be enumerate() , it spits out the index as well as actual element when iterating over it using for loop (If you are using enumerate , you would need to put a condition to check that index should be less than len(numbers) - 2).
You should then get the elements from index+1 pos and index+2 position as well, and sum them and check if thats equal to 7 , if so you should return True.
A common mistake many make is to return False if the above (2) condition is not met, but actually what you need to do is to return it only when there are no matches at all (at the end of the function) .
You need a loop through the list to evaluate all elements. In your code, you only evaluate the first 3 elements.
Try this:
def lucky_sevens(numbers):
for i in range(0, len(numbers)):
if sum(numbers[i:i + 3]) == 7:
print True
return
print False
The reason yours doesn't work is because you're not looping it, you only check the first 3 elements in the list.
What about using recursion?
def lucky_sevens(numbers, index=0):
if index <= len(numbers):
if sum(numbers[index:index + 4]) == 7:
return True
else:
index += 1
return lucky_sevens(numbers[1:], index)
return False

Python Method Returning None

I'm having a very odd problem. I wrote a method that determines the degree of a formula describing a set of numbers, when given the said set. The method is fairly simple, I've added in a couple of lines for debugging purposes:
def getdeg(numlist, cnt): #get the degree of the equation describing numlist
count = cnt #initial run should be with cnt as 0
templist = []
for i in range(len(numlist) - 1): #exclude the last item (which doesn't have an item after it)
templist.append(numlist[i+1] - numlist[i]) #append the val of index i+1 minus index i
count += 1
print(templist)
if not allEqual(templist):
print("Not all equal, iterating again")
getdeg(templist, count)
else:
print(count)
return count
def allEqual(numlist):
if len(numlist) == 1:
return True
for i in range(len(numlist) -1):
if not (numlist[i] == numlist[i+1]):
return False
return True
Now, I'm running this on a set of numbers I KNOW to be described by a 3rd-degree equation, like so:
x = getdeg([2, 8, 9, 11, 20], 0)
print(x)
Fairly simple, yes? Except when you run this, it prints out the following:
[6, 1, 2, 9]
Not all equal, iterating again
[-5, 1, 7]
Not all equal, iterating again
[6, 6]
3
None
Everything is looking good, right up until that "None." What is it doing there? I would assume that the else conditional isn't being executed, but it's printing out 3 just fine, so it obviously is. That also means that the program "knows" what the value of count is, but it's not returning it right. Could someone enlighten me as to what on earth is going on?
if not allEqual(templist):
print("Not all equal, iterating again")
getdeg(templist, count)
Remember, when a method recursively calls itself, you still need to explicitly return the value if you want a value to be returned.
if not allEqual(templist):
print("Not all equal, iterating again")
return getdeg(templist, count)
You need to return a value in the if clause as well.
return getdeg(templist, count)

Count negative values in a list of integers using Python?

I am having problems with this CodingBat question:
Given a list of integers, return the count of the negative values.
count_negative([-1, -2, -3]) → 3
count_negative([2, 2, 2, 2, 2]) → 0
count_negative([-5, -3, 4]) → 2
Why doesn't this code run correctly?
def count_negative(list):
for value in list:
total = 0
total += value
return total
You are setting total back to zero after every loop. Put it outside the loop:
Also, the function will break after the first loop, because after a function returns something it breaks. Also put return total outside of the loop:
total = 0
for value in list:
total += value
return total
I don't see how this will determine whether a number is a negative or not. You can use an if-statement inside of your loop.
if value < 0:
total += 1
Or you can just use a list comprehension:
sum(1 for i in lst if i < 0)
By the way, never name something list. It overrides the built-in. I'm rather surprised your question did it.
Turn it into a pd.DataFrame then use df[df>0].count()/len(df)

Categories