python how to decode words using stack? - python

i have a txt file which is written like this:
6
abcd<<<<<<
n<J<g<1<A<
ABCD<<<1>>>2<<3>->>>>>>
and i want to decode this file by python using 'stack' .
at this file, '<' means cursor moves this ← way
'>'means cursor moves → this way
and '-' means delete the left word right after cursor's location.
so finally, what i should want is
abcd
A1gJn
A1BC32
i tried to make a certain function to solve this question
but i don't know what is wrong with my function.
The written below is what i made.
def decodeString_stack(string):
"""Recover a string from a keylog string
input: string(string), output:(decoded string)
deCoded[ ] : list of decoded string(cursor left)
temp[ ] : list of decoded string(cursor right)
"""
deCoded=[]; temp=[]
for ch in string:
if ch=='<':
x=deCoded.pop()
temp.append(x)
elif ch=='>':
x=temp.pop()
deCoded.append(x)
elif ch=='-':
del deCoded[len(deCoded)-1]
return ''.join(deCoded)
it always stops because list is empty one
import time
fr=open("input.txt",'r')
fw=open("output_txt",'w')
print('start decoding')
startTime=time.time()
for aLine in fr:
deCoded=decodeString_stack(aLine)
print(deCoded)
exeTime=time.time()-startTime
print("decode complete(laspe time= %.2f sec)" %exeTime)
fr.close(); fw.close()
how can i make it right?

Notice that you are defining an empty list, 'deCoded', then immediately trying to 'pop()' from it. For pop to work, something has to be in the list. I suspect this is homework so I won't delve too far into a solution - just note that pop is taking something off the stack, but you can't take something off if nothing exists : )
deCoded=[]; temp=[]
for ch in string:
if ch=='<':
x=deCoded.pop()
temp.append(x)
Without giving away too much, hopefully this will get you started. Also, if you don't use it already, I highly recommend Pycharm. You can get it free - and it will allow you to step debug through your code. It will be a life saver.
def decode_line(line : str):
temp = []
decoded = []
for char in line:
if char == "<":
if temp:
c = temp.pop()
decoded.append(c)
elif char == ">":
pass
elif char == "-":
pass
else:
temp.append(char)
reversed = decoded[::-1]
return reversed
with open('source.txt') as source:
for line in source:
out = decode_line(line)
print(out)

Related

modified textfile python script

I am totally new in python world. Here I am looking for some suggestion about my problem. I have three text file one is original text file, one is text file for updating original text file and write in a new text file without modifying the original text file. So file1.txt looks like
$ego_vel=x
$ped_vel=2
$mu=3
$ego_start_s=4
$ped_start_x=5
file2.txt like
$ego_vel=5
$ped_vel=5
$mu=6
$to_decel=5
outputfile.txt should be like
$ego_vel=5
$ped_vel=5
$mu=6
$ego_start_s=4
$ped_start_x=5
$to_decel=5
the code I tried till now is given below:
import sys
import os
def update_testrun(filename1: str, filename2: str, filename3: str):
testrun_path = os.path.join(sys.argv[1] + "\\" + filename1)
list_of_testrun = []
with open(testrun_path, "r") as reader1:
for line in reader1.readlines():
list_of_testrun.append(line)
# print(list_of_testrun)
design_path = os.path.join(sys.argv[3] + "\\" + filename2)
list_of_design = []
with open(design_path, "r") as reader2:
for line in reader1.readlines():
list_of_design .append(line)
print(list_of_design)
for i, x in enumerate(list_of_testrun):
for test in list_of_design:
if x[:9] == test[:9]:
list_of_testrun[i] = test
# list_of_updated_testrun=list_of_testrun
break
updated_testrun_path = os.path.join(sys.argv[5] + "\\" + filename3)
def main():
update_testrun(sys.argv[2], sys.argv[4], sys.argv[6])
if __name__ == "__main__":
main()
with this code I am able to get output like this
$ego_vel=5
$ped_vel=5
$mu=3
$ego_start_s=4
$ped_start_x=5
$to_decel=5
all the value I get correctly except $mu value.
Will any one provide me where I am getting wrong and is it possible to share a python script for my task?
Looks like your problem comes from the if statement:
if x[:9] == test[:9]:
Here you're comparing the first 8 characters of each string. For all other cases this is fine as you're not comparing past the '=' character, but for $mu this means you're evaluating:
if '$mu=3' == '$mu=6'
This obviously evaluates to false so the mu value is not updated.
You could shorten to if x[:4] == test[:4]: for a quick fix but maybe you would consider another method, such as using the .split() string function. This lets you split a string around a specific character which in your case could be '='. For example:
if x.split('=')[0] == test.split('=')[0]:
Would evaluate as:
if '$mu' == '$mu':
Which is True, and would work for the other statements too. Regardless of string length before the '=' sign.

Weird error in loop not understanding why the range is out of index

I was asked to:-
Write a program to input a string and then using a function change(), create a new string
with all the consonants deleted from the string. The function should take in the string as
a parameter and return the converted string.
my code :-
str=input("enter a string: ")
def change(stri):
for i in range(0,len(stri)):
for e in ['a','e','i','o','u','A','E','I','O','U']:
if stri[i]==e:
if i==len(stri)-1:
stri = stri[0:i-1] + "" + stri[i: ]
else:
stri = stri[0:i] + "" + stri[i+1: ]
else:
continue
return stri
str=change(str)
print(str)
output :-
Traceback (most recent call last):
File "main.py", line 13, in <module> str=change(str)
File "main.py", line 5, in change if stri[i]==e:
IndexEnoi: string index out of range
^ for any string
Please someone help me out this is my imp project
As said by Johny Mopp: "Let's say len(stri) == 10. Your for loop then is for i in range(0, 10):. But then in the loop you modify stri so that it's new length is less than 10. You will now get an index out of range error at if stri[i]==e: because i is too large"
Use this instead:
text=input("enter a string: ")
vowels = ['a','e','i','o','u','A','E','I','O','U']
for x in vowels:
text = text.replace(x,"")
print(text)
Generally speaking, don't try to reinvent the wheel. Make use of all functions Python offers you.
The issue you are facing is common when deleting from the same object that you are iterating. Eventually you delete a part of the object that is already queued up as part of a future iteration in the for loop and you get an error.
The best way around this, in your case, is to write your vowel only string out to a new variable keeping your stri variable intact as it was passed into your function.
A quick rewrite of your code with the addition of the new variable to catch your output string would look like:
vowels=['a','e','i','o','u','A','E','I','O','U']
stri='This is a test string'
stro=''
for character in stri:
if character in vowels:
stro=stro+character
print(stro)
I believe the issue you have is that you change the string inside the for loop. You delete letters but still have the same range (len(stri) is not updated while changing the stri). Try with the word without vowels. You will not get any error.
But there is a much simpler way of doing this if I understand your task correctly.
def change2(str):
return ''.join([letter for letter in str if letter not in ['a','e','i','o','u','A','E','I','O','U']])
print(change2(input('enter a string: ')))
The join method creates the new string and returns it. The separator between the list elements is a string that calls join() method. In this example, it is an empty string.
You should use a new string variable for concatenation. You are changing the passed string to the function that's why it gives the error.
str=input("enter a string: ")
def change(stri):
nstr = ''
for i in range(0,len(stri)):
for e in ['a','e','i','o','u','A','E','I','O','U']:
print(stri[i])
if stri[i]==e:
if i==len(stri)-1:
nstr = stri[0:i-1] + "" + stri[i: ]
else:
nstr = stri[0:i] + "" + stri[i+1: ]
else:
continue
return nstr
str=change(str)
print(str)

Find Similar Elements in List using Python

I need to look for similar Items in a list using python. (e.g. 'Limits' is similar to 'Limit' or 'Download ICD file' is similar to 'Download ICD zip file')
I really want my results to be similar with chars, not with digits (e.g. 'Angle 1' is similar to 'Angle 2'). All these strings in my list end with an '\0'
What I am trying to do is split every item at blanks and look if any part consists of a digit.
But somehow it is not working as I want it to work.
Here is my code example:
for k in range(len(split)): # split already consists of splitted list entry
replace = split[k].replace(
"\\0", ""
) # replace \0 at every line ending to guarantee it is only a digit
is_num = lambda q: q.replace(
".", "", 1
).isdigit() # lambda i found somewhere on the internet
check = is_num(replace)
if check == True: # break if it is a digit and split next entry of list
break
elif check == False: # i know, else would be fine too
seq = difflib.SequenceMatcher(a=List[i].lower(), b=List[j].lower())
if seq.ratio() > 0.9:
print(Element1, "is similar to", Element2, "\t")
break
Try this, its using get_close_matches from difflib instead of sequencematcher.
from difflib import get_close_matches
a = ["abc/0", "efg/0", "bc/0"]
b=[]
for i in a:
x = i.rstrip("/0")
b.append(x)
for i in range(len(b)):
print(get_close_matches(b[i], (b)))

matching parentheses using a file

I am trying to match parentheses from a line in a file but when I use the code below without getting data from a file and entering it instead it works and matched the parentheses. I don't know how to allow it to work with numbers and letters in between too.
i have tried many different ways but this has worked the best so far. I think there is firstly something wrong with what i am printing but i have tried everything that i know to fix that. i am also new to python so it might not be the best code.
class Stack:
def __init__(self):
self._items = []
def isEmpty(self):
return self._items == []
def push(self,item):
self._items.append(item)
def pop(self):
return self._items.pop()
stack = Stack()
open_list = ["[","{","("]
close_list = ["]","}",")"]
def open_file():
file = open("testing.txt","r")
testline = file.readline()
count = 1
while testline != "":
testline = testline[:-1]
check(testline,count)
testline = file.readline()
count = count + 1
def check(testline,count):
stack = []
for i in testline:
if i in open_list:
stack.append(i)
elif i in close_list:
pos = close_list.index(i)
if ((len(stack) > 0) and
(open_list[pos] == stack[len(stack)-1])):
stack.pop()
else:
print ("Unbalanced")
print (count)
if len(stack) == 0:
print ("Balanced")
print (count)
def main():
open_file()
if __name__=="__main__":
main()
output:
if the file contains
dsf(hkhk[khh])
ea{jhkjh[}}
hksh[{(]
sd{hkh{hkhk[hkh]}}]
the output is
Balanced
1
Unbalanced
2
Unbalanced
2
Unbalanced
3
Unbalanced
4
Balanced
4
The first four are correct but it adds 2 and i have no idea where it is coming from. I need the count for later purposes when i am printing (ie line 1 is balanced)
Time to learn the basis of debugging...
#emilanov has given hints for the open_file function, so I will focus on the check function.
for i in range (0,len(testline),1):
Is probably not what you want: i will take integer values from 0 to len(testline) -1. The rule is: when things go wrong, use a debugger or add trace prints. Here
for i in range (0,len(testline),1):
print(i) # trace - comment out for production code
would have made the problem evident.
What you want is probably:
for i in testline:
There are some problems with your open_file() function.
The while-loop finishes only when testline == "" returns true. So when later you do check(testline), you actually give the function an empty string, so it can't really do it's job.
I assume the purpose of the while loop is to remove the newline character \n for each line in the file? The problem is you're not saving the intermediate lines anywhere. Then when file.readline() returns a "" because the file doesn't have any more lines, you give that empty string to the function.
Some suggestions
# A way to remove newlines
testline = testline.replace("\n", "")
# Check all the lines
lines = file.readlines()
count = len(lines)
for testline in lines:
testline = testline.replace("\n", "")
check(testline)
# And if you're sure that the file will have only one line
testline = file.readline()[:1] # read line and remove '\n'
check(testline)
Remember, a string is just a list full of characters. So you can do len(string) to see the length. Or you can do len(file.readlines()) to see how many lines a file has. Either way, you can get rid of the count variable.
Printing
When you call print(check()) it first calls the check() function with no parameters, so it can't actually check anything. That's why you can't see the right print statement.
A suggested edit would be to move the print statement at the end of your open_file() function, so that you have print(check(testline))
Another possible solution would be to put a return statement in your open_file() function.
def open_file():
# Some code...
return check(testline)
def check():
# Some code...
print(open_file())
The easiest will probably be to replace the return statements in check() with print statements though.

Open file and read to find first instance of number. Python

Im stuck on a problem for an assignment, I need to write a program that opens a file on my computer, and scans that file for the first instance of a number. Once it is found it will return
The first number in , filenm is x
otherwise it will say there is no number in filenm.
My code so far is below:
When i run it no matter what it always says theres no number :(
filenm = raw_input("Enter a file name: ")
datain=open(filenm,"r")
try:
c=datain.read(1)
result = []
for line in datain:
c=datain.read(1)
while int(c) >= 0:
c = datain.read(1)
result.append(c)
except:
pass
if len(result) > 0:
print "The first number is",(" ".join(result))+" . "
else:
print "There is no number in" , filenm + "."
That's all you need:
import re
with open("filename") as f:
for line in f:
s=re.search(r'\d+',line)
if s:
print(s.group())
break
open the file;
read it in a loop char-by-char;
check if the char is digit, print whatever you want;
it means there are no numbers in the file, if end-of-file is reached, print "no numbers"
Use <string>.isdigit() method to check if the given string (a single character in your case) is a digit.
I don't recommend mixing iterating through a file
for line in datain:
with using the read method (or any similar one)
c=datain.read(1)
Just stick with one or the other. Personally, I would go with iterating here.
readlines() method returns a list of all the lines in the file. You can then iterate trough the list of characters in each line:
filenm = raw_input("Enter a file name: ")
datain=open(filenm,"r")
try:
result = []
for line in datain.readlines():
print 'line: ' + line
for each in line:
try:
# attempt casting a number to int
int(each)
# if it worked it add it to the result list
result.append(each)
except:
pass
except:
pass
print result
if len(result) > 0:
print "The first number is",(" ".join(result[0]))+". "
else:
print "There is no number in" , filenm + "."
This will only work with the first number character it finds, not sure if you actually need to extract multi digit numbers.
My thoughts:
1) As others noted, don't mask the exception. It would be better to let it be thrown - at least that way you find out what went wrong, if something went wrong.
2) You do want to read the file a line at a time, using for line in file:. The reason for this is that the numbers you want to read are basically "words" (things separated by spaces), and there isn't a built-in way to read the file a word at a time. file.read(1) reads a single byte (i.e. character, for an ASCII file), and then you have to put them together into words yourself, which is tedious. It's much easier to tell Python to split a line into words. At least, I'm assuming here that you're not supposed to pick out the "20" from "spam ham20eggs 10 lobster thermidor".
.readlines() is somewhat redundant; it's a convenience for making a list of the lines in the file - but we don't need that list; we just need the lines one at a time. There is a function defined called .xreadlines() which does that, but it's deprecated - because we can just use for line in file:. Seriously - just keep it simple.
3) int in Python will not return a negative value if the input is non-numeric. It will throw an exception. Your code does not handle that exception properly, because it would break out of the loop. There is no way to tell Python "keep going from where you threw the exception" - and there shouldn't be, because how is the rest of the code supposed to account for what happened?
Actually your code isn't too far off. There are a number of problems. One big one is that the try/except hides errors from you which might have help you figure things out yourself. Another was that you're reading the file with a mixture of a line at a time (and ignoring its contents entirely) as well as a character at a time.
There also seems to be a misunderstand on your part about what the int() function does when given a non-numeric character string, what it does is raise an exception rather than returning something less than 0. While you could enclose a call to it it in a try/except with the except being specifically for ValueError, in this case however it would be easier to just check ahead of time to see if the character is a digit since all you want to do is continue doing that until one that isn't is seen.
So here's one way your code could be revised that would address the above issues:
import string
filenm = raw_input("Enter a file name: ")
datain = open(filenm,"r")
# find first sequence of one or more digits in file
result = []
while True:
c = datain.read(1)
while c in string.digits: # digit?
result.append(c)
c = datain.read(1)
if c == "" or len(result) > 0: # end-of-file or a number has been found
break # get out of loop
if len(result) > 0:
print "The first number is'", "".join(result) + "'."
else:
print "There is no number in'", filenm + "'."
close(datain)

Categories

Resources