Reputation: 91
I have created a class, named: bird
. Each instance of that class has two attributes:
creed
(which can be either "C"
or "D"
in value), andlife
(which starts with a value of 100, and changes as the program executes).The program simulates random encounters of two live birds, the birds change the value of life
after each encounter. Once reaching 0, the bird is excluded from further interactions (i.e. dead).
After several iterations, I wish to know how many birds of each creed are "alive".
import random
class Bird:
Doves = 100
Crows = 100
# Initializer / Instance Attributes
def __init__(self, creed, life):
self.creed = creed
self.life = life
def slct_parties():
first = random.randint(0, (Bird.Crows + Bird.Doves -1))
second = random.randint(0, (Bird.Crows + Bird.Doves -1))
while first == second or population[first].life < 1 or population[second].life < 1:
first = random.randint(0, (Bird.Crows + Bird.Doves - 1))
second = random.randint(0, (Bird.Crows + Bird.Doves - 1))
return first, second
# initiating Population
population = []
for bird in range(0, Bird.Crows):
population.append(Bird('C', 100))
for bird in range(0, Bird.Doves):
population.append(Bird('D', 100))
for x in range(1, 1000):
Contest = slct_parties()
l1 = population[Contest[0]].life
l2 = population[Contest[1]].life
# battle
if population[Contest[0]].creed != population[Contest[0]].creed:
if population[Contest[0]].creed == 'D':
population[Contest[0]].life += 1
population[Contest[1]].life += 1
else:
population[Contest[0]].life += -5
population[Contest[1]].life += -10
elif population[Contest[0]].creed == 'C':
population[Contest[0]].life += 5
population[Contest[1]].life += -20
else:
population[Contest[0]].life += -20
population[Contest[1]].life += 5
print("The battle was between {} number {} with {} life, and {} number {} with {} life"
.format(population[Contest[0]].creed, Contest[0], population[Contest[0]].life, population[Contest[1]].creed,
Contest[1], population[Contest[1]].life))
After 1,000 battles, some birds have died. How many birds? Which creed?
single liner (Thanks to Carcigenicate)
dead_crows = len([bird for bird in population if bird.creed == "c" and bird.life <= 0])
function (Thanks to zixuan)
def DeadConter(crd):
dead = 0
for bird in population:
if bird.life <= 0 and bird.creed == crd:
dead += 1
else:
pass
return dead
Upvotes: 2
Views: 113
Reputation: 2283
You can also define 2 values that both start at 0 before the definition of the class that count how many birds are dead, like adding one cDead += 1
when a bird becomes "dead". After the 1000 battles, subtract 100 from the first value and subtract 100 from the second value. You get then, how many bird of each creed are alive. You can also count how many birds of each creed are dead, like this.
import random
c_dead = 0
d_dead = 0
class Bird:
Doves = 100
Crows = 100
# Initializer / Instance Attributes
def __init__(self, creed, life):
self.creed = creed
self.life = life
def slct_parties():
first = random.randint(0, (Bird.Crows + Bird.Doves -1))
second = random.randint(0, (Bird.Crows + Bird.Doves -1))
while first == second or population[first].life < 1 or population[second].life < 1:
first = random.randint(0, (Bird.Crows + Bird.Doves - 1))
second = random.randint(0, (Bird.Crows + Bird.Doves - 1))
return first, second
# initiating Population
population = []
for bird in range(0, Bird.Crows):
population.append(Bird('C', 100))
for bird in range(0, Bird.Doves):
population.append(Bird('D', 100))
for x in range(1, 1000):
Contest = slct_parties()
l1 = population[Contest[0]].life
l2 = population[Contest[1]].life
# battle
if population[Contest[0]].creed != population[Contest[0]].creed:
if population[Contest[0]].creed == 'D':
population[Contest[0]].life += 1
population[Contest[1]].life += 1
else:
population[Contest[0]].life += -5
population[Contest[1]].life += -10
elif population[Contest[0]].creed == 'C':
population[Contest[0]].life += 5
population[Contest[1]].life += -20
else:
population[Contest[0]].life += -20
population[Contest[1]].life += 5
for bird in population:
if bird.life <= 0:
if bird.creed == "C":
c_dead += 1
elif bird.creed == "D":
d_dead += 1
else:
print("Dead birds failed to count") # should never happen, this is a good check for bugs
print("The battle was between {} number {} with {} life, and {} number {} with {} life"
.format(population[Contest[0]].creed, Contest[0], population[Contest[0]].life, population[Contest[1]].creed,
Contest[1], population[Contest[1]].life))
#print dead birds here
print("Number of alive birds")
print(str(100-c_dead) + ": Doves" + " " + str(100-d_dead) + ": Crows")
I added the else
line because this code is untested, I don't know if there are any bugs.
EDIT: The code has been tested now and I've changed a few lines to get it working.
Upvotes: 1
Reputation: 45736
If you want to count them after the fact and not keep running tallies, just iterate over the population:
c_dead = 0
d_dead = 0
for bird in population:
if bird.life <= 0: # The bird is dead
if bird.creed == "c":
c_dead += 1 # Figure out what creed it is and increment a counter
else
d_dead += 1
This could be cleaned up using a dictionary or some other container, but I think this is the simplest way to show the idea.
In the comments, you noted that you were looking for something along the lines of count(population, creed="c", life>0)
. That can't be achieved exactly, but you can use a list comprehension to filter out the birds you don't want to count.
c_dead = len([bird for bird in population if bird.creed == "c" and bird.life <= 0])
d_dead = len([bird for bird in population if bird.creed == "d" and bird.life <= 0])
I wouldn't recommend this way though. This requires two full iterations of the population
, whereas the first only requires one. If this operation was frequent, and the populations was large, it could cause performance problems.
Upvotes: 1
Reputation: 376
Try adding an external variable before the init, initialize it at zero and increment its value by one in the init (+1 for every instance). Then create a function that checks if a bird has died or not and if so, decrease the value of the variable by one
Upvotes: 1