How do add onto a text file when after writing a code? - python-3.x

So I am trying to get the code to read the inFile text line by line. It has to split each line then run through the check if valid or not. For some reason it only reads the last line and then prints in the outFile 00-7141858-X so I am assuming it is reading by each line to get down there there first. But it only went through the processes on the last line?
019-923-3241
818-851-703X
5703781188
031-X287085-
00-7141858-X
I want the outfile to look something like this
019-923-3241 - valid
818-851-703X - invalid
5703781188 - valid
031-X287085- invalid
00-7141858-X - valid
Thanks!
def pre_process (processed_S):
st = ''
for ch in processed_S:
if ch == '-':
st = st + ''
else:
st = st + ch
return st
def digit_check (processed_S):
digit_nums = '0123456789Xx'
nums = set(digit_nums)
for ch in processed_S:
if not ch in nums:
print ("Invalid ISBN")
return processed_S
def length_check(processed_S):
if len(processed_S) < 10 or len(processed_S) > 10:
print ("Invalid ISBN")
def value_placement (processed_S):
first_nine = '0123456789'
nums2 = set (first_nine)
for ch in range(len(processed_S) - 1):
if not str(ch) in nums2:
print ("Invalid ISBN")
return processed_S
def check_x (processed_S):
last_letter = '0123456789Xx'
nums3 = set (last_letter)
if not str(processed_S[-1]) in nums3:
print ("Invalid ISBN")
return processed_S
def main():
inFile = open ('isbn.txt', 'r')
outFile = open ('isbnOut.txt', 'w')
for line in inFile:
line = line.strip()
processed_S = pre_process (line)
st = digit_check (processed_S)
st2 = length_check (processed_S)
st3 = value_placement (processed_S)
st4 = check_x (processed_S)
count = 0
s2 = []
for i in processed_S:
if i.isdigit():
count += int(i)
s2.append(count)
if i == 'X':
i = '10'
count += int(i)
s2.append(count)
s2_count = 0
for j in s2:
if i.isdigit():
s2_count += int(j)
if s2_count % 11 != 0:
outFile.write(processed_S)
outFile.write(" - Invalid\")
else:
outFile.write(processed_S)
outFile.write(" - valid\n")
inFile.close()
outFile.close()
main()

Almost there. You need to write to the file instead of appending though. And don't forget the newline.
outFile.write(processed_S)
outFile.write(" - Invalid\n")

There are several issues with your code. The one you're asking about is due to an indentation issue. Here's the loop in your code that reads from your input file:
for line in inFile:
line = line.strip()
processed_S = pre_process (line)
This only does the strip on each line, throwing the results away afterwards. The pre_process call is only done after the loop ends, and it only happens on the last value that line was given.
To fix this, you need to indent the processed_S = preprocess (line) line and most of the following ones so that they're at the same level as line = line.strip().
Other issues:
Your various whatever_check functions don't do anything but print if the check fails (and they may print multiple times!). Probably you should make them return a True or False value, rather than printing and returning the inputted string.
digit_check will only fail if one of value_placement or check_x will also fail. It's probably not necessary to have all three (either keep the latter two, or just make one function that tests everything). Something like all(c in digits for c in s[:-1]) and s[-1] in (digits + 'X') would do all the tests in one line.
Other stuff that's not really wrong, but could be improved:
Use the with statements to make sure your files get closed after you're done with them, rather than relying on your own manual close calls.
with open ('isbn.txt', 'r') as infile, open ('isbnOut.txt', 'w') as outfile:
# the rest
Your loop to add up the ISBN checksum could be simplified:
checksum = t = 0
for c in processed_S:
if c.isdigit():
t += int(c)
else: # c must be X, or a previous test should have failed
t += 10
checksum += t
if checksum % 11 == 0:
# valid
Probably the checksum test should go into a separate function from main. Furthermore, it and the other tests you have for validity should be called from a higher level valid_isbn function that takes care of the preprocessing and all the checks. This will let main be greatly simplified. Ideally to:
def main():
with open ('isbn.txt', 'r') as infile, open ('isbnOut.txt', 'w') as outfile:
for line in infile:
if verify_isbn(line):
outfile.write(line.strip() + " - valid\n")
else:
outfile.write(line.strip() + " - invalid\n")

I don't really remember the solution but this solved it apparently. Just came back to fix the solution.
def pre_process (processed_S):
st = ''
for ch in processed_S:
if ch == '-':
st = st + ''
else:
st = st + ch
return st
def digit_check (processed_S):
digit_nums = '0123456789Xx'
nums = set(digit_nums)
for ch in processed_S:
if not ch in nums:
print ("Invalid ISBN")
return processed_S
def length_check(processed_S):
if len(processed_S) < 10 or len(processed_S) > 10:
print ("Invalid ISBN")
def value_placement (processed_S):
first_nine = '0123456789'
nums2 = set (first_nine)
for ch in range(len(processed_S) - 1):
if not str(ch) in nums2:
print ("Invalid ISBN")
return processed_S
def check_x (processed_S):
last_letter = '0123456789Xx'
nums3 = set (last_letter)
if not str(processed_S[-1]) in nums3:
print ("Invalid ISBN")
return processed_S
def main():
inFile = open ('isbn.txt', 'r')
outFile = open ('isbnOut.txt', 'w')
for line in inFile:
line = line.strip()
processed_S = pre_process (line)
st = digit_check (processed_S)
st2 = length_check (processed_S)
st3 = value_placement (processed_S)
st4 = check_x (processed_S)
count = 0
s2 = []
for i in processed_S:
if i.isdigit():
count += int(i)
s2.append(count)
if i == 'X':
i = '10'
count += int(i)
s2.append(count)
s2_count = 0
for j in s2:
if i.isdigit():
s2_count += int(j)
if s2_count % 11 != 0:
outFile.write(processed_S)
outFile.write(" - Invalid\n")
else:
outFile.write(processed_S)
outFile.write(" - valid\n")
inFile.close()
outFile.close()
main()

Related

finding time and memory inefficiencies in my program

I need to find time and memory inefficiencies in this program. I've tried several things: changing the variable names and also changed the code to delete the for-loops. These things made the program not work unfortunately. Can anyone help?
import sys
def longest(doc):
infile = open(doc, "r")
text = infile.read()
longest_seq = []
current_seq = []
current_start = ""
first_letters = [""]
for word in text.split():
current_start = word[0]
if current_start == first_letters[-1]:
# same first letter as previous word
current_seq.append(word)
elif current_start != first_letters[-1]:
# done with the current sequence
current_seq = [word]
first_letters.append(word[0])
if len(longest_seq) < len(current_seq):
longest_seq = current_seq
infile.close()
return longest_seq
def main(argv):
if len(argv) != 2:
print("Usage: {} File".format(argv[0]), file=sys.stderr)
exit(-1)
seq = longest(argv[1])
slength = len(longest(argv[1]))
print("longest sequence of consecutive words starting with the same letter:")
print("\'{}\'".format(' '.join(seq)))
print("length: {}\n".format(slength))
if __name__ == "__main__":
main(sys.argv)

how to move a character to a certain inputted index

I am trying to make my own text editor where it asks for a file and prints a > that can then be moved to the specified index of the line so that it can then delete a character. I don't know the best way to move it. So far I have
def print_file(data, cursor):
"""Prints the file contents (data), with the cursor in the right place."""
# Variable fm will store the formatted representation
# of the file with position information, etc.
fm = ""
pos = 0
# Break the "file" (represented by a string) up into lines.
lines = data.split("\n")
for x, line in enumerate(lines):
length = len(line)
if length != 0:
# Edge case for the end of the "file".
if data[-1] != "\n" and x == len(lines) - 1:
length -= 1
fm += str("{0:70} |{1:3d}:{2:3d}|\n".format(line, pos, pos + length))
# If the cursor points to char on this line add it.
if pos <= cursor <= pos + length:
fm += " " * (cursor - pos) + "^\n"
# Start at the next character.
pos += length + 1
print(fm, end="")
#end of function
def move_cursor(location):
"""Moves the cursor to the right location"""
#end of function
cursor = 0
is_open = False
is_modified = False
file = str(input(">open "))
#Open filename
file == "(filename)"
file = open(file, "r")
file_data = file.read()
print_file(file_data, cursor)
command = str(input("> "))
#Move position
if command == "move(int)":
move_cursor(location)
I think the best way would be to make a function and then call it inside the loop, but am unsure how to actually get it to move to the index....

Caesar Cipher shift on new lines

I am having a problem with my code trying to do an advanced caesar cipher shift. I changed a certain letter to another, and then added a string to certain parts of a file before encoding, but am having problems doing the shifting now. This is my code:
import string
import sys
count = 1
cont_cipher = "Y"
#User inputs text
while cont_cipher == "Y":
if count == 1:
file = str(input("Enter input file:" ""))
k = str(input("Enter shift amount: "))
purpose = str(input("Encode (E) or Decode (D) ?: "))
#Steps to encode the message, replace words/letter then shift
if purpose == "E":
my_file = open(file, "r")
file_contents = my_file.read()
#change all "e"s to "zw"s
for letter in file_contents:
if letter == "e":
file_contents = file_contents.replace(letter, "zw")
#add "hokie" to beginning, middle, and end of each line
lines = file_contents.split('\n')
def middle_message(lines, position, word_to_insert):
lines = lines[:position] + word_to_insert + lines[position:]
return lines
new_lines = ["hokie" + middle_message(lines[x], len(lines[x])//2, "hokie") + "hokie" for x in range(len(lines))]
#math to do the actual encryption
def caesar(word, shifts):
word_list = list(new_lines)
result = []
s = 0
for c in word_list:
next_ord = ord(c) + s + 2
if next_ord > 122:
next_ord = 97
result.append(chr(next_ord))
s = (s + 1) % shifts
return "".join(result)
if __name__ == "__main__":
print(caesar(my_file, 5))
#close file and add to count
my_file.close()
count = count + 1
The error I am getting is:
TypeError: ord() expected a character, but string of length 58 found
I know that I need to split it into individual characters, but am not sure how to do this. I need to use the updated message and not the original file in this step...

Python: Checking Characters in String

So I keep trying to make this work but I do not know where it is going wrong. The text file contains:
III
###
This is what I have so far. I do not see what is wrong.
CHARACTERS = ["I","#"]
def checkFile():
inFile = open("random.txt","r")
text = inFile.read()
inFile.close()
x = True
for line in text:
line.strip()
for i in range(len(line)):
if line[i] in CHARACTERS:
x = True
else:
x = False
return False
return True
def main():
check = checkFile()
if check == False:
sys.exit()
elif check == True:
print("bye")
sys.exit()
main()
It should print "bye" because all the characters in the file are in the list; however it just exits without the print statement.
When a txt file contains two lines of text, one on top of each other, it also includes a hidden '\n'. To change that add '\n' to CHARACTERS, or copy the following code:
CHARACTERS = ["I","#", "\n"]
def checkFile():
inFile = open("random.txt","r")
text = inFile.read()
inFile.close()
x = True
for line in text:
line.strip()
for i in range(len(line)):
if line[i] in CHARACTERS:
x = True
else:
x = False
return False
return True
def main():
check = checkFile()
if check == False:
sys.exit()
elif check == True:
print("bye")
sys.exit()
main()
EDIT: I created a txt file called test.txt and I pasted your text into it. I then ran the following code:
>>> file = open('test.txt', 'r').read()
>>> file
'III\n\n###\n'
>>>
Because there are two lines in between, it has teo '\n's. You can get rid of this by either adding '\n' to CHARACTERS, or by calling text = inFile.read().split() with the split()
When you call line.strip(), you are not assigning line.strip() to any value. Thus, the '\n' remains 'unstripped', so to speak. Instead, call line = line.strip().

Something wrong with call function

I don't know where does it goes wrong. I can get the correct result if I just call out my valid_ISBN(isbn) function, but when I write the file, the result become all invalid. (maybe something wrong with function call, but I don't know how to fix it)
def main():
# Call and open the File
inFile = open("isbn.txt", "r")
for line in inFile:
line_strip = line.replace("-", "").replace(" ", "").rstrip("\n")
isbn = line_strip # the function call
# Output file
str = []
str.append(line)
outFile = open("isbnOut.txt", "a")
for i in str:
if valid_ISBN(isbn) == "valid":
outFile.write(i.strip() + " valid\n")
else:
outFile.write(i.strip() + " invalid\n")
inFile.close()
outFile.close()
def valid_ISBN(isbn):
if len(isbn) != 10 or (isbn[0:9].isdigit()) == False:
print("invalid")
else:
return partial_sums(isbn)
def partial_sums(s1):
lst1 =[]
sum1 = 0
for i in range(len(s1)):
if (i == (len(s1) -1)) and ((s1[i] == "x") or (s1[i] == "X")):
sum1 = sum1 + 10
else:
sum1 = sum1 + int(s1[i])
lst1.append(sum1)
#print(lst1)
sum_of_s1(lst1)
def sum_of_s1(s2):
lst2 = []
sum2 = 0
for i in s2:
sum2 += i
lst2.append(sum2)
#print(lst2)
checkISBN(lst2[-1])
def checkISBN(value):
if value % 11 == 0:
print("valid")
else:
print("invalid")
main()
2 Test case for isbn text file (no new line):
019-923-3241
818-851-703X
In your main function:
Every time you read a line in from your input file you initialize str and fill it with just one value. You open your output file, do your validity checks for your one value in str, and finally write the one value to the the output file.
The next time you read the file you do the same stuff... so str isn't needed at all
Also using str as a variable name is bad form. In your console write in help(str) and you will see why.
Now to deal with your actual complaint:
Your problem is the fact that there is no new line.
when you say for line in some_open_file_handler:... what python does is populate line with everything up to the next newline character or the end of the file.
If your input file has no new lines seperating isbns then the first value of line would be 019-923-3241 818-851-703X. Thus the line line_strip = line.replace("-", "").replace(" ", "").rstrip("\n") set linestrip to 0199233241818851703X
This should fix it:
'line.split() will yield ['019-923-3241','818-851-703X']
outFile = open("isbnOut.txt", "a")
for line in open("isbn.txt", "r"):
isbns = line.split() #this splits stuff up by whitespace.
for isbn in isbns:
isbn = isbn.replace("-", "").replace(" ", "").rstrip("\n")
if valid_ISBN(isbn) == "valid":
outFile.write(i.strip() + " valid\n")
else:
outFile.write(i.strip() + " invalid\n")

Resources