I'm trying to count the amount of numbers that are length of 5 and has exactly two repeating numbers (where zero can be leading like 00123). What I did:
def checkNumber(num):
temp = [0] * 10
for d in map(int, str(num)):
temp[d] += 1
contains_two_unique_digits = False
for d in temp:
if d > 2:
return False
if d == 2:
if contains_two_unique_digits:
return False
contains_two_unique_digits = True
return True
counter = 0
for num in range(10000,100000):
counter += checkNumber(num)
print(counter)
But of course it does not count the cases with a leading zeros. How can I add them here? Python does not allow 001234 numbers.
The zfill method of the str type might be of help.
>>> "123".zfill(5)
'00123'
>>> "123456789".zfill(5)
'123456789'
To convert an int to a str, simply use str:
>>> str(123)
'123'
If you NEED to accept integers in python, then you are correct that no solution can be made. If you can accept a string and treat the values inside as integers, then you can definitely make it happen. A integer or float with leading zeros will always cause an error in Python.
def checkNumber(string_input):
# is it a string?
if not isinstance(string_input, str):
string_input = str(string_input)
# does it have five characters?
if not len(string_input) == 5:
raise ValueError('You must enter a string of length 5.')
counter_list = [0] * 10
# iterate over the string and count how many of each integer we have
for value in string_input:
if value.isdigit():
counter_list[int(value)] += 1
# check to see if any of them have identically two
for value_count in counter_list:
if value_count == 2:
return True
return False
print(checkNumber('01234'))
If you want to iterate over numbers by their digit representation, then itertool.product() will likely be more useful. itertools.product(string.digits, repeat=5) will yield each of the numbers you need, as digit tuples.
Taking advantage of collections.Counter can also help here, and avoids the flag / loop logic.
from collections import Counter
from itertools import product
from typing import Tuple
import string
def has_two_repeats(digits: Tuple[str, ...]):
counts = Counter(digits).values()
return (
# no digits occur more than 2 times
sum(count > 2 for count in counts) == 0 and
# one digit occcurs two times
sum(count == 2 for count in counts) == 1
)
def all_two_repeats_five_digits() -> int:
return sum(
has_two_repeats(digits)
for digits in product(string.digits, repeat=5)
)
print(all_two_repeats_five_digits())
This question already has answers here:
How to find all occurrences of a substring?
(32 answers)
Closed 12 months ago.
How do I find multiple occurrences of a string within a string in Python? Consider this:
>>> text = "Allowed Hello Hollow"
>>> text.find("ll")
1
>>>
So the first occurrence of ll is at 1 as expected. How do I find the next occurrence of it?
Same question is valid for a list. Consider:
>>> x = ['ll', 'ok', 'll']
How do I find all the ll with their indexes?
Using regular expressions, you can use re.finditer to find all (non-overlapping) occurences:
>>> import re
>>> text = 'Allowed Hello Hollow'
>>> for m in re.finditer('ll', text):
print('ll found', m.start(), m.end())
ll found 1 3
ll found 10 12
ll found 16 18
Alternatively, if you don't want the overhead of regular expressions, you can also repeatedly use str.find to get the next index:
>>> text = 'Allowed Hello Hollow'
>>> index = 0
>>> while index < len(text):
index = text.find('ll', index)
if index == -1:
break
print('ll found at', index)
index += 2 # +2 because len('ll') == 2
ll found at 1
ll found at 10
ll found at 16
This also works for lists and other sequences.
I think what you are looking for is string.count
"Allowed Hello Hollow".count('ll')
>>> 3
Hope this helps
NOTE: this only captures non-overlapping occurences
For the list example, use a comprehension:
>>> l = ['ll', 'xx', 'll']
>>> print [n for (n, e) in enumerate(l) if e == 'll']
[0, 2]
Similarly for strings:
>>> text = "Allowed Hello Hollow"
>>> print [n for n in xrange(len(text)) if text.find('ll', n) == n]
[1, 10, 16]
this will list adjacent runs of "ll', which may or may not be what you want:
>>> text = 'Alllowed Hello Holllow'
>>> print [n for n in xrange(len(text)) if text.find('ll', n) == n]
[1, 2, 11, 17, 18]
FWIW, here are a couple of non-RE alternatives that I think are neater than poke's solution.
The first uses str.index and checks for ValueError:
def findall(sub, string):
"""
>>> text = "Allowed Hello Hollow"
>>> tuple(findall('ll', text))
(1, 10, 16)
"""
index = 0 - len(sub)
try:
while True:
index = string.index(sub, index + len(sub))
yield index
except ValueError:
pass
The second tests uses str.find and checks for the sentinel of -1 by using iter:
def findall_iter(sub, string):
"""
>>> text = "Allowed Hello Hollow"
>>> tuple(findall_iter('ll', text))
(1, 10, 16)
"""
def next_index(length):
index = 0 - length
while True:
index = string.find(sub, index + length)
yield index
return iter(next_index(len(sub)).next, -1)
To apply any of these functions to a list, tuple or other iterable of strings, you can use a higher-level function —one that takes a function as one of its arguments— like this one:
def findall_each(findall, sub, strings):
"""
>>> texts = ("fail", "dolly the llama", "Hello", "Hollow", "not ok")
>>> list(findall_each(findall, 'll', texts))
[(), (2, 10), (2,), (2,), ()]
>>> texts = ("parallellized", "illegally", "dillydallying", "hillbillies")
>>> list(findall_each(findall_iter, 'll', texts))
[(4, 7), (1, 6), (2, 7), (2, 6)]
"""
return (tuple(findall(sub, string)) for string in strings)
For your list example:
In [1]: x = ['ll','ok','ll']
In [2]: for idx, value in enumerate(x):
...: if value == 'll':
...: print idx, value
0 ll
2 ll
If you wanted all the items in a list that contained 'll', you could also do that.
In [3]: x = ['Allowed','Hello','World','Hollow']
In [4]: for idx, value in enumerate(x):
...: if 'll' in value:
...: print idx, value
...:
...:
0 Allowed
1 Hello
3 Hollow
This code might not be the shortest/most efficient but it is simple and understandable
def findall(f, s):
l = []
i = -1
while True:
i = s.find(f, i+1)
if i == -1:
return l
l.append(s.find(f, i))
findall('test', 'test test test test')
# [0, 5, 10, 15]
For the first version, checking a string:
def findall(text, sub):
"""Return all indices at which substring occurs in text"""
return [
index
for index in range(len(text) - len(sub) + 1)
if text[index:].startswith(sub)
]
print(findall('Allowed Hello Hollow', 'll'))
# [1, 10, 16]
No need to import re. This should run in linear time, as it only loops through the string once (and stops before the end, once there aren't enough characters left to fit the substring). I also find it quite readable, personally.
Note that this will find overlapping occurrences:
print(findall('aaa', 'aa'))
# [0, 1]
>>> for n,c in enumerate(text):
... try:
... if c+text[n+1] == "ll": print n
... except: pass
...
1
10
16
This version should be linear in length of the string, and should be fine as long as the sequences aren't too repetitive (in which case you can replace the recursion with a while loop).
def find_all(st, substr, start_pos=0, accum=[]):
ix = st.find(substr, start_pos)
if ix == -1:
return accum
return find_all(st, substr, start_pos=ix + 1, accum=accum + [ix])
bstpierre's list comprehension is a good solution for short sequences, but looks to have quadratic complexity and never finished on a long text I was using.
findall_lc = lambda txt, substr: [n for n in xrange(len(txt))
if txt.find(substr, n) == n]
For a random string of non-trivial length, the two functions give the same result:
import random, string; random.seed(0)
s = ''.join([random.choice(string.ascii_lowercase) for _ in range(100000)])
>>> find_all(s, 'th') == findall_lc(s, 'th')
True
>>> findall_lc(s, 'th')[:4]
[564, 818, 1872, 2470]
But the quadratic version is about 300 times slower
%timeit find_all(s, 'th')
1000 loops, best of 3: 282 µs per loop
%timeit findall_lc(s, 'th')
10 loops, best of 3: 92.3 ms per loop
Brand new to programming in general and working through an online tutorial. I was asked to do this as well, but only using the methods I had learned so far (basically strings and loops). Not sure if this adds any value here, and I know this isn't how you would do it, but I got it to work with this:
needle = input()
haystack = input()
counter = 0
n=-1
for i in range (n+1,len(haystack)+1):
for j in range(n+1,len(haystack)+1):
n=-1
if needle != haystack[i:j]:
n = n+1
continue
if needle == haystack[i:j]:
counter = counter + 1
print (counter)
The following function finds all the occurrences of a string inside another while informing the position where each occurrence is found.
You can call the function using the test cases in the table below. You can try with words, spaces and numbers all mixed up.
The function works well with overlapping characters.
theString
aString
"661444444423666455678966"
"55"
"661444444423666455678966"
"44"
"6123666455678966"
"666"
"66123666455678966"
"66"
Calling examples:
1. print("Number of occurrences: ", find_all("123666455556785555966", "5555"))
output:
Found in position: 7
Found in position: 14
Number of occurrences: 2
2. print("Number of occurrences: ", find_all("Allowed Hello Hollow", "ll "))
output:
Found in position: 1
Found in position: 10
Found in position: 16
Number of occurrences: 3
3. print("Number of occurrences: ", find_all("Aaa bbbcd$###abWebbrbbbbrr 123", "bbb"))
output:
Found in position: 4
Found in position: 21
Number of occurrences: 2
def find_all(theString, aString):
count = 0
i = len(aString)
x = 0
while x < len(theString) - (i-1):
if theString[x:x+i] == aString:
print("Found in position: ", x)
x=x+i
count=count+1
else:
x=x+1
return count
#!/usr/local/bin python3
#-*- coding: utf-8 -*-
main_string = input()
sub_string = input()
count = counter = 0
for i in range(len(main_string)):
if main_string[i] == sub_string[0]:
k = i + 1
for j in range(1, len(sub_string)):
if k != len(main_string) and main_string[k] == sub_string[j]:
count += 1
k += 1
if count == (len(sub_string) - 1):
counter += 1
count = 0
print(counter)
This program counts the number of all substrings even if they are overlapped without the use of regex. But this is a naive implementation and for better results in worst case it is advised to go through either Suffix Tree, KMP and other string matching data structures and algorithms.
Here is my function for finding multiple occurrences. Unlike the other solutions here, it supports the optional start and end parameters for slicing, just like str.index:
def all_substring_indexes(string, substring, start=0, end=None):
result = []
new_start = start
while True:
try:
index = string.index(substring, new_start, end)
except ValueError:
return result
else:
result.append(index)
new_start = index + len(substring)
A simple iterative code which returns a list of indices where the substring occurs.
def allindices(string, sub):
l=[]
i = string.find(sub)
while i >= 0:
l.append(i)
i = string.find(sub, i + 1)
return l
You can split to get relative positions then sum consecutive numbers in a list and add (string length * occurence order) at the same time to get the wanted string indexes.
>>> key = 'll'
>>> text = "Allowed Hello Hollow"
>>> x = [len(i) for i in text.split(key)[:-1]]
>>> [sum(x[:i+1]) + i*len(key) for i in range(len(x))]
[1, 10, 16]
>>>
Maybe not so Pythonic, but somewhat more self-explanatory. It returns the position of the word looked in the original string.
def retrieve_occurences(sequence, word, result, base_counter):
indx = sequence.find(word)
if indx == -1:
return result
result.append(indx + base_counter)
base_counter += indx + len(word)
return retrieve_occurences(sequence[indx + len(word):], word, result, base_counter)
I think there's no need to test for length of text; just keep finding until there's nothing left to find. Like this:
>>> text = 'Allowed Hello Hollow'
>>> place = 0
>>> while text.find('ll', place) != -1:
print('ll found at', text.find('ll', place))
place = text.find('ll', place) + 2
ll found at 1
ll found at 10
ll found at 16
You can also do it with conditional list comprehension like this:
string1= "Allowed Hello Hollow"
string2= "ll"
print [num for num in xrange(len(string1)-len(string2)+1) if string1[num:num+len(string2)]==string2]
# [1, 10, 16]
I had randomly gotten this idea just a while ago. Using a While loop with string splicing and string search can work, even for overlapping strings.
findin = "algorithm alma mater alison alternation alpines"
search = "al"
inx = 0
num_str = 0
while True:
inx = findin.find(search)
if inx == -1: #breaks before adding 1 to number of string
break
inx = inx + 1
findin = findin[inx:] #to splice the 'unsearched' part of the string
num_str = num_str + 1 #counts no. of string
if num_str != 0:
print("There are ",num_str," ",search," in your string.")
else:
print("There are no ",search," in your string.")
I'm an amateur in Python Programming (Programming of any language, actually), and am not sure what other issues it could have, but I guess it's working fine?
I guess lower() could be used somewhere in it too if needed.
I'm creating a python script which prints out the whole song of '99 bottles of beer', but reversed. The only thing I cannot reverse is the numbers, being integers, not strings.
This is my full script,
def reverse(str):
return str[::-1]
def plural(word, b):
if b != 1:
return word + 's'
else:
return word
def line(b, ending):
print b or reverse('No more'), plural(reverse('bottle'), b), reverse(ending)
for i in range(99, 0, -1):
line(i, "of beer on the wall")
line(i, "of beer"
print reverse("Take one down, pass it around")
line(i-1, "of beer on the wall \n")
I understand my reverse function takes a string as an argument, however I do not know how to take in an integer, or , how to reverse the integer later on in the script.
Without converting the number to a string:
def reverse_number(n):
r = 0
while n > 0:
r *= 10
r += n % 10
n /= 10
return r
print(reverse_number(123))
You are approaching this in quite an odd way. You already have a reversing function, so why not make line just build the line the normal way around?
def line(bottles, ending):
return "{0} {1} {2}".format(bottles,
plural("bottle", bottles),
ending)
Which runs like:
>>> line(49, "of beer on the wall")
'49 bottles of beer on the wall'
Then pass the result to reverse:
>>> reverse(line(49, "of beer on the wall"))
'llaw eht no reeb fo selttob 94'
This makes it much easier to test each part of the code separately and see what's going on when you put it all together.
Something like this?
>>> x = 123
>>> str(x)
'123'
>>> str(x)[::-1]
'321'
best way is
x=12345
a=str(x)[::-1]\\ In this process i have create string of inverse of integer (a="54321")
a=int(a) \\ Here i have converted string a in integer
or
one line code is
a=int(str(x)[::-1]))
def reverse(x):
re = 0
negative = x < 0
MAX_BIG = 2 ** 31 -1
MIN_BIG = -2 ** 31
x = abs(x)
while x != 0:
a = int(x % 10)
re = re * 10 + a
x = int(x // 10)
reverse = -1 * re if negative else re
return 0 if reverse < MIN_BIG or reverse > MAX_BIG else reverse
this is for 32 - bit integer ( -2^31 ; 2^31-1 )
def reverse_number(n):
r = 0
while n > 0:
r = (r*10) + (n % 10)
print(r)
r *=10
n //= 10
return r
print(reverse_number(123))
You can cast an integer to string with str(i) and then use your reverse function.
The following line should do what you are looking for:
def line(b, ending):
print reverse(str(b)) or reverse('No more'), plural(reverse('bottle'),reverse(str(b))), reverse(ending)
Original number is taken in a
a = 123
We convert the int to string ,then reverse it and again convert in int and store reversed number in b
b = int("".join(reversed(str(a))))
Print the values of a and b
print(a,b)
def reverse_number(n):
r = 0
while n > 0:
r *= 10
r += n % 10
n /= 10
return r
print(reverse_number(123))
This code will not work if the number ends with zeros, example 100 and 1000 return 1
def reverse(num):
rev = 0
while(num != 0):
reminder = num % 10
rev = (rev * 10 ) + reminder
num = num // 10
print ("Reverse number is : " , rev )
num=input("enter number : ")
reverse(int(num))
#/ always results into float
#// division that results into whole number adjusted to the left in the number line
I think the following code should be good to reverse your positive integer.
You can use it as a function in your code.
n = input() # input is always taken as a string
rev = int(str(n)[::-1])
If you are having n as integer then you need to specify it as str here as shown. This is the quickest way to reverse a positive integer
import math
def Function(inputt):
a = 1
input2 = inputt
while(input2 > 9):
input2 = input2/10
a = a + 1
print("There are ", a, " numbers ")
N = 10
m = 1
print(" THe reverse numbers are: ")
for i in range(a):
l = (inputt%N)/m
print(math.floor(l), end = '')
N = N*10
m = m*10
print(" \n")
return 0
enter = int(input("Enter the number: "))
print(Function(enter))
More robust solution to handle negative numbers:
def reverse_integer(num):
sign = [1,-1][num < 0]
output = sign * int(str(abs(num))[::-1])
An easy and fast way to do it is as follows:
def reverse(x: int|str) -> int:
reverse_x = int(''.join([dgt for dgt in reversed(num:=str(x)) if dgt != '-']))
if '-' in num:
reverse_x = -reverse_x'
return reverse_x
First we create a list (using list comprehension) of the digits in reverse order. However, we must exclude the sign (otherwise the number would turn out like [3, 2, 1, -]). We now turn the list into a string using the ''.join() method.
Next we check if the original number had a negative sign in it. If it did, we would add a negative sign to reverse_x.
Easily you can write this class:
class reverse_number:
def __init__(self,rvs_num):
self.rvs_num = rvs_num
rvs_ed = int(str(rvs_num)[::-1])
print(rvs_ed)
You can use it by writing:
reverse_number(your number)
I have written it in a different way, but it works
def isPalindrome(x: int) -> bool:
if x<0:
return False
elif x<10:
return True
else:
rev=0
rem = x%10
quot = x//10
rev = rev*10+rem
while (quot>=10):
rem = quot%10
quot = quot//10
rev = rev*10+rem
rev = rev*10+quot
if rev==x:
return True
else:
return False
res=isPalindrome(1221)
This question already has answers here:
Python equivalent to atoi / atof
(7 answers)
Closed 9 years ago.
I looked around and I do not see a clear answer for Python to convert an alphanumeric string to a numeric one. Here is an example of numbers I would like to convert.
"1234alpha" --> 1234
"a1234asdf" --> 0
"1234.56yt" --> 1234.56
Any advice would be appreciated.
DK
For a change itertools and no regex:
>>> import itertools as it
>>> number = ''.join(it.takewhile(str.isdigit, '123dfd'))
>>> int(number) if number else 0
123
>>> number = ''.join(it.takewhile(str.isdigit, 'a123dfd'))
int(number) if number else 0
0
Somewhat uglier it works for floats:
>>> number = ''.join(it.takewhile(lambda x: x.isdigit() or
x == '.', '123.45dfd'))
>>> float(number) if number else 0
123.45
Floats, negatives:
def make_number(alphanum):
sign = 1
if alphanum and alphanum[0] in '+-':
sign = int(alphanum[0] + '1')
alphanum = alphanum[1:]
try:
return float(''.join(it.takewhile(lambda x: x.isdigit()
or x == '.', alphanum))) * sign
except ValueError:
return 0
Conclusion: Changing the requirements along the way can turn a simple solution into a complicated one.
To support positive/negative integer/float numbers, you could use a slightly modified regexp from Extract float/double value:
import re
re_float = re.compile("""(?x)
^
[+-]?\ * # first, match an optional sign *and space*
( # then match integers or f.p. mantissas:
\d+ # start out with a ...
(
\.\d* # mantissa of the form a.b or a.
)? # ? takes care of integers of the form a
|\.\d+ # mantissa of the form .b
)
([eE][+-]?\d+)? # finally, optionally match an exponent
""")
def extract_number(s, default=None):
m = re_float.match(s)
if not m:
return default # no number found
f = float(m.group(0)) #XXX to support huge numbers, try/except int() first
return int(f) if f.is_integer() else f
Example
for s in sys.stdin:
print(extract_number(s, default=0))
Input
1234alpha
a1234asdf
1234.56yt
-1e20.
Output
1234
0
1234.56
-100000000000000000000
You can use the re module:
import re
def alp(s):
m = re.match('\d+', s)
return int(m.group(0)) if m is not None and m.start() == 0 else 0
In [3]: alp('a1234asdf')
Out[3]: 0
In [4]: alp('1234alpha')
Out[4]: 1234
If you want to include negative integers:
def alp_neg(s):
m = re.match('[+-]?\d+', s)
return int(m.group(0)) if m is not None and m.start() == 0 else 0
If you want floats too:
def alp_floats(s):
m = re.match('[+-]?\d+(\.\d+)?', s)
return float(m.group(0)) if m is not None and m.start() == 0 else 0
In [7]: alp_floats('-12.2ss31.232sadas')
Out[7]: -12.2
import re
def str_to_int(string):
match = re.match("\d+", string)
if match:
try:
return int(match.group())
except ValueError:
return float(match.group())
else:
return 0
str_to_int("1234alpha")
1234
str_to_int("a1234asdf")
0
import ast
from itertools import takewhile
ast.literal_eval(''.join(takewhile(lambda x: x<='9', string)) or '0')
When the rules for what is OK become hard to define, you might consider this binary search approach that tries to find the bound.
def binsearch_prefix(seq, predicate):
best_upper = 0
lower, upper = 0, len(seq)
while lower < upper:
mid = (lower + upper) / 2
if predicate(seq[:mid]):
best_upper = mid
lower = mid + 1
else:
upper = mid
return seq[:best_upper]
It will return the part of the string that you consider acceptable. For example, this could be your accept function:
def can_float(s):
try:
float(s)
return True
except ValueError:
return False
Example:
print binsearch_prefix(can_float, "1234alpha") # "1234"
print binsearch_prefix(can_float, "a1234asdf") # ""
print binsearch_prefix(can_float, "1234.56yt") # "1234.56"
You may then format the prefix any way you like.
Maybe use regular expressions?
import re
def str2num(s):
try:
num = re.match(r'^([0-9]+)', s).group(1)
except AttributeError:
num = 0
return int(num)
print str2num('1234alpha')
print str2num('a1234asdf')
Output:
1234
0