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.