I was making a poker simulator and tried to define a function which would identify a straight and give it a handstrength value of 5.
def straightCheck(playerHand):
playerHand.sort()
print(playerHand)
for playerHand in range(len(playerHand)):
for i in playerHand:
if playerHand[i] == playerHand [i+1] -1:
straight = True
else:
straight = False
if straight == True:
handstrength = 5
x = [1,3,5,4,2]
straightCheck(x)
i can't figure out what is wrong with is but it keeps returning this error message:
for i in playerHand:
TypeError: 'int' object is not iterable
First of all you are trying to iterate of an integer, which cannot (and shouldn't) be done. It seems like your two nested for loops should just be one for, like for i in range(len(playerHand) - 1), when the -1 is used so that you don't try to accessplayerHand[len(playerHand)].
In addition, since you set straight to True or False in every iteration, only your last iteration will count, so you'll get false positives.
Finally, I'm not sure whether you want your function to return a value, but currently your function returns no data (unless handstrength is a global variable). Also, please note that currently, by using .sort() you are actually sorting playerHand, thus changing it from within the function - this might not be what you want.
A possible function to check whether a hand is straight, similar to your code, is this:
def is_straight(playerHand):
playerHand.sort()
for i in range(len(playerHand) - 1):
if playerHand[i] != playerHand [i+1] - 1:
return False
return True
This function returns True if playerHand is straight, and False otherwise.
What about this. You sort the list, then convert it to a set and back to a list, which makes it unique. Then the length must be 5 and if so, the difference between max and min for 5 consecutive numbers must be 4. I can't mathematically prove this here, but it should be. ;)
>>> x=[2,1,5,3,4]
>>> y=sorted(x)
>>> y=list(set(y))
>>> if len(y) == 5 and y[4]-y[0] == 4:
... print "straight"
...
straight
Also see this here: Check for consecutive numbers
Related
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?
I am trying to create this function as described in docstring but either I get just 1st doctest passed or fail with IndexError: list index out of range. I feel this current approach will work if somehow I can increment the loop counter again inside the loop without falling off range. I tried
def menu_is_boring(meals):
"""Given a list of meals served over some period of time, return True if the
same meal has ever been served two days in a row, and False otherwise.
>>> menu_is_boring(['Egg', 'Spam'])
False
>>> menu_is_boring(['Spam', 'Eggs', 'Spam', 'Spam', 'Bacon', 'Spam'])
True
"""
for i in range(len(meals)):
x = (meals[i] == meals[i+1]) and (meals[i] == meals[i+2])
return x
To solve the Index error I tried using while loop but that fails with syntax error:
for i in range(len(meals)):
x = (meals[i] == meals[(while i<len(meals): i+=1 )]) and (meals[i] == meals[while i<len(meals):i+=2])
Will a nested loop somehow work or am I over complicating this?
P.S. There is solution available to the problem but I am trying to see what is wront with my approach or get a hint , instead of jumping to the solution directly. This my 1st question so please excuse me if it is not following all the guidelines.
Just remember the last meal:
def menu_is_boring(meals):
last = None
for meal in meals:
if meal == last:
return True
last = meal
return False
It looks like you're checking for 3 days in a row with x = (meals[i] == meals[i+1]) and (meals[i] == meals[i+2]). Also, the IndexError is caused by the fact that you're trying to access the n+1th and n+2th elements of a list with n elements. To avoid that, you should run the loop till n-1 or n-2 as necessary.
So all you have to do is:
for i in range(len(meals)-1): # Run the loop till n-1
x = meals[i] == meals[i+1] # Check for nth and n+1th meal to be same
return x
Having said that, this section will not solve your problem, and will always return the value for the last meal pair, since x is getting overwritten on every iteration of the loop. To solve that, you can return a True as soon as you find a repetition.
def menu_is_boring(meals):
for i in range(len(meals)-1):
if meals[i] == meals[i+1]:
return True
return False
You can test it by calling the function and printing its return value.
print (menu_is_boring(['Spam', 'Eggs', 'Spam', 'Spam', 'Bacon', 'Spam']))
I'm a high highschool student taking an online course for python, and one of the assignments is to create a function similar to fizz buzz, except instead of "fizz" and "buzz", they simply use "three" and "five". I wrote a function but unfortunately it completely failed, and doesn't do its job at all. I've been having a hard time to figure out what to input instead of "for x in range(101):", I think that's where my problem is. Any pointers/guidance would be very helpful, I'm completely lost.
The instructions are here and here is my code:
def student_func(x):
for x in range(101):
if x % 3 == 0 and x % 5 == 0:
return('threefive')
elif x % 3 == 0:
return('three')
elif x % 5 == 0:
return('five')
else:
return x
Edit:A couple of people were recommending me to delete the loop, since it was starting off the function with 0(I should've realized that). However when I took it out the output became None. Am I doing something else wrong, or am I misunderstanding? Thanks for the speedy answers however, I'm still very inexperienced
Code with new error:
def student_func(x):
if x % 3 == 0 and x % 5 == 0:
return('threefive')
elif x % 3 == 0:
return('three')
elif x % 5 == 0:
return('five')
else:
print(x)
So, a few things to note. First, the range(n) function returns an iterator that will go through 0, 1, 2, ..., n-1. Thus, the first value you will iterate over in your code will be 0. Think about how your for loop will handle that.
Second, because you're assigning x to be the values iterated over from the range function, you're never actually testing the x being passed into the function.
Third, note that every branch of the if-elif-else tree inside the loop has a return statement, thus the loop is only going to go around once before returning a value. That sort of defeats the purpose of using a loop.
Lastly, make sure you are aware of how 0 % n evaluates. Think about things and see if you can reach a conclusion about why your program is returning student_func(1) = 'threefive'.
The issue is that the "tester" which tests your function gives the function the number/argument - x. However, what you are doing is testing the function from 0 - 100. The question does not ask you to test your function with numbers from 0 - 100. Therefore, you should remove the for loop.
Why is it giving the output "threefive"? Well, the function first tests in the loop the number 0. It satisfies the first if statement, and returns (so it gets out of the function).
Right now your code is looping through every value from 0 to 100 and returning if the first value (0) is divisible by both three and five, which of course it is. The function is only asking you to check if a single value is divisible by three, or five, or both. Why would you need a loop?
Your function isn't supposed to loop; it's supposed to examine only the single value passed in as the argument. The teacher's function will call your function with a variety of inputs.
Take out the for loop statement and it should work.
Right now I'm trying to get my program to take a two dimensional list as an input and return either true or false depending on whether or not it is "rectangular" (eg. [[2,3],[1,5],[6,9]] is rectangular whereas [[2,3],[1,8,6]] is not.) So far I've come up with this:
def rectangular(List):
n = List
for i in n:
if len(i) != len(n[0]):
return False
elif len(i) == len(n[0]):
i
I can't seem to figure out how to create a "true" case. Using the elif above I'm able to cycle through the list but if i were to add a return true portion it stops as soon as that is the case. Would a while loop work better in this case? All help is appreciated! Thanks.
If you get to the end without finding a false case, then you know it's true, right? There aren't any other possibilities.
So, you can just remove the elif entirely, and just add a return True at the end:
def rectangular(List):
n = List
for i in n:
if len(i) != len(n[0]):
return False
return True
As a side note, your elif that has exactly the opposite condition as the if is better written as just else:. That way, there's no chance of you getting the opposite condition wrong, no need for your readers to figure out that it's the opposite, etc.
Also, there's no reason to take the argument as List, then bind the same value to n and use that. Why not just take n in the first place?
def rectangular(n):
for i in n:
if len(i) != len(n[0]):
return False
return True
You can make this more concise, and maybe more Pythonic, by replacing the for statement with a generator expression and the all function:
def rectangular(n):
return all(len(i) == len(n[0]) for i in n)
But really, this isn't much different from what you already have. You should learn how this works, but if you don't understand it yet, there's no problem doing it the more verbose way.
If you want to get clever:
def rectangular(n):
lengths = {len(i) for i in n}
return len(lengths) == 1
We're making a set of all of the lengths. Sets don't have duplicates, so this is a set of all of the distinct lengths. If there's only 1 distinct length, that means all of the lengths are the same.
However, note that for an empty list, this will return False (because there are 0 lengths, not 1), while the other two will return True (because a condition is vacuously true for all values if there are no values to test). I'm not sure which one you want, but it should be relatively easy to figure out how to change whichever one you choose to do the opposite.
Try using the all function with a generator:
def rectangular(lst):
first_len = len(lst[0])
# I used lst[1:] to skip the 0th element
return all(len(x) == first_len for x in lst[1:])
The all function returns True if all elements of an iterable are True, and False otherwise.
It's good that you didn't call your variable list, but capitalized names usually represent a class in Python, so lst is a better choice than List.
NOTE: I made the assumption that "rectangular" means each sublist is the same length. If in reality each sublist should be (say) 2 elements long, just replace first_len with the literal 2 and remove the [1:] on lst[1:]. You may also want to add some exception handling in case you pass a list with only one element.
You can make sure that the lengths of all elements of the list are the same length. Or in Python:
all(map(lambda m: len(m) == len(x[0]), x))
Where x is what you want to check.
The only problem with this solution is that the if the list looks like [ [1,2], [1,[1,2]], 'ab' ], it is still going to return True. So you additionally need to do some type checking.
I am trying to write a recursive function that does a Boolean check if a list is sorted. return true if list is sorted and false if not sorted. So far I am trying to understand if I have the 'base case' correct (ie, my first 'if' statement):
def isSorted(L, i=[]):
if L[i] > L[i + 1]:
return false
else:
return true
Am I correct with my initial if "L[i] > L[i + 1]:" as base case for recursion?
Assuming my 'base case' is correct I am not sure how to recursively determine if the list is sorted in non-descending order.
here is what I came up with. I designate the default list to 0; first check to see if first item is the last item. if not, should check each item until it reaches the end of the list.
def isSorted(L):
# Base case
if len(L) == 1:
return True
return L[0] <= L[1] and isSorted(L[1:])
This is how I would start. Write a function with the following signature:
function isSorted(currentIndex, collection)
Inside the function, check to see if currentIndex is at the end of the collection. If it is, return true.
Next, check to see if collection[index] and collection[index+1] are sorted correctly.
If they aren't, return false
If they are, return isSorted(currentIndex+1, collection)
Warning: this is a horrible use for recursion
No, the base case will be when you reach the end of the list, in which case you return true.
Otherwise, if the two elements you are looking at are out of order return false.
Otherwise, return the result of a recursive call on the next elements down the list.
I agree with #MStodd: recursion is not the way to solve this problem in Python. For a very long list, Python may overflow its stack! But for short lists it should be okay, and if your teacher gave you this problem, you need to do it this way.
Here is how you should think about this problem. Each recursive call you should do one of three things: 0) return False because you have found that the list is not sorted; 1) return True because you have reached your base case; 2) break the work down and make the remaining problem smaller somehow, until you reach your base case. The base case is the case where the work cannot be broken down any further.
Here is a broad outline:
def recursive_check(lst, i):
# check at the current position "i" in list
# if check at current position fails, return False
# update current position i
# if i is at the end of the string, and we cannot move it any more, we are done checking; return true
# else, if i is not at the end of the string yet, return the value returned by a recursive call to this function
For example, here is a function that checks to see if there is a character '#' in the string. It should return True if there is no # anywhere in the string.
def at_check(s, i):
if s[i] == '#':
return False
i += 1
if i >= len(s):
return True
else:
return at_check(s, i)
I wrote the above exactly like the outline I gave above. Here is a slightly shorter version that does the same things, but not in exactly the same order.
def at_check(s, i=0):
if i >= len(s):
return True
if s[i] == '#':
return False
return at_check(s, i+1)
EDIT: notice that I put i=0 in the arguments to at_check(). This means that the "default" value of i will be 0. The person calling this function can just call at_check(some_string) and not explicitly pass in a 0 for the first call; the default argument will provide that first 0 argument.
The only time we really need to add one to i is when we are recursively calling the function. The part where we add 1 is the important "breaking down the work" part. The part of the string we haven't checked yet is the part after i, and that part gets smaller with each call. I don't know if you have learned about "slicing" yet, but we could use "slicing" to actually make the string get smaller and smaller with each call. Here is a version that works that way; ignore it if you don't know slicing yet.
def at_check(s):
if s == '': # empty string
return True
if s[-1] == '#': # is last character '#'?
return False
return at_check(s[:-1]) # recursive call with string shortened by 1
In this version, an empty string is the basis case. An empty string does not contain #, so we return True. Then if the last character is # we can return False; but otherwise we chop off the last character and recursively call the function. Here, we break the work down by literally making the string get shorter and shorter until we are done. But adding 1 to the index variable, and moving the index through the string, would be the same thing.
Study these examples, until you get the idea of using recursion to break down the work and make some progress on each recursive call. Then see if you can figure out how to apply this idea to the problem of finding whether a list is sorted.
Good luck!