Adjust my input to the right - python - python

I'm trying to adjust my text in python, so that the input gets adjusted to the right. I want the last character in the input to be in the 60th position. I therefore used the following script:
def adjust_right(s):
print(' '*60 - len(s)*' '+s)
adjust_right(input())
This works if I change the - to a +, but that does the reverse.
My question is: Why does this generate an error, when it works perfectly with a +, instead of a -?
Could the answer be, that if len(s) > 60, we get a negative amount of spaces? If this is the case, how should I rewrite my code?

I think you mean:
print(' '*(60 - len(s))+s)
You're trying to subtract a string of spaces from another string of spaces. The reason that + works is that it concatenates the strings. But Python doesn't have string subtraction.

You're subtracting strings due to order of operations, to avoid this:
print(s.rjust(60)) # right justify string with length = 60

Python has no string subtraction. (This is because it is considered "unpythonic" - most operations like these are syntax sugar/syrup, can be done easily by the programmer, or has functions to do operations)
You should use ' '*60.strip(len(s)*' '). This will take len(s)*' ' off of ' '*60. If it can't it won't do anything.

Related

How to separate user's input with two separators? And controlling the users input

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.

Indexing the wrong character for an expression

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.

Python "zfill()" equivalent in OCaml

I'm a beginner and I have to learn Ocaml for scientific programming. I just have one question:
Is there an equivalent of Python's .zfill() method in Ocaml to make leading zeros appear in a string?
Strings in OCaml are immutable. That means you're not supposed to modify a string but to create a new one.
There is no zfill function in the standard library, but you can easily make one that way:
let zfill s width =
let to_fill = width - (String.length s) in
if to_fill <= 0 then s
else (String.make to_fill '0') ^ s
I don't think there's one.
You can do it easily with build-in functions when you're working with numbers. For instance, to print the number 142857 with leading 0's over 30 characters, use Printf.printf "%030d" 142857.
You can also make it work with strings if you're fine with using leading spaces instead of leading zeros. For instance, Printf.printf "%30s" "abcdefg".
Finally if you have to, you can define your own function if need be.
The way the first two options work is by using Printf, which is an extremely useful too you really should learn at some point. Here is its documentation for OCaml, but a lot of programming languages have a similar tool.
In %030d, we started from %d which is a placeholder that will be replaced by an integer (in our case, 142857). We fixed its minimum width to 30 (right-aligned by default) by adding 30 between the two characters: %30d. Finally, we added the option to make the leading characters zeros instead of spaces by adding a 0 after the percent sign.
%30s is just a placeholder for a right-aligned string of at least 30 characters (with leading spaces, because the options for leading zeros only works with numbers).
Now here's a zfill function if for some reason you can't use a well-chosen Printf format in your scenario:
let zfill n s =
let length = Bytes.length s in
if n <= length then
s
else
let result = Bytes.make n '0' in
Bytes.blit s 0 result (n-length) length;
result
;;
Notice that if performance is an issue (though it probably isn't), this should perform faster than the solution of creating a string of zeros and then concatenating it with s, as while blit is done "in-place", string concatenation is not, so a temporary string of zeros has to be created. In most scenarios, it shouldn't matter all that much and you can use either option.

how to sum up a list of strings

Given a list of strings as such,
xs = ['1\n','2\n','3\n','4\n','5\n']
sum up the integers to return the sum as a string and append the sum to the list so that the returned list
xs = ['1\n','2\n','3\n','4\n','5\n','Sum:15\n']
I understand the process of going through the list and iterating this, I just don't understand how to get rid of the \n character so that I can only use the integer to find the sum?
def my_fun(x):
return x+["Sum: %s\n"%sum(map(int,x)),]
This uses a generator:
>>> xs + ['Sum:{0}\n'.format(str(sum(int(s) for s in xs)))]
['1\n', '2\n', '3\n', '4\n', '5\n', 'Sum:15\n']
To answer your question a bit more directly (leaving out the iteration since you said that's not the problem):
Believe it or not, int actually ignores the trailing newline when you use it to parse:
>>> int('1\n')
1
Once you have an int, you can do arithmetic as normal.
This is a documented feature in Python 2 and 3:
Optionally, the literal can be preceded by + or - (with no space in between) and surrounded by whitespace.
-Python int documentation (emphasis mine)
If you're interested in more streamlined ways of doing the iteration, you can see Joran's answer and the comments on it, but if this is some kind of assignment, I wouldn't use them if I were you. It benefits you more to work through the problems yourself. You of course want to use the more advanced features for professional work.

Implementing error message for code in Python

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.

Categories