generating promotion code using python - python

By using python language, what would be a clever / efficient way of generating promotion codes.
Like to be used for generating special numbers for discount coupons.
like: 1027828-1
Thanks

The following isn't particularly pythonic or particularly efficient, but it might suffice:
import random
def get_promo_code(num_chars):
code_chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
code = ''
for i in range(0, num_chars):
slice_start = random.randint(0, len(code_chars) - 1)
code += code_chars[slice_start: slice_start + 1]
return code

1027828-1 is extremely small. An attacker can make a ~million guesses using only a couple lines of code and maybe a few days.
This is a good way to produce a hard to predict number using python, it works under linux and windows. It is base64'ed for binary safety, depending what you are doing with it you might want to urllib.urlencode() but I would avoid base10 because it doesn't store as much information.
import os
import base64
def secure_rand(len=8):
token=os.urandom(len)
return base64.b64encode(token)
print(secure_rand())
As a side note this is generating a full byte, which is base256. 256^8 is 18446744073709551616 which should be large enough.
As it was pointed out base64 isn't a very good token for humans to use. Consider an alternate encoding like url-safe base64 or perhaps humanhash as they would be easier to type in.

if you need a 6-digit # you could do this until you found a unique value:
import random
print str(random.randint(100000, 999999))
or go sequentially...

Try this:
import random
coupon = open("coupons.txt", "a")
def generate(amount):
for x in range(0, amount):
a = random.randint(1000, 9999)
a = str(a)
b = random.randint(1000, 9999)
b = str(b)
c = random.randint(1000, 9999)
c = str(c)
total = ""
total = str(total)
total = a + " " + b + " " + c
coupon.write(total)
coupon.write("\n")
amount = int(input("How many coupons do you want to generate: "))
generate(amount)
coupon.close()
print("\nCode's have been generated!")
You can make the coupons as long as you want. They save into a txt file called coupons.txt also.

I've come up with an answer for this that I think is fairly clever, but relies on a couple of assumptions that might not be true for your situation.
The resulting code is purely numeric.
The resulting code is technically variable-length; [10, 20].
If these work for you, then so might this solution:
def code(seed = None):
if (not seed) or (type(seed) != str) or (len(seed) < 10):
seed = str(uuid.uuid4())[:10]
code = ""
for character in seed:
value = str(ord(character))
code += value
return code[:20]
In this function, a string-typed seed is used as the base of the code. For each character in the string, convert it into its ASCII representation, then append it to the code.
By default, the function yields codes like this: '97534957569756524557', and can be invoked with any arbitrary seed. For example...
code("pcperini's answer") == '11299112101114105110'
code(str(time.time())) == '49524956514950505257'

Related

Extract numbers from a string in python without the use of isdigit or re. tools

Let's say I have a string of integers generated by user input, where each integer is separated by a space (Code below for example)...
How can I search through that string and store each integer separately for use later on in the program? (I.E. Assigning each integer to its own variable) I can't use isdigit and cant use re tools, and I can't store the ints into a list.
userEntry = input("Please enter a Fahrenheit temperature: ")
for i in range(4):
userEntry += " " + input("Please enter another fahrenheit:")
Things I AM allowed to use: string methods, index find/search methods, for loops, if statements, while loops.
Something like this will parse the string into space-separated strings, using slices... (I notice the first answer came in while I was working on this, but this is slightly different, so...)
def extractor(mystr):
start = 0
for a in range(len(mystr)):
if mystr[a] == ' ' or mystr[a] == len(mystr) - 1:
temp = mystr[start:a]
print(temp)
start = a + 1
This is more like a C approach, very un-Pythonic, but standard programming fare. If you will only ever have 5 user entries, this is perhaps manageable. If you can't use a list of those variables, or if you have an unknown number of user entries, or if you have to check to make sure the user actually entered a digit and not a letter, then more work is required, but that's the basic C-string parser. Useful to know if you ever want to dive into Python internals I suppose.
If you need to convert each extracted string to an int, and exceptions are allowed, place this inside the if statement to check for type correctness:
try:
myvar1 = int(temp)
except ValueError:
print("Not an int")
Note that if you absolutely cannot use lists, (*or exec as in the above answer) then the only likely option is to keep slicing off the end of the string, i.e you'd have to do something like the following at the end of each if statement, then write that for loop out 4 more times, changing the variable name each time manually.
mystr = mystr[start:len(mystr)]
break
This will of course not work if you have a variable number of user entries. And is incredibly tedious... I suspect the instructor may have intended something different. Note that the real-world process for all that is just:
result = [int(x) for x in mystr.split(' ') if x.isdigit()]
I am not sure what your use case is, and I can not think of a way where you can assign the numbers to variable in a loop, which is what you have to do if you are not allowed to use a loop. The only way I can think of is exec and I do not feel that is allowed for your task. Regardless, I am posting the answer, in case it is usable:
last_space_index = 0
characters_checked = 0
var_num = 1
userEntry = "12.8 -15.8 125.9 0 -40.0"
for character in userEntry:
characters_checked += 1
if character == ' ':
number = float(userEntry[last_space_index:characters_checked])
var_name = 'var'+str(var_num)
var_num += 1
expression = var_name + ' = number'
# expression becomes 'var1 = number'
exec(expression)
last_space_index = characters_checked
last_number = float(userEntry[last_space_index:])
var_name = 'var'+str(var_num)
expression = var_name + ' = last_number'
exec(expression)
# if you know the number of variables you are going to get
print(var1, var2, var3, var4, var5)
# else:
# for i in range(1,var_num+1):
# var_name = 'var'+str(i)
# command = 'print('+var_name+')'
# exec(command)
Output:
>>> 12.8 -15.8 125.9 0 -40.0
You can replace print with whatever you actually want to do.
And this is completely futile if you are allowed to use dictionary, sets or tuple.

Python - turn some of the words in list/str to dots. len(list)?

I've started learning Python last week on codecademy and Google etc. but got stuck and couldn't find the answer anywhere so signed up on stackoverflow.com looking for your support.
I'm trying to build a program that only takes first 5 letters of any name and the remainder of the letter(s) to be shows as blank dot(s). e.g.
Adrian: "Adria."
Michael: "Micha.."
Alexander: "Alexa...." etc.
I tried to "fix" it with the "b" variable but that just prints three dots "..." regardless of how long the name is.
This is what I've got so far:
def namecheck():
name = raw_input("Name?")
if len(name) <=5:
print name
else:
if len(name) >5:
name = name[0:5]
b = ("...")
print name + b
namecheck()
I'm a total newbie so I apologise for any wrong spacing here, thank you for your support and patience.
As an alternative to sequence multiplication (one which is somewhat more self-documenting, and hopefully less confusing to maintainers), just use str.ljust to do your padding:
def namecheck():
name = raw_input("Name?")
# Reduce to first five (or less) characters, then pad with .s to original length
# with str.ljust
print name[:5].ljust(len(name), '.')
print name[:5] + '.' * (len(name) - 5) works fine, it's just a bit arcane (and also involves more temporary values, though in practice, the lack of actual method calls makes it faster on CPython).
you can try to use the function replace().
name = 'abcdefg'
name.replace(name[5:], '.' * len(name[5:]))
output: 'abcde..'
name='randy12345'
name.replace(name[5:],'.' * len(name[5:]))
output: 'randy.....'
name[5:] means get all the element starting 6 (5+1 because it start with 0)
'.' * len(name[5:] then this code count it and multiply it by dot
name.replace(name[5:],'.' * len(name[5:])) then use replace function to replace the excess element with dots
The most concise way I can think of:
def namecheck():
name = raw_input("Name?")
print(name[0:5] + '.' * (len(name) - 5))
namecheck()
Try something like this:
def namecheck():
name = raw_input("Name?")
if len(name) <= 5:
print name
else:
print name[0:5] + '.' * (len(name)-5)
namecheck()

python code to generate password list [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am researching wireless security and trying to write a python script to generate passwords, not random, but a dictionary of hex numbers. The letters need to be capital, and it has to go from 12 characters to 20 characters. I went from 11 f's to 20 f's, this seems like it would meet the requirements. I then tried to place them in a text file. After I made the file, I chmod'ed it to 777 and then clicked run. It has been a few minutes, but I cannot tell if it is working or not. I am running it in kali right now, on a 64 bit core i3 with 8gb of ram. I'm not sure how long it would be expected to take, but this is my code, let me know if it looks right please:
# generate 10 to 32 character password list using hex numbers, 0-9 A-F
def gen_pwd(x):
x = range(17592186044415 -295147905179352830000)
def toHex(dec):
x = (dec % 16)
digits = "0123456789ABCDEF"
rest = dec / 16
if (rest == 0):
return digits[x]
return toHex(rest) + digits[x]
for x in range(x):
print toHex(x)
f = open(/root/Home/sdnlnk_pwd.txt)
print f
value = x
string = str(value)
f.write(string)
gen_pwd
how bout just
password = hex(random.randint(1000000,100000000))[2:]
or
pw_len = 12
my_alphabet = "1234567890ABCDEF"
password = "".join(random.choice(my_alphabet) for _ in range(pw_len))
or what maybe closer to what you are trying to do
struct.pack("Q",12365468987654).encode("hex").upper()
basically you are overcomplicating a very simple task
to do exactly what you are asking you can simplify it
import itertools, struct
def int_to_chars(d):
'''
step 1: break into bytes
'''
while d > 0: # while we have not consumed
yield struct.pack("B",d&0xFF) # decode char
d>>=8 # shift right one byte
yield "" # a terminator just in case its empty
def to_password(d):
# this will convert an arbitrarily large number to a password
return "".join(int_to_chars(d)).encode("hex").upper()
# you could probably just get away with `return hex(d)[2:]`
def all_the_passwords(minimum,maximum):
#: since our numbers are so big we need to resort to some trickery
all_pw = itertools.takewhile(lambda x:x<maximum,
itertools.count(minimum))
for pw in all_pw:
yield to_password(pw)
all_passwords = all_the_passwords( 0xfffffffffff ,0xffffffffffffffffffff)
#this next bit is gonna take a while ... go get some coffee or something
for pw in all_passwords:
print pw
#you will be waiting for it to finish for a very long time ... but it will get there
You can use time.time() to get the execution time. and if you are using python 2 use xrange() instead range because xrange return an iterator :
import time
def gen_pwd(x):
def toHex(dec):
x = (dec % 16)
digits = "0123456789ABCDEF"
rest = dec / 16
if (rest == 0):
return digits[x]
return toHex(rest) + digits[x]
for x in range(x):
print toHex(x)
f = open("/root/Home/sdnlnk_pwd.txt")
print f
value = x
string = str(value)
f.write(string)
start= time.time()
gen_pwd()
last=time.time()-start
print last
Note : you need () to call your function and "" in your open() function. also i think your first range is an extra command , as its wrong , you need to remove it.
Disclaimer
I'd like to comment on the OP question but I need to show some code and also the output that said code produces, so that I eventually decided to present my comment in the format of an answer.
OTOH, I hope that this comment persuades the OP that her/his undertaking, while conceptually simple (see my previous answer, 6 lines of Python code), is not feasible with available resources (I mean, available on Planet Earth).
Code
import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
pg = lambda n: locale.format("%d", n, grouping=True)
def count_bytes(low, hi):
count = low+1
for i in range(low+1,hi+1):
nn = 15*16**(i-1)
nc = i+1
count = count + nn*nc
return count
n_b = count_bytes(10,20)
n_d = n_b/4/10**12
dollars = 139.99*n_d
print "Total number of bytes to write on disk:", pg(n_b)
print """
Considering the use of
WD Green WD40EZRX 4TB IntelliPower 64MB Cache SATA 6.0Gb/s 3.5\" Internal Hard Drives,
that you can shop at $139.99 each
(see <http://www.newegg.com/Product/Product.aspx?Item=N82E16822236604>,
retrieved on December 29th, 2014)."""
print "\nNumber of 4TB hard disk drives necessary:", pg(n_d)
print "\nCost of said hard disks: $" + pg(dollars)
Output
Total number of bytes to write on disk: 25,306,847,157,254,216,063,385,611
Considering the use of
WD Green WD40EZRX 4TB IntelliPower 64MB Cache SATA 6.0Gb/s 3.5" Internal Hard Drives,
that you can shop at $139.99 each
(see <http://www.newegg.com/Product/Product.aspx?Item=N82E16822236604>,
retrieved on December 29th, 2014).
Number of 4TB hard disk drives necessary: 6,326,711,789,313
Cost of said hard disks: $885,676,383,385,926
My comment on what the OP wants to do
Quite a bit of disk storage (and money) is needed to accomplish your undertaking.
Perspective
Projected US Federal debt at the end of fiscal year 2014 is $18.23 trillion, my estimated cost, not considering racks, power supplies and energy bills, is $886 trillion.
Recommended reading
Combinatorial_Explosion#SussexUniversity,
There is hope
If you are still convinced to pursue your research project on wireless security in the direction you've described, it is possible that you can get a substantial volume discount on the drives'purchase.
characters=["a","b","c"]
for x,y in zip(range(5),characters):
print (hex(x)+y)
Output:
>>>
0x0a
0x1b
0x2c
>>>
You see, its actually doing that with a short way. It is not possible if you use a range like that, keep it small and try to add another things to your result.
Also for file process, here is a better way:
with open("filepath/name","a+") as f:
f.write("whateveryouwanttowrite")
I was working with password generators, well better if you define a dict with complicated characters and compile them like:
passw={"h":"_*2ac","e":"=.kq","y":"%.hq1"}
x=input("Wanna make some passwords? Enter a sentence or word: ")
for i in x:
print (passw[i],end="")
with open("passwords.txt","a+") as f:
f.write(passw[i])
Output:
>>>
Wanna make some passwords? Enter a sentence or word: hey
_*2ac=.kq%.hq1
>>>
So, just define a dict with keys=alphabet and values=complicated characters, and you can make very strong passwords with simple words-sentences.I just wrote it for an example, of course you can add them to dict later, you dont have to write. But basic way is for that is better I think.
Preamble
I don't want to comment on what you want to do.
Code MkI
Your code can be trimmed (quite a bit) to the following
with open("myfile", "w") as f:
for x in xrange(0xff,0xff*2+1): f.write("%X\n"%x)
Comments on my code
Please note that
You can write hex numbers in source code as, ehm, hex numbers and you can mix hex and decimal notation as well
The to_hex function is redundant as python has (surprise!) a number of different ways to format your output as you please (here I've used so called string interpolation).
Of course you have to change the filename in the open statement and
adjust the extremes of the interval generated by xrange (it seems
you're using python 2.x) to your content.
Code MkII
Joran Beasley remarked that (at least in Python 2.7) xrange internally uses a C long and as such it cannot step up to the task of representing
0XFFFFFFFFFFFFFFFFFFFF. This alternative code may be a possibility:
f = open("myfile", "w")
cursor = 0XFFFFFFFFFF
end = 0XFFFFFFFFFFFFFFFFFFFF
while cursor <= end:
f.write("%X\n"%cursor)
cursor += 1
all of this is well and good, however, none of it accomplishes my purpose. if python cannot handle such large numbers, i will have to use something else. as i stated, i do not want to generate random anything, i need a list of sequential hex characters which are anywhere from 12 characters to 20 characters long. it is to make a dictionary of passwords which are nothing more than a hex number that should be about 16 characters long.
does anyone have any suggestions on what i can use for this purpose? i think some type of c language should do the trick, but i know less about c or c++ than python. sounds like this will take a while, but that's ok, it is just a research project.
i have come up with another possibility, counting in hex starting from 11 f's and going until i reach 20 f's. this would produce about 4.3 billion numbes, which should fit in a 79 million page word document. sounds like it is a little large, but if i go from 14 f's to 18 f's, that should be manageable. here is the code i am proposing now:
x = 0xffffffffffffff
def gen_pwd(x):
while x <= 0xffffffffffffffffff:
return x
string = str(x)
f = open("root/Home/sdnlnk_pwd.txt")
print f.upper(string, 'a')
f.write(string)
x = x + 0x1
gen_pwd()

What's wrong with my python multiprocessing code?

I am an almost new programmer learning python for a few months. For the last 2 weeks, I had been coding to make a script to search permutations of numbers that make magic squares.
Finally I succeeded in searching the whole 880 4x4 magic square numbers sets within 30 seconds. After that I made some different Perimeter Magic Square program. It finds out more than 10,000,000 permutations so that I want to store them part by part to files. The problem is that my program doesn't use all my processes that while it is working to store some partial data to a file, it stops searching new number sets. I hope I could make one process of my CPU keep searching on and the others store the searched data to files.
The following is of the similar structure to my magic square program.
while True:
print('How many digits do you want? (more than 20): ', end='')
ansr = input()
if ansr.isdigit() and int(ansr) > 20:
ansr = int(ansr)
break
else:
continue
fileNum = 0
itemCount = 0
def fileMaker():
global fileNum, itemCount
tempStr = ''
for i in permutationList:
itemCount += 1
tempStr += str(sum(i[:3])) + ' : ' + str(i) + ' : ' + str(itemCount) + '\n'
fileNum += 1
file = open('{0} Permutations {1:03}.txt'.format(ansr, fileNum), 'w')
file.write(tempStr)
file.close()
numList = [i for i in range(1, ansr+1)]
permutationList = []
itemCount = 0
def makePermutList(numList, ansr):
global permutationList
for i in numList:
numList1 = numList[:]
numList1.remove(i)
for ii in numList1:
numList2 = numList1[:]
numList2.remove(ii)
for iii in numList2:
numList3 = numList2[:]
numList3.remove(iii)
for iiii in numList3:
numList4 = numList3[:]
numList4.remove(iiii)
for v in numList4:
permutationList.append([i, ii, iii, iiii, v])
if len(permutationList) == 200000:
print(permutationList[-1])
fileMaker()
permutationList = []
fileMaker()
makePermutList(numList, ansr)
I added from multiprocessing import Pool at the top. And I replaced two 'fileMaker()' parts at the end with the following.
if __name__ == '__main__':
workers = Pool(processes=2)
workers.map(fileMaker, ())
The result? Oh no. It just works awkwardly. For now, multiprocessing looks too difficult for me.
Anybody, please, teach me something. How should my code be modified?
Well, addressing some things that are bugging me before getting to your asked question.
numList = [i for i in range(1, ansr+1)]
I know list comprehensions are cool, but please just do list(range(1, ansr+1)) if you need the iterable to be a list (which you probably don't need, but I digress).
def makePermutList(numList, ansr):
...
This is quite the hack. Is there a reason you can't use itertools.permutations(numList,n)? It's certainly going to be faster, and friendlier on memory.
Lastly, answering your question: if you are looking to improve i/o performance, the last thing you should do is make it multithreaded. I don't mean you shouldn't do it, I mean that it should literally be the last thing you do. Refactor/improve other things first.
You need to take all of that top-level code that uses globals, apply the backspace key to it, and rewrite functions that pass data around properly. Then you can think about using threads. I would personally use from threading import Thread and manually spawn Threads to do each unit of I/O rather than using multiprocessing.

Python - Converting a Number to a Letter without an if statement

I am making a program for my own purposes (a naming program) that completely generates a random name. The problem is I cannot assign a number to a letter, so as a being 1 and z being 26, or a being 0 and z being 25. It gives me a SyntaxError. I need to assign this because the random integer (1,26) triggers a letter (if the random integer is 1, select A) and prints the name.
EDIT:
I have implemented your advice, and it works, I am grateful for this, but I wish to have my program create readable names, or more procedural. Here is an example of a name after I tweaked my program: ddjau. Now that doesn't look like a name, so I want it my program to work as if it were creating REAL names, like Samuel or other common names. Thanks!
EDIT (2):
Thanks, Adam, but I need a sort of 'seed' for the user to enter for the start of the name is. (Seed = A, Name = Adam. Seed = G, Name = George.) Should I do this by searching the file line by line, at the very beginning? If so, how do I do this?
Short Answer
Look into Python dictionaries to allow the 1 = 'a' type assignments. Below I have working example that would generate a random name based on gender and a 'litter'.
Disclaimer
I do not fully understand (via the code) what you're trying to accomplish with char/ord and a random letter. Also note having absolutely no idea of your design goals or requirements, I have made the example more complex than it may need to be for instructional purposes.
Additional Resources
* Python Docs for dictionary
* Using Python dictionary relationship to search both ways
In response to the last edit
If you are looking to build random 'real' names, I think your best bet will be to use a large list of names and just pick a random one. If I were you I'd look into something linking to the census results: males and females. Note that male_names.txt and female_names.txt are a copy of the list found at the census website. As a disclaimer, I'm sure there is a more efficient way to load / read the file. Just use this example as a proof on concept.
Update
Here's a quick and dirty way to seed the random values. Again I am not sure that this is the most pythonic way or most efficient way, but it works.
Example
import random
import time
def get_random_name(gender, seed):
if(gender == 'male'):
file = 'male_names.txt'
elif(gender == 'female'):
file = 'female_names.txt'
fid = open(file,'r')
names = []
total_names = 0
for line in fid:
if(line.lower().startswith(seed)):
names.append(line)
total_names = total_names + 1
random_index = random.randint(0,total_names)
return names[random_index]
if (__name__ == "__main__"):
print 'Welcome to Name Database 2.2\n'
print '1. Boy'
print '2. Girl'
bog = raw_input('\nGender: ')
print 'What should the name start with?'
print 'A, Ab, Abc, B, Ba, Br, etc...'
print ''
l = raw_input('Leter(s): ').lower()
new_name = ''
if bog == '1': # Boy
print get_random_name('male',l)
elif bog == '2':
print get_random_name('female',l)
Output
Welcome to Name Database 2.2
1. Boy
2. Girl
Gender: 2
What should the name start with?
A, Ab, Abc, B, Ba, Br, etc...
Leter(s): br
BRITTA
chr (see here) and ord (see here) are the two functions you're looking for (though you already seem to know about the latter). Follow those links for a more detailed explanation.
The first gives you a one-character string based on the integer, the second does the reverse operaion (technically, it handles Unicode as well, which chr doesn't, though you have unichr for that if you need it).
You can base your code on the following:
ch = "E"
print ord (ch) - ord ("A") + 1 # should give 5 for the fifth letter
val = 7
print chr (val + ord ("A") - 1) # should give G, the seventh letter
I'm not entirely sure what you're trying to do, but you can convert a number into a letter with the chr() function. chr() takes an ASCII code, so if you want to use the range [0, 25] instead you can adapt it like so:
chr(25 + ord('a')) # 'z'

Categories