One part of my program allows the user to check whether the clues they have entered are correct with the solved version which is in an external file named solved.txt... So far I have the code shown below however it is only showing the three clue pairings at the beginning of the program which are correct, not the ones which I have added throughout the program. I think this is just something minor but I am a bit stuck on what to change.
Here is my code so far...
def check_clues():
# Dictionary to hold all of the symbol/letter combos
coded_dict = {}
# Go through each symbol/letter combination together
with open("words.txt") as fw, open("solved.txt") as fs:
for fw_line, fs_line in zip(fw, fs):
for fw_symbol, fs_letter in zip(fw_line.strip(), fs_line.strip()):
# Add the symbol/letter combination to the dictionary
coded_dict[fw_symbol] = fs_letter
correct_clues = []
with open("clues.txt") as fc:
for fc_line in fc:
# If the symbol is in the dictionary and the letter matches the symbol
if fc_line[1] in coded_dict and coded_dict[fc_line[1]] == fc_line[0]:
# Add a correct clue to your list
correct_clues.append(fc_line.strip())
print("You got a total of {0} correct: {1}".format(len(correct_clues), ", ".join(correct_clues)))
if __name__ == "__main__":
check_clues()
Below is a link to what is in each of the files...
http://www.codeshare.io/vgwrC
If needed, I will add the code for all of my program...
Related
I am trying to build a script that copies a specified number of lines from one document to multiple other documents. The copied lines are supposed to be appended to the end of the docs. In case I want to delete lines from the end of the docs, the script also has to be able to delete a specified number of lines.
I want to be able to run the script from the command line and want to pass two args:
"add" or "del"
number of lines (counting from the end of the document)
A command could look like this:
py doccopy.py add 2 which would copy the last 2 lines to the other docs, or:
py doccopy.py del 4 which would delete the last 4 lines from all docs.
So far, I have written a function that copies the number of lines I want from the original document,
def copy_last_lines(number_of_lines):
line_offset = [0]
offset = 0
for line in file_to_copy_from:
line_offset.append(offset)
offset += len(line)
file_to_copy_from.seek(line_offset[number_of_lines])
changedlines = file_to_copy_from.read()
a function that pastes said lines to a document
def add_to_file():
doc = open(files_to_write[file_number], "a")
doc.write("\n")
doc.write(changedlines.strip())
doc.close()
and a main function:
def main(action, number_of_lines):
if action == "add":
for files in files_to_write:
add_to_file()
elif action == "del":
for files in files_to_write:
del_from_file()
else:
print("Not a valid action.")
The main function isn't done yet, of course and I have yet to figure out how to realize the del_from_file function.
I also have problems with looping through all the documents.
My idea was to make a list including all the paths to the documents i want to write in and then loop through this list and to make a single variable for the "original" document, but I don't know if that's even possible the way I want to do it.
If possible, maybe someone has an idea for how to realize all this with a single list, have the "original" document be the first entry and loop through the list starting with "1" when writing to the other docs.
I realize that the code I've done so far is a total clusterfuck and I ask a lot of questions, so I'd be grateful for every bit of help. I'm totally new to programming, I just did a Python crash course in the last 3 days and my first own project is shaping out to be way more complicated than I thought it would be.
This should do what you ask, I think.
# ./doccopy.py add src N dst...
# Appends the last N lines of src to all of the dst files.
# ./doccopy.py del N dst...
# Removes the last N lines from all of the dst files.
import sys
def process_add(args):
# Fetch the last N lines of src.
src = argv[0]
count = int(args[1])
lines = open(src).readlines()[-count:]
# Copy to dst list.
for dst in args[2:}
open(dst,'a').write(''.join(lines))
def process_del(args):
# Delete the last N lines of each dst file.
count = int(args[0])
for dst in args[1:]:
lines = open(dst).readlines()[:-count]
open(dst,'w').write(''.join(lines))
def main():
if sys.argv[1] == 'add':
process_add( sys.argv[2:] )
elif sys.argv[1] == 'del':
process delete( sys.argv[2:] )
else:
print( "What?" )
if __name__ == "__main__":
main()
I've been trying to create a program which allows users to view a text file's contents and delete some or all of a single entry block.
An example of the text's file contents can be seen below:
Special Type A Sunflower
2016-10-12 18:10:40
Asteraceae
Ingredient in Sunflower Oil
Brought to North America by Europeans
Requires fertile and moist soil
Full sun
Pine Tree
2018-12-15 13:30:45
Pinaceae
Evergreen
Tall and long-lived
Temperate climate
Tropical Sealion
2019-01-20 12:10:05
Otariidae
Found in zoos
Likes fish
Likes balls
Likes zookeepers
Big Honey Badger
2015-06-06 10:10:25
Mustelidae
Eats anything
King of the desert
As such, the entry block refers to all lines without a horizontal space.
Currently, my progress is at:
import time
import os
global o
global dataset
global database
from datetime import datetime
MyFilePath = os.getcwd()
ActualFile = "creatures.txt"
FinalFilePath = os.path.join(MyFilePath, ActualFile)
def get_dataset():
database = []
shown_info = []
with open(FinalFilePath, "r") as textfile:
sections = textfile.read().split("\n\n")
for section in sections:
lines = section.split("\n")
database.append({
"Name": lines[0],
"Date": lines[1],
"Information": lines[2:]
})
return database
def delete_creature():
dataset = get_dataset()
delete_question = str(input("Would you like to 1) delete a creature or 2) only some of its information from the dataset or 3) return to main page? Enter 1, 2 or 3: "))
if delete_question == "1":
delete_answer = str(input("Enter the name of the creature: "))
for line in textfile:
if delete_answer in line:
line.clear()
elif delete_question == "2":
delete_answer = str(input("Enter the relevant information of the creature: "))
for line in textfile:
if delete_answer in line:
line.clear()
elif delete_question == "3":
break
else:
raise ValueError
except ValueError:
print("\nPlease try again! Your entry is invalid!")
while True:
try:
option = str(input("\nGood day, This is a program to save and view creature details.\n" +
"1) View all creatures.\n" +
"2) Delete a creature.\n" +
"3) Close the program.\n" +
"Please select from the above options: "))
if option == "1":
view_all()
elif option == "2":
delete()
elif option == "3":
break
else:
print("\nPlease input one of the options 1, 2 or 3.")
except:
break
The delete_function() is meant to delete the creature by:
Name, which deletes the entire text block associated with the name
Information, which deletes only the line of information
I can't seem to get the delete_creature() function to work, however, and I am unsure of how to get it to work.
Does anyone know how to get it to work?
Many thanks!
Your problem with removing lines from a section is that you specifically hardcoded which line represents what. Removing a section in your case will be easy, removing a line will, if you do not change your concept, involve setting the line in question to empty or to some character representing the empty string later.
Another question here is, do you need your sections to remain ordered as they were entered, or you can have them sorted back in a file in some other order.
What I would do is to change the input file format to e.g. INI file format. Then you can use the configparser module to parse and edit them in an easy manner.
The INI file would look like:
[plant1]
name="Some plant's English name"
species="The plant's Latin species part"
subspecies="The plant's subspecies in Latin ofcourse"
genus="etc."
[animal1]
# Same as above for the animal
# etc. etc. etc.
configparser.ConfigParser() will let you load it in an dictionarish manner and edit sections and values. Sections you can name animal1, plant1, or use them as something else, but I prefer to keep the name inside the value, usually under the name key, then use configparser to create a normal dictionary from names, where its value is another dictionary containing key-value pairs as specified in the section. And I reverse the process when saving the results. Either manually, or using configparser again.
The other format you might consider is JSON, using the json module.
Using its function dumps() with separators and indentation set correctly, you will get pretty human-readable and editable output format. The nice thing is that you save the data structure you are working with, e.g. dictionary, then you load it and it comes back as you saved it, and you do not need to perform some additional stuff to get it done, as with configparser. The thing is, that an INI file is a bit less confusing for an user not custom to JSON to construct, and results in less errors, while JSON must be strictly formatted, and any errors in opening and closing the scopes or with separators results in whole thing not working or incorrect input. And it easily happens when the file is big.
Both formats allows users to put empty lines wherever they want and they will not change the way the file will be loaded, while your method is strict in regard to empty lines.
If you are expecting your database to be edited only by your program, then use the pickle module to do it and save yourself the mess.
Otherwise you can:
def getdata (stringfromfile):
end = {}
l = [] # lines in a section
for x in stringfromfile.strip().splitlines():
x = x.strip()
if not x: # New section encountered
end[l[0].lower()] = l[1:]
l = []
continue
end.append(x)
end[l[0].lower()] = l[1:] # Add last section
# Connect keys to numbers in the same dict(), so that users can choose by number too
for n, key in enumerate(sorted(end)):
end[n] = key
return end
# You define some constants for which line is what in a dict():
values = {"species": 0, "subspecies": 1, "genus": 2}
# You load the file and parse the data
data = getdata(f.read())
def edit (name_or_number, edit_what, new_value):
if isinstance(name_or_number, int):
key = data[name_or_number]
else:
key = name_or_number.lower().strip()
if isinstance(edit_what, str):
edit_what = values[edit_what.strip().lower()]
data[key][edit_what] = new_value.strip()
def add (name, list_of_lines):
n = len(data)/2 # Number for new entry for numeric getting
name = name.strip().lower()
data[name] = list_of_lines
data[n] = name
def remove (name):
name = name.lower().strip()
del data[name]
# Well, this part is bad and clumsy
# It would make more sense to keep numeric mappings in separate list
# which will do this automatically, especially if the database file is big-big-big...
# But I started this way, so, keeping it simple and stupid, just remap everything after removing the item (inefficient as hell itself)
for x in data.keys():
if isinstance(x, int):
del data[x]
for n, key in enumerate(sorted(data)):
data[n] = key
def getstring (d):
# Serialize for saving
end = []
for l0, ls in d.items():
if isinstance(l0, int):
continue # Skip numeric mappings
lines = l0+"\n"+"\n".join(ls)
end.append(lines)
return "\n\n".join(end)
I didn't test the code. There might be bugs.
If you need no specific lines, you can modify my code easily to search in the lines using the list.index() method, or just use numbers for the lines if they exist when you need to get to them. For doing so with configparser, use generic keys in a section like: answer0, answer1..., or just 0, 1, 2..., Then ignore them and load answers as a list or however. If you are going to use configparser to work on the file, you will get sometimes answer0, answer3... when you remove.
And a warning. If you want to keep the order in which input file gives the creatures, use ordereddict instead of the normal dictionary.
Also, editing the opened file in place is, of course, possible, but complicated and inadvisable, so just don't. Load and save back. There are very rare situations when you want to change the file directly. And for that you would use the mmap module. Just don't!
I made a dictionary in IDE and made a function to take input from user and it takes the input but when I rerun that program and try to print the output It don`t show anything.
Here is the code, help if anyone want to.
# Created dictionary.
list = {}
# Made a Function to save data.
def up():
v = int(input(f"How many inputs you want to give : "))
for i in range(v):
a = input(f"Give words you want to put : ")
b = input(f"Assign : ")
list.update({a:b})
print(f"Saved",{a:b})
value = input(f"What you want to do ? \nSee List or update it. \nIf you want to update type 'u' , If you want to see list type 's' ")
if value == "s":
print(list)
elif value == "u":
up()
Information in your variables is stored during the execution of your script. It is not automatically carried across to different executions of your script. Each one is a blank slate. Even if it weren't, the first line of your program sets list to an empty dictionary.
At the moment, you're putting salt on your broccoli, eating it, then expecting the broccoli you eat tomorrow to also have salt on it.
You could serialise the dictionary to a file, that can be read back in on next execution, rather than starting with an empty dictionary each time.
I'm using Python 3 to create a brute-force Vigenere decipher-er. Vigenere codes are basically adding strings of letters together.
The way I want my code to work is the user puts in however any keys they want (this bit's done), the letters are turned into their numbers (also done) then it adds every pair of keys together (working on this, also what I need help with) and prints out the two keys and what they added to.
To do this, I need to be able to keep track of which pairs of keys have been added together. How can I do this?
BTW, my current code is this. I'm doing this both fro the decoding and the programming practice, so I really just want the way to keep track of added key pairs, not the whole program.
#defines start variables
import math
alph = "abcdefghijklmnopqrstuvwxyz"
keyqty = int(input("how many keys?"))
listofkeys = []
listofindex = []
timer = 0
#gets keys
while True:
if timer >= keyqty:
break
else:
pass
listofkeys.append(input("key: ").lower())
timer += 1
tempkey = ""
#blank before key
for item in listofkeys:
listofindex.append("")
for letter in item:
listofindex.append(alph.find(letter)
timer = 0
newkey = False
key1index = []
key2index = []
endex = []
printletter = ""
doneadds = []
Obviously, it still needs some other work, but some help would be appreciated.
You can either use a set for fast lookup (amortized constant time).
tried = set()
for ...
if word not in tried:
try()
tried.add(word)
or use itertools.product() to generate your trials without the need of keeping track of the already tried ones.
for password in itertools.product(alph, repeat=keyqty):
try(password)
For a game I am planning, I want to create a piece of code that will write one specific value from a list of all the items in my game into the player's inventory (e.g.: player gets item "potion", which would require searching the items CSV for potion and then putting the relevant info into the CSV). Whenever I run my code however I get the error "TypeError: '_io.TextIOWrapper' object is not subscriptable".
I've tried researching and asking peers but the closest I've gotten to a clear solution is someone mentioning writing to a list from the CSV, but they didn't explain much more. Hoping someone could elaborate on this for me or provide an easier solution.
import csv
allitems = open("ALLITEMS.csv")
checkallitems = csv.reader(allitems)
playerinv = open("INVENTORY.csv")
checkinv = csv.reader(playerinv)
item = input("")
for x in checkallitems:
print(allitems[x][0])
if item == allitems[x][0]:
playerinv.write(allitems[x][0]+"\n")
allitems.close()
playerinv.close()
The problem is allitems is a file object returned by open and the statement for x in checkallitems iterates over the lines of such file so, you are trying to use a list as index in that file. Also, you have to open INVENTORY.csv in write mode (using 'w' or 'a') to be able to write to it.
Just use x instead of allitems[x]. The snippet below should do the job:
for x in checkallitems:
if item == x[0]:
playerinv.write(x[0]+"\n")
So, the complete code could be:
Code
import csv
allitems = open("ALLITEMS.csv")
checkallitems = csv.reader(allitems)
playerinv = open("INVENTORY.csv", 'a')
checkinv = csv.reader(playerinv)
item = input("")
for x in checkallitems:
if item == x[0]: # Check if the item is equal to the first item on the list
playerinv.write(x[0]+"\n")
allitems.close()
playerinv.close()
I dont know what do you want to accomplish, so I tried to stick as much as possible to your code.
If you want to only write the item provided by the user if it is found the current list of items, this would do the job:
Code
import csv
allitems = open("ALLITEMS.csv")
checkallitems = csv.reader(allitems)
playerinv = open("INVENTORY.csv", 'a')
checkinv = csv.reader(playerinv)
item = input("")
for x in checkallitems:
if item in x: # Check if the item is in the current list
playerinv.write(item +"\n")
allitems.close()
playerinv.close()
I hope this can help you. Let me know if any of this worked for you, otherwise, tell me what went wrong.