Home>
■ Question

I wrote code for the following problems, and the test passed, but when I tried to run it, I got an "Execution Timed Out (12000 ms)" message.
Since it works in tests, you probably need to optimize your code.
I'd like to know how to rewrite this code, and if there is something wrong with the grammar.

■ Site in question

https://www.codewars.com/kata/growth-of-a-population/train/shell

■ Problem

A town has "$1" inhabitants. The population increases by "$2"% every year, and "$3" new residents live every year.
How many years does the town need to make residents more than "$4"?

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 (number of inhabitants is an integer)

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

It will need 3 entire years.

* If the percentage parameter is 2, you need to convert it to 0.02.

#!/bin/bash
nbYear () {
    human = $1
    year = 0
    inc = `echo" scale = 5;$2/100 "| bc` #convert to percentage
    while true
    do
      human = `echo" $human + $human * $inc + $3 "| bc | sed s/\. [0-9,] * $// g` # round down
      year = $(($year + 1))
      if ["$(echo" $human>= $4 "| bc)" -eq 1];then
        echo $year
        break
      fi
    done
}
nbYear $1 $2 $3 $4
  • Answer # 1

    I don't think it's too slow.
    Also, theifcondition is unclear. I think this would be an error. Did you attach a different code?

    There is no need to use bc, so you can use bash's calculation function only.

    #!/bin/bash
    nbYear () {
        year = 0
        human = $1
        inc = $2
        come = $3
        limit = $4
        while true
        do
          let human + = human * inc/100 + come
          let year ++
          if [$human -ge $limit];then
            echo $year
            break
          fi
        done
    }
    nbYear $1 $2 $3 $4


    Since it is not checked whether the argument is valid (4 numbers), an invalid argument is an infinite loop.

  • Answer # 2

    #Truncate after decimal point

    There is a full-width space before the comment.

    Further, if ... then condition judgment is

    if [$human -ge $4];then
    Is

    not good?

  • Answer # 3

    Or if you want to use bc, if you let bc do it all, you can do it in one process.

    If you can only do bash's computing power,

    #!/bin/bash
    nbYear () {
      total = $1
      percent = $2
      inc = $3
      limit = $4
      year = $([[$# -eq 5]]&&echo $5 || echo 0)
      percent_inc = $(($total * 100 * $percent/10000))
      total = $(($total + $percent_inc + $inc))
      year = $((year + 1))
      echo "$year: total = $total (percent = $percent_inc, inc = $inc)"
      if [[$total -ge $limit]];then
        echo "Over: $year on Humans is $total"
      else
        nbYear $total $percent $inc $limit $year
      fi
    }
    nbYear $1 $2 $3 $4
    Is it

    ?
    Since it doesn't go through bc, it doesn't consider a small number at all, and shells are rounded down, so it is more straightforward to handle those that can be rounded down like the number of people.

    Since no error is detected, I think that I will die by looping at the upper limit of bash and causing segmentation.

    Result:

    # sh test.sh 1000 2 50 1200
    1: total = 1070 (percent = 20, inc = 50)
    2: total = 1141 (percent = 21, inc = 50)
    3: total = 1213 (percent = 22, inc = 50)
    Over: 3 on Humans is 1213