I am pretty new to Python. I completed a challenge using a script I created. I am sure it can be improved upon and more efficient. I would appreciate suggestions to improve and simplify this script for future use. The challenge was to read from a file and run the value found in the file through base 16, base 32, & base 64 five times each. Below is the script I created. The last variable (v64) contains the flag.
Thank You!
> import base64
>
> i = 0
> with open('encodedflag.txt') as fp:
> v = fp.read()
>
> while i <= 4:
> decoded_16 = base64.b16decode(v)
> v = decoded_16
> i += 1
>
> v32 = v
>
> j = 0
>
> while j <= 4:
> decode_32 = base64.b32decode(v32)
> v32 = decode_32
> j += 1
>
> v64 = v32
>
> k = 0
>
> while k <= 4:
> decode_64 = base64.b64decode(v64)
> v64 = decode_64
> k += 1
>
> print(v64)
This question already has answers here:
Python: Mapping from intervals to values
(6 answers)
Closed 3 years ago.
I have too many if statements and I have a hard time understanding the dictionary system.
It seems like an easy fix, but everything I try I make it worse.
"""
Find the place where the person was born.
Possible locations are following: Kuressaare, Tartu, Tallinn, Kohtla-Järve, Narva, Pärnu,
Paide, Rakvere, Valga, Viljandi, Võru and undefined. Lastly if the number is incorrect the function must return
the following 'Wrong input!'
:param birth_number: int
:return: str
"""
return
if not is_valid_birth_number(birth_number):
return "Wrong input!"
if 10 >= birth_number >= 1:
return "Kuressaare"
elif 20 >= birth_number >= 11:
return "Tartu"
elif 220 >= birth_number >= 21:
return "Tallinn"
elif 270 >= birth_number >= 221:
return "Kohtla-Järve"
elif 370 >= birth_number >= 271:
return "Tartu"
elif 420 >= birth_number >= 371:
return "Narva"
elif 470 >= birth_number >= 421:
return "Pärnu"
elif 490 >= birth_number >= 471:
return "Tallinn"
elif 520 >= birth_number >= 491:
return "Paide"
elif 570 >= birth_number >= 521:
return "Rakvere"
elif 600 >= birth_number >= 571:
return "Valga"
elif 650 >= birth_number >= 601:
return "Viljandi"
elif 710 >= birth_number >= 651:
return "Võru"
elif 999 >= birth_number >= 711:
return "undefined"
Need to get rid of idcode.py:149:1: C901 'get_birth_place' is too complex (16) error.
Use a list that maps the end of each range to the return value.
if not is_valid_birth_number(birth_number):
return "Wrong input!"
locations = [(10, "Kuressaare"), (220, "Tartu"), (270, "Tallinn"), ...]
for limit, loc in locations:
if birth_number <= limit:
return loc
You don't need the beginning and end of each range, because they're in order. Just the end of the range is enough.
An example with bisect.
import bisect
locations = {
1: 'Kuressaare',
2: 'Tartu',
3: 'Tallinn',
4: 'Kohtla-Järve',
5: 'Tartu'
}
birth_number_levels = [1, 11, 21, 221, 271, 371]
position = bisect.bisect(birth_number_levels, birth_number)
return locations[position]
I prefer keeping data together as #Barmar did. This leads to:
import bisect
locations = [
(10, 'Kuressaare'),
(20, 'Tartu'),
(220, 'Tallinn'),
(270, 'Kohtla-Järve'),
(370, 'Tartu')
]
birth_number_levels = [location[0] for location in locations]
position = bisect.bisect_left(birth_number_levels, birth_number)
return locations[position][1]
I'd go with a dictionary, which contains keys as ranges and the value is the name of location.
Then iterate over it checking if the given birth_number is in the key.
Basically:
loc_dict = {
range(1, 11): "Kuressaare",
range(11, 21): "Tartu",
etc...
}
for loc_range, loc_name in loc_dict.items():
if birth_number in loc_range:
return loc_name
I think that's a pretty clear way of handling that.
It's easier to loop through a list than to have to code specific if statements, plus this can be completely dynamic.
def bd(birth_number):
x = ((10,"Kuressaare"),(20,"Tartu"),(220,"Tallinn"),(270,"Tartu"),(370,"Kohtla-Järve"),(420,"Tartu"),(470,"Narva"),(490,"Pärnu"),(520,"Tallinn"),(570,"Paide"),(600,"Rakvere"))
if not isinstance(birth_number, (int, long)):
return "Wrong input!"
for i in x:
if birth_number<= i[0]:
return i[1]
return "undefined"
print(bd(300))
When making a tax calculator, I seem to continue to be getting an error at the "=" in the following line of code:
elif int(vermogen) >= 30001 and <= 100800:
But I can't see a way to fix this. I've tried removing the integers but that didn't help, I've also tried to change my symbols to > and < instead of <= >= but that also didn't help. I think I made an obvious mistake but I don't seem to find it. When removing the "=" behind the "<" The syntax error moves from the "=" to the "<". I hope to hear from you soon. Here is the code I've been using/ It's in dutch, but that shouldn't affect anything.
vermogen = input('Hoeveelheid vermogen: ')
N_schijf1 = 30000
N_schijf2 = 70800
N_schijf3 = 877200
P_schijf2 = 424.8
P_schijf3 = 11403.6
if int(vermogen) <= 30000:
print("Je betaalt 0 euro aan vermogensbelasting")
elif int(vermogen) >= 30001 and <= 100800:
vermogen_betalen = int(vermogen) - N_schijf1
betalen_vermogen = vermogen_betalen * 0.006
print("Je betaalt",betalen_vermogen,"euro aan vermogensbelasting")
elif int(vermogen) >= 100801 and <= 978000:
vermogen_betalen = int(vermogen) - N_schijf1 - P_schijf2
betalen_vermogen = vermogen_betalen * 0.013
tebetalen_vermogen = P_schijf2 + betalen_vermogen
print("Je betaalt",tebetalen_vermogen,"euro aan vermogensbelasting")
elif int(vermogen) >= 978001:
vermogen_betalen = int(vermogen) - N_schijf1 - P_schijf2 - P_schijf3
betalen_vermogen = vermogen_betalen * 0.0161
tebetalen_vermogen = P_schijf2 + P_schijf3 + betalen_vermogen
print("Je betaalt",tebetalen_vermogen,"euro aan vermogensbelasting")
print("Test")
You must have a complete condition on each side of the and. Operands don't carry across the and into the next condition.
You could write:
int(vermogen) >= 30001 and int(vermogen) <= 100800
Or just:
30001 <= int(vermogen) <= 100800
since Python supports chaining of comparisons
you need to change your if from:
elif int(vermogen) >= 100801 and <= 978000:
elif int(vermogen) >= 30001 and <= 100800:
to
elif int(vermogen) >= 100801 and int(vermogen) <= 978000:
elif int(vermogen) >= 30001 and int(vermogen) <= 100800:
I'm getting count of messages from json file, but i have an error... And i do not know why. In this program bot has to send information about member in mention. If I write msg = None at the beginning of the code, it won't send like > messages = 10 it will send messages = None
PROGRAM
if args[0] == '!in':
await client.delete_message(message)
highclass = None
gm = ""
clan = None
if (roleLeaders in message.author.roles or roleHunter in message.author.roles or roleDeputy in message.author.roles):
for member in message.mentions:
user = member
userjoin = str(user.joined_at)
joinpars= userjoin.split()
join = joinpars[0]
msg1 = user_get_msg(member.id)
time1 = user_get_time(member.id)
s = str(msg1)
last = int(s[-1])
st = str(time1)
stm = time1 // 60
sth = stm // 60
std = sth // 24
if time1 <= 60:
lastt = int(st[-1])
if lastt == 0:
time = '{0} секунд'.format(time1)
if lastt == 1 and not time1 == 11:
time = '{0} секунду'.format(time1)
if ((time1 >= 11 and time1 <= 19) or (lastt >= 5 and lastt <= 9)):
time = '{0} секунд'.format(time1)
if (lastt >= 2 and lastt <= 4) and not (time1 >= 11 and time1 <= 19):
time = '{0} секунды'.format(time1)
if time1 <= 3600 and time1 > 60:
lastt = int(str(stm)[-1])
if lastt == 0:
time = '{0} минут'.format(stm)
if lastt == 1 and not stm == 11:
time = '{0} минуту'.format(stm)
if ((stm >= 11 and stm <= 19) or (lastt >= 5 and lastt <= 9)):
time = '{0} минут'.format(stm)
if (lastt >= 2 and lastt <= 4) and not (stm >= 11 and stm <= 19):
time = '{0} минуты'.format(stm)
if time1 <= 86400 and time1 >3600:
lastt = int(str(sth)[-1])
if lastt == 0:
time = '{0} часов'.format(sth)
if lastt == 1 and not sth == 11:
time = '{0} час'.format(sth)
if ((sth >= 11 and sth <= 19) or (lastt >= 5 and lastt <= 9)):
time = '{0} часов'.format(sth)
if (lastt >= 2 and lastt <= 4) and not (sth >= 11 and sth <= 19):
time = '{0} часа'.format(sth)
if time1 >= 86400:
lastt = int(str(std)[-1])
if lastt == 0:
time = '{0} дней'.format(std)
if lastt == 1 and not std == 11:
time = '{0} день'.format(std)
if ((std >= 11 and std <= 19) or (lastt >= 5 and lastt <= 9)):
time = '{0} дней'.format(std)
if (lastt >= 2 and lastt <= 4) and not (std >= 11 and std <= 19):
time = '{0} дня'.format(std)
if msg1 >= 0:
if last == 0 or msg1 == 0:
msg = '{0} записок'.format(msg1)
if msg1 == 1 or (last == 1 and msg1 >= 21):
msg = '{0} записку'.format(msg1)
if (msg1 >= 2 and msg1 <= 4) or (msg1 >= 22 and msg1 <= 24):
msg = '{0} записки'.format(msg1)
if (last >= 5 and last <= 9):
msg = '{0} записок'.format(msg1)
for role in member.roles:
with open('class.json', 'r') as roleread:
if role.id in roleread.read():
highclass = '<#&{0}>'.format(role.id)
with open('clans.json', 'r') as fp:
if role.id in fp.read():
gm = '> Является участником гильдии <#&{0}>.'.format(role.id)
if roleGM in member.roles:
gm = '> Является **мастером** гильдии <#&{0}>.'.format(role.id)
await asyncio.sleep(0.01)
await client.send_message(message.channel, 'Персонаж {0}:\n'
'> Прибыл в город **{1}**;\n'
'> Принимал участие в жизни города **{2}**;\n'
'> Написал **{3}**;\n'
'> Имеет класс {4};\n'
'{5}'.format(member.mention, join, time, msg, highclass, gm))
ERROR
File "soul.py", line 497, in on_message
'{5}'.format(member.mention, join, time, msg, highclass, gm))
UnboundLocalError: local variable 'msg' referenced before assignment
I've tried everything, what I could. Can somebody help me?
Look at how you assign a value to msg:
if last == 0 or msg1 == 0:
msg = '{0} some useless tex'.format(msg1)
if msg1 == 1 or (last == 1 and msg1 >= 21):
msg = '{0} some useless tex'.format(msg1)
if (msg1 >= 2 and msg1 <= 4) or (msg1 >= 22 and msg1 <= 24):
msg = '{0} some useless tex'.format(msg1)
if (last >= 5 and last <= 9):
msg = '{0} some useless tex'.format(msg1)
So, what happens if, say, msg1 is some value in the range 10-20 (and last is not 0)? Then none of these ifs will trigger. So msg will never get assigned anything. But you'll try to use it anyway, and get that error.
You probably want something like this:
if last == 0 or msg1 == 0:
msg = '{0} some useless tex'.format(msg1)
elif msg1 == 1 or (last == 1 and msg1 >= 21):
msg = '{0} some useless tex'.format(msg1)
elif (msg1 >= 2 and msg1 <= 4) or (msg1 >= 22 and msg1 <= 24):
msg = '{0} some useless tex'.format(msg1)
elif (last >= 5 and last <= 9):
msg = '{0} some useless tex'.format(msg1)
else:
msg = '{0} WARNING! UNEXPECTED VALUE!'.format(msg1)
(Notice that changing all those ifs to elifs could be a semantically meaningful change. If two conditions could both be true, your original code would execute both of them, so the second one would override what the first did, but the new code will only execute the first one. If it makes a difference, this is actually more often what you want—but if you wanted the other behavior, you may need to rewrite or reorder your conditions.)
I am trying to re-create the column 'sig', below, but in a faster, more efficient way.
My attempt is 'sig2' but that, too, runs into its own errors.
import numpy as np
import pandas as pd
a = np.random.standard_normal(500)
A = pd.DataFrame(np.cumsum(a))
A['Max'] = pd.rolling_max(A[0],10)
A['Min'] = pd.rolling_min(A[0],10)
A['Mean'] = pd.rolling_mean(A[0],3)
A['sig'] = 0
for t in range(1,A.shape[0]):
if (A['Max'][t] > A['Max'][t-1]) & (A['sig'][t-1]==0):
A['sig'][t] = 1
elif (A['Min'][t] < A['Min'][t-1]) & (A['sig'][t-1]==0):
A['sig'][t] = -1
elif ((A[0][t] > A['Mean'][t]) & (A['sig'][t-1]==-1)) | ((A[0][t] < A['Mean'][t]) & (A['sig'][t-1]==1)):
A['sig'][t] = 0
else:
A['sig'][t] = A['sig'][t-1]
state = 0
B = A.shift()
def get_val(A,B,prev_state):
global state
if (A['Max'] > B['Max']) & (prev_state==0):
state = 1
return state
elif (A['Min'] < B['Min']) & (prev_state==0):
state = -1
return state
elif ((A[0] > A['Mean']) & (prev_state==-1)) | ((A[0] < A['Mean']) & (prev_state==1)):
state = 0
return state
else:
return state
A['sig2'] = A.apply(lambda x: get_val(x,B,state))
Thank you