How do i generate random numbers but have the numbers avoid numbers already used.
I have a TXT file with thousands of sets of numbers and i need to generate a series of random numbers while avoiding these.
IE, TXT - 0102030405
my random number needs to avoid this number.
on a side note, how can i split up the TXT 10 digit number into 5, two digit numbers?
then how can i generate random numbers based off of that.
You could load up all previously found random numbers into a dictionary, then just check whether new_random in dictionary, and if it is try a new random number.
For the second party, say your ten digit number is stored in variable ten_digits.
ten_digits = '1234567890'
you can break this up into 5 two digit numbers by doing
[x + y for x, y in zip(ten_digits[::2], ten_digits[1::2]
>>> ['12', '34', '56', '78', '90']
If you need to maintain the file (which I think you do, in order to add new numbers), I would suggest you to "forget" using a plain text file and use SQLite or any other embedded DB that is backed up in a file, as you probably don't want to load all the numbers in memory.
The "feature" (or better said, data structure) you want from SQLite is a B-Tree, so you can retrieve the numbers fast. I'm saying this, because you could also try to find a library that implements B-Trees, and then you wouldn't need SQLite.
Are you using the numbers as IDs? You should probably look into using a hash table.
http://en.wikipedia.org/wiki/Hash_table
I'm not terribly familiar with Python but I'm sure there is a substring function you can give it (as arguments) an index to start the substring and the number of characters to copy.
If you your list is relatively small you could load it into a set and check against that:
random_number not in number_set
To split the number you could use slices:
s='0102030405'
n=2
result = [s[i:i+n] for i in range(0, len(s), n)]
Related
I am trying to see how I can create a set of unique IDs of a fixed length (say length 12) in python which uses a specific subset of all alphanumeric characters. The usecase here is that these IDs need to be read by people and referred to in printed documents, and so I am trying to avoid using characters L, I, O and numbers 0, 1. I of course need to be able to generate a new ID as needed.
I looked into the UUID function in other answers but wasn't able to find a way to use that function to meet my requirements. I've done a lot of searching, but apologies if this is duplicate.
Edit: So far I tried using UUID as described here. And also the hashids function. But could not figure out a way to do it using them. The next best solution I could come up with is create a list of random strings, and check against all existing ids. But that seems woefully inefficient.
For a set of characters to sample you could use string.ascii_uppercase (A-Z) plus string.digits (0-9), but then remove unwanted characters 'LIO01'. From there you can use random.choices to generate a sequence of length k while allowing repeated characters.
import string
import random
def unique_id(size):
chars = list(set(string.ascii_uppercase + string.digits).difference('LIO01'))
return ''.join(random.choices(chars, k=size))
>>> unique_id(12)
'HBFXXHWZ8349'
>>> unique_id(12)
'A7W5WK636BYN'
>>> unique_id(12)
'WJ2JBX924NVK'
You could use an iterator like itertools.combinations
import itertools
import string
valid_chars = set(string.ascii_lowercase + string.digits) - set('lio01')
# Probably would want to persist the used values by using some sort of database/file
# instead of this
used = set()
unique_id_generator = itertools.combinations(valid_chars, 12)
generated = "".join(next(unique_id_generator))
while generated in used:
generated = "".join(next(unique_id_generator))
# Once an unused value has been found, add it to used list (or some sort of database where you can keep track)
used.add(generated)
This generator will continue to produce all possible combinations (without replacement) of all ascii lower case characters and digits excluding the ones you mentioned. If you need this upper case, you can use .upper() and if you want to allow replacement, you can use itertools.combinations_with_replacement.
If 'xyz' is not considered to be the same as 'xzy', take a look at itertools.permutations.
I bumped to a similar problem and the simplest solution I could think of is this one:
Answer
from secrets import token_urlsafe
id = ''.join([c for c in token_urlsafe(10) if c not in '-_OI0l'])[:5]
print(id) # 'a3HkR'
Explanation
token_urlsafe(10) String with 10 random chars from [a-z, A-Z, 0-9, -, _]
if c not in '-_OI0l' remove characters you don't want
[:5] Take just 5 from the beginning, if you want 5 for example.
Strengths
Readable
One-liner
Customizable
Can be highly secure if needed
Limitations
You can check the uniqueness in other ways, or just pick as long an id as needed so that randomness takes care of that for you.
The above example can create 459 165 024 different ids.
If you remove many characters or you want more characters you have to make the number in token_urlsafe(number) also bigger to not run into an IndexError.
I tried to use input (Py3) /raw_input() (Py2) to get a list of numbers, however with the code
numbers = input()
print(len(numbers))
the input [1,2,3] and 1 2 3 gives a result of 7 and 5 respectively – it seems to interpret the input as if it were a string. Is there any direct way to make a list out of it? Maybe I could use re.findall to extract the integers, but if possible, I would prefer to use a more Pythonic solution.
In Python 3.x, use this.
a = [int(x) for x in input().split()]
Example
>>> a = [int(x) for x in input().split()]
3 4 5
>>> a
[3, 4, 5]
>>>
It is much easier to parse a list of numbers separated by spaces rather than trying to parse Python syntax:
Python 3:
s = input()
numbers = list(map(int, s.split()))
Python 2:
s = raw_input()
numbers = map(int, s.split())
Using Python-like syntax
The standard library provides ast.literal_eval, which can evaluate certain strings as though they were Python code. This does not create a security risk, but it can still result in crashes and a wide variety of exceptions.
For example: on my machine ast.literal_eval('['*1000 + ']'*1000) will raise MemoryError, even though the input is only two kilobytes of text.
As explained in the documentation:
The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, None and Ellipsis.
(The documentation is slightly inaccurate. ast.literal_eval also supports addition and subtraction of numbers - but not any other operators - so that it can support complex numbers.)
This is sufficient for reading and parsing a list of integers formatted like Python code (e.g. if the input is [1, 2, 3]. For example:
>>> import ast
>>> ast.literal_eval(input("Give me a list: "))
Give me a list: [1,2,3]
[1, 2, 3]
Do not ever use eval for input that could possibly ever come, in whole or in part, from outside the program. It is a critical security risk that enables the creator of that input to run arbitrary code.
It cannot be properly sandboxed without significant expertise and massive restrictions - at which point it is obviously much easier to just use ast.literal_eval. This is increasingly important in our Web-connected world.
In Python 2.x, raw_input is equivalent to Python 3.x input; 2.x input() is equivalent to eval(raw_input()). Python 2.x thus exposed a critical security risk in its built-in, designed-to-be-beginner-friedly functionality, and did so for many years. It also has not been officially supported since Jan 1, 2020. It is approximately as outdated as Windows 7.
Do not use Python 2.x unless you absolutely have to; if you do, do not use the built-in input.
Using your own syntax
Of course, it is clearly possible to parse the input according to custom rules. For example, if we want to read a list of integers, one simple format is to expect the integer values separated by whitespace.
To interpret that, we need to:
Split the string at the whitespace, which will give us a list
Convert strings into integers, and apply that logic to each string in the list.
All of those tasks are covered by the common linked duplicates; the resulting code is shown in the top answer here.
Using other syntaxes
Rather than inventing a format for the input, we could expect input in some other existing, standard format - such as JSON, CSV etc. The standard library includes tools to parse those two. However, it's generally not very user-friendly to expect people to type such input by hand at a prompt. Normally this kind of input will be read from a file instead.
Verifying input
ast.literal_eval will also read and parse many things that aren't a list of integers; so subsequent code that expects a list of integers will still need to verify the input.
Aside from that, if the input isn't formatted as expected, generally some kind of exception will be thrown. Generally you will want to check for this, in order to repeat the prompt. Please see Asking the user for input until they give a valid response.
You can use .split()
numbers = raw_input().split(",")
print len(numbers)
This will still give you strings, but it will be a list of strings.
If you need to map them to a type, use list comprehension:
numbers = [int(n, 10) for n in raw_input().split(",")]
print len(numbers)
If you want to be able to enter in any Python type and have it mapped automatically and you trust your users IMPLICITLY then you can use eval
Another way could be to use the for-loop for this one.
Let's say you want user to input 10 numbers into a list named "memo"
memo=[]
for i in range (10):
x=int(input("enter no. \n"))
memo.insert(i,x)
i+=1
print(memo)
you can pass a string representation of the list to json:
import json
str_list = raw_input("Enter in a list: ")
my_list = json.loads(str_list)
user enters in the list as you would in python: [2, 34, 5.6, 90]
Answer is trivial. try this.
x=input()
Suppose that [1,3,5,'aA','8as'] are given as the inputs
print len(x)
this gives an answer of 5
print x[3]
this gives 'aA'
a=[]
b=int(input())
for i in range(b):
c=int(input())
a.append(c)
The above code snippets is easy method to get values from the user.
Get a list of number as input from the user.
This can be done by using list in python.
L=list(map(int,input(),split()))
Here L indicates list, map is used to map input with the position, int specifies the datatype of the user input which is in integer datatype, and split() is used to split the number based on space.
.
I think if you do it without the split() as mentioned in the first answer. It will work for all the values without spaces. So you don't have to give spaces as in the first answer which is more convenient I guess.
a = [int(x) for x in input()]
a
Here is my ouput:
11111
[1, 1, 1, 1, 1]
try this one ,
n=int(raw_input("Enter length of the list"))
l1=[]
for i in range(n):
a=raw_input()
if(a.isdigit()):
l1.insert(i,float(a)) #statement1
else:
l1.insert(i,a) #statement2
If the element of the list is just a number the statement 1 will get executed and if it is a string then statement 2 will be executed. In the end you will have an list l1 as you needed.
Consider the string Building Centre. If asked to abbreviate this to fit a specific number of characters, you and I may choose very different but equally valid representations. For instance, three valid 7 character representations are:
BLD CNT
BLD CTR
BLDNGCT
These are generated by:
Using only existing letters in the string (can't abbreviate using z)
Using them in the order they appear (LBD is not valid since L does not come before B in Building).
Selecting up to as many characters (including spaces) as indicated.
I'm looking to write a breadth or depth of search based algorithm to generate all such short forms for a given string and desired length.
Before I go about writing the script, I am wondering if something similar has already been implemented. If not, how would you suggest I write something like this? Besides itertools, are there any useful libraries?
Yes, this can be beautifully done with itertools:
import itertools
text = 'Building Centre'
length = 7
shorts = [''.join(short) for short in itertools.combinations(text, length)]
print(shorts) # 6435 different versions!
Note that itertools.combinations does indeed preserve the order. You way want to check out the docs
Edit
If short forms with fewer than length characters should be allowed as well, you can use
shorts = list(itertools.chain(*((''.join(short) for short in itertools.combinations(text, l))
for l in range(1, length + 1))))
As stated in the comments, some short forms get generated twice. To fix this, use e.g. shorts = list(set(shorts)).
Yes, this is homework.
I have the basic idea. I know that basically I need to introduce a for loop and set if's saying if the value is above 9 then it's a, b, c, and so forth. But what I need is to get the for loop to grab the integer and its index number to calculate and go back and forth and then print out the hex. by the way its an 8 bit binary number and has to come out in two digit hex form.
thanks a lot!!
I'm assuming that you have a string containing the binary data.
In Python, you can iterate over all sorts of things, strings included. It becomes as simple as this:
for char in mystring:
pass
And replace pass with your suite (a term meaning a "block" of code). At this point, char will be a single-character string. Nice an straight forward.
For getting the character ordinal, investigate ord (find help for it yourself, it's not hard and it's good practice).
For converting the number to hex, you could use % string formatting with '%x', which will produce a value like '9f', or you could use the hex function, which will produce a value like '0x9f'; there are other ways, too.
If you can't figure any thing out, ask; but try to work it out first. It's your homework. :-)
So assuming that you've got the binary number in a string, you will want to have an index variable that gets incremented with each iteration of the for loop. I'm not going to give you the exact code, but consider this:
Python's for loop is designed to set the index variable (for index in list) to each value of a list of values.
You can use the range function to generate a list of numbers (say, from 0 to 7).
You can get the character at a given index in a string by using e.g. binary[index].
I tried to use input (Py3) /raw_input() (Py2) to get a list of numbers, however with the code
numbers = input()
print(len(numbers))
the input [1,2,3] and 1 2 3 gives a result of 7 and 5 respectively – it seems to interpret the input as if it were a string. Is there any direct way to make a list out of it? Maybe I could use re.findall to extract the integers, but if possible, I would prefer to use a more Pythonic solution.
In Python 3.x, use this.
a = [int(x) for x in input().split()]
Example
>>> a = [int(x) for x in input().split()]
3 4 5
>>> a
[3, 4, 5]
>>>
It is much easier to parse a list of numbers separated by spaces rather than trying to parse Python syntax:
Python 3:
s = input()
numbers = list(map(int, s.split()))
Python 2:
s = raw_input()
numbers = map(int, s.split())
Using Python-like syntax
The standard library provides ast.literal_eval, which can evaluate certain strings as though they were Python code. This does not create a security risk, but it can still result in crashes and a wide variety of exceptions.
For example: on my machine ast.literal_eval('['*1000 + ']'*1000) will raise MemoryError, even though the input is only two kilobytes of text.
As explained in the documentation:
The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, None and Ellipsis.
(The documentation is slightly inaccurate. ast.literal_eval also supports addition and subtraction of numbers - but not any other operators - so that it can support complex numbers.)
This is sufficient for reading and parsing a list of integers formatted like Python code (e.g. if the input is [1, 2, 3]. For example:
>>> import ast
>>> ast.literal_eval(input("Give me a list: "))
Give me a list: [1,2,3]
[1, 2, 3]
Do not ever use eval for input that could possibly ever come, in whole or in part, from outside the program. It is a critical security risk that enables the creator of that input to run arbitrary code.
It cannot be properly sandboxed without significant expertise and massive restrictions - at which point it is obviously much easier to just use ast.literal_eval. This is increasingly important in our Web-connected world.
In Python 2.x, raw_input is equivalent to Python 3.x input; 2.x input() is equivalent to eval(raw_input()). Python 2.x thus exposed a critical security risk in its built-in, designed-to-be-beginner-friedly functionality, and did so for many years. It also has not been officially supported since Jan 1, 2020. It is approximately as outdated as Windows 7.
Do not use Python 2.x unless you absolutely have to; if you do, do not use the built-in input.
Using your own syntax
Of course, it is clearly possible to parse the input according to custom rules. For example, if we want to read a list of integers, one simple format is to expect the integer values separated by whitespace.
To interpret that, we need to:
Split the string at the whitespace, which will give us a list
Convert strings into integers, and apply that logic to each string in the list.
All of those tasks are covered by the common linked duplicates; the resulting code is shown in the top answer here.
Using other syntaxes
Rather than inventing a format for the input, we could expect input in some other existing, standard format - such as JSON, CSV etc. The standard library includes tools to parse those two. However, it's generally not very user-friendly to expect people to type such input by hand at a prompt. Normally this kind of input will be read from a file instead.
Verifying input
ast.literal_eval will also read and parse many things that aren't a list of integers; so subsequent code that expects a list of integers will still need to verify the input.
Aside from that, if the input isn't formatted as expected, generally some kind of exception will be thrown. Generally you will want to check for this, in order to repeat the prompt. Please see Asking the user for input until they give a valid response.
You can use .split()
numbers = raw_input().split(",")
print len(numbers)
This will still give you strings, but it will be a list of strings.
If you need to map them to a type, use list comprehension:
numbers = [int(n, 10) for n in raw_input().split(",")]
print len(numbers)
If you want to be able to enter in any Python type and have it mapped automatically and you trust your users IMPLICITLY then you can use eval
Another way could be to use the for-loop for this one.
Let's say you want user to input 10 numbers into a list named "memo"
memo=[]
for i in range (10):
x=int(input("enter no. \n"))
memo.insert(i,x)
i+=1
print(memo)
you can pass a string representation of the list to json:
import json
str_list = raw_input("Enter in a list: ")
my_list = json.loads(str_list)
user enters in the list as you would in python: [2, 34, 5.6, 90]
Answer is trivial. try this.
x=input()
Suppose that [1,3,5,'aA','8as'] are given as the inputs
print len(x)
this gives an answer of 5
print x[3]
this gives 'aA'
a=[]
b=int(input())
for i in range(b):
c=int(input())
a.append(c)
The above code snippets is easy method to get values from the user.
Get a list of number as input from the user.
This can be done by using list in python.
L=list(map(int,input(),split()))
Here L indicates list, map is used to map input with the position, int specifies the datatype of the user input which is in integer datatype, and split() is used to split the number based on space.
.
I think if you do it without the split() as mentioned in the first answer. It will work for all the values without spaces. So you don't have to give spaces as in the first answer which is more convenient I guess.
a = [int(x) for x in input()]
a
Here is my ouput:
11111
[1, 1, 1, 1, 1]
try this one ,
n=int(raw_input("Enter length of the list"))
l1=[]
for i in range(n):
a=raw_input()
if(a.isdigit()):
l1.insert(i,float(a)) #statement1
else:
l1.insert(i,a) #statement2
If the element of the list is just a number the statement 1 will get executed and if it is a string then statement 2 will be executed. In the end you will have an list l1 as you needed.