For some reason I misread the question at first (distracted by heart burn, let's go with that as my excuse). I read it as them giving birth every 7 years instead of starting to give birth at age 7, and somehow also skipped the part about maxAge of 40 and assumed maxAge of 30. So, here's the incorrect code I wrote that solves a slightly different problem: let max = 30 let size = 1 let period = 7 let count = 1 let years = 100 let hat = new Set () let genesis = { age: 0 , max: 30 , size: size, period: period, children: new Set () } hat.add (genesis) function isDead ( entity ) { return (entity.age >= entity.max) } function birthReady ( entity ) { return (entity.age % entity.period == 0 ) } for ( let i = 0 ; i < years; i++) { hat.forEach (rabbit => { rabbit.age++ if (isDead (rabbit)) { hat.delete (rabbit) count-- } else { if (birthReady (rabbit)) { for ( let j = 0 ; j < rabbit.size; j++) { let child = { age: 0 , max: max, size: size, period: period, children: new Set () } rabbit.children.add (child) hat.add (child) count++ } } } }) } console .log (genesis) console .log (count) I'll refactor it a bit to solve the actual problem in a moment. EDIT 1: Fixed, but horribly inefficient for the task at hand: let max_birth = 30 let max_age = 40 let birth_start = 7 let size = 1 let period = 1 let count = 1 let years = 100 let hat = new Set () let genesis = { age: 0 , birth_start: birth_start, max_birth: max_birth, max_age: max_age, size: size, period: period, children: new Set () } hat.add (genesis) function isDead ( entity ) { return (entity.age >= entity.max_age) } function birthReady ( entity ) { return ( (entity.age % entity.period == 0 ) && (entity.age <= entity.max_birth) && (entity.age >= entity.birth_start) ) } for ( let i = 0 ; i < years; i++) { hat.forEach (rabbit => { rabbit.age++ if (isDead (rabbit)) { hat.delete (rabbit) count-- } else { if (birthReady (rabbit)) { for ( let j = 0 ; j < rabbit.size; j++) { let child = { age: 0 , birth_start: birth_start, max_birth: max_birth, max_age: max_age, size: size, period: period, children: new Set () } rabbit.children.add (child) hat.add (child) count++ } } } }) } console .log (genesis) console .log (count) Going to Refactor again with something more efficient. BRB ... EDIT 2: Completely refactored and a lot more efficient: let options = { birth_start: 7 , max_birth: 30 , // age agter which entity stops birthing max_age: 40 , // age after which entity dies litter_size: 1 , birth_period: 1 , years: 100 , } let dead_entities = {count: 0 } let entities = Array (options.max_age + 1 ).fill ( 0 ) entities[ 0 ] = 1 function year ( entities, dead_entities, options ) { dead_entities.count += entities [options.max_age] for ( let i = options.max_age; i > 0 ; i--) { entities [i] = entities [i - 1 ] } entities [ 0 ] = 0 let birth_range = ( options.max_birth < options.max_age ? entities.slice ( options.birth_start, options.max_birth + 1 ) : entities.slice (options.birth_start) ) let new_entities = 0 for ( let i = 0 ; i < birth_range.length; i++) { if (i % options.birth_period == 0 ) { new_entities += birth_range [i] * options.litter_size } } entities [ 0 ] += new_entities } for ( let i = 0 ; i < options.years; i++) { year (entities, dead_entities ,options) } console .log ( "alive: " , entities.reduce ((population, cohort) => population + cohort) ) console .log ( "dead: " , dead_entities) The only thing I don't like about this solution is it's readability.