Random number having 11 to 20 digits - python

How to generate random numbers in python having(11 to 20 digits) that should not start with 0 in beginning?
e.g:23418915901
def key_more_than_10():
v=random.randint(11,20)
char_set = string.digits+string.digits+string.digits
s= ''.join(random.sample(char_set,v))
return s
I used this code but since string.digits(give numbers between 0 to 9) it doesnt help me?
There should be an equal possibility to have 11 digits number and a 20 digits number.

Simple:
>>> help(random.randint)
Help on method randint in module random:
randint(self, a, b) method of random.Random instance
Return random integer in range [a, b], including both end points.
>>> random.randint(10000000000,99999999999999999999)
35677750742418249489
Of course, if you actually want a string (not sure why you would), you could wrap a str() around the whole thing:
>>> str(random.randint(1000000000,99999999999999999999))
'91138793919270489115'

How about a literal translation of what you want into code:
import random
DIGITS = '0123456789'
ndigits = random.randint(11, 20)
digits = [random.choice(DIGITS[1:])] + [random.choice(DIGITS) for i in xrange(ndigits-1)]
print int(''.join(digits))
The number of digits in the almost random result should be uniformly distributed between 11..20. Not quite random because restricting the first digit to a something other than a zero precludes it.

I would choose randrange for this
Help on method randrange in module random:
randrange(self, start, stop=None, step=1, int=<type 'int'>, default=None, maxwidth=9007199254740992L) method of random.Random instance
Choose a random item from range(start, stop[, step]).
This fixes the problem with randint() which includes the
endpoint; in Python this is usually not what you want.
Do not supply the 'int', 'default', and 'maxwidth' arguments.
so
random.randrange(1e11, 1e20)
will do what you want. For a string use this
str(random.randrange(1e11, 1e20))

Related

Why is 'int" not iterable in Python, but 'str' are?

I'm getting some practice with list comprehensions and I ran into the following error:
Find all of the numbers from 1-1000 that have a 3 in them
result = [i for i in range(1, 1001) if 3 in i]
print(result)
result = [i for i in range(1, 1000) if 3 in i]
TypeError: argument of type 'int' is not iterable
but it works perfectly if I write this code:
result = [i for i in range(1, 1001) if "3" in str(i)]
print(result)
...So clearly strings are iterable. But ints are not. Why?
Because it’s not clear what iterating over an int would do. You seem to expect that it iterates over the decimal digits (?) but I for example find that unreasonable: I’d find it much more natural to iterate over its bits (i.e. its binary digits). Inside memory, ints are represented as binary numbers, not decimal numbers, so I could argue that mine is the more natural expectation.
But since there’s no obviously right answer, Python’s designers decided not to make int iterable at all.
By contrast, for strings there’s an immediately intuitive “right” answer (although the devil is in the details): we iterate over its characters. Unfortunately that actually opens a can of worms since whole books have been written about the definition of “character”, and in practice something subtly different happens (if you’re curious, start reading The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)). But the answer “we iterate over characters” is close enough.
From a conceptual perspective, the answer by #KonradRudolph is the right one.
But from a technical perspective, what makes an object able to be iterated over? This property is called being iterable. And in Python, an object is iterable as long as it implements the magic method __iter__. Magic methods are special methods Python looks for in a class if it wants to use certain built-in behavior. Like iterating over an object, or adding two objects with +.
And so, we could easily implement our own number class that is iterable:
class IterableInt:
def __init__(self, i):
self.i = i
def __iter__(self):
return map(int, str(self.i))
Here I chose iterable to mean what you expected, i.e. iterating over the decimal digits. Iterating over the binary digits instead would only mean changing one line.
Note that this is not really a number (yet), you cannot add or multiply it. For that one would probably want to inherit from int, but that complicates things a bit more and is left as an exercise.
In any case, now we have an iterable integer:
n = IterableInt(123)
print(3 in n)
# True
print(list(n))
# [1, 2, 3]
If you need to find out if an object is iterable, there are two ways. One is called "Look before you leap" (LBYL), you can test for the existence of the __iter__ method or use the typing module:
hasattr(n, "__iter__")
# True
hasattr(123, "__iter__")
# False
from typing import Iterable
isinstance(n, Iterable)
# True
isinstance(123, Iterable)
# False
And the other is "it’s easier to ask for forgiveness than permission" (EAFP), where you just assume the object is iterable and deal with it if it is not:
try:
3 in 123
except TypeError:
print("too bad, should have used IterableInt")
Because a string is an array of characters. An int is not a sequence of anything (it can be represented as a sequence of digits, but that is not what it is).
if you want to check the int, you have to match with every digit in the int by every tenth place.
from math import floor
def check_if_number_exists(number, digit_to_find):
# check if the number is positive
if number < 0:
Number = -number
else:
Number = number
while(Number != 0):
# run loop for extracting each digit
Digit = Number % 10 # gives the last number
Number = floor(Number / 10) # removing the last digit
if Digit == digit_to_find:
print("the number contains " + str(digit_to_find) + ' in ' + str(number))
break
check_if_number_exists(45638, 3)
you check any number you want with above code.
you cannot do the same way you did for str because int is different from string. A small example
s + e + v + e + n = seven (string is array which comprise of letters)
43567 = 40000 + 3000 + 500 + 60 + 7 (not 4+3+5+6+7)
hope you understand, why iteration dont work on int

Pass several arguments to function from map()

For example, if I want to detect all odd numbers in an array and set them to zero, I can use:
def setToZeroIfOdd(n):
if n % 2 == 0:
pass
else:
return 0
numbers = range(1,1000)
numbers = map(setToZeroIfOdd, numbers)
which works like a charm.
But when I try something like
def setToZeroIfDivisibleBy(n, divisor):
if n % divisor == 0:
return 0
else:
pass
numbers = map(setToZeroIfDivisibleBy(divisor=3), numbers)
it expects two arguments. Likewise,
numbers = map(setToZeroIfDivisibleBy, numbers, divisor=3)
does not work. How can I pass that divisor argument from within map()?
You can use functools.partial to make partial functions
from functools import partial
def setToZeroIfDivisibleBy(n, divisor):
if n % divisor == 0:
return 0
else:
pass
numbers = range(1,1000)
numbers = map(partial(setToZeroIfDivisibleBy, divisor=3), numbers)
Try using lambda function
numbers = map(lambda n: setToZeroIfDivisibleBy(n, divisor=3), numbers)
And rather than pass did you mean return n?
You make a function which returns a function:
def setToZeroIfDivisibleBy(divisor):
def callback(n):
if n % divisor == 0:
return 0
else:
pass
return callback
numbers = map(setToZeroIfDivisibleBy(3), numbers)
BTW, you can entirely omit empty branches like else: pass; it doesn't do anything. Since it results in a None, I don't think that's what you want either. You probably want return n there instead.
Another approach, instead of using partial, is to supply an infinite (or at least, long enough) sequence of 2nd arguments for the two-argument function:
from itertools import repeat
numbers = map(setToZeroIfDivisibleBy, numbers, repeat(3))
In Python 2, map will append None as necessary to the shorter of the two sequences to make them the same length. Assuming that will cause problems (either because your function cannot handle None as an input value or you end up with an infinite loop), you can either use itertools.imap, which stops after exhausting the shorter sequence:
from itertools import imap, repeat
numbers = list(imap(setToZeroIfDivisibleBy, numbers, repeat(3)))
or pass the length of numbers as a second argument to repeat so that the two sequences are the same length.
from itertools import repeat
numbers = map(setToZeroIfDivisibleBy, numbers, repeat(3, len(numbers)))

How do I convert a set to an interger in python? [duplicate]

This question already has answers here:
Convert list of ints to one number?
(19 answers)
Closed 5 years ago.
I want to generate a random 4 digit number in which none of the digits are repeated.
import random
sets = random.sample(range(0,9), 4)
This generates a random set of 4 digits but I want this as an integer. how do I do that?
(Assuming OP meant all the digits)
Instead of using numbers and have to manipulate to str and back to int, just start with ascii digits:
>>> import string
>>> ''.join(random.sample(string.digits, 4))
'4561'
You can convert to int() if necessary.
It's unclear what the OP intends to do if the first digit is 0.
For a purely numerical approach you can use functools.reduce:
>>> import functools as ft
>>> ft.reduce(lambda s, d: 10*s + d, random.sample(range(10), 4))
2945
You can do this by converting each digit to a string, joining them, and casting them as an integer.
int("".join(map(str,random.sample(range(0,9),4))))
if you need to generate 4 digit number, just for knowledge purpose use.
As suggested by AChampion this solution can contain duplicates
from random import randint
randint(1000, 9999)
Use bernie Solution to generate a random 4 digit number in which none of the digits are repeated.
int("".join(map(str,random.sample(range(0,9),4))))
In case if you want potentially infinite sequence of numbers with 4 unique digits (or any other condition – write your own)
import random
def numbers_gen(left_end, right_end):
while True:
yield random.randint(left_end, right_end)
def are_digits_unique(number):
number_string = str(number)
return list(set(number_string)) == list(number_string)
four_digits_numbers_gen = number_gen(left_end=1000,
right_end=9999)
four_digits_numbers_with_unique_digits_gen = filter(are_digits_unique,
four_digits_numbers_gen)
Works only in Python 3 because filter returns iterator-object (in Python 2.7 it returns list, more at docs)
You can multiply with powers of 10:
sum(10**a*b for a, b in enumerate(reversed(sets)))
This works as long as the first element of sets is not zero.
You could try:
import random
my_set = set()
while len(my_set) < 4:
x = random.choice(range(0,9))
my_set.add(x)
my_num = int("".join(map(str, my_set)))
One line:
int("".join(random.sample("0123456789",4)))

Str in Python's map and sum

Why do you need to use the function 'str' in the following code?
I am trying to count the sum of digits in a number.
My code
for i in number:
sum(map(int, str(i))
where number is the following array
[7,79,9]
I read my code as follows
loop though the array such that
count sum of the integer digits
by getting given digits in a number by map increasingly
such that each object (given number) is converted to String // This does not make sense
Manual says this for str
Type: type
Base Class: <type 'type'>
String Form: <type 'str'>
Namespace: Python builtin
Docstring:
str(object) -> string
Return a nice string representation of the object.
If the argument is a string, the return value is the same object.
Given 79 you need to get [7, 9] in order to sum up this list.
What does it mean to split a number into digits? It means to represent the number in a numerical system with some base (base 10 in this case). E. g. 79 is 7 * 10**1 + 9 * 10**0.
And what is the simplest (well, at least in this context) way to get such a representation of a number? To convert it to a string of decimals!
Your code does exactly that:
>>> str(79)
'79'
# Another way to say this is [int(c) for c in str(79)]
>>> map(int, str(79))
[7, 9]
>>> sum(map(int, str(79)))
16
What happens when you try that code without using str()?
The str() is used to convert the integer into a sequence of characters, so that map() can iterate over the sequence. The key point here is that a "string" can be treated as a "sequence of characters".
Why do you need to use the function 'str' in the following code?
Because map takes an iterable, like a list or a tuple or a string.
The code in question adds upp all the numbers in an integer. And it does it by a little clever hack. It converts the number into a sequence of numbers by doing
map(int, str(i))
This will convert the integer 2009 to the list [2, 0, 0, 9]. The sum() then adds all this integers up, and you get 11.
A less hacky version would be:
>>> number = [7,79,9]
>>> for i in number:
... result = 0
... while i:
... i, n = divmod(i, 10)
... result +=n
... print result
...
7
16
9
But your version is admittedly more clever.

In Python, how do I create a string of n characters in one line of code?

I need to generate a string with n characters in Python. Is there a one line answer to achieve this with the existing Python library? For instance, I need a string of 10 letters:
string_val = 'abcdefghij'
To simply repeat the same letter 10 times:
string_val = "x" * 10 # gives you "xxxxxxxxxx"
And if you want something more complex, like n random lowercase letters, it's still only one line of code (not counting the import statements and defining n):
from random import choice
from string import ascii_lowercase
n = 10
string_val = "".join(choice(ascii_lowercase) for i in range(n))
The first ten lowercase letters are string.lowercase[:10] (if you have imported the standard library module string previously, of course;-).
Other ways to "make a string of 10 characters": 'x'*10 (all the ten characters will be lowercase xs;-), ''.join(chr(ord('a')+i) for i in xrange(10)) (the first ten lowercase letters again), etc, etc;-).
if you just want any letters:
'a'*10 # gives 'aaaaaaaaaa'
if you want consecutive letters (up to 26):
''.join(['%c' % x for x in range(97, 97+10)]) # gives 'abcdefghij'
Why "one line"? You can fit anything onto one line.
Assuming you want them to start with 'a', and increment by one character each time (with wrapping > 26), here's a line:
>>> mkstring = lambda(x): "".join(map(chr, (ord('a')+(y%26) for y in range(x))))
>>> mkstring(10)
'abcdefghij'
>>> mkstring(30)
'abcdefghijklmnopqrstuvwxyzabcd'
This might be a little off the question, but for those interested in the randomness of the generated string, my answer would be:
import os
import string
def _pwd_gen(size=16):
chars = string.letters
chars_len = len(chars)
return str().join(chars[int(ord(c) / 256. * chars_len)] for c in os.urandom(size))
See these answers and random.py's source for more insight.
If you can use repeated letters, you can use the * operator:
>>> 'a'*5
'aaaaa'

Categories

Resources