HiveBrain v1.2.0
Get Started
← Back to all entries
snippetpythonMinor

Generate set of random numbers and remove lowest

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
randomlowestnumbersremovegenerateandset

Problem

I'm learning some Python with my kids, and we're making a program to generate D & D characters from user input.

One portion of the code is to generate stats, which are a set of six numbers where each number is the sum of three random values from 1-6. We're total softies, though, so for each value, we're generating four values from 1-6 and tossing out the lowest. We're also doing this seven times, and throwing out the lowest of the seven, to end up with a list of six values.

import random

stats = []

for i in range(7):
    rolls = []

    for j in range(4):
        roll = random.randint(1,6)
        rolls.append(roll)

    stat = sum(rolls) - min(rolls)
    stats.append(stat)

stats.remove(min(stats))

print stats


It works, but I feel like there might be more elegant solutions/more Pythonic approaches. Any suggestions?

Solution

This seems like a nice thing to do with your kids!

Python has these things called comprehensions.
For example a list comprehension for the first 5 multiples of 2 could be either:

[i * 2 for i in range(1, 6)]
[i for i in range(11) if i % 2 == 0]


The latter one is a bit harder to understand, and you don't need to know it. So I'll give you an example of what the first one would be if it were not a comprehension.

list_ = []
for i in range(1, 6):
    list_.append(2 * i)


You could change rolls to be a list comprehension, and remove some varibles:

stats = []
for _ in range(7):
    rolls = [random.randint(1, 6) for _ in range(4)]
    stats.append(sum(rolls) - min(rolls))
stats.remove(min(stats))
print stats


There's a way you could do this all in two comprehensions.
But you are not allowed to define variables in comprehensions.
So you would need to use sorted and a slice to get the rolls.
I personally think this is harder to understand, and could be a challenge to teach your kids.

roll = sum(sorted(random.randint(1, 6) for _ in range(4))[1:])


However if you think it's nice, you could use it:

stats = [
    sum(sorted(random.randint(1, 6) for _ in range(4))[1:])
    for _ in range(7)
]
stats.remove(min(stats))
print stats


It's a lot shorter than your original, mostly due to not defining variables like roll.
But could be harder to understand.

Code Snippets

[i * 2 for i in range(1, 6)]
[i for i in range(11) if i % 2 == 0]
list_ = []
for i in range(1, 6):
    list_.append(2 * i)
stats = []
for _ in range(7):
    rolls = [random.randint(1, 6) for _ in range(4)]
    stats.append(sum(rolls) - min(rolls))
stats.remove(min(stats))
print stats
roll = sum(sorted(random.randint(1, 6) for _ in range(4))[1:])
stats = [
    sum(sorted(random.randint(1, 6) for _ in range(4))[1:])
    for _ in range(7)
]
stats.remove(min(stats))
print stats

Context

StackExchange Code Review Q#116574, answer score: 8

Revisions (0)

No revisions yet.