tags:

views:

190

answers:

2

The task is to generate a given number of numeric pins of a given length. Here's the code I came up with for a particular case of numeric pins that don't start with 0:

def generate_pins(length, count):
    return random.sample(range(int('1' + '0' * (length - 1)), int('9' * length)), count)

How would you implement it?

EDIT: Pins shouldn't repeat.

EDIT2: Probably let's extend this example so that pin can contain any alphanumeric symbol.

+4  A: 

random.sample guarantees no repetition ("sampling without replacement", per the docs); is this condition part of your specs?

As expressed (without any word "distinct" to indicate lack of repetition), I'd do:

import random
import string

def generate_pins(length, count):
  return [''.join(random.choice(string.digits) for x in xrange(length))
          for x in xrange(count)]

With an additional condition that all the pins returned be unique:

def generate_pins(length, count, alphabet=string.digits):
  alphabet = ''.join(set(alphabet))
  if count > len(alphabet)**length:
    raise ValueError("Can't generate more than %s > %s pins of length %d out of %r" %
                      count, len(alphabet)**length, length, alphabet)
  def onepin(length):
    return ''.join(random.choice(alphabet) for x in xrange(length))
  result = set(onepin(length) for x in xrange(count))
  while len(result) < count:
    result.add(onepin(length))
  return list(result)

assuming that the specs require you to return a list.

Edit: given the OP's late clarification and spec changes, the second answer looks good, except string.ascii_lowercase + string.digits (or some variants thereof e.g. if both lowercase and uppercase ASCII letters are desired) should be used in onepin. You should specify better exactly what "alphabet" string you want to draw characters from (maybe pass it to generate_pins as an argument, with None indicating generate_pins should pick a default alphabet such as e.g. string.digits).

Further edit: added optional alphabet argument and checks about number of distinct pins that can be generated given length and that alphabet.

Alex Martelli
Learning from the maestro! Great use of set(), I keep forgetting about them. A word of caution regarding the top example: The OP's pins were such that they didn't have zero as the first digit; was this by design or just a convenience... Also, Alex' solution is not limited with regards to pin length, unlike the original snipped, owing to range() requiring int (?)
mjv
Guess shouldn't be expecting more answers. :)
alex
@mjv, tx for the spotting, editing to fix. (Actually, some Javascript recently, though mostly Python - no C++ or Java in a while -- but that was just a real typo;-).
Alex Martelli
@Anurag yep you did, almost drove me crazy to understand why that brace had just disappeared!-)
Alex Martelli
sorry try generate_pins(2, 101)
Anurag Uniyal
@Anurag, good point, with an alphabet of length 10 you just can't generate 101 distinct pins. When asked to perform impossible tasks, looping forever MUST be acceptable in general (since to prove a task's impossible in the general case would be equivalent to solving Turing's machine termination problem;-). In this specific case you might check you're being asked to generate a feasible number of pins and raise an exception immediately otherwise.
Alex Martelli
+1  A: 

As OP haven't said random PINs, only criteria seems to be unique pins here is the fastest way

def generate_pins(length, count):
  start=10**length
  return range(start,start+count,1)

also you can not always guarantee uniqeness, same length and count at same time e.g. try generate_pins(1,11) for Alex's answer.

Anurag Uniyal