How to replace all "&int-int" with the respective string slices in an input string? - python

I have a school project question (for Python) that goes like this:
Given a string_input such as "abcd&1-4efg", the function must remove the "&1-4" and insert the string slice from 1 to 4 where the "&1-4" was.
eg. if string_input = "abcd&1-4efg",
"&1-4" is removed.
The remaining characters are indexed as follows: a=0, b=1, c=2, d=3, e=4, f=5, g=6
The new string becomes:
"abcdbcdeefg"
I've managed to write a long chunk of code to do this, but I'm wondering if anyone has any more efficient solutions?
Things to note:
The instructions can include double digits (eg. &10-15)
If the index isn't found, the returned string should print "?" for every missing index
(eg. "abcd&5-10efgh" would return "abcdfgh???efgh")
Intructions can be back-to-back (eg. "&10-15abcdef&1-5&4-5pqrs")
The code I've written is:
def expand(text):
text += "|"
import string
digits_dash = string.digits + "-"
idx_ref_str = ""
replace_list = []
record_val = False
output_to_list = []
instruct = ""
and_idx_mark = 0
#builds replace_list & idx_ref_list
for idx in range(len(text)):
if text[idx] == "&" and record_val==True:
output_to_list.append(instruct)
output_to_list.append(and_idx_mark)
replace_list.append(output_to_list)
output_to_list, instruct, inst_idx, and_idx_mark = [],"",0,0
and_idx_mark = idx
continue
elif text[idx] == "&":
record_val = True
and_idx_mark = idx
continue
#executes if currently in instruction part
if record_val == True:
#adds to instruct
if text[idx] in digits_dash:
instruct += text[idx]
#take info, add to replace list
else:
output_to_list.append(instruct)
output_to_list.append(and_idx_mark)
replace_list.append(output_to_list)
output_to_list, instruct, inst_idx, and_idx_mark, record_val = [],"",0,0,False
#executes otherwise
if record_val == False:
idx_ref_str += text[idx]
idx_ref_str = idx_ref_str[:-1]
text = text[:-1]
#converts str to int indexes in replace list[x][2]
for item in replace_list:
start_idx = ""
end_idx = ""
#find start idx
for char in item[0]:
if char in string.digits:
start_idx += char
elif char == "-":
start_idx = int(start_idx)
break
#find end idx
for char in item[0][::-1]:
if char in string.digits:
end_idx = char + end_idx
elif char == "-":
end_idx = int(end_idx)
break
start_end_list = [start_idx,end_idx]
item+=start_end_list
#split text into parts in list
count = 0
text_block = ""
text_block_list = []
idx_replace = 0
for char in text:
if char == "&":
text_block_list.append(text_block)
text_block = ""
count += len(replace_list[idx_replace][0])
idx_replace +=1
elif count > 0:
count -= 1
else:
text_block += char
text_block_list.append(text_block)
#creates output str
output_str = ""
for idx in range(len(text_block_list)-1):
output_str += text_block_list[idx]
#creates to_add var to add to output_str
start_repl = replace_list[idx][1]
end_repl = replace_list[idx][1] + len(replace_list[idx][0])
find_start = replace_list[idx][2]
find_end = replace_list[idx][3]
if end_idx >= len(idx_ref_str):
gap = end_idx + 1 - len(idx_ref_str)
to_add = idx_ref_str[find_start:] + "?" * gap
else:
to_add = idx_ref_str[find_start:find_end+1]
output_str += to_add
output_str += text_block_list[-1]
return output_str

Here's how I would do it. Always open to criticism.
import re
s = 'abcd&1-4efg'
c = re.compile('&[0-9]+-[0-9]+')
if (m := c.search(s)):
a, b = m.span()
left = s[:a]
right = s[b:]
o = [int(x) for x in m.group(0)[1:].split('-')]
mid = (left+right)[o[0]:o[1]+1]
print(left + mid + right)

Related

Replacing a character in a string but it duplicate

This is a line of code I create that will replace a '_' with a character from a string
def test():
time = -1
in_time = 0
n = 'c__rd_nate'
new_n = ''
word = 'coordinate'
chr = 'i'
for w in word:
time = time + 1
if w == chr:
for i in n:
if in_time == time:
u = i.replace(i, chr)
new_n = new_n + u
in_time = in_time + 1
else:
in_time = in_time + 1
new_n = new_n + i
if len(word) == in_time:
break
Output:
>>>c__rdinate
But when applying the same rules for the duplicate character 'o' in word
def test():
time = -1
in_time = 0
n = 'c__rd_nate'
new_n = ''
word = 'coordinate'
chr = 'o'
for w in word:
time = time + 1
if w == chr:
for i in n:
if in_time == time:
u = i.replace(i, chr)
new_n = new_n + u
in_time = in_time + 1
else:
in_time = in_time + 1
new_n = new_n + i
if len(word) == in_time:
break
Output:
>>>co_rd_natec__rd_nate
I know what the error is but I'm stuck at creating a solution for this type of problem!
This is some more output in the same situation!
def test():
time = -1
in_time = 0
n = 'd__r'
new_n = ''
word = 'door'
chr = 'o'
for w in word:
time = time + 1
if w == chr:
for i in n:
if in_time == time:
u = i.replace(i, chr)
new_n = new_n + u
in_time = in_time + 1
else:
in_time = in_time + 1
new_n = new_n + i
if len(word) == in_time:
break
print(new_n)
test()
Output:
>>>do_rd__r
Converting the string to a list and then performing item assingment would be much more convenient.
This is a much more simplified way of constructing the code:
def test():
count = 0
n = list('c__rd_nate')
word = 'coordinate'
chr = 'o'
for w in word:
if w == chr:
n[count] = chr
count += 1
print(''.join(n))
output:
coord_nate
Edit:
If you would prefer to still keep the variable new_n then you can do something like this:
def test():
count = 0
n = list('c__rd_nate')
new_n = ''
word = 'coordinate'
chr = 'o'
for w in word:
if w == chr:
n[count] = chr
new_n = new_n + n[count]
count += 1
print(new_n)
output:
coord_nate
I think, you don't have to complicate too much. If you used indexing, problem can be solved with ease. If pattern matches, then concatenate that letter from variable "word" else concatenate from variable "n"
n = 'c__rd_nate'
new_n = ''
word = 'coordinate'
chr = 'o'
for i in range(len(word)):
if word[i] == chr:
new_n += word[i]
else:
new_n += n[i]
print(new_n)
This works for both 'o' and 'i'.
Output for 'o'
coord_nate
Output for 'i'
c__rdinate
def test():
n = 'doorian'
word = 'd__r_an'
ch = 'o'
return ''.join(_l if _l == '_' and word_l == ch else word_l
for word_l, _l in zip(word, n))
Or in cycle
def test():
n = 'doorian'
word = 'd__r_an'
ch = 'o'
res = ''
for word_l, _l in zip(word, n):
if _l == '_' and word_l == ch:
res += _l
else:
res += word_l
return res

Python reverse each word in a sentence without inbuilt function python while preserve order

Not allowed to use "Split(),Reverse(),Join() or regexes" or any other
helping inbuilt python function
input something like this:
" my name is scheven "
output like this:
"ym eman si nevehcs"
you need to consider removing the starting,inbetween,ending spaces aswell in the input
I have tried 2 tries, both failed i will share my try to solve this and maby an idea to improve it
First try:
def reverseString(someString):
#lenOfString = len(someString)-1
emptyList = []
for i in range(len(someString)):
emptyList.append(someString[i])
lenOfString = len(emptyList)-1
counter = 0
while counter < lenOfString:
if emptyList[counter] == " ":
counter+=1
if emptyList[lenOfString] == " ":
lenOfString-=1
else:
swappedChar = emptyList[counter]
emptyList[counter] = emptyList[lenOfString]
emptyList[lenOfString] = swappedChar
counter+=1
lenOfString-=1
str_contactantion = ""
#emptyList = emptyList[::-1]
#count_spaces_after_letter=0
for letter in emptyList:
if letter != " ":
str_contactantion+=letter
#str_contactantion+=" "
str_contactantion+=" "
return str_contactantion
second try:
def reverse(array, i, j):
emptyList = []
if (j == i ):
return ""
for k in range(i,j):
emptyList.append(array[k])
start = 0
end = len(emptyList) -1
if start > end: # ensure i <= j
start, end =end, start
while start < end:
emptyList[start], emptyList[end] = emptyList[end], emptyList[start]
start += 1
end -= 1
strconcat=""
for selement in emptyList:
strconcat+=selement
return strconcat
def reverseStr(someStr):
start=0
end=0
help=0
strconcat = ""
empty_list = []
for i in range(len(someStr)):
if(someStr[i] == " "):
continue
else:
start = i
j = start
while someStr[j] != " ":
j+=1
end = j
#if(reverse(someStr,start,end) != ""):
empty_list.append(reverse(someStr,start,end))
empty_list.append(" ")
for selement in empty_list:
strconcat += selement
i = end + 1
return strconcat
print(reverseStr(" my name is scheven "))
The following works without managing indices:
def reverseString(someString):
result = crnt = ""
for c in someString:
if c != " ":
crnt = c + crnt # build the reversed current token
elif crnt: # you only want to do anything for the first space of many
if result:
result += " " # append a space first
result += crnt # append the current token
crnt = "" # and reset it
if crnt:
result += " " + crnt
return result
reverseString(" my name is scheven ")
# 'ym eman si nevehcs'
Try this:
def reverseString(someString):
result = ""
word = ""
for i in (someString + " "):
if i == " ":
if word:
result = result + (result and " ") + word
word = ""
else:
word = i + word
return result
You can then call it like this:
reverseString(" my name is scheven ")
# Output: 'ym eman si nevehcs'
Try this:
string = " my name is scheven "
def reverseString(someString):
result = ''
curr_word = ''
for i in someString:
if i == ' ':
if curr_word:
if result:
result = f'{result} {curr_word}'
else:
result = f'{result}{curr_word}'
curr_word = ''
else:
curr_word = f'{i}{curr_word}'
return result
print(repr(reverseString(string)))
Output:
'ym eman si nevehcs'
Note: if you're allowed to use list.append method, I'd suggest using a collections.deque as it's more performant than appending to a list. But of course, in the end you'll need to join the list together, and you mentioned that you're not allowed to use str.join, so that certainly poses an issue.

Find the total number of occurrence of a string in a cyclic string

I'm currently learning Python and I'm stuck on this specific question.
Image
Here is my current code:
word = input()
text = 0
wordch = 0
positions = 0
repeated = 0
while repeated != 2:
for i in range(0, len(tablet)):
if tablet[i] == word[wordch]:
text += 1
wordch += 1
if text == len(word):
positions += 1
text = 0
wordch = 0
elif repeated == 1 and text == len(word):
positions += 1
text = 0
wordch = 0
break
elif i == len(tablet)-1:
repeated += 1
break
elif tablet[i] != word[wordch]:
text == 0
wordch == 0
print(positions)
I would hope for a code that is really basic using the same concepts but please do answer.
Thank you!
I have tried to solve the problem by using a different approach. As we know that we can only use (len(fav_word)) - 1 letters if we tried to create the substring in a cyclic manner from the end since if we took any more characters, we would have created them from the start itself without the cycle.
So, I just created a new string from the original string by appending the starting (len(fav_word)) - 1 to the original string and then find all occurrences of the fav_string in the new string.
def find_all(a_str, sub):
start = 0
while True:
start = a_str.find(sub, start)
if start == -1: return
yield start
start += 1
x = "cabccabcab"
fav = "abc"
y = x + x[0:len(fav)-1]
print(len(list(find_all(y, fav)))) # Output: 3
x = "ababa"
fav = "aba"
y = x + x[0:len(fav)-1]
print(len(list(find_all(y, fav)))) # Output: 2
x = "aaaaaa"
fav = "aa"
y = x + x[0:len(fav)-1]
print(len(list(find_all(y, fav)))) # Output: 6
x = "abaaba"
fav = "aaba"
y = x + x[0:len(fav)-1]
print(len(list(find_all(y, fav)))) # Output: 2
def find_str(g,find):
lg = len(g)
lf = len(find)
x=0
s=""
for index, i in enumerate(g):
if i == find[0]:
if index+lf <= lg:
s = "".join(g[index:index+lf])
if s == find:
x+=1
else:
rem = "".join(g[index:])
lr = len(rem)
for index,i in enumerate(g):
rem+=i
lr+=1
if lr == lf:
if rem == find:
x+=1
break
return x
print(find_str("abaaba","aaba"))
def split(word):
return [char for char in word]
x = "aaaaaa"
pattern = "aa"
mylist=split(x)
ok=True
occurrences=0
buffer=""
while ok:
char=mylist.pop(0)
buffer+=char
if buffer==pattern:
occurrences+=1
buffer=""
if len(mylist)==0:
ok=False
print(occurrences)
output:3

python caesar chr and ord without newline and just iterate in the alphabet

I have some problem with my caesar code.
1) I don't know how to check if a character is a punctuation and print without sum.
2) print the char on the same line but when it's finished return a newline.
3) Iterate through the alphabet with big number return me a punctuation, how can I do to return just a character?
import sys
import string
def main():
if len(sys.argv) != 2:
print("Usage: caesar.py k")
else:
k = int(sys.argv[1])
if k == 1 or k <= 26:
text = input("plaintext: ");
j = len(text)
for i in range(j):
#check if is a character
if text[i].isalpha:
if text[i].islower():
print(chr(ord(text[i]) + k),end = "")
if text[i].isupper():
print(chr(ord(text[i]) + k),end = "")
elif text[i].punctuation():
print(text[i])
else:
print("You have to introduce a number between 1 and 26")
main()
Try this code:
import string
def encrypt_ceasar(s, shift):
assert abs(shift) < 26, 'shift is between -25 and 25 (inclusive)'
encrypted_s = ''
for char in s:
if char.isalpha():
is_upper = char.isupper()
char = char.lower()
pos_alphabet = ord(char) - ord('a')
new_pos = (pos_alphabet + shift) % 26
encryted_char = chr(ord('a') + new_pos)
if is_upper:
encryted_char = encryted_char.upper()
encrypted_s += encryted_char
else:
encrypted_s += char
return encrypted_s
def decrypt_ceasar(s, shift):
return encrypt_ceasar(s, -shift)
if __name__ == "__main__":
s = 'AbC1$de#zy'
encrypted_s = encrypt_ceasar(s, 3)
print('s:', s)
print('encrypted_s:', encrypted_s)
print('again s:', decrypt_ceasar(encrypted_s, 3))
Output:
s: AbC1$de#zy
encrypted_s: DeF1$gh#cb
again s: AbC1$de#zy

How to make my Python code read from the second line for my lexer

I am busy building a small compiler that reads the file, finds keywords and then does what the keyword specifies. I have an issue that it starts reading the file from the begining each time and icould not find a way to solve this problem with out nested if statements.
swift.py:
from sys import *
import re
tokens = ["PRINT"]
def open_file(filename):
with open (filename, "r") as filecontents:
data = filecontents.read().replace('\n', ' ')
return data
def lex(filecontents):
words = filecontents.split(" ")
filecontents = list(filecontents)
word = []
states = 0
statesRun = False
statesBool = True
string = ""
stringAmount = 0
toks = ""
i = 0.0
for i in range(len(words)):
if words[int(i)].upper() == tokens[0].upper():
word.append("PRINT")
for char in filecontents:
toks += char
if char == "\"":
if states == 0:
statesRun = True
if char == "\"" and statesBool == False:
states = 1
string += char
statesRun = False
statesBool = False
elif states == 1:
statesRun = False
if statesRun:
string += char
stringAmount += 1
word.append("STRING:" + string)
string = ""
statesBool = True
statesRun = False
states = 0
return word
def parse(toks):
i = 0
while(i < len(toks)):
if toks[i].upper() + " " + toks[i+1][0:6].upper() == "PRINT STRING":
print(toks[i+1][7:])
i+=2
class core():
data = open_file(argv[1])
toks = lex(data)
parse(toks)
core()
test.swift:
print "Hello"
print "jobs"
input in cmd:
python swift.py test.swift
I have researched programming languages, compilers, interpreters, parsers, lexers and syntax. I based this code of of this youtube seris(episode 1 - 2)
episode 2
Works now thanks to Markku K!
from sys import *
import re
lines = []
tokens = ["PRINT"]
def open_file(filename):
data = open(filename, "r")
for line in data.readlines():
lines.append(line.replace('\n', ''))
with open (filename, "r") as filecontents:
data = filecontents.read().replace('\n', ' ')
return data
def lex(filecontents):
words = filecontents.split(" ")
filecontents = list(filecontents)
word = []
states = 0
statesRun = False
statesBool = True
string = ""
stringAmount = 0
toks = ""
i = 0.0
z = 0
for i in range(len(words)):
if words[int(i)].upper() == tokens[0].upper():
word.append("PRINT")
for char in lines[z]:
toks += char
if char == "\"":
if states == 0:
statesRun = True
if char == "\"" and statesBool == False:
states = 1
string += char
statesRun = False
statesBool = False
elif states == 1:
statesRun = False
if statesRun:
string += char
stringAmount += 1
word.append("STRING:" + string)
string = ""
statesBool = True
statesRun = False
states = 0
z += 1
return word
def parse(toks):
i = 0
while(i < len(toks)):
if toks[i].upper() + " " + toks[i+1][0:6].upper() == "PRINT STRING":
print(toks[i+1][7:])
i+=2
def run():
data = open_file(argv[1])
toks = lex(data)
parse(toks)
run()

Categories