DEV Community

Cover image for Daily Challenge #271 - Simulate Population Growth
dev.to staff
dev.to staff

Posted on

Daily Challenge #271 - Simulate Population Growth

In a small town the population is p0 = 1000 at the beginning of a year. The population regularly increases by 2 percent per year and moreover 50 new inhabitants per year come to live in the town. How many years does the town need to see its population greater or equal to p = 1200 inhabitants?

Note: Always keep the number of inhabitants as an integer. Round up when necessary.

At the end of the first year there will be: 
1000 + 1000 * 0.02 + 50 => 1070 inhabitants

At the end of the 2nd year there will be: 
1070 + 1070 * 0.02 + 50 => 1141 inhabitants

At the end of the 3rd year there will be:
1141 + 1141 * 0.02 + 50 => 1213

It will need 3 entire years to get to 1200 folks.

Parameters:
p0, percent, aug (inhabitants coming or leaving each year), p (population to surpass)

the function nb_year should return n number of entire years needed to get a population greater or equal to p.

aug is an integer, percent a positive or null number, p0 and p are positive integers (> 0)

Examples:
nb_year(1500, 5, 100, 5000) -> 15
nb_year(1500000, 2.5, 10000, 2000000) -> 10

Tests:
nbYear(1500, 5, 100, 5000)
nbYear(1500000, 2.5, 10000, 2000000)
nbYear(1500000, 0.25, 1000, 2000000)

Good luck!


This challenge comes from g964 on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Top comments (9)

Collapse
 
rushsteve1 profile image
Steven vanZyl

Using an iterative style in Clojure. I think an iterative style is best suited for a sequential problem like this, and Clojure felt like a good fit.

(defn nb_year [p0 percent aug p]
  (count
    (take-while
      #(<= % p)
      (iterate
        #(Math/ceil (+ % (* % (/ percent 100)) aug))
        p0))))
Collapse
 
bravemaster619 profile image
bravemaster619 • Edited

This is a 7kyu question in codewar but it's a bit tricky.

I remember I solved it after tens of submissions, because one or two tests were failed for some reason.

Turned out that I should have to deal with integers more carefully.

Here is an answer for ruby version:

def nb_year(p0, percent, aug, p)
    year = 0
    while p0 < p
      year += 1
      p0 = spawn(p0, percent, aug)
    end
    year
end

def spawn(p, percent, aug)
  (p + (p * percent / 100).floor + aug)
end
Collapse
 
dry profile image
Hayden Mankin

Javascript

Using a generator function to calculate the successive years

function nbYear(p0, percent, aug, p) {
  let i, population = pop(p0, percent / 100, aug);
  for (i = 0; population.next().value < p; i++);
  return i;
}

function * pop(p, r, ann) {
  while (true) {
    yield p;
    p += p * r + ann;
  }
}
Collapse
 
qm3ster profile image
Mihail Malo • Edited

If you're using generators, go wild :v

const chain = (...fns) => x => fns.reduce((x, fn) => fn(x), x)
const count = it => {
  let i = 0
  for (_ of it) i++
  return i
}
const takeWhile = fn => function * takeWhile(it) {
  for (x of it) {
    if (!fn(x)) break
    yield x
  }
}

function * pop(p, r, ann) {
  while (true) {
    yield p
    p += p * r + ann
  }
}

const nbYear = (p0, percent, aug, p) => chain(
  takeWhile(x => x < p),
  count,
)(pop(p0, percent / 100, aug))

or at least

function nbYear(p0, percent, aug, p) {
  const population = pop(p0, percent / 100, aug)
  let i = 0
  for (pop of population) {
    if (pop > p) return i
    i++
  }
}

(even though the following is actually shorter)

function nbYear(p0, percent, aug, p) {
  const population = pop(p0, percent / 100, aug)
  let i = 0
  while (population.next().value < p) i++
  return i
}
Collapse
 
peter279k profile image
peter279k

Here is my solution with PHP code snippets:

function nbYear($p0, $percent, $aug, $p) {
  $percent = $percent / 100;
  $entry = 0;
  while ($p0 < $p) {
    $p0 = $p0 + $p0 * $percent + $aug;
    $entry += 1;
  }

  return $entry;
}
Collapse
 
cipharius profile image
Valts Liepiņš • Edited

Lazy Haskell goodness:

import Data.Maybe (fromMaybe)
import Data.List (findIndex)

nbYear :: Int -> Double -> Int -> Int -> Int
nbYear p0 growth aug pGoal = fromMaybe 0 $ maybeYears
  where
    maybeYears = findIndex (>= pGoal) $ p0 : nbYear' p0
    nbYear' p =
      let p' = (ceiling $ fromIntegral p * (1 + growth')) + aug
      in p' : nbYear' p'
    growth' = growth / 100

General idea of the solution is to generate an infinite list of population growth per year with the recursive function nbYear'. Since Haskell is lazy, I can then use this infinite list to find the first item in the list, which exceeds the goal population.

Collapse
 
moufeed_m profile image
Mofid Jobakji
const nbYear = (p0,percent,aug,final)=> 
p0 < final ? 1+nbYear(p0 + p0 *(percent/100)+aug ,percent,aug,final) : 0;
Collapse
 
mgilangjanuar profile image
M Gilang Januar • Edited
const nb_year = (p0, percent, aug, p) => p <= p0 
  ? 0 
  : 1 + nb_year(p0 * (percent / 100) + aug + p0, percent, aug, p)
Collapse
 
highcenburg profile image
Vicente G. Reyes
def nb_year(p0, percent, aug, p,  year = 0):
  if (p0 >= p):
    return year
  else:
    year += 1
    pop = p0 + p0 * (percent/100) + aug
    return nb_year(pop, percent, aug, p, year)