Timeout error in "simple" code - python

I have the following statement:
There are two type of commands:
store email_content urgency, where email_content is a String consisting of [a-zA-Z0-9_] and urgency is a positive integer
get_next_email - a request that expects email_content with highest urgency as a response. If there are 1+ emails with same urgency, output the one that was stored first. If there are no outstanding emails print "-1" string on a newline.
Input example:
4
store email1 1
store email2 10
store email3 10
get_next_email
Output:
email2
My code:
emails = {}
urgencies = set()
for _ in range(int(input())):
info = input().strip().split(" ")
if info[0] == "store":
info[2] = int(info[2])
urgencies.add(info[2])
if info[2] in emails:
emails[info[2]].append(info[1])
else:
emails[info[2]] = [info[1]]
elif info[0] == "get_next_email":
if emails:
maxval = max(urgencies)
print(emails[maxval].pop(0))
if emails[maxval] == []:
emails.pop(maxval, None)
urgencies.remove(maxval)
else:
print("-1")
I get a runtime error, which according to what I've read is a consecuence of the compexity being very big, and I don't think my code is that complex. What am I doing wrong? And what can I do to improve this? Thanks!
EDIT: It's a contest, the exact error is: Terminated due to timeout (10s)

Related

count distinct gmail addresses

need to count distinct gmail addresses provided by user as input, here are the conditions:
not case sensitive :
"a#gmail.com" == "A#GmaiL.com"
The ‘.’ character in the string in the local name is ignored :
"aa#gmail.com" == "a.a#gmail.com"
Gmail domain is same as googlemail
"aa#gmail.com" == "aa#googlemail.com"
my issue is with the very last one. How to implement the last condition in my code?
distinct_emails=[]
email = []
count=0
for i in range(int(input())):
item = input().lower().replace(".","")
email.append(item)
for i in email:
if i not in distinct_emails:
count = count + 1
distinct_emails.append(i)
print(count)
You could try something like this, where for gmail and googlemail addresses, you check for the swapped versions before appending it to the distinct_emails list.
distinct_emails=[]
email = []
count=0
for i in range(int(input())):
item = e.lower()
# don't remove `.` after the `#`.
parts = item.split("#")
email.append(parts[0].replace(".", "") + "#" + parts[1])
for i in email:
# consider googlemail and gmail to be equivalent
if not any(e in distinct_emails for e in [i, i.replace('#googlemail.com', '#gmail.com'), i.replace('#gmail.com', '#googlemail.com')]):
count = count + 1
distinct_emails.append(i)
print(count)

Pull variable data from all outlook emails that have a particular subject line then take date from the body

I get an email every day with fruit quantities sold on the day. Though I now have come up with some code to log the relevant data going forward, I have been unable to do it going backwards.
The data is stored in the body of the email like so:
Date of report:,01-Jan-2020
Apples,8
Pears,5
Lemons,7
Oranges,9
Tomatoes,6
Melons,3
Bananas,0
Grapes,4
Grapefruit,8
Cucumber,2
Satsuma,1
What I would like for the code to do is first search through my emails and find the emails that match a particular subject, iterate line by line through and find the variables I'm searching for, and then log them in a dataframe with the "Date of Report" logged in a date column and converted into the format: "%m-%d-%Y".
I think I can achieve this by doing some amendments to the code I've written to deal with keeping track of it going forward:
# change for the fruit you're looking for
Fruit_1 = "Apples"
Fruit_2 = "Pears"
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
messages.Sort("[ReceivedTime]", True)
# find data email
for message in messages:
if message.subject == 'FRUIT QUANTITIES':
if Fruit_1 and Fruit_2 in message.body:
data = str(message.body)
break
else:
print('No data for', Fruit_1, 'or', Fruit_2, 'was found')
break
fruitd = open("fruitd.txt", "w") # copy the contents of the latest email into a .txt file
fruitd.write(data)
fruitd.close()
def get_vals(filename: str, searches: list) -> dict:
#Searches file for search terms and returns the values
dct = {}
with open(filename) as file:
for line in file:
term, *value = line.strip().split(',')
if term in searches:
dct[term] = float(value[0]) # Unpack value
# if terms are not found update the dictionary w remaining and set value to None
if len(dct.keys()) != len(searches):
dct.update({x: None for x in search_terms if x not in dct})
return dct
searchf = [
Fruit_1,
Fruit_2
] # the list of search terms the function searches for
result = get_vals("fruitd.txt", searchf) # search for terms
print(result)
# create new dataframe with the values from the dictionary
d = {**{'date':today}, **result}
fruit_vals = pd.DataFrame([d]).rename(columns=lambda z: z.upper())
fruit_vals['DATE'] = pd.to_datetime(fruit_vals['DATE'], format='%d-%m-%Y')
print(fruit_vals)
I'm creating a .txt titled 'fruitd' because I was unsure how I could iterate through an email message body any other way. Unfortunately I don't think creating a .txt for each of the past emails is really feasible and I was wondering whether there's a better way of doing it?
Any advice or pointers would be most welcome.
**EDIT Ideally would like to get all the variables in the search list; so Fruit_1 & Fruit_2 with room to expand it to a Fruit_3 + Fruit_4 (etc) if necessary.
#PREP THE STUFF
Fruit_1 = "Apples"
Fruit_2 = "Pears"
SEARCHF = [
Fruit_1,
Fruit_2
]
#DEF THE STUFF
# modified to take a list of list of strs as `report` arg
# apparently IDK how to type-hint; type-hinting removed
def get_report_vals(report, searches):
dct = {}
for line in report:
term, *value = line
# `str.casefold` is similar to `str.lower`, arguably better form
# if there might ever be a possibility of dealing with non-Latin chars
if term.casefold().startswith('date'):
#FIXED (now takes `date` str out of list)
dct['date'] = pd.to_datetime(value[0])
elif term in searches:
dct[term] = float(value[0])
if len(dct.keys()) != len(searches):
# corrected (?) `search_terms` to `searches`
dct.update({x: None for x in searches if x not in dct})
return dct
#DO THE STUFF
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
messages.Sort("[ReceivedTime]", True)
results = []
for message in messages:
if message.subject == 'FRUIT QUANTITIES':
# are you looking for:
# Fruit_1 /and/ Fruit_2
# or:
# Fruit_1 /or/ Fruit_2
if Fruit_1 in message.body and Fruit_2 in message.body:
# FIXED
data = [line.strip().split(",") for line in message.body.split('\n')]
results.append(get_report_vals(data, SEARCHF))
else:
pass
fruit_vals = pd.DataFrame(results)
fruit_vals.columns = map(str.upper, fruit_vals.columns)

Extract emails from the entered values in python

My objective is: I need to ask the user to enter the number of emails and then initiate a for loop to register the input email. Then, the emails will be segregated based on '#professor.com' and '#student.com'. This will be counted as appended in the list. Following is what I have tried
email_count = int(input('how many emails you want'))
student_email_count = 0
professor_email_count = 0
student_email = '#student.com'
professor_email = '#professor.com'
for i in range(email_count):
email_list = str(input('Enter the emails')
if email_list.index(student_email):
student_email_count = student_email_count + 1
elif email_list.index(professor_email):
professor_email_count = professor_email_count + 1
Can someone help to shorten this and write it professional with explanations for further reference? Here, the appending part is missing. Could someone through some light there too ?
Thanks
prof_email_count, student_email_count = 0, 0
for i in range(int(input("Email count # "))):
email = input("Email %s # " % (i+1))
if email.endswith("#student.com"): # str.endswith(s) checks whether `str` ends with s, returns boolean
student_email_count += 1
elif email.endswith("#professor.com"):
prof_email_count += 1
Is what a (somewhat) shortened rendition of your code would look like. Main differences is that I'm using str.endswith(...) over str.index(...), also that I've removed the email_count, student_email and professor_email variables which didn't seem to be used anywhere else in the context.
EDIT:
To answer your comment on scalability, you could implement a system such as this:
domains = {
"student.com": 0,
"professor.com": 0,
"assistant.com": 0
}
for i in range(int(input("Email count # "))):
email = input("Email %s # " % (i+1))
try:
domain = email.split('#')[1]
except IndexError:
print("No/invalid domain passed")
continue
if domain not in domains:
print("Domain: %s, invalid." % domain)
continue
domains[domain] += 1
Which allows for further scalability as you can add more domains to the domains dictionary, and access the count per domains[<domain>]
It seems your iteration accepts one email at a time; and executes email_count times. You can use this simple code to count students and professors:
st = '#student.com'
prof = '#professor.com'
for i in range(email_count):
email = str(input('Enter the email'))
if st in email:
student_email_count += 1
elif prof in email:
professor_email_count += 1
else:
print('invalid email domain')
If you are using Python 2.7, you should change input to raw_input.
Here's a scalable version for your code, using defaultdict to support unlimited domains.
email_count = int(input('how many emails you want'))
student_email_count = 0
professor_email_count = 0
from collections import defaultdict
domains = defaultdict(int)
for i in range(email_count):
email = str(raw_input('Enter the email\n'))
try:
email_part = email.split('#')[1]
except IndexError:
print('invalid email syntax')
else:
domains[email_part] += 1

Bad search filter

Im trying to filter few attributes from the ldap server but get errors,
ldap.FILTER_ERROR: {'desc': 'Bad search filter'}
Code:-
import ldap
ldap.OPT_REFERRALS = 0
ldap_server="ldapps.test.com"
username = "testuser"
password= "" #your password
connect = ldap.open(ldap_server)
dn='uid='+username;
print 'dn =', dn
try:
result = connect.simple_bind_s(username,password)
print 'connected == ', result
filter1 = "(|(uid=" + username + "\*))"
result = connect.search("DC=cable,DC=com,DC=com",ldap.SCOPE_SUBTREE,filter1)
print result
except ldap.INVALID_CREDENTIALS as e:
connect.unbind_s()
print "authentication error == ", e
Your search filter is, in fact, bad.
The | character is for joining several conditions together in an OR statement. For example, if you wanted to find people with a last name of "smith", "jones", or "baker", you would use this filter:
(|(lastname=smith)(lastname=jones)(lastname=baker))
However, your filter only has one condition, so there's nothing for the | character to join together. Change your filter to this and it should work:
"(uid=" + username + "\*)"
By the way, what are you trying to do with the backslash and asterisk? Are you looking for people whose usernames actually end with an asterisk?

Need to handle keyerror exception python

I'm getting a keyerror exception when I input a player name here that is not in the records list. I can search it and get back any valid name, but if I input anything else, i get a keyerror. I'm not really sure how to go about handling this since it's kindof confusing already dealing with like 3 sets of data created from parsing my file.
I know this code is bad I'm new to python so please excuse the mess - also note that this is a sortof test file to get this functionality working, which I will then write into functions in my real main file. Kindof a testbed here, if that makes any sense.
This is what my data file, stats4.txt, has in it:
[00000] Cho'Gath - 12/16/3 - Loss - 2012-11-22
[00001] Fizz - 12/5/16 - Win - 2012-11-22
[00002] Caitlyn - 13/4/6 - Win - 2012-11-22
[00003] Sona - 4/5/9 - Loss - 2012-11-23
[00004] Sona - 2/1/20 - Win - 2012-11-23
[00005] Sona - 6/3/17 - Loss - 2012-11-23
[00006] Caitlyn - 14/2/16 - Win - 2012-11-24
[00007] Lux - 10/2/14 - Win - 2012-11-24
[00008] Sona - 8/1/22 - Win - 2012-11-27
Here's my code:
import re
info = {}
records = []
search = []
with open('stats4.txt') as data:
for line in data:
gameid = [item.strip('[') for item in line.split(']')]
del gameid[-1]
gameidstr = ''.join(gameid)
gameid = gameidstr
line = line[7:]
player, stats, outcome, date = [item.strip() for item in line.split('-', 3)]
stats = dict(zip(('kills', 'deaths', 'assists'), map(int, stats.split('/'))))
date = tuple(map(int, date.split('-')))
info[player] = dict(zip(('gameid', 'player', 'stats', 'outcome', 'date'), (gameid, player, stats, outcome, date)))
records.append(tuple((gameid, info[player])))
print "\n\n", info, "\n\n" #print the info dictionary just to see
champ = raw_input() #get champion name
#print info[champ].get('stats').get('kills'), "\n\n"
#print "[%s] %s - %s/%s/%s - %s-%s-%s" % (info[champ].get('gameid'), champ, info[champ].get('stats').get('kills'), info[champ].get('stats').get('deaths'), info[champ].get('stats').get('assists'), info[champ].get('date')[0], info[champ].get('date')[1], info[champ].get('date')[2])
#print "\n\n"
#print info[champ].values()
i = 0
for item in records: #this prints out all records
print "\n", "[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (records[i][0], records[i][1]['player'], records[i][1]['stats']['kills'], records[i][1]['stats']['deaths'], records[i][1]['stats']['assists'], records[i][1]['outcome'], records[i][1]['date'][0], records[i][1]['date'][1], records[i][1]['date'][2])
i = i + 1
print "\n" + "*" * 50
i = 0
for item in records:
if champ in records[i][1]['player']:
search.append(records[i][1])
else:
pass
i = i + 1
s = 0
if not search:
print "no availble records" #how can I get this to print even if nothing is inputted in raw_input above for champ?
print "****"
for item in search:
print "\n[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (search[s]['gameid'], search[s]['player'], search[s]['stats']['kills'], search[s]['stats']['deaths'], search[s]['stats']['assists'], search[s]['outcome'], search[s]['date'][0], search[s]['date'][1], search[s]['date'][2])
s = s + 1
I tried setting up a Try; Except sort of thing but I couldn't get any different result when entering an invalid player name. I think I could probably set something up with a function and returning different things if the name is present or not but I think I've just gotten myself a bit confused. Also notice that no match does indeed print for the 8 records that aren't matches, though thats not quite how I want it to work. Basically I need to get something like that for any invalid input name, not just a valid input that happens to not be in a record in the loop.
Valid input names for this data are:
Cho'Gath, Fizz, Caitlyn, Sona, or Lux - anything else gives a keyerror, thats what I need to handle so it doesn't raise an error and instead just prints something like "no records available for that champion" (and prints that only once, rather then 8 times)
Thanks for any help!
[edit] I was finally able to update this code in the post (thank you martineau for getting it added in, for some reason backticks aren't working to block code and it was showing up as bold normal text when i pasted. Anyways, look at if not search, how can I get that to print even if nothing is entered at all? just pressing return on raw_input, currently it prints all records after **** even though i didn't give it any search champ
where is your exact error occurring?
i'm just assuming it is when champ = raw_input() #get champion name
and then info[champ]
you can either check if the key exists first
if champ not in info:
print 'no records avaialble'
or use get
if info.get(champ)
or you can just try and access the key
try:
info[champ]
# do stuff
except KeyError:
print 'no records available'
the more specific you can be in your question the better, although you explained your problem you really didn't include any specifics Please always include a traceback if available, and post the relevant code IN your post not on a link.
Here's some modifications that I think address your problem. I also reformatted the code to make it a little more readable. In Python it's possible to continue long lines onto the next either by ending with a \ or just going to the next line if there's an unpaired '(' or '[' on the previous line.
Also, the way I put code in my questions or answer here is by cutting it out of my text editor and then pasting it into the edit window, after that I make sure it's all selected and then just use the {} tool at the top of edit window to format it all.
import re
from pprint import pprint
info = {}
records = []
with open('stats4.txt') as data:
for line in data:
gameid = [item.strip('[') for item in line.split(']')]
del gameid[-1]
gameidstr = ''.join(gameid)
gameid = gameidstr
line = line[7:]
player, stats, outcome, date = [item.strip() for item in line.split('-', 3)]
stats = dict(zip(('kills', 'deaths', 'assists'), map(int, stats.split('/'))))
date = tuple(map(int, date.split('-')))
info[player] = dict(zip(('gameid', 'player', 'stats', 'outcome', 'date'),
(gameid, player, stats, outcome, date)))
records.append(tuple((gameid, info[player])))
#print "\n\n", info, "\n\n" #print the info dictionary just to see
pprint(info)
champ = raw_input("Champ's name: ") #get champion name
#print info[champ].get('stats').get('kills'), "\n\n"
#print "[%s] %s - %s/%s/%s - %s-%s-%s" % (
# info[champ].get('gameid'), champ, info[champ].get('stats').get('kills'),
# info[champ].get('stats').get('deaths'), info[champ].get('stats').get('assists'),
# info[champ].get('date')[0], info[champ].get('date')[1],
# info[champ].get('date')[2])
#print "\n\n"
#print info[champ].values()
i = 0
for item in records: #this prints out all records
print "\n", "[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (
records[i][0], records[i][1]['player'], records[i][1]['stats']['kills'],
records[i][1]['stats']['deaths'], records[i][1]['stats']['assists'],
records[i][1]['outcome'], records[i][1]['date'][0],
records[i][1]['date'][1], records[i][1]['date'][2])
i = i + 1
print "\n" + "*" * 50
i = 0
search = []
for item in records:
if champ in records[i][1]['player']:
search.append(records[i][1])
i = i + 1
if not search:
print "no match"
exit()
s = 0
for item in search:
print "\n[%s] %s - %s/%s/%s - %s - %s-%s-%s" % (search[s]['gameid'],
search[s]['player'], search[s]['stats']['kills'],
search[s]['stats']['deaths'], search[s]['stats']['assists'],
search[s]['outcome'], search[s]['date'][0], search[s]['date'][1],
search[s]['date'][2])
s = s + 1

Categories