FIRST QUESTION
For example, if i want to print a lot of lines with the same width, i could use
print(f'{"INFO":=^50}')
print(f'{"some info":<50}')
print(f'{"another info":>50}')
And will get
=======================INFO=======================
some info
another info
But, what if I want to get something like this?
=======================INFO=======================
some info.............................another info
Ok.
I can do it
print(f'{"INFO":=^50}')
print('some info' + f'{"another info":.>{50-len("some info")}}')
Maybe python has another, the easiest way to do it?
SECOND QUESTION
For align we can use >, <, ^, and =
And = works only with numbers. And it works the same as >
For example
print(f'{13:.=5}')
print(f'{13:.>5}')
...13
...13
So Why do we need =, if it works the same? To be sure that the value is a number? What are the pluses it gives more?
For your second question, the answer is in Format Specification Mini-Language:
'='
Forces the padding to be placed after the sign (if any) but before the
digits. This is used for printing fields in the form ‘+000000120’.
This alignment option is only valid for numeric types. It becomes the
default when ‘0’ immediately precedes the field width.
This becomes clear when you have a signed number:
print(f'{-13:0=5}')
# -0013
print(f'{-13:0>5}')
# 00-13
What you are trying to do is an alignment inbetween two variables. That's quite specific. What then about alignment between three variables, four etc... ?
You can however approach it as an alignment problem for each of the two variables: split the 50 in two parts.
print(f'{"INFO":=^50}')
print(f'{"some info":.<25}{"another info":.>25}')
=======================INFO=======================
some info.............................another info
Related
I want to separate the users input using two different separators which are ":" and ";"
Like the user should input 4 subject and it's amounts. The format should be:
(Subject:amount;Subject:amount;Subject:amount;Subject:amount)
If the input is wrong it should print "Invalid Input "
Here's my code but I can only used one separator and how can I control the users input?
B = input("Enter 4 subjects and amount separated by (;) like Math:90;Science:80:").split(";")
Please help. I can't figure it out.
If you are fine with using regular expressions in python you could use the following code:
import re
output_list = re.split("[;:]", input_string)
Where inside the square brackets you include all the characters (also known as delimiters) that you want to split by, just make sure to keep the quotes around the square brackets as that makes a regex string (what we are using to tell the computer what to split)
Further reading on regex can be found here if you feel like it: https://medium.com/factory-mind/regex-tutorial-a-simple-cheatsheet-by-examples-649dc1c3f285
However, if you want to do it without importing anything you could do this, which is another possible solution (and I would recommend against, but it gets the job done well):
input_string = input_string.replace(";", ":")
output_list = input_string.split(":")
Which works by first replacing all of the semicolons in the input string with colons (it could also work the other way around) and then splitting by the remaining character (in this case the colons)
Hope this helped, as it is my first answer on Stack overflow.
My program seems to be indexing the wrong character or not at all.
I wrote a basic calculator that allows expressions to be used. It works by having the user enter the expression, then turning it into a list, and indexing the first number at position 0 and then using try/except statements to index number2 and the operator. All this is in a while loop that is finished when the user enters done at the prompt.
The program seems to work fine if I type the expression like this "1+1" but if I add spaces "1 + 1" it cannot index it or it ends up indexing the operator if I do "1+1" followed by "1 + 1".
I have asked in a group chat before and someone told me to use tokenization instead of my method, but I want to understand why my program is not running properly before moving on to something else.
Here is my code:
https://hastebin.com/umabukotab.py
Thank you!
Strings are basically lists of characters. 1+1 contains three characters, whereas 1 + 1 contains five, because of the two added spaces. Thus, when you access the third character in this longer string, you're actually accessing the middle element.
Parsing input is often not easy, and certainly parsing arithmetic expressions can get tricky quite quickly. Removing spaces from the input, as suggested by #Sethroph is a viable solution, but will only go that far. If you all of a sudden need to support stuff like 1+2+3, it will still break.
Another solution would be to split your input on the operator. For example:
input = '1 + 2'
terms = input.split('+') # ['1 ', ' 2'] note the spaces
terms = map(int, terms) # [1, 2] since int() can handle leading/trailing whitespace
output = terms[0] + terms[1]
Still, although this can handle situations like 1 + 2 + 3, it will still break when there's multiple different operators involved, or there are parentheses (but that might be something you need not worry about, depending on how complex you want your calculator to be).
IMO, a better approach would indeed be to use tokenization. Personally, I'd use parser combinators, but that may be a bit overkill. For reference, here's an example calculator whose input is parsed using parsy, a parser combinator library for Python.
You could remove the spaces before processing the string by using replace().
Try adding in:
clean_input = hold_input.replace(" ", "")
just after you create hold_input.
My program is given an object with parameters, and I need to get the parameters' values.
The object my program is given will look like this:
Object = """{{objectName|
parameter1=random text|
parameter2=that may or may not|
parameter3=contain any letter (well, almost)|
parameter4=this is some [[problem|problematic text]], Houston, we have a problem!|
otherParameters=(order of parameters is random, but their name is fixed)}}"""
(all parameters might or might not exist)
I am trying to get the properties values.
In the first 3 lines, its pretty easy. a simple regex will find it:
if "parameter1" in Object:
parameter1 = re.split(r"parameter1=(.*?)[\|\}]", Object)[1]
if "parameter2" in Object:
parameter2 = re.split(r"parameter2=(.*?)[\|\}]", Object)[1]
and so on.
The problem is with parameter4, the above regex (property4=(.*?)[\|\}]) will only return this is some [[problem, since the regex stops at the vertical bar.
Now here is the thing: vertical bar will only appear as part of the text inside "[[]]".
For example, parameter1=a[[b|c]]d might appear, but parameter1=a|bc| will never appear.
I need a regex which will stop at vertical bar, unless it is inside double square brackets. So for example, for parameter4, I will get this is some [[problem|problematic text]], Houston, we have a problem!
Worked here when I removed the "?":
parameter4 = re.split(r"parameter4=(.*)[\|\}]", object_)[1]
I also changed the name of the variable to "object_" because "object" is a built-in object in Python
Best.
Apparently, there is no perfect solution.
For other readers possibly reading this question in the future, the closest solution is, as pointed by Wiktor Stribiżew in the comments, parameter4=([^[}|]*(?:\[\[.*?]][^[}|]*)*).
This regex will only work if the param text does not contain any single [, } and | but may contain [[...]] sub-strings.
If you want to understand this regex better, you might want to have a look here: https://regex101.com/r/bWVvKg/2
I am trying to match a string with a regular expression but it is not working.
What I am trying to do is simple, it is the typical situation when an user intruduces a range of pages, or single pages. I am reading the string and checking if it is correct or not.
Expressions I am expecting, for a range of pages are like: 1-3, 5-6, 12-67
Expressions I am expecting, for single pages are like: 1,5,6,9,10,12
This is what I have done so far:
pagesOption1 = re.compile(r'\b\d\-\d{1,10}\b')
pagesOption2 = re.compile(r'\b\d\,{1,10}\b')
Seems like the first expression works, but not the second.
And, would it be possible to merge both of them in one single regular expression?, In a way that, if the user introduces either something like 1-2, 7-10 or something like 3,5,6,7 the expression will be recogniced as good.
Simpler is better
Matching the entire input isn't simple, as the proposed solutions show, at least it is not as simple as it could/should be. Will become read only very quickly and probably be scrapped by anyone that isn't regex savvy when they need to modify it with a simpler more explicit solution.
Simplest
First parse the entire string and .split(","); into individual data entries, you will need these anyway to process. You have to do this anyway to parse out the useable numbers.
Then the test becomes a very simple, test.
^(\d+)(?:-\(d+))?$
It says, that there the string must start with one or more digits and be followed by optionally a single - and one or more digits and then the string must end.
This makes your logic as simple and maintainable as possible. You also get the benefit of knowing exactly what part of the input is wrong and why so you can report it back to the user.
The capturing groups are there because you are going to need the input parsed out to actually use it anyway, this way you get the numbers if they match without having to add more code to parse them again anyway.
This regex should work -
^(?:(\d+\-\d+)|(\d+))(?:\,[ ]*(?:(\d+\-\d+)|(\d+)))*$
Demo here
Testing this -
>>> test_vals = [
'1-3, 5-6, 12-67',
'1,5,6,9,10,12',
'1-3,1,2,4',
'abcd',
]
>>> regex = re.compile(r'^(?:(\d+\-\d+)|(\d+))(?:\,[ ]*(?:(\d+\-\d+)|(\d+)))*$')
>>> for val in test_vals:
print val
if regex.match(val) == None:
print "Fail"
else:
print "Pass"
1-3, 5-6, 12-67
Pass
1,5,6,9,10,12
Pass
1-3,1,2,4.5
Fail
abcd
Fail
def parse(expression):
operators= set("*/+-")
numbers= set("0123456789")#not used anywhere as of now
opExtrapolate= []
numExtrapolate= []
buff=[]
for i in expression:
if i in operators:
if len(buff) >0: #prevents buff if multiple operators
numExtrapolate.append(''.join(buff))
buff= []
opExtrapolate.append(i)
opExtrapolation=opExtrapolate
else:
buff.append(i)
numExtrapolate.append(''.join(buff))
numExtrapolation=numExtrapolate
print(numExtrapolation)
print("z:", len(opExtrapolation))
return numExtrapolation, opExtrapolation
def errors():
numExtrapolation,opExtrapolation=parse(expression)
#Error for muliple operators
if (len(numExtrapolation) ==3) and (len(opExtrapolation) !=2):
print("Bad1")
if (len(numExtrapolation) ==2) and (len(opExtrapolation) !=1):
print("Bad2")
#
I posted similar code in an older question however the premise for questions is different in this post.
The code above takes a mathematical input entered in a variable expression by the user and it splits it into operands and operators. The errors function will later print errors if the input is incorrect.
Input would look something like this , where the operators can only be in the set("*/+-") and operands are real numbers. so an example input would be 45/23+233
With the help of an SO user I was able to get one of the errors to work(error for multiple operators), but I am having trouble implementing a few more error messages.
1)If the input contains items that are not numbers or not the allowed operators then an error message is displayed
2)If a user enters a number such as .23 or something like 554. where there is no number before the decimal place or after the decimal place then a different error is displayed.(note that a number like 0.23 is fine).
3)If the user attempts to divide by zero an error is displayed.
::What I have tried:
In the else statement of parse(), I tried to put conditions on buff.append(i) so that it would only run that code if buff.isdigit()==true but I got errors saying that there were no digits in buff. I also tried creating a set called "numbers"(in code below) and limiting buff.append(i) to that set through a for statement similar to the initial for statement. But unfortunately nothing worked. Any and all help would be appreciated.
Please don't introduce large amounts of code more advanced than the code below. I am trying to fix a problem, not completely change my code. Thanks for all your help.
You can use regular expressions to do these checks:
If the input contains items that are not numbers or not the allowed operators then an error message is displayed
if not re.match(r'[\d.*/+\- ]+$', expression):
print("Bad3") # Characters exist that are not allowed
Explanation: [\d.*/+\- ] will only match digits, your operators, and spaces, the + means to allow one or more of those characters, and the $ matches at the very end of the string. re.match() starts at the beginning of the string so this means that only those characters are allowed.
If a user enters a number such as .23 or something like 554. where there is no number before the decimal place or after the decimal place then a different error is displayed.(note that a number like 0.23 is fine).
if re.search(r'(?<!\d)\.|\.(?!\d)', expression):
print("Bad4") # There is a '.' without a digit before or after it
Explanation: \. in a regex matches a literal '.' character. The | in the middle is an alternation, so the regex will match if the expression on either side of it matches. (?<!\d) means that the previous character is not a number, and (?!\d) means that the next character is not a number, so this regex means "match a '.' that is not preceeded by a digit OR match a '.' that is not followed by a digit".
If the user attempts to divide by zero an error is displayed.
if re.search(r'/ *[0.]+(?![.\d])', expression):
print("Bad5") # Division by 0
Explanation: This matches / followed by any number of spaces, then one or more 0 or . characters, so this will match if anywhere in expression you have something like / 0, / 0.0, or / 0.00. The (?![.\d]) means that the next character can't be a digit or ., which will prevent you from matching something like / 0.4.
I will give you some indications, but not solve it for you :).
If you need more, ask a precise question and I'll answer it.
The answers I give you are NOT directly related with your code.
You can test if a string variable can be an integer by trying to cast it :
try:
var2 = int(var)
I let you see what Error it gives
For a version that doesn't use try, you can look at the isdigit method
You can see if a string variable if one of your operator by checking it
if (var in ["+", "-", "/", "*"])
to check even more, you can look at the variable's length first
if len(var) != and ... see above
To check if a user inputs something like .543 and refuse it, and can look at the first element of your string variable :
if myvar[0] is ".":
To check if your user wants to divide by 0, you can simply check whether the last number is equals to 0
if int(myvar) == 0:
All these expect you to be able to get operators and numbers first though.
The other solution would be to use regular expressions to perform these checks before parsing your numbers and operators.
It seems quite complex compared to the exercise you are trying to achieve though as it is homework. Might be a good idea to look at them anyway.