How do I read a random character from a plain text file - python

I do not know how to read a random character from a text file, and would like to learn how.
This is what happened when I started messing around with python! I know I will be doing something like this later on in school so I am practising. Reading a line would not suffice as you will see - I am open to tips and just a straight answer as I realise my code is very sloppy. The Raspberry Pi with this code on is running Raspbian lite with a few bits extra installed (a gui, idle), and runs python 3.5.3.
I write some of these to a text file:
f = open("selected.txt","w")
chars = 'abcdefghijklmnopqrstuvwxyz'
ucchars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
smbls = '`¬!"£$%^&*()-_=+{[}]:;#~#<,>.?'
nos = '1234567890'
space = ' '
Like this:
usechars = input('Use lower case letters? answer y or n.')
if usechars == 'y':
f.write(chars)
useucchars = input('Use upper case letters? answer y or n.')
if useucchars == 'y':
f.write(ucchars)
usesmbls = input('Use symbols? answer y or n.')
if usesmbls == 'y':
f.write(smbls)
usenos = input('Use numbers 0-9? answer y or n.')
if usenos == 'y':
f.write(nos)
usespace = input('Use spaces? answer y or n.')
if usespace == 'y':
f.write(space)
I would like to print a selected amount of random characters from the text file and print it in the shell, but I do not know how to get a random single character from a text file. If there would be a better way of doing it (probably the case) or you need more code please tell me. Thanks in advance.
UPDATE
here is the code:
f.close()
with open("selected.txt","r") as f:
contents = f.read
random_character = random.choice(contents)
for i in range(amnt):
password = ''
for c in range(length):
password += random_character
print(password)

If the file is not very large an easy way to pick a random character is to read it into a string first, then just select a random character from the string:
import random
with open("selected.txt", "r") as f:
contents = f.read() # NOTE the () after read
random_character = random.choice(contents)
print("The random character I've chosen is: ", random_character)
If you'd like to create a string with random choices you can use your for loop, but you have to choose a new random character inside the loop:
with open("selected.txt","r") as f:
contents = f.read()
password = ''
for i in range(amnt):
random_character = random.choice(contents)
for c in range(length):
password += random_character
print(password)

Related

Passwords/username from a file

I've recently been having trouble writing a program that involves taking the password and username from a .txt file. So far I have written:
username_file = open("usernameTest1.txt","rt")
name = username_file.readlines()
username_file.close()
print(username_file)
print(name)
print(name[0])
print()
print(name[1])
Player1Name = name[0]
print(Player1Name)
nametry = ""
while nametry != (name[0]):
while True:
try:
nametry = input("What is your Username player1?: ")
break
except ValueError:
print("Not a valid input")
(The various prints are to help me to see what the error is)
The password is successfully extracted from the file however when it is put into a variable and put through an if statement, it doesn't work!
Any help would be much appreciated!
Hopefully this is a simple fix!
Your problem is that readlines() function lets the \n character remain in your text lines and that causes the texts to not match. You can use this instead when opening the file:
name = username_file.read().splitlines()
give it a try.
the readlines function doen't strip the newline character from the end of the lines, so eventough you wrote "samplename" as input, it won't equal "samplename\n".
You can try this:
name = [x.rstrip() for x in username_file.readlines()]

How to make a quiz with answers from an external file?

I am trying to make a quiz but my answers are in an external file, so but everytime I run it with my correct answers they say they are incorrect.
Here is my code:
randNum = int(random.randint(0, 4))
song = open("songList.csv","rt")
with open("songList.csv", "rt") as f:
songn = str(song.readlines()[randNum])
reader= csv.reader(f)
for row in reader:
print (songn[0])
guess = input("What is the song called?")
score = 0
correct_guess = False
while True:
if guess == songn:
correct_guess = True
break
score += 1
if score>=total:
break
song_guess = input("Incorrect! Try again:\n> ")
if correct_guess:
print("Answer correct!")
else:
print("game over")
As pointed out in the comments, you have trailing newline characters in one of the strings. Hence they aren't equal.
However I wouldn't just remove the newline. It is always good practice, if your logic allows it, to normalize strings before you test for equality. There are lots of things you can do to normalize:
def normalize(string):
string = string.strip() # Remove any leading or trailing whitespaces
string = string.lower() # Make all letters lowercase
string = " ".join(string.split()) # If the user hit spacebar twice, for example, will remove the double space. Note can have side effects.
return string
Then check
if normalize(string1) == normalize(string2):
do_something()
In fact, if you are dealing with user input, even this might not be sufficient. For example, if the user makes a typo, it won't match.
So I recommend also looking at the fuzzywuzzy library
from fuzzywuzzy import fuzz
def similar(string1, string2):
ratio = fuzz.ratio(string1, string2)
return ratio >= 85 # number between 0 and 100. Higher means fewer differences are allowed
Fuzzywuzzy is very powerful and easy to use. For more info: https://github.com/seatgeek/fuzzywuzzy

How to Print Random Words from a Text File

I have a text file with 2000 words, one word on each line. I'm trying to create a code that prints out two random words from the textfile on the same line every 10 seconds. The beginning part of my text file is shown below:
slip
melt
true
therapeutic
scarce
visitor
wild
tickle
.
.
.
The code that I've written is:
from time import sleep
import random
my_file = open("words.txt", "r")
i = 1
while i > 0:
number_1 = random.randint(0, 2000)
number_2 = random.randint(0, 2000)
word_1 = my_file.readline(number_1)
word_2 = my_file.readline(number_2)
print(word_1.rstrip() + " " + word_2.rstrip())
i += 1
sleep(10)
When I execute the code instead of printing two random words it starts printing all the words in order from the top of the text. I'm not sure why this is happening since number_1 and number_2 are inside the loop so every time two words print number_1 and number_2 should be changed to two other random numbers. I don't think replacing number_1 and number_2 outside of the loop will work either since they'll be fixed to two values and the code will just keep on printing the same two words. Does anyone know what I can do to fix the code?
readline() doesn't take any parameters and just returns the next line in your file input*. Instead, try to create a list using readlines(), then choose randomly from that list. So here, you'd make word_list = my_file.readlines(), then choose random elements from word_list.
*Correction: readline() does take a parameter of the number of bytes to read. The documentation for the function doesn't seem to explicitly state this. Thanks E. Ducateme!
my_file.readline(number_1) does not do what you want. The argument for readline is the max size in bytes of a line you can read rather than the position of the line in the file.
As the other answer mentioned, a better approach is to first read the lines into a list and then randomly select words from it:
from time import sleep
import random
my_file = open("words.txt", "r")
words = my_file.readlines()
i = 1
while i > 0:
number_1 = random.randint(0, 2000)
number_2 = random.randint(0, 2000)
word_1 = words[number_1]
word_2 = words[number_2]
print(word_1.rstrip() + " " + word_2.rstrip())
i += 1
sleep(10)

Converting characters in a variable to their original ascii form

Okay, so I've been doing a lot of research and I couldn't find any answers so I came here to ask for some help.
My problem that I have encountered is I am having trouble taking a variable, then in the background of my code converting each individual string of that variable back to its ascii form and manipulating it using math, such as +, -, * and /. Here is my code..
Note: I had one theory, which is using a for loop to say for each character in this variable, do... blah blah. Here's my code anyways.
import random
import sys
import time
invalid_input = True
def start():
print("Welcome to the Encryption / Decryption Program!")
menuAnswer = input("Please select the number corresponding to the option you would like (1 - 3)\n---------------------------------\n[1] Encrypt\n[2] Decrypt\n[3] Exit the program\n---------------------------------\n")
if menuAnswer == '1':
print("You have chosen to Encrypt!")
invalid_input = False
message = open("sample.txt","r")
msgName = input("What is the name of the text document you would like to Encrypt?\n")
msgName = msgName.upper()
if msgName == 'SAMPLE':
key = '' #This variable will have the encryption key stored inside of it.
for i in range(0,8):
random_number = (random.randint(33,162)) #Generate a random ascii number from the range 33 to 162
key +=str(chr(random_number)) #Convert and store this ascii number as a character to the variable 'Key'
print(key)
print("Remember this key, as you will need it to decrypt your file!")
#\\ Offset //# #Finding the offset, must be able to convert each individual character of the key variable and return it to its usual form to manipulate using math.
else:
print("Invalid Filename")
elif menuAnswer == '2':
print("You have chosen to Decrypt!")
invalid_input = False
elif menuAnswer == '3':
print("You have chosen to exit!")
invalid_input = False
time.sleep(1)
print("Exiting...")
time.sleep(1.5)
exit()
else:
print("Invalid Input, Please try again!")
while invalid_input:
start()
Sorry if this question was difficult to understand, I am really confused myself and have been stuck on this for a week straight.
If I understand correctly you want to convert each character of your string to its ascii number and then do some sort of math operation on it and then convert it back to a string which you can do using ord() like so
s = 'Sample'
tmp = ''
for i in s:
tmp += chr(ord(i)+1)
print tmp
Tbnqmf
Although with the code you have you don't need to convert it to a string and then back to characters to manipulate it you can just manipulate it as soon as you pick a random number like so
import random
def start():
key = ''
for i in range(0,8):
random_number = (random.randint(33,162))
key +=chr(random_number+1)
print(key)
start()
Note you need to be careful when manipulating your characters since you could manipulate it to a number that is not an ascii character

String to integer implicit change when not called for?

I'm trying to create a simple encryption/decryption code in Python like this (maybe you can see what I'm going for):
def encrypt():
import random
input1 = input('Write Text: ')
input1 = input1.lower()
key = random.randint(10,73)
output = []
for character in input1:
number = ord(character) - 96
number = number + key
output.append(number)
output.insert(0,key)
print (''.join(map(str, output)))
def decrypt():
text = input ('What to decrypt?')
key = int(text[0:2])
text = text[2:]
n=2
text = text
text = [text[i:i+n] for i in range(0, len(text), n)]
text = map(int,text)
text = [x - key for x in text]
text = ''.join(map(str,text))
text = int(text)
print (text)
for character in str(text):
output = []
character = int((character+96))
number = str(chr(character))
output.append(number)
print (''.join(map(str, output)))
When I run the decryptor with the output from the encryption output, I get "TypeError: Can't convert 'int' object to str implicitly."
As you can see, I've added some redundancies to help try to fix things but nothing's working. I ran it with different code (can't remember what), but all that one kept outputting was something like "generatorobject at ."
I'm really lost and I could use some pointers guys, please and thank you.
EDIT: The problem arises on line 27.
EDIT 2: Replaced "character = int((character+96))" with "character = int(character)+96", now the problem is that it only prints (and as I can only assume) only appends the last letter of the decrypted message.
EDIT 2 SOLVED: output = [] was in the for loop, thus resetting it every time. Problem solved, thank you everyone!
Full traceback would help, but it looks like character = int(character)+96 is what you want on line 27.

Categories