Standardizing American or European Decimal values in Python - python

A user can input 6.500,00 6,500.00 or 6500 or 6.500 or 6,500 to mean Decimal("6500")
In python, how can you receive any of those as values as inputs and always return the right value as a Decimal?

some kind of a forloop with a lot of replace.
b = ['6.500,00','6,500.00','6.500','6,500','6 500']
for a in b:
if(',' in a and '.' in a):
if(a.index(',') > a.index('.')):
print a.replace('.','').replace(',','.')
else:
print a.replace(',','')
elif(',' in a or ' ' in a or '.' in a):
print a.replace(',','').replace(' ','').replace('.','')
else:
print a
alltough now you never know if the user really wants to input a decimal.

After a bit more of investigating and asking people, I found the python locale module mentioned above by #MarkRansom and also the Babel module that would help with this too. Essentially, if you don't also have the locale, it's practically impossible to know what a number means.

Related

Brute Force Created In Python | Numerical Only | Up to 4 Digits

Thank you very much for taking the time to read this. I am a tadpole when it comes to write python and right now I just written the framework to create a brute force algo to sort up to 3 digits worth of numbers. Am I in the right direction?
I am assuming the web app actually reveal the number of digits it is send to your email. I first learn about this from TryHackMe.
Now it can randomly create up to 4 digit numbers as seen in BookFace and the above can crack the code as seen using their example. My question is am I doing it in the right way? Because I seen other people's sample of bruteforce and they use a lot of function. Am I being too long winded?
import random
digits = 4 #reveal the number of digits
i=0
z=0
x="" #init password to nothing
#generate random password up to 4 digits
while i < digits:
z = random.randint(0,9)
print(z)
x = str(x) + str(z)
i+=1
y = 1
print("Code Random Generated: " + x)
if digits == 1:
while y!=int(x):
print(y)
y+=1
elif digits == 2:
while y!=int(x):
if len(str(y)) == 1:
print("0" + format(y))
elif len(str(y)) == 2:
print(y)
y+=1
elif digits == 3:
while y!=int(x):
if len(str(y)) ==1:
print("00" + format(y))
elif len(str(y)) == 2:
print("0" + format(y))
elif len(str(y)) == 3:
print(y)
y+=1
elif digits == 4:
while y!=int(x):
if len(str(y)) ==1:
print("000" + format(y))
elif len(str(y)) == 2:
print("00" + format(y))
elif len(str(y)) == 3:
print("0" + format(y))
elif len(str(y)) == 4:
print(y)
y+=1
if y !=0:
print("Reset Code Revealed: " + format(y))
You are sort of asking for a code review, not for a problem's solution. This is what Code Review Stack Exchange is for.
Anyway, let's look at my own solution to the problem :
"""
An humble try at cracking simple passwords.
"""
import itertools
import random
from typing import Callable, Iterable, Optional
def generate_random_numerical_password(ndigits: int) -> str:
return "".join(str(random.randint(0, 9)) for _ in range(ndigits))
def guesses_generator(ndigits: int) -> Iterable[str]:
yield from ("".join(digits) for digits in itertools.product("0123456789", repeat=ndigits))
PasswordOracle = Callable[[str], bool]
def cracker(ndigits: int, oracle: PasswordOracle) -> Optional[str]:
for guess in guesses_generator(ndigits):
if oracle(guess):
return guess
else:
return None
if __name__ == "__main__":
NDIGITS = 4 # difficulty
print(f"the difficulty (number of digits) is set to {NDIGITS}")
password = generate_random_numerical_password(NDIGITS)
print(f"the password to crack is {password!r}")
password_oracle = lambda guess: guess == password # do not use `is`, see Python's string interning
if match := cracker(NDIGITS, password_oracle):
print("Cracked!")
else:
print("Error, not found")
Some differences :
The different parts of the program are clearly delimited using functions (password creation and cracking).
The guess generation is generalized : if the number of digits become 5, you will have to write another (tedious and error-prone) elif.
The "flow" of the program is made very clear in the "main" part : generate a password and the corresponding oracle, call the cracker and check if a result was found. There is very few lines to read, and using descriptive names helped too.
The names come from the domain ("cracking") : "guess", "difficulty", "generator" instead of abstract ones like "x" and "y".
Some language knowledge is used : standard types operations (str-joining instead of concatenation), generators (yield from), libraries (itertools.product), syntax (walrus oparetor if match := cracker(...), ...
There is more documentation : comments, docstring at the top of the module, type annotations, ... all of these helping to understand how the program works.
My question is am I doing it in the right way? Because I seen other people's sample of bruteforce and they use a lot of function. Am I being too long winded?
I did not do use functions on purpose to do like the others people, but because I see things in a different way than you, which I will try to explain.
In the end, both your solution and mine solve the initial problem "crack a four-digit password". In this way, they are not much different. But there could be other ways to consider :
Will the problem change ? Could the password be 5 digits, or contain alphabetic characters, or special characters ? In such cases, how long will it take to adapt the script ? This is the malleability of the code.
How clear is the code ? If I have a bug to fix, how long will it take me to find where it comes from ? What if it is someone new to Python ? Or someone that knows Python well but never saw the code ? This is the maintainability of the code.
How easy is it to test the code ? What can be tested ? This is teastability.
How fast is the code ? How much memory does it uses ? This is performance ?
Can the program crash ? What if the program is given bad inputs ? Could it cause an infinite loop ? This is program-safety.
...
Depending on how your objectives about malleability, maintainability, testability, performance, safety, ... (other qualities of a program), but also depending on the context. who is writing the code ? Who will read it later ? How much experienced they are ? How much time do they have to finish writing it ? Will it be run only once then thrown away or will it be deployed on millions of devices ?
All of that affects how you write it. If I was in your shoes (beginner to Python, writing a run-once-then-forget script) I would have done the same as you. The difference is the context and the objectives. I wrote my code as an example to show you the difference. But neither is good nor bad.
You are not bad at running just because you are slower than an Olympic athlete. You can only be bad relative to a context and objectives. In Physical Education class, you are graded on your running speed according to the average for your age and the progress you made.
Seeing things in their perspective is a very useful skill, not just for programming.
Whan you compare your code to other's, yours seem less "clever", less "clean", less "elegant". But you are comparing apples to oranges. You are not the others. If your solution was accepted (correct and fast enough) that's a good start at your level.
My years of professionnal experience working with several other people on tens-of-thousand-lines codebases that have to be maintained for 20 years are a different set of contexts and objectives than you learning the language in fun ways (TryHackMe). Neither is objectively bad, both are subjectively good.
TL;DR : your code is fine for a beginner, you still have lots to learn if you want to, and keep having fun !

function returns none instead of a tuple

I am using python 2.7. I wrote a code to generate passwords. For doing this, I used the random module to generate how many characters of different types(uppercase, lowercase, special and numbers) to be used to generate a password of a given length. When a wrote a function for this, it was supposed to return a tuple, but it returns None. Why is it happening?
I tried the casual debugging method of putting print statements in between and figuring out where it went wrong. Everything works just fine, except it returns None.
def passlen(a):
"""Gives length of different characters to be put into passwords"""
uplen=random.randrange(0, a)
lwlen=random.randrange(0, a)
speclen=random.randrange(0, a)
nmbrlen=random.randrange(0, a)
if uplen+lwlen+speclen+nmbrlen==a:
print (uplen, lwlen, speclen, nmbrlen)
return(uplen, lwlen, speclen, nmbrlen)
else:
passlen(a)
x=input("how many characters in the password?")
print(passlen(x))
Expected results are 4-tuples, but it gives None instead.
So you want four random numbers that add to a? Of course you can try choosing four random numbers until you find a set that adds up to a, but that might take a while for large values of a (and you definitely don't want to do this recursively).
Much better to choose three split points between 0 and a:
def passlen(a):
splits = sorted([random.randrange(0,a) for _ in range(3)])
uplen = splits[0]
lwlen = splits[1] - uplen
speclen = splits[2] - uplen - lwlen
nmbrlen = a - uplen - lwlen - speclen
return uplen, lwlen, speclen, nmbrlen
Thanks to Kamiccolo for trying to help out.
The function should look like this:
def passlen(a):
"""Gives length of different characters to be put into passwords"""
uplen=int(random.randrange(0, a))
lwlen=int(random.randrange(0, a))
speclen=int(random.randrange(0, a))
nmbrlen=int(random.randrange(0, a))
bab=(uplen, lwlen, speclen, nmbrlen)
if uplen+lwlen+speclen+nmbrlen==a:
return bab
else:
return passlen(a)
A duplicate thread also helped me in this.

Currency with 3 decimal digits in python

I have the following code which compares the input value that comes as a string with the one the function constracts. Basically checks the if the number the user enters is correct. The function works but only for 2 decimal points but the user is allowed to enter 2 to 4 decimal digits... How can I construct the right value?
def check_currency(self, amount):
amount = amount.replace("+", "")
amount = amount.replace("-", "")
sInput = amount.replace(",", ".")
locale.setlocale(locale.LC_ALL, self.LANG)
result = locale.currency(float(sInput), symbol=False, grouping=True)
if (amount == result):
return True
else:
return False
PS: The self.LANG get the respective value based on the system that the code runs on.
You aren't missing anything. locale.currency formats numbers according to the values in the dict returned by locale.localeconv() and that's what it's supposed to do. Naturally, 'frac_digits' is typically 2 since... well... you know.
Regarding what to do:
First, you can check 'int_frac_digits' in localeconv() - maybe it's good enough for you.
If not, since locale.currency is located in a Python source module, you can rig... I mean, override its logic. Looking at the source, the simplest method appears to be to replace locale.localeconv() with a wrapper.
Be wary though since such a change will be global. If you don't want it to affect other code using locale, alter local copies of the entities (or the entire module) or make a changed entity e.g. require an additional parameter to behave differently.
On a conceptual note: locale is actually correct - for its purpose - in not allowing to alter the representation. Its task is to format information of a few types according to the local convention - so whatever culture you user pertains to, they will see information in the way they are used to. If you alter the format in any way - that wouldn't any longer be "the local convention"! In fact, by requiring 3 decimal digits, you are already making assumptions about the local convention - which may not stand. E.g. in a decent share of currencies, even small sums can numerically be in the thousands.
def check_currency(self, amount):
amount = amount.replace("+", "")
amount = amount.replace("-", "")
sInput = amount.replace(",", ".")
length = len(amount)
decimals = len(sInput[sInput.find(".")+1:])
locale.setlocale(locale.LC_ALL, self.LANG)
if not sInput:
return "Empty Value"
if decimals<=2:
digit = decimals
result = locale.format('%%.%if' % digit, abs(Decimal(sInput)), grouping=True, monetary=True)
if decimals>2:
sInput = amount.replace(".", "")
digit = 0
result = locale.format('%%.%if' % digit, abs(Decimal(sInput)), grouping=True, monetary=True)
if (amount == result):
return True
else:
return False
I changed the function as you see above and it works perfect !! You can check the code above for anyone who might need it :)
Thank you again

How can I make a variable equal more then one string - Python

I am working on a quiz game and when I get asked any question, i type in the right answer, which I defined in the a variable that holds that correct answer but it says it is wrong if it isn't the first word for that variable (In this case, Metallica). Here is what my code looks like.
q1answer = "Metallica" or "metallica" or "Slayer" or "slayer" or "Anthrax" or "anthrax" or "Megadeth" or "megadeth"
answerinput = str(input("name one of the 'Big Four' metal bands'"))
if answerinput == q1answer:
print ("You got the right answer!")
else:
print ("That is the wrong answer...")
Now, if I was to type in 'Metallica' it would be correct because it is the first word for the q1answer variable. But, if I type metallica, Slayer, slayer, Anthrax, anthrax, megadeth or Megadeth, I would get the wrong answer text. Is there a way for all of these strings to be working for this one variable if i was to type anything but the first word in that variable? I'm a rookie in python so any help would be great.
Put them in a set and test for a correct answer using in instead:
q1answer = {"Metallica", "metallica", "Slayer", "slayer", "Anthrax", "anthrax", "Megadeth", "megadeth"}
...
if answerinput in q1answer:
Right now, your series of ors is just resulting in the first one - "Metallica". You can also stop duplicating every name for case-insensitivity and instead use lower:
if answerinput.lower() in q1answer:
Change your code like this:
q1answer = ("metallica", "slayer", "anthrax", "megadeth")
...
if answerinput.lower() in q1answer:
...

Possible Google Riddle?

My friend was given this free google website optimizer tshirt and came to me to try and figure out what the front logo meant.
t-shirt
So, I have a couple of guesses as to what it means, but I was just wondering if there is something more.
My first guess is that each block represents a page layout, and the logo "You should test that" just means that you should use google website optimizer to test which is the best layout. I hope that this isn't the answer, it just seems to simple and unsatisfying.
Well, I've spent the past hour trying to figure out if there is any deeper meaning, but to no avail. So, I'm here hoping that someone might be able to help.
I did though write a program to see if the blocks represent something in binary. I'll post the code below. My code tests every permutation of reading a block as 4 bits, and then tries to interpret these bits as letters, hex, and ip addresses.
I hope someone knows better.
#This code interprets the google t-shirt as a binary code, each box 4 bits.
# I try every permutation of counting the bits and then try to interpret these
# interpretations as letters, or hex numbers, or ip addresses.
# I need more interpretations, maybe one will find a pattern
import string
#these represent the boxes binary codes from left to right top to bottom
boxes = ['1110', '1000', '1111', '0110', '0011', '1011', '0001', '1001']
#changing the ordering
permutations = ["1234", "1243", "1324", "1342", "1423", "1432",
"2134", "2143", "2314", "2341", "2413", "2431",
"3124", "3142", "3214", "3241", "3412", "3421",
"4123", "4132", "4213", "4231","4312", "4321"]
#alphabet hashing where 0 = a
alphabet1 = {'0000':'a', '0001':'b', '0010':'c', '0011':'d',
'0100':'e', '0101':'f', '0110':'g', '0111':'h',
'1000':'i', '1001':'j', '1010':'k', '1011':'l',
'1100':'m', '1101':'n', '1110':'o', '1111':'p'}
#alphabet hasing where 1 = a
alphabet2 = {'0000':'?', '0001':'a', '0010':'b', '0011':'c',
'0100':'d', '0101':'e', '0110':'f', '0111':'g',
'1000':'h', '1001':'i', '1010':'j', '1011':'k',
'1100':'l', '1101':'m', '1110':'n', '1111':'o'}
hex = {'0000':'0', '0001':'1', '0010':'2', '0011':'3',
'0100':'4', '0101':'5', '0110':'6', '0111':'7',
'1000':'8', '1001':'9', '1010':'a', '1011':'b',
'1100':'c', '1101':'d', '1110':'e', '1111':'f'}
#code to convert from a string of ones and zeros(binary) to decimal number
def bin_to_dec(bin_string):
l = len(bin_string)
answer = 0
for index in range(l):
answer += int(bin_string[l - index - 1]) * (2**index)
return answer
#code to try and ping ip addresses
def ping(ipaddress):
#ping the network addresses
import subprocess
# execute the code and pipe the result to a string, wait 5 seconds
test = "ping -t 5 " + ipaddress
process = subprocess.Popen(test, shell=True, stdout=subprocess.PIPE)
# give it time to respond
process.wait()
# read the result to a string
result_str = process.stdout.read()
#For now, need to manually check if the ping worked, fix later
print result_str
#now iterate over the permuation and then the boxes to produce the codes
for permute in permutations:
box_codes = []
for box in boxes:
temp_code = ""
for index in permute:
temp_code += box[int(index) - 1]
box_codes.append(temp_code)
#now manipulate the codes using leter translation, network, whatever
#binary
print string.join(box_codes, "")
#alphabet1
print string.join( map(lambda x: alphabet1[x], box_codes), "")
#alphabet2
print string.join( map(lambda x: alphabet2[x], box_codes), "")
#hex
print string.join( map(lambda x: hex[x], box_codes), "")
#ipaddress, call ping and see who is reachable
ipcodes = zip(box_codes[0:8:2], box_codes[1:8:2])
ip = ""
for code in ipcodes:
bin = bin_to_dec(code[0] + code[1])
ip += repr(bin) + "."
print ip[:-1]
#ping(ip[:-1])
print
print
t-shirt.
I emailed the Website Optimizer Team, and they said "There's no secret code, unless you find one. :)"
I think Google are just trying to drive their point home - here are a bunch of different representations of the same page, test them, see which is best.
Which block do you like best?
I think it's simply a design, nothing secret, or mysterious.
What if it doesn't mean anything, what if it is just a neat design they came up with?
It says: "You are getting closer".
Well, I can't see an immediate pattern. But if you are testing IP, why not take two blocks of 4 as a single binary number.
Probably it's a base 4 notation?
I would try that, but I don't have any approach to this.
It reminded me of cellular automata:
http://www.wolframalpha.com/input/?i=rule+110
Anyone going that direction?

Categories

Resources