So I have made a code that is sort of a brute force password guesser that is made to guess a 3 letter password.
I know this code is not correct because the while statement is obviously wrong so how could I fix that?
Also how could I make this code interact with other programs?
For example:
Winrar has some files that need a 3 word password and has an enter screen where you type the password. How could I make this my code interact or 'type' within that password enter box?
import random
import string
while password != correct:
letter 1 = random.choice(string.letters)
letter 2 = random.choice(string.letters)
letter 3 = random.choice(string.letters)
word = '%s%s%s'%(letter1, letter2, letter3)
if word == password:
print "The code is %s"%(word)
else:
break;
This is a terrible way to go about this, but....
import random
import string
while True:
# Do it until the `if` block says it's right, then break.
word = ''.join([random.choice(string.letters) for _ in range(3)])
if word == password:
print "The code is %s" % (word)
break
EDIT: ''.join([random.choice(string.letters) for _ in range(3)]) explained, as per your request in the comments.
[x for x in list_of_xs] is a list comprehension. You can do transformations on the resultant item (for example, all perfect squares from roots 1-10 is [x**2 for x in range(1,11)] or more simply [x**2 for x in [1,2,3,4,5,6,7,8,9,10] ]. There's lots of info out there on this, and tons of canonical SO answers.
random.choice(string.letters) you already use, so that much you get. ''.join is using the str.join command, which combines an iterable of strings into one string, using the str as a separator. ", ".join(["Eggs","Cheese","Bread","Milk"]) results in "Eggs, Cheese, Bread, Milk". In this case I'm using an empty string to combine.
Basically I'm building a list of three random.choice(string.letters) (the _ isn't anything special, it's just notation for the next programmer that comes along that this variable isn't necessary. [do_something for _ in range(x)] is a common idiom for a list of do_somethings x long), then combining them together with an empty string in between them (in other words, NOTHING in between them)
Maybe
import random
import string
while word != password:
# do the same stuff
But honestly what you're trying to do is:
import itertools as it
for attempt in (''.join(combo) for combo in it.combinations(string.letters,3)):
if attempt == password:
print "success:",attempt
else:
print "failure"
To pre-empt your question, itertools (which I imported as it) has a method combinations that returns all of the unique combinations of the iterable you hand it of the sequence length r. The notation is itertools.combinations(iterable,r). It returns a list of tuples, which then need to be combined in the same way I did above.
The only failing of THIS method is that it can't catch passwords like "aaa". Any repeated characters won't show up in combinations.
As far as your title: "How can I make this code interact with other programs" is too broad for this question. It's not a good fit unfortunately.
Related
Please note I am only allowed to use Math and Random class
so for this, I was considering using "for loop" for the number of of digits restriction from quantity_digit and use ''.join() function to add things up. The list might be like this ["333322","999883"].
I was wondering how do I for each iteration, randomly pick an element and within that element, pick random number from it. Can this be done? Please help
so this is I want to do
define the function
2)for loop for addition of the characters from the string
choose random string from the list each iteration
and (each iteration) in that list I want to select several characters from that specific String
use join() function to add things up
ok this is a fairly basic solution, u can add modifications to it
from random import choices
from string import digits
password = lambda quantity_digit, quantity_list: [''.join(choices(digits, k=quantity_digit)) for _ in range(quantity_list)]
print(password(10, 2))
i guess this is a more beginner friendly answer
import random
def random_password(quantity_digit, quantity_list):
main_list = []
for i in range(quantity_list):
temp_string = ''
for j in range(quantity_digit):
temp_string += random.choice('1234567890')
main_list.append(temp_string)
return main_list
Explaination
generating an empty list to which we will add the random number
in the first for loop, we are generating an empty string
then we are adding random numbers to the empty string (quantity_digit times)
then we are adding this string to the main_list
Demonstartion
print(random_password(10, 2))
output:
['5810832344', '5716136790']
print(''.join(random_password(10, 2)))
output:
87651084999133098434
My understanding of the problem is this... You have a list of strings. Each string contains some digits. You want to make a 'password' by randomly selecting one of the strings in your reference list and then randomly selecting one of the digits from that string. You want to be able to specify a length of the resulting string.
If that's the case then:
from random import choice
reference = ['333322', '999883']
def make_password(ref, length):
return ''.join(choice(choice(ref)) for _ in range(length))
print(make_password(reference, 6))
Output: (example)
292393
I think I was close to figuring out how to print out all the possible words based on user input from my set dictionary. it's based on the assumption that the user input is 'ART' so the possible words I have in my dictionary are ART, RAT, TART, and TAR but only the three letter combinations are printing out. can anyone tell me where I am going wrong? Thanks!
Dictionary = ["tar","art","tart","rat"] #creates dictionary of set words
StoredLetters = input('input your word here: ') #allows the user to input any word
list(StoredLetters)
def characters(word):
Dictionary = {}
for i in word:
Dictionary[i] = Dictionary.get(i, 0) + 1
return Dictionary
def all_words(StoredLetters, wordSet):
for word in StoredLetters:
flag = 1
words = characters(word)
for key in words:
if key not in wordSet:
flag = 0
else:
if wordSet.count(key) != words[key]:
flag = 0
if flag == 1:
print(word)
if __name__ == "__main__":
print(all_words(Dictionary, StoredLetters))
It appears there are a few things that could contribute to this.
You are swapping the parameters on all words def allwords(Dictionary, StoredLetters): when you call it in main allwords(StoredLetters, Dictionary). Without specifying the name (look up named parameters in python) you would be swapping the input.
In the characters function it would appear you are resetting the dictionary variable. Try using unique names when creating new variables. This is causing the dictionary of words you set at the top to be emptied out when characters(word) is called
First off, you are confusing things by having the name of your variable StoredLetters also being the name of one of the arguments to your all_words function.
Second, you are actually passing in StoredLetters, which is art, as the 2nd argument to the function, so it is wordSet in the function, not StoredLetters!
You should really keep things more clear by using different variable names, and making it obvious what are you using for which argument. words isn't really words, it's a dictionary with letters as keys, and how many times they appear as the values! Making code clear and understandable goes a long way to making it easy to debug. You have word, StoredLetters, wordSet, another StoredLetters argument, words = characters(word) which doesn't do what is expected. This could all use a good cleanup.
As for the functionality, with art, each letter only appears once, so for tart, which has t twice, if wordSet.count(key) != words[key] will evaluate as True, and flag will be set to 0, and the word will not be printed.
Hope that helps, and happy coding!
Based on the follow-up comments, the rule is that we must use all characters in the target word, but we can use each character as many times as we want.
I'd set up the lookup "dictionary" data structure as a Python dict which maps sorted, unique characters as tuples in each dictionary word to a list of the actual words that can be formed from those characters.
Next, I'd handle the lookups as follows:
Sort the unique characters of the user input (target word) and index into the dictionary to get the list of words it could make. Using a set means that we allow repetition and sorting the characters means we normalize for all of the possible permutations of those letters.
The above alone can give false positives, so we filter the resulting word list to remove any actual result words that are shorter than the target word. This ensures that we handle a target word like "artt" correctly and prevent it from matching "art".
Code:
from collections import defaultdict
class Dictionary:
def __init__(self, words):
self.dictionary = defaultdict(list)
for word in words:
self.dictionary[tuple(sorted(set(word)))].append(word)
def search(self, target):
candidates = self.dictionary[tuple(sorted(set(target)))]
return [x for x in candidates if len(x) >= len(target)]
if __name__ == "__main__":
dictionary = Dictionary(["tar", "art", "tart", "rat"])
tests = ["art", "artt", "ar", "arttt", "aret"]
for test in tests:
print(f"{test}\t=> {dictionary.search(test)}")
Output:
art => ['tar', 'art', 'tart', 'rat']
artt => ['tart']
ar => []
arttt => []
aret => []
The issues in the original code have been addressed nicely in the other answers. The logic doesn't seem clear since it's comparing characters to words and variable names often don't match the logic represented by the code.
It's fine to use a frequency counter, but you'll be stuck iterating over the dictionary, and you'll need to check that each count of a character in a dictionary word is greater than the corresponding count in the target word. I doubt the code I'm offering is optimal, but it should be much faster than the counter approach, I think.
I am trying to make a program where I can enter some characters in python and the program then goes through all the possible combinations of those letters. Then it compares that to check if it is in the dictionary or is a word. If it is, it gets appended to a list that will be printed out at the end. I had to look up how to do certain things and was doing great until I got this error. I can't find any forum that has this message. Can someone help me and tell me what I need to do to get it to work? Here is my code.
import itertools
import enchant
how_many_letters=True
letters=[]
possible_words=[]
d = enchant.Dict("en_US")
print("Welcome to combination letters helper!")
print("Type the word 'stop' to quit entering letters, other wise do it one at a time.")
while how_many_letters==True:
get_letters=input("Enter the letters you have with not counting spaces:")
if get_letters=='stop':
how_many_letters=False
letters.append(get_letters)
length=len(letters)
length=length-1
del letters[length:]
print(letters)
for i in range(length):
for subset in itertools.combinations(letters, i):#Subset is the combination thing
print(subset)
check=d.check(subset)
print(check)
if check==True:
possible_words.append(check)
print(possible_words)
Thanks in advance.
The answer to you question is this:
for i in range(1, length + 1):
for subset in itertools.combinations(letters, i):#Subset is the combination thing
s = ''.join(subset)
print(s)
check=d.check(s)
print(check)
if check==True:
possible_words.append(s)
print(possible_words)
You need to pass enchant a string not a tuple and your range was not working.
(It's possible you may want to look at itertools.permutations(), I don't know if that is what you want though.)
i'm super duper new in python. I'm kinda stuck for one of my class exercises.
The question goes something like this: You have a file that contains characters i.e. words. (I'm still at the stage where all the terms get mixed up, I apologize if that is not the correct term)
Example of the file.txt content: accbd
The question asks me to import the file to python editor and make sure that no letter occurs more than letter that comes later than it in the alphabet. e.g. a cannot occur more frequently than b; b cannot occur more than c, and so on. In the example file, c occurs more frequently than d, so I need to raise an error message.
Here's my pathetic attempt :
def main():
f=open('.txt','r') # 1st import the file and open it.
data = f.read() #2nd read the file
words = list(data) #3rd create a list that contains every letter
newwords = sorted(words) # sort according to alphabetical order
I'm stuck at the last part which is to count that the former word doesn't occur more than the later word, and so on. I tried two ways but neither is working. Here's trial 1:
from collections import counter
for i in newwords:
try:
if counter(i) <=counter(i+1):
print 'ok'
else:
print 'not ok between indexes %d and %d' % (i, i+1)
except:
pass
The 2nd trial is similar
for i in newwords:
try:
if newwords.count(i) <= newwords.count(i+1):
print 'ok'
else:
print 'ok between indexes %d and %d' % (i, i+1)
except:
pass
What is the correct way to compare the count for each word in sequential order?
I had posted an answer, but I see it's for an assignment, so I'll try to explain instead of just splatting a solution here.
My suggestion would be to solve it in three steps:
1) in the first line, create a list of sorted characters that appear in the string:
from the data string you can use set(data) to pick every unique character
if you use sort() on this set you can create a list of characters, sorted alphabetically.
2) then use this list in a for loop (or list comprehension) to create a second list, of their number of occurrences in data, using data.count(<letter in the list>); note that the elements in this second list are technically sorted based on the alphabetical order of the letters in the first list you made (because of the for loop).
3) compare this second list of values with a sorted version of itself (now sorted by values), and see if they match or not. If they don't match, it's because some of the initial letters appears too many times compared to the next ones.
To be a little more clear:
In [2]: string = 'accbd'
In [3]: import collections
In [4]: collections.Counter(string)
Out[4]: Counter({'c': 2, 'a': 1, 'b': 1, 'd': 1})
Then it's just a for loop with enumerate(list_).
I want to randomise the case of a string, heres what I have:
word="This is a MixeD cAse stRing"
word_cap=''
for x in word:
if random.randint(0,1):
word_cap += x.upper()
else:
word_cap += x.lower()
word = word_cap
print word
Im wondering if you could use list comprehension to make it faster.
I couldnt seem to use the lower() and upper() functions in randomchoice
i tried to do something like
''.join(randomchoice(x.upper(),x.lower()) for x in word)
but i think thats wrong. something like that though is possible?
import random
s = 'this is a lower case string'
''.join(random.choice((str.upper,str.lower))(x) for x in s)
random.choice randomly selects one from two functions str.upper, str.lower.
Then this function is applied to x for each letter in the input string s.
If initial string has all the letters in lowercase, that I would use this code:
''.join(x.upper() if random.randint(0,1) else x for x in s)
because the initial code would use redundant str.lowercase on half of the letters in the case of lowercase initial string.
By the way, look at the other answer by Michael J. Barber. Python have hefty charges for function calls. In his code he calls str.upper only once. In my code str.upper is called for about half the symbols of the initial string. So still a temporary upper-cased string is created in memory, the time efficiency of his code may be much greater.
Lo and behold:
Code timing comparisons: https://ideone.com/eLygn
Try this:
word="this is a lower case string"
caps = word.upper()
''.join(x[random.randint(0,1)] for x in zip(word, caps))
This should outperform your version because it makes many fewer calls to upper and because, more importantly, it avoids the O(N^2) successive appends you used in the version with the loops.
With the modification to the question, you'll need to create both the lowercase and uppercase versions:
word="This is a MixeD cAse stRing"
caps = word.upper()
lowers = word.lower()
''.join(random.choice(x) for x in zip(caps, lowers))
As suggested by Tim Pietzcker in the comments, I've used random.choice to select the letters from the tuples created by the zip call.
Since the question has been changed to focus more on speed, the fastest approach is likely to be using Numpy:
''.join(numpy.where(numpy.random.randint(2, size=len(caps)), list(caps), list(lowers)))