i+ =1 generating a Syntax error in for loop - python

eg.
name = 'python'
length = len(name)
i = 0
for n in range(-1,(-length-1), -1):
print( name[i], '\t', name[n])
i+ = 1
I remove the i+ = 1 which generates a semantic error. I'm a beginner and am using the python tutorial provided by the python website. Basically I'm practicing forward and backward indexing.
name = 'python'
length = len(name)
i = 0
for n in range(-1,(-length-1), -1):
print( name[i], '\t', name[n])
i+ = 1
I'm expecting it to run an output of the name forward then backwards

Your error lies in your i+ = 1 statement, which should be i += 1
Try this:
name = 'python'
length = len(name)
i = 0
for n in range(-1,(-length-1), -1):
print( name[i], '\t', name[n])
i += 1

There should be no blank space between the + and =.
i += 1

You can not arbitrarily spread spaces through your code. Certain tokens that Python recognizes have to be written exactly as they are documented. This is true for e.g. class that you can't write cl a ss, and it's also true for what you are using here wich is called an operator. It needs to be written +=, the same way == can't have a space in it etc.

As other commenters have already pointed out, the += is used as a += b and not a+ = b, which the case you have when you do i+ = 1
For simplicity, and since you say you are a beginner, might I suggest using i = i+1 instead.
In addition, you can also simplify your for loop by using length attribute to calculate the index from the end of the string. range(length) is the same as doing range(0,length,1)
name = 'python'
length = len(name)
i = 0
for i in range(length):
print(name[i], '\t', name[length-i-1])
i += 1
The output will be
p n
y o
t h
h t
o y
n p

avoid space between + and =
use i+=1 instead i+ =1
refer here: Behaviour of increment and decrement operators in Python

Related

How to add or subtract 1 to a sum based on a certain value in a text?

After reading a text, I need to add 1 to a sum if I find a ( character, and subtract 1 if I find a ) character in the text. I can't figure out what I'm doing wrong.
This is what I tried at first:
file = open("day12015.txt")
sum = 0
up = "("
for item in file:
if item is up:
sum += 1
else:
sum -= 1
print(sum)
I have this long text like the following example (((())))((((( .... If I find a ), I need to subtract 1, if I find a (, I need to add 1. How can I solve it? I'm always getting 0 as output even if I change my file manually.
your for loop only gets all the string in the file so you have to loop through the string to get your desired output.
Example .txt
(((())))(((((
Full Code
file = open("Data.txt")
sum = 0
up = "("
for string in file:
for item in string:
if item is up:
sum += 1
else:
sum -= 1
print(sum)
Output
5
Hope this helps.Happy Coding :)
So you need to sum +1 for "(" character and -1 for ")".
Do it directly specifying what to occur when you encounter this character. Also you need to read the lines from a file as you're opening it. In your code, you are substracting one for every case that is not "(".
file = open("day12015.txt")
total = 0
for line in file:
for character in line:
if character == "(":
total += 1
elif character == ")":
total -= 1
print(sum)
That's simply a matter of counting each character in the text. The sum is the difference between those counts. Look:
from pathlib import Path
file = Path('day12015.txt')
text = file.read_text()
total = text.count('(') - text.count(')')
For the string you posted, for example, we have this:
>>> p = '(((())))((((('
>>> p.count('(') - p.count(')')
5
>>>
Just for comparison and out of curiosity, I timed the str.count() and a loop approach, 1,000 times, using a string composed of 1,000,000 randoms ( and ). Here is what I found:
import random
from timeit import timeit
random.seed(0)
p = ''.join(random.choice('()') for _ in range(1_000_000))
def f():
return p.count('(') - p.count(')')
def g():
a, b = 0, 0
for c in p:
if c == '(':
a = a + 1
else:
b = b + 1
return a - b
print('f: %5.2f s' % timeit(f, number=1_000))
print('g: %5.2f s' % timeit(g, number=1_000))
f: 8.19 s
g: 49.34 s
It means the loop approach is 6 times slower, even though the str.count() one is iterating over p two times to compute the result.

Ignoring Changed Index Check (Python)

I have made a script:
our_word = "Success"
def duplicate_encode(word):
char_list = []
final_str = ""
changed_index = []
base_wrd = word.lower()
for k in base_wrd:
char_list.append(k)
for i in range(0, len(char_list)):
count = 0
for j in range(i + 1, len(char_list)):
if j not in changed_index:
if char_list[j] == char_list[i]:
char_list[j] = ")"
changed_index.append(j)
count += 1
else:
continue
if count > 0:
char_list[i] = ")"
else:
char_list[i] = "("
print(changed_index)
print(char_list)
final_str = "".join(char_list)
return final_str
print(duplicate_encode(our_word))
essentialy the purpose of this script is to convert a string to a new string where each character in the new string is "(", if that character appears only once in the original string, or ")", if that character appears more than once in the original string. I have made a rather layered up script (I am relatively new to the python language so didn't want to use any helpful in-built functions) that attempts to do this. My issue is that where I check if the current index has been previously edited (in order to prevent it from changing), it seems to ignore it. So instead of the intended )())()) I get )()((((. I'd really appreciate an insightful answer to why I am getting this issue and ways to work around this, since I'm trying to gather an intuitive knowledge surrounding python. Thanks!
word = "Success"
print(''.join([')' if word.lower().count(c) > 1 else '(' for c in word.lower()]))
The issue here has nothing to do with your understanding of Python. It's purely algorithmic. If you retain this 'layered' algorithm, it is essential that you add one more check in the "i" loop.
our_word = "Success"
def duplicate_encode(word):
char_list = list(word.lower())
changed_index = []
for i in range(len(word)):
count = 0
for j in range(i + 1, len(word)):
if j not in changed_index:
if char_list[j] == char_list[i]:
char_list[j] = ")"
changed_index.append(j)
count += 1
if i not in changed_index: # the new inportant check to avoid reversal of already assigned ')' to '('
char_list[i] = ")" if count > 0 else "("
return "".join(char_list)
print(duplicate_encode(our_word))
Your algorithm can be greatly simplified if you avoid using char_list as both the input and output. Instead, you can create an output list of the same length filled with ( by default, and then only change an element when a duplicate is found. The loops will simply walk along the entire input list once for each character looking for any matches (other than self-matches). If one is found, the output list can be updated and the inner loop will break and move on to the next character.
The final code should look like this:
def duplicate_encode(word):
char_list = list(word.lower())
output = list('(' * len(word))
for i in range(len(char_list)):
for j in range(len(char_list)):
if i != j and char_list[i] == char_list[j]:
output[i] = ')'
break
return ''.join(output)
for our_word in (
'Success',
'ChJsTk(u cIUzI htBp#qX)OTIHpVtHHhQ',
):
result = duplicate_encode(our_word)
print(our_word)
print(result)
Output:
Success
)())())
ChJsTk(u cIUzI htBp#qX)OTIHpVtHHhQ
))(()(()))))())))()()((())))()))))

Inserting string to string regularly ( 1234567891234 -> 1,2345,6789,1234 )

How to insert ' # ' for each n index from backward?
ex) n=4
evil = '01234567891234oooooooooooooooo321'
to
stan = '0#1234#5678#9123#4ooo#oooo#oooo#oooo#o321'
i tried using list with for,if statement, got stuck. something shameful like this
a = 1234567891234
b = [ a[-i] for i in range(1,len(a)+1)]
for i in range(len(b)):
c += b[i]
if i%4==0: #stuck
c += ','
c.reverse()
What is the optimum way?
You might use a pattern asserting optional repetitions of 4 characters to the right, and replace that position with #
import re
pattern = r"(?=(?:.{4})*$)"
s = "01234567891234oooooooooooooooo321"
print(re.sub(pattern, "#", s))
Output
0#1234#5678#9123#4ooo#oooo#oooo#oooo#o321#
Python demo
cut the string into chunks (backwards) and then concat them using the seperator
evil = '01234567891234oooooooooooooooo321'
l = 4
sep = '#'
sep.join([evil[max(i-l,0):i] for i in range(len(evil), 0, -l)][::-1])
'0#1234#5678#9123#4ooo#oooo#oooo#oooo#o321'
chunks function as in this answer
def chunks(lst, n):
"""Yield successive n-sized chunks from lst."""
for i in range(0, len(lst), n):
yield lst[i:i + n]
evil = '01234567891234oooooooooooooooo321'
n = 4
stan = "#".join(chunks(evil[::-1], n))[::-1]
print(stan) # Output: 0#1234#5678#9123#4ooo#oooo#oooo#oooo#o321
Input string is reversed ([::-1]), split into chunks, joined by "#" and then reversed back again. (It's possible to skip reverses if you calculate how many characters there will be in the first set of characters)
A naive solution would be using parts of evil string:
evil = '01234567891234oooooooooooooooo321'
n = 4
start = len(evil) % n
insert = '#'
stan = evil[:start] + insert
for i in range(start, len(evil) - n, n):
stan += evil[i:i+n] + insert
stan += evil[-n:]
For this, I would go backwards through your string evil by reversing the string and iterating through it in a for loop. Then I set a count variable to keep track of how many loops it's done, and reset to 0 when it equals 4. All of this looks like the below:
count = 0
for char in evil[::-1]:
if count == 4:
count = 0
count += 1
You can then establish a new empty string (new_str), and append each character of evil to, each time checking if count is 4, and adding a # to the string as well before resetting the count. Full code:
count = 0
new_str = ''
for char in evil[::-1]:
if count == 4:
new_str += '#'
count = 0
count += 1
new_str += char
This will produce the new string reversed, so you need to reverse it again to get the desired result:
new_str = new_str[::-1]
Output:
'123o#oooo#oooo#oooo#ooo4#3219#8765#4321#0'
You can do it like this:
evil = '01234567891234oooooooooooooooo321'
''.join(j if i%4 else f'#{j}' for i, j in enumerate(evil[::-1]))[::-1][:-1]
Output:
'0#1234#5678#9123#4ooo#oooo#oooo#oooo#o321'
An exact method: use divmod to get the reminder and quotient of the string when divided in "blocks" of size 4 then slice.
evil = '01234567891234oooooooooooooooo321'
size = 4
q, r = divmod(len(evil), size)
sep = '#'
stan = f"{evil[:r]}{sep}{sep.join(evil[r+i*size: r+(i+1)*size] for i in range(q))}"
print(stan)
Remark: if the length of the string is a multiple of the block's size the new string will start with sep. Assumed as default behavior since lake of explanation

remove substring from string using python

I would like to remove 2 last sub-strings from a string like the following example :
str="Dev.TTT.roker.{i}.ridge.{i}."
str1="Dev.TTT.roker.{i}.ridge.{i}.obj."
if in the last two strings between the dot . there is a {i} we have to remove it as well.
so the result of python script should be loke this :
the expected result for str is : Dev.TTT.
the expected result for str1 is : Dev.TTT.roker.{i}.
you can simply split by . and ignore empty string or {i}.
Also do not use keyword as variable. In your case dont use str as variable name.
def solve(s):
x = s.split('.')
cnt = 2
l = len(x) - 1
while cnt and l:
if x[l] == '' or x[l] == '{i}':
l -= 1
continue
else:
cnt -= 1
l -= 1
return '.'.join(x[:l+1]) + '.'
str1="Dev.TTT.roker.{i}.ridge.{i}."
str2="Dev.TTT.roker.{i}.ridge.{i}.obj."
print(solve(str1))
print(solve(str2))
output:
Dev.TTT.
Dev.TTT.roker.{i}.

Addition of two binaries numbers in Python

Hey guys i have a trouble when i want to add two binaries numbers in Python, i mean i can enter a chain of character in a form of a string but i don't know how to select a specific value in the chain. Here is my code:
chaina = input('Enter your first binary number')
chainb = input('Enter your second binary number')
liste = str()
r = 0
for i in range [-1,chaina]:
t = 0
t = chaina() + chainb() + r
if t == 2 :
r = 1
liste = str(t) + liste
elif t == 0 or t == 1:
r = 0
liste = str(t) + liste
To add two binary numbers chaina and chainb:
bin(eval('0b{} + 0b{}'.format(chaina, chainb)))
Or, if you want the binary number without the leading '0b':
format(eval('0b{} + 0b{}'.format(chaina, chainb)), 'b')
Explanation
Assume for illustration that chaina = '1010' and chainb = '1111'. Then:
>>> '0b{} + 0b{}'.format(chaina, chainb)
'0b1010 + 0b1111'
By applying eval() on this string, we get the same result as if we typed the expression 0b1010 + 0b1111 directly into Python console.
>>> 0b1010 + 0b1111
25
>>> eval('0b1010 + 0b1111')
25
Finally, bin() produces a binary representation of the number passed to it as an argument:
>>> bin(25)
'0b11001'
The same thing is accomplished by calling format() with a 'b' argument:
>>> format(25, 'b')
'11001'
All put together, we are getting the expressions shown above.
Why don't you simply convert them into decimal and add them as you would do with decimals:
y = '0b101010'
z = '0b101010'
print(int(y,2) + int(z,2))
print(bin((int(y,2) + int(z,2))))
Assuming that you want to do a binary sum by hand, you must:
process both numbers starting from the end (reversed will help here)
consistently add bits processing carry until the lengther of both numbers is exhausted
reorder the result bits (here again reversed)
Code could be (assuming that you can be sure that chaina and chainb only consist in 0 and 1 characters, no test for it here):
def binsum(chaina, chainb):
def next0(it):
"""Retrieve next digit from a binary representation, 0 when exhausted"""
try:
return int(next(it))
except StopIteration:
return 0
a = reversed(chaina) # reverse chains to start with lowest order bit
b = reversed(chainb)
r = 0
result = [] # future result
for i in range(n):
t = next0(a) + next0(b) + r # add with carry
if t > 1:
t -= 2
r = 1
else:
r = 0
result.append('1' if t else '0')
if r != 0: # do not forget last carry
result.append('1')
return ''.join(result)
A couple of suggestions
normalize the lengths of the bit strings
l0, l1 = map(len, (str0, str1))
if l0 < l1:
str0 = "0"*(l1-l0) + str0
elif l1 < l0:
str1 = "0"*(l0-l1) + str1
do a loop on the reversed strings elements and construct the binary string bottom up
remainder = 0
result = ""
for bit_0, bit1 in zip(reversed(str0), reversed(str1)):
bit_0, bit_1 = map(int, (bit_0, bit_1))
new_bit, remainder = f(bit_0, bit_1, remainder)
result = str(new_bit) + result
if remainder != 0
...
writing f(bit_0, bit_1, remainder) and treating what to do if remainder is not null at the end of the loop is left as an exercise.

Categories