acount total number of letter ONLY alphabet - python-3.x

I have a txt about a English story. My work is counting the total number of letters in this story(alphabet only from "a" to "z" and "A"to "Z" ) . this is what I have wrote:
def count():
file=open("xxx.txt","r")
for line in file:
I dont know how to type next, cuz I only need letter but not 'space",not"!",how can I improve it?

Easy way is to just count them all, then add up the ones you care about (ascii_letters in this case)
from collections import Counter
from string import ascii_letters
def count():
c = Counter()
with open("xxx.txt","r") as file:
for line in file:
c.update(line)
return sum(v for k, v in c.items() if k in ascii_letters)
Another terse approach is to use regex
def count():
with open("xxx.txt","r") as file:
return len(re.findall('[a-zA-Z]', file.read()))
Apparently this is homework and the teacher has imposed some arbitrary restrictions. Still not really any point using ord or chr here
def count():
c = 0
with open("xxx.txt","r") as file:
for line in file:
for ch in line:
if 'a' <= ch <= 'z' or 'A' <= ch <= 'Z':
c += 1
return c

Related

Finding a substring that occurs k times in a long string

I'm trying to solve some algorithm task, but the solution does not pass the time limit.
The condition of the task is the following:
You are given a long string consisting of small Latin letters. We need to find all its substrings of length n that occur at least k times.
Input format:
The first line contains two natural numbers n and k separated by a space.
The second line contains a string consisting of small Latin letters. The string length is 1 ≤ L ≤ 10^6.
n ≤ L, k ≤ L.
Output Format:
For each found substring, print the index of the beginning of its first occurrence (numbering in the string starts from zero).
Output indexes in any order, in one line, separated by a space.
My final solution looks something like this:
def polinomial_hash(s: str, q: int, R: int) -> int:
h = 0
for c in s:
h = (h * q + ord(c)) % R
return h
def get_index_table(inp_str, n):
q = 1000000007
power = q ** (n-1)
R = 2 ** 64
M = len(inp_str)
res_dict = {}
cur_hash = polinomial_hash(inp_str[:n], q, R)
res_dict[cur_hash] = [0]
for i in range(n, M):
first_char = inp_str[i-n]
next_char = inp_str[i]
cur_hash = (
(cur_hash - ord(first_char)*(power))*q
+ ord(next_char)) % R
try:
d_val = res_dict[cur_hash]
d_val += [i-n+1]
except KeyError:
res_dict[cur_hash] = [i-n+1]
return res_dict
if __name__ == '__main__':
n, k = [int(i) for i in input().split()]
inp_str = input()
for item in get_index_table(inp_str, n).values():
if len(item) >= k:
print(item[0], end=' ')
Is it possible to somehow optimize this solution, or advise some alternative options?!

suggestion for improving my long python code with a shorter and correct version

As a part of an online exercise, I want to Write a function, persistence, that takes in a positive parameter num and returns its
multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit.
For example:
persistence(39) => 3 # Because 3*9 = 27, 2*7 = 14, 1*4=4
# and 4 has only one digit.
persistence(999) => 4 # Because 9*9*9 = 729, 7*2*9 = 126,
# 1*2*6 = 12, and finally 1*2 = 2.
persistence(4) => 0 # Because 4 is already a one-digit number.
This is my code:
def persistence(n):
count=0
if n<10:
return(count)
else:
count+=1
a=([int(d) for d in str(n)])
result = 1
for i in a:
result=result*i
if result<10:
return(count)
else:
count+=1
a=([int(d) for d in str(result)])
result1 = 1
for i in a:
result1=result1*i
if result1<10:
return(count)
else:
count+=1
a=([int(d) for d in str(result1)])
result2=1
for i in a:
result2=result2*i
if result2<10:
return(count)
else:
count+=1
a=([int(d) for d in str(result1)])
result3=1
for i in a:
result3=result3*i
if result3<10:
return(count)
but when I try n=999 it gives me 2 which is incorrect. Also it is limited to only 4 multiplicative persistence. How can I improve this code. Tnx in advance!
Your code does not work because you don't know how many times you need to perform the operation to get a single digit number. What you can do in this situation is create a loop and let it run as long as the number is greater than 10. You can try something like this:
from functools import reduce
from operator import mul
def persistence(n):
count = 0
while n >= 10:
n = reduce(mul, map(int, str(n)))
count += 1
return count
And the reason why it does not work for 999 is because the if statement in the second for loop. You are checking if result1 is smaller than 10 inside the loop.
I found this short answer as well:
import operator
def persistence(n):
i = 0
while n>=10:
n=reduce(operator.mul,[int(x) for x in str(n)],1)
i+=1
return i

conting of input names

I have a python homework which I need to take n from input to know how many names I have to take from input, save them to a dictionary then count how many each name was inputed, something like voting system.
so far I couldn't save my input into a dic.
Because I stored all inputs in a list after I assign my list with a dict, it turns to str.
for example:
how many vote u want to input : 4
take your votes:
jack
jasmin
jack
sara
result:
jack 2
jasmin 1
sara 1
My code:
vorodi=[]
n=int(input())
counter={}
for i in range(0,n):
vorodi.append(input())
for letter in vorodi:
if letter not in counter:
counter[letter]+=1
else:
counter[letter]=1
print(counter)
This is a classic case where you will want to use defaultdict. With defaultdict you specify the type of new keys and so if the key is not present it will be initialized to the default of the type specified. So you could do:
from collections import defaultdict
n = int(input())
counter = defaultdict(int)
for i in range(n):
counter[input()] += 1
print(counter.items())
OR:
with regular dict using the get method with the default argument:
n = int(input())
counter = {}
for i in range(n):
name = input()
count = counter.get(name, 0)
counter[name] = count + 1
OR:
with regular dict using the setdefault method with the default argument:
n = int(input())
counter = {}
for i in range(n):
name = input()
counter.setdefault(name, 0)
counter[name] += 1
To print it as you showed you can simply iterate the dict afterwards:
for k,v in counter.items():
print(k, v)

Format output right to left

I am trying to learn how to format print to make it look neat. My program would count how many vowels are in a piece of text. But wont print the way I would like which is right to left
As example -
I would like it to print as:
a : 100
e : 50
i : 31
o : 10
u : 1
Currently I have it printing as the following:
a : 100
e : 50
i : 31
o : 10
u : 1
Here is my code and the printing option so far....
import sys
vowels = {i:0 for i in 'aeiou'}
def check(string):
for char in string:
if char in vowels:
vowels[char] +=1
return vowels
def main():
for line in sys.stdin:
lines = line.lower().strip()
check(lines)
sortvowels = sorted(vowels, key=vowels.get, reverse=True)
for r in sortvowels:
print(' {:} {} {:>d}'.format(r,":",vowels[r]))
#for keys, values in sorted(vowels.items(),reverse=False):
# print('{} : {:d}'.format(keys, vowels[maximum]))
if __name__ == '__main__':
main()
I solved this problem by obtaining the max value from my dictionary,
I had to add the additional code,
formt = max(vowels.values())
finalformat = len(str(formt))
I did this by formt = max(vowels.values())
In order to actually use this, I had to convert that into a string.
I did this by finalformat = len(str(formt))
To finally be able to print I did the following:
sortvowels = sorted(vowels, key=vowels.get, reverse=True)
for r in sortvowels:
print('{} {} {:>{}}'.format(r,":",vowels[r],finalformat))

Three consecutive characters that are also alphabetical

Write a program that accepts a word as input and determines whether or not it has three consecutive letters that are also consecutive letters in the alphabet.
This one has been hard for me. My though process was to use ord() and get a mean, and if the mean = the 2nd character it was right.
word = input("Please enter a word:")
n = len(word)
for i in range(n-2):
i = 0
if ord (word [i+1]) - ord (word [i]) == 1:
print("This works!")
elif ord (word [i+2] - ord (word [i+1] - ord (word [i]) == 1:
print ("This also works.
else:
print("This doesn't work.")
Using the mean is not a good idea. The mean of 8,9,10 is 9, but so is the mean of 5,9,13.
How about doing what the question states:
def consec(s, n=3):
l = len(s)
if l < n:
raise ValueError("String too short to contain repetition of length {}".format(n))
for i in range(l-2):
# Check if you get the same letter by adding 1 or 2 to the next ones
# or by substracting 1 or 2...
if ord(s[i]) == ord(s[i+1])+1 == ord(s[i+2])+2 or \
ord(s[i]) == ord(s[i+1])-1 == ord(s[i+2])-2:
return s[i:i+3]
return ""
This is case-sensitive, by the way:
In [11]: consec("cba")
Out[11]: 'cba'
In [12]: consec("Abc")
Out[12]: ''
In [13]: consec("cdskj sdoifsdjflkduf sdfjstudfu0gnfgsba")
Out[13]: 'stu'

Resources