-3

I have to random choose names from a list in python using random.randint.

I have done it so far. but i am unable to figure out how to print them without repetition. some of the name repeat them after 10 to 15 names.

please help me out. I am not allowed to use any high functions. I should do it with simple functions. here is my program.

import random
names = [about 150 names]
print([names[random.randint(0, len(names)-1)] for i in range(user_input)])
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
user3209210
  • 31
  • 3
  • 4
  • You are allowed to use "random" library, so I assume you are allowed to use shuffle http://stackoverflow.com/questions/976882/shuffling-a-list-of-objects-in-python – sashkello Jan 18 '14 at 09:46
  • 1
    As a side note, there is never a good reason to use `foo[randint(0, len(foo)-1)]`. First, that's just a more complicated (and easier to get wrong) way of writing `foo[randrange(len(foo))]`. More importantly, even that is just a more complicated (and easier to get wrong) way of writing `choice(foo)`. – abarnert Jan 18 '14 at 09:52

4 Answers4

3

If you can destructively modify names, just pop the values instead of copying them. Then they're not there anymore, so you won't be able to repeat.

If you can't destructively modify names, just do the same to a copy:

tmp = names[:]
result = [tmp.pop(random.randrange(len(tmp))) for _ in range(user_input)]

This does have quadratic performance, since each pop from the middle of the list has to shift half the list up one notch. But for 150 names, this is unlikely to be a problem. For example, on my laptop, picking 100 values out of 150 names takes 83 microseconds.

If you really aren't allowed to use even randrange, you can write it yourself:

def randrange(x): return randint(0, x-1)
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • 1
    `copy` is one the standard module's names. – thefourtheye Jan 18 '14 at 10:06
  • @thefourtheye: It is so trivial to write either `randrange` or `randint` in terms of the other (especially if you've even skimmed the docs) that I don't think it even needs explaining. But I've added it to the answer just in case. You were right about using `copy`, thought—and it also pushed my code a little too close to 80 columns. Fixed. – abarnert Jan 18 '14 at 10:10
  • @thefourtheye: Also, he only actually says "I am not allowed to use any high functions." `randrange` has been clean for 900 days, and it resents you implying that it's using again. – abarnert Jan 18 '14 at 10:12
  • I understand that `randrange` and `randint` can be replaced easily with the other very easily. But the first line of the question says `I have to random choose names from a list in python using random.randint.`. – thefourtheye Jan 18 '14 at 10:14
1

These restrictions are pretty silly. I'm not sure what "high functions" are, but you still need help after I provided the function in your last question, so perhaps function declarations aren't allowed?

Still, you can do the same thing without a function. You just need to keep track of indices you've already used. Here's another go:

indices = []
for x in range(5):
    index = random.randint(0, len(population)-1)
    while index in indices:
        index = random.randint(0, len(population)-1)
    indices.append(index)
names = [population[i] for i in indices]
Community
  • 1
  • 1
jayelm
  • 7,236
  • 5
  • 43
  • 61
0

Assuming, that you can only use randint and basic operations (loops, assignments and sublistings) - you can do the "in place shuffling trick" (modern version of Fisher Yates) to achieve such a result

copy = names[:]    
for i in xrange( user_input-1, 1, -1 ):
  swap = random.randint(0, i) 
  copy[i],copy[swap] = copy[swap],copy[i]

print copy[ :user_input ]
lejlot
  • 64,777
  • 8
  • 131
  • 164
  • 2
    You don't need 3 lines of code, or a temp variable, to swap two values in Python, just `copy[i], copy[swap] = copy[swap], copy[i]`. – abarnert Jan 18 '14 at 09:54
  • David - thanks for pointing out that I misscoded the ranges, now it is a correct FY – lejlot Jan 18 '14 at 11:48
-1

Generate an array of random numbers of the same length as names

sortarr = [random.randint(0, 10*len(names)) for i in range(len(names))] 

and sort your names array based on this new array

names = [name for sa, name in sorted(zip(sortarr, names))]

What it does is assigns some random numbers to the names. They can be repeating, but it will not make repeating names because if two numbers are the same, they will be assigned to some arbitrary names.

sashkello
  • 17,306
  • 24
  • 81
  • 109
  • I cant understand your point. May be because i am new programmer. I will appreciate your effort if you will explain me your point. – user3209210 Jan 18 '14 at 10:05
  • This doesn't do anything at all to avoid repeats. Multiplying by 10 makes them a bit less likely, but it doesn't actually solve the problem. – abarnert Jan 18 '14 at 10:27
  • For evidence, try this: `sum(len({randint(10*len(names)) for i in range(len(names))}) for _ in range(1000)) / 1000.0`. It'll be around 142.8, meaning that on average, picking 150 values gives you 142.8 unique values and 7.2 repeats. (Or you could just run your code once and look at the results; the odds of having no repeats are pretty slim.) – abarnert Jan 18 '14 at 10:30
  • @abarnert For evidence RUN THE LINES I'VE PROVIDED! Change random.randint(0, 10*len(names)) to random.randint(0, len(names)) if you want, even then there will be no repetitions. – sashkello Jan 18 '14 at 10:49
  • @sashkello: Your `sortarr` has 8 repeats when I run it that way. If two names have the same sort index attached to them, they will retain their original order. So this is not a uniform shuffle. – abarnert Jan 18 '14 at 10:51
  • @sashkello: If it isn't clear why that's not a uniform shuffle, consider the case where `sortarr = [1 for _ in range(150)]`. What happens then? The names aren't shuffled at all. Unless you have 150 distinct indices, you're not shuffling enough. – abarnert Jan 18 '14 at 10:53
  • @abarnert "This doesn't do anything at all to avoid repeats" - so, you were wrong here. I didn't claim it is a uniform shuffle, it is pretty close to it though. OP was asking to random shuffle, not necessarily uniform... If two numbers in sortarr are equal, it will leave two numbers in the same order, just as if the second one was larger by 1. – sashkello Jan 18 '14 at 10:53
  • @abarnert This last comment is irrelevant. Uniform shuffle has a tiny probability of returning the exact same array, it is perfectly normal. – sashkello Jan 18 '14 at 10:58
  • @sashkello: "This doesn't do anything at all to avoid repeats" is 100% true of your `sortarr`. And it's relevant, because that is exactly why your shuffle is not uniform. And when someone doesn't specify what kind of shuffle he wants, he almost always wants a uniform shuffle. Otherwise, you could just `if rand() < 0.5: a[0], a[-1] = a[-1], a[0]` and say "that's random"—which is _true_, but it's still clearly a bad answer. Yours is bad in the same way, just to a lesser degree. Going out of your way to provide less randomness is generally not considered a good thing. – abarnert Jan 18 '14 at 11:11