Check a tuple for at least 5 consecutive numbers [closed] - python-3.x

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I have a tuple A and I would like to check if it contains at least 5 consecutive numbers somewhere. What is the most time efficient way to do this?
A= (1, 4, 5, 6, 7, 8, 12) -->TRUE
This is used in a montecarlo siulation to check if a 7 card poker hand contain a straight.

Assuming a sorted tuple of 7 different integers. If there are 5 integers in series, i.e. (n, n+1, n+2, n+3, n+4), they must start on position 0, 1 or 2 and end on position 4, 5, or 6 respectively.
straight = any(a[4+i] - a[i] == 4 for i in (0,1,2))
Update: If the sequence length is not fixed:
(suggested by tobias_k in comments)
straight = any(a[4+i] - a[i] == 4 for i in range(len(a)-4))

I don't think there's a simple one-liner for this, but you basically just have to loop the elements in the list and check whether it's one more than the last one, and return True if the running count reaches 5. You also have to consider the case that there are two cards with the same value.
def has_straight(values, req=5):
last = count = None
for x in values:
if x - 1 == last:
count += 1 # one more on the straight
elif x == last:
pass # same value as before
else:
count = 1 # start a new straight
if count >= req:
return True
last = x
return False
Some examples:
has_straight((1, 4, 5, 6, 7, 10, 12)) # no straight -> False
has_straight((1, 4, 5, 6, 7, 8, 12)) # straight in middle -> True
has_straight((1, 2, 3, 4, 5, 10, 12)) # at beginning -> True
has_straight((1, 2, 8, 9, 10, 11, 12)) # at very end -> True
has_straight((1, 2, 2, 3, 4, 4, 5)) # straight with dupes -> True
Complexity would be O(n), which is as good as it could possibly get, as you have to check each number.

Related

Count list elements without duplicates [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I'm new to Python and finding my way.
I have this code here:
L = ['l','u','k','e','l','i']
k = [L.count(c) for c in L]
print(k)
And it gives this result:
[2, 1, 1, 1, 2, 1]
which is great but I want to get to this result
[2, 1, 1, 1, 1]
That is, a result in which the 'l' is not counted twice.
How do I do that?
NB: the list L here is from user input, I convert user input to list L so I can't tell beforehand what the user will input but once its typed in, I want to convert the string into a list and count all the elements without counting an element twice.
you can do something like that
L = ['l','u','k','e','l','i']
import collections
s = collections.Counter(L)
s
Counter({'l': 2, 'u': 1, 'k': 1, 'e': 1, 'i': 1})
s.values()
dict_values([2, 1, 1, 1, 1])
Use a dictionary:
L = ['l','u','k','e','l','i']
counts = {}
for l in L:
counts[l] = counts.get(l, 0) + 1
print(counts)
# {'k': 1, 'l': 2, 'e': 1, 'u': 1, 'i': 1}

Is there a way to find the sum of the number after the ending of 9?

The question is:
Return the sum of the numbers in the array, except ignore sections of numbers starting with a 6 and extending to the next 9 (every 6 will be followed by at least one 9).
sixty_nine([4, 5, 6, 7, 8, 9]) --> 9
sixty_nine([4, 5,7,8, 6, 7, 8, 9,34]) --> it should return -- 58
but it returns -- 24(by ignoring 34)
i am not able to understand how to take the sum of numbers after 9
arr = [4, 5,7,8, 6, 7, 8, 9,34]
def sixty_nine(arr):
sums = 0
l = len(arr)
for i in range(l):
if arr[i] == 6 and 9 in arr[i:]:
for j in arr[0:i]:
sums = sums + j
return sums
sixty_nine(arr)
t=The output of this program is --- 24
You code contains various errors, among them you are returning inside your for-loop which prevents it from traversing the whole list.
I suggest treating this problem in two steps. First write a generator which filters out sublists of the form [6, ..., 9].
Then use sum which can sum any iterable, generators included.
def ignore_between(lst, a, b):
i = 0
while i < len(lst):
if lst[i] == a:
try:
i = lst.index(b, i) + 1
continue
except ValueError:
pass
yield lst[i]
i += 1
lst = [4, 5, 7, 8, 6, 7, 8, 9, 34]
output = sum(ignore_between(lst, 6, 9))
print(output) # 58

Find set with smallest number of elements from a list of sets [duplicate]

This question already has answers here:
How does the min/max function on a nested list work?
(4 answers)
Closed 4 years ago.
I have a list of sets -
inconsistent_case = [{0, 1, 2, 3, 6, 7}, {4, 5}]
I want -
{4, 5} (set with smallest number of elements)
My code -
length = float("inf")
small = {}
for x in inconsistent_case:
if len(x) < length:
length = len(x)
small = x
print(small)
Which gives me -
{4, 5}
Is there any fastest and/or easiest way to do this?
Yes, specify the key for min:
>>> inconsistent_case = [{0, 1, 2, 3, 6, 7}, {4, 5}]
>>> min(inconsistent_case, key=len)
{4, 5}
If multiple items are minimal, the function returns the first one encountered.

Can this numpy.where() approach be adapted for two conditions instead of one? [duplicate]

This question already has answers here:
Numpy where function multiple conditions
(9 answers)
Closed 5 years ago.
I can get numpy.where() to work for one condition but not two conditions.
For one condition:
import numpy as np
a = np.array([1, 2, 3, 4, 5, 1, 2, 3, 1, 2, 1, 1, 1, 2, 4, 5])
i, = np.where(a < 2)
print(i)
>> [ 0 5 8 10 11 12] ## indices where a[i] = 1
For two conditions:
# condition = (a > 1 and a < 3)
# i, = np.where(condition)
i, = np.where(a > 1 and a < 3)
print(i)
>> ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
I read up on a.any() and a.all() in this other SO post, but this doesn't work for my purpose since I want all indices that fit the condition rather than a single boolean value.
Is there a way to adapt this for two conditions?
Use np.where((a > 1) & (a < 3))

Python - assigning digits of a number to variables [duplicate]

This question already has answers here:
How to split an integer into a list of digits?
(10 answers)
Closed last month.
I'm writing a program which calculates the check digit of an ISBN number. I have to read the user's input (nine digits of an ISBN) into an integer variable, and then multiply the last digit by 2, the second last digit by 3 and so on. How can I "split" the integer into its constituent digits to do this? As this is a basic homework exercise I am not supposed to use a list.
Just create a string out of it.
myinteger = 212345
number_string = str(myinteger)
That's enough. Now you can iterate over it:
for ch in number_string:
print ch # will print each digit in order
Or you can slice it:
print number_string[:2] # first two digits
print number_string[-3:] # last three digits
print number_string[3] # forth digit
Or better, don't convert the user's input to an integer (the user types a string)
isbn = raw_input()
for pos, ch in enumerate(reversed(isbn)):
print "%d * %d is %d" % pos + 2, int(ch), int(ch) * (pos + 2)
For more information read a tutorial.
while number:
digit = number % 10
# do whatever with digit
# remove last digit from number (as integer)
number //= 10
On each iteration of the loop, it removes the last digit from number, assigning it to digit.
It's in reverse, starts from the last digit, finishes with the first
list_of_ints = [int(i) for i in str(ISBN)]
Will give you a ordered list of ints. Of course, given duck typing, you might as well work with str(ISBN).
Edit: As mentioned in the comments, this list isn't sorted in the sense of being ascending or descending, but it does have a defined order (sets, dictionaries, etc in python in theory don't, although in practice the order tends to be fairly reliable). If you want to sort it:
list_of_ints.sort()
is your friend. Note that sort() sorts in place (as in, actually changes the order of the existing list) and doesn't return a new list.
On Older versions of Python...
map(int,str(123))
On New Version 3k
list(map(int,str(123)))
(number/10**x)%10
You can use this in a loop, where number is the full number, x is each iteration of the loop (0,1,2,3,...,n) with n being the stop point. x = 0 gives the ones place, x = 1 gives the tens, x = 2 gives the hundreds, and so on. Keep in mind that this will give the value of the digits from right to left, so this might not be the for an ISBN but it will still isolate each digit.
Convert it to string and map over it with the int() function.
map(int, str(1231231231))
Recursion version:
def int_digits(n):
return [n] if n<10 else int_digits(n/10)+[n%10]
Converting to str is definitely slower then dividing by 10.
map is sligthly slower than list comprehension:
convert to string with map 2.13599181175
convert to string with list comprehension 1.92812991142
modulo, division, recursive 0.948769807816
modulo, division 0.699964046478
These times were returned by the following code on my laptop:
foo = """\
def foo(limit):
return sorted(set(map(sum, map(lambda x: map(int, list(str(x))), map(lambda x: x * 9, range(limit))))))
foo(%i)
"""
bar = """\
def bar(limit):
return sorted(set([sum([int(i) for i in str(n)]) for n in [k *9 for k in range(limit)]]))
bar(%i)
"""
rac = """\
def digits(n):
return [n] if n<10 else digits(n / 10)+[n %% 10]
def rabbit(limit):
return sorted(set([sum(digits(n)) for n in [k *9 for k in range(limit)]]))
rabbit(%i)
"""
rab = """\
def sum_digits(number):
result = 0
while number:
digit = number %% 10
result += digit
number /= 10
return result
def rabbit(limit):
return sorted(set([sum_digits(n) for n in [k *9 for k in range(limit)]]))
rabbit(%i)
"""
import timeit
print "convert to string with map", timeit.timeit(foo % 100, number=10000)
print "convert to string with list comprehension", timeit.timeit(bar % 100, number=10000)
print "modulo, division, recursive", timeit.timeit(rac % 100, number=10000)
print "modulo, division", timeit.timeit(rab % 100, number=10000)
After own diligent searches I found several solutions, where each has advantages and disadvantages. Use the most suitable for your task.
All examples tested with the CPython 3.5 on the operation system GNU/Linux Debian 8.
Using a recursion
Code
def get_digits_from_left_to_right(number, lst=None):
"""Return digits of an integer excluding the sign."""
if lst is None:
lst = list()
number = abs(number)
if number < 10:
lst.append(number)
return tuple(lst)
get_digits_from_left_to_right(number // 10, lst)
lst.append(number % 10)
return tuple(lst)
Demo
In [121]: get_digits_from_left_to_right(-64517643246567536423)
Out[121]: (6, 4, 5, 1, 7, 6, 4, 3, 2, 4, 6, 5, 6, 7, 5, 3, 6, 4, 2, 3)
In [122]: get_digits_from_left_to_right(0)
Out[122]: (0,)
In [123]: get_digits_from_left_to_right(123012312312321312312312)
Out[123]: (1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 3, 1, 2, 3, 1, 2, 3, 1, 2)
Using the function divmod
Code
def get_digits_from_right_to_left(number):
"""Return digits of an integer excluding the sign."""
number = abs(number)
if number < 10:
return (number, )
lst = list()
while number:
number, digit = divmod(number, 10)
lst.insert(0, digit)
return tuple(lst)
Demo
In [125]: get_digits_from_right_to_left(-3245214012321021213)
Out[125]: (3, 2, 4, 5, 2, 1, 4, 0, 1, 2, 3, 2, 1, 0, 2, 1, 2, 1, 3)
In [126]: get_digits_from_right_to_left(0)
Out[126]: (0,)
In [127]: get_digits_from_right_to_left(9999999999999999)
Out[127]: (9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9)
Using a construction tuple(map(int, str(abs(number)))
In [109]: tuple(map(int, str(abs(-123123123))))
Out[109]: (1, 2, 3, 1, 2, 3, 1, 2, 3)
In [110]: tuple(map(int, str(abs(1412421321312))))
Out[110]: (1, 4, 1, 2, 4, 2, 1, 3, 2, 1, 3, 1, 2)
In [111]: tuple(map(int, str(abs(0))))
Out[111]: (0,)
Using the function re.findall
In [112]: tuple(map(int, re.findall(r'\d', str(1321321312))))
Out[112]: (1, 3, 2, 1, 3, 2, 1, 3, 1, 2)
In [113]: tuple(map(int, re.findall(r'\d', str(-1321321312))))
Out[113]: (1, 3, 2, 1, 3, 2, 1, 3, 1, 2)
In [114]: tuple(map(int, re.findall(r'\d', str(0))))
Out[114]: (0,)
Using the module decimal
In [117]: decimal.Decimal(0).as_tuple().digits
Out[117]: (0,)
In [118]: decimal.Decimal(3441120391321).as_tuple().digits
Out[118]: (3, 4, 4, 1, 1, 2, 0, 3, 9, 1, 3, 2, 1)
In [119]: decimal.Decimal(-3441120391321).as_tuple().digits
Out[119]: (3, 4, 4, 1, 1, 2, 0, 3, 9, 1, 3, 2, 1)
Use the body of this loop to do whatever you want to with the digits
for digit in map(int, str(my_number)):
I have made this program and here is the bit of code that actually calculates the check digit in my program
#Get the 10 digit number
number=input("Please enter ISBN number: ")
#Explained below
no11 = (((int(number[0])*11) + (int(number[1])*10) + (int(number[2])*9) + (int(number[3])*8)
+ (int(number[4])*7) + (int(number[5])*6) + (int(number[6])*5) + (int(number[7])*4) +
(int(number[8])*3) + (int(number[9])*2))/11)
#Round to 1 dp
no11 = round(no11, 1)
#explained below
no11 = str(no11).split(".")
#get the remainder and check digit
remainder = no11[1]
no11 = (11 - int(remainder))
#Calculate 11 digit ISBN
print("Correct ISBN number is " + number + str(no11))
Its a long line of code, but it splits the number up, multiplies the digits by the appropriate amount, adds them together and divides them by 11, in one line of code. The .split() function just creates a list (being split at the decimal) so you can take the 2nd item in the list and take that from 11 to find the check digit. This could also be made even more efficient by changing these two lines:
remainder = no11[1]
no11 = (11 - int(remainder))
To this:
no11 = (11 - int(no11[1]))
Hope this helps :)
Similar to this answer but more a more "pythonic" way to iterate over the digis would be:
while number:
# "pop" the rightmost digit
number, digit = divmod(number, 10)
How about a one-liner list of digits...
ldigits = lambda n, l=[]: not n and l or l.insert(0,n%10) or ldigits(n/10,l)
Answer: 165
Method: brute-force! Here is a tiny bit of Python (version 2.7) code to count'em all.
from math import sqrt, floor
is_ps = lambda x: floor(sqrt(x)) ** 2 == x
count = 0
for n in range(1002, 10000, 3):
if n % 11 and is_ps(sum(map(int, str(n)))):
count += 1
print "#%i: %s" % (count, n)
Just assuming you want to get the i-th least significant digit from an integer number x, you can try:
(abs(x)%(10**i))/(10**(i-1))
I hope it helps.

Resources