3
\$\begingroup\$

Task

Take the (integer) number of human years that the dog has lived, \$n\$, as input and return its age in dog years, \$d\$, to two decimal places.
The number of human years, \$n\$, will be between \$1\$ and \$122\$ inclusive: \$n \in [1,122], n \in \Bbb{N}\$.

According to BBC's Science Focus Magazine, the correct function for determining your dog's age is: $$ n = 16 \times \ln(d) + 31 $$ Where

\$n\$ is the age in human years

\$d\$ is the age in dog years

Rules

The final output in dog years must be a decimal, rounded to 2 decimal places.

\$\endgroup\$
12
  • 8
    \$\begingroup\$ Is 'rounded to 2 digits' a firm rule? Neither of the current answers do this. \$\endgroup\$
    – Dingus
    Commented Aug 2, 2020 at 12:37
  • 4
    \$\begingroup\$ At 969 years, floating point imprecision becomes significant (the correct answer is 28874468684703116351749853 point something, while a simple calculation with doubles returns 28874468684703116489129984.00. Are you sure you want to set the upper limit to such a high value? \$\endgroup\$ Commented Aug 2, 2020 at 13:00
  • 2
    \$\begingroup\$ Ok, I set the max age to 122, which keeps the maximum age to 295.15. Thanks! \$\endgroup\$
    – Razetime
    Commented Aug 2, 2020 at 13:06
  • 5
    \$\begingroup\$ ...also I imagine trailing zeros may be implicit, right? (i.e. that 0.5 is an acceptable output when given an input of 20 [rather than 0.50]) \$\endgroup\$ Commented Aug 2, 2020 at 15:03
  • 3
    \$\begingroup\$ This question misinterprets the formula. n and d are the wrong way around. From the source paper: (equivalent) human_age = 16 ln(dog_age) + 31 \$\endgroup\$
    – roblogic
    Commented Dec 12, 2020 at 4:36

20 Answers 20

5
\$\begingroup\$

Io, 114 bytes

While you all are enjoying rounding built-ins in your language, Io doesn't have any of those convenient rounding built-ins...

method(x,I :=((((x-31)/16)exp*100)round asString);I=if(I size<3,"0","").. I;I asMutable atInsertSeq(I size-2,"."))

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Perl 5, 36 31 bytes

printf"%.2f",1.0644944**($_-31)

Try it online!

Command line one-liner examples:

echo 52 | perl -ne 'printf"%.2f\n",2.71828**(($_-31)/16)'
echo 52 | perl -ne 'printf"%.2f\n",1.06449445**($_-31)'
echo 52 | perl -ne 'printf"%.2f",1.06449445**($_-31)'
echo 52 | perl -ne 'printf"%.2f",1.0644944**($_-31)'

for a in {1..122};do echo "Man: $a Dog: "`echo $a|perl -ne'printf"%.2f\n",1.0644944**($_-31)'`;done
\$\endgroup\$
8
  • 1
    \$\begingroup\$ printf"%.2f\n",1.06449445**($_-31) saves two. \$\endgroup\$ Commented Aug 2, 2020 at 16:51
  • 1
    \$\begingroup\$ Do you need the \n? (You can only take one input at a time without it, but there's nothing wrong with that.) \$\endgroup\$
    – Dingus
    Commented Aug 3, 2020 at 3:22
  • \$\begingroup\$ @JonathanAllan Thanks, and I also see that for the range 0-125 then 1.06449445 can be shortened to 1.0644944 and still give the same results when rounding to 2 decimals. \$\endgroup\$
    – Kjetil S
    Commented Aug 3, 2020 at 7:48
  • \$\begingroup\$ Thanks to @Dingus also. \$\endgroup\$
    – Kjetil S
    Commented Aug 3, 2020 at 7:49
  • 1
    \$\begingroup\$ Shorter yet: 27 bytes \$\endgroup\$
    – Xcali
    Commented Dec 12, 2020 at 6:46
3
\$\begingroup\$

Jelly, 10 bytes

_31÷⁴Æeær2

A monadic Link accepting a float which yields a float. (As a full program a decimal input causes the result to be printed.)

Try it online!

How?

_31÷⁴Æeær2 - Link: float, n
 31        - 31
_          - subtract         -> n-31
    ⁴      - 16
   ÷       - divide           -> (n-31)/16
     Æe    - exp(x)           -> exp((n-31)/16)
         2 - 2
       ær  - round to 10^(-y) -> round(exp((n-31)/16), 2)
\$\endgroup\$
3
\$\begingroup\$

Integral, 14 11 Bytes

My first Integral answer!

x▼◄w‼5*↕u*‼

Try it!

An alternative: ▲w‼!◄5*↕u*‼ (11 bytes)

Explanation

x              Push 32
 ▼             x-1
  ◄            Subtraction
   w           Push 16
    ‼          Divide
     5         e ^ a
      *        100
       ↕       Multiplicaiton
        u      Round to the closest integer
         *     100
          ‼    Division
\$\endgroup\$
2
\$\begingroup\$

Orst, 9 bytes

31FᎽGć2Š

Try it online!

As bytes, this is

F3 F1 1B FF 30 1C 64 F2 42

Or, encoded as UTF-8,

óñÿ0dòB

which can be run by omitting the -u flag (filled by default on TIO). Note the not shown 0x1b and 0x1c bytes

How it works

31FᎽGć2Š - Full program. n is pushed to the stack
31       - Push 31
  F      - Subtract; n-31
   Ꮍ     - Push 16
    G    - Divide; (n-31)÷16
     ć   - Exp; exp((n-31)÷16)
      2Š - Round to 2 decimal places
\$\endgroup\$
2
  • \$\begingroup\$ Just curious: What's with the "undefined bytes?" \$\endgroup\$
    – Makonede
    Commented Apr 20, 2021 at 1:08
  • 1
    \$\begingroup\$ @Makonede Orst uses a 512 byte code byte, using a continuation byte (FF). When adding Orst to TIO, it was easier to use "undefined" than try to add in a special byte-counting script \$\endgroup\$ Commented Apr 20, 2021 at 1:09
2
\$\begingroup\$

APL+WIN, 13 bytes

Prompts for input of n:

⍎2⍕*(⎕-31)÷16

Try it online! Courtesy of Dyalog Classic

\$\endgroup\$
2
\$\begingroup\$

Vyxal s, 23 bytes

31-16/W∆ehS\.€ḣh2wi\.$W

Try it Online!

From this answer two stupid features of Vyxal:

  • Why \$ln(x)^{-1}\$ needs to take a list instead of digit?
  • Seriously it cannot round a digit to n decimal places, so that part is handrolled.
\$\endgroup\$
2
  • \$\begingroup\$ y'know, there's nicer and more direct ways of asking for feature requests ;p \$\endgroup\$
    – lyxal
    Commented Jun 7, 2021 at 13:14
  • \$\begingroup\$ @lyxal I'll refer to the Vyxal room as soon as possible (tomorrow) \$\endgroup\$
    – Wasif
    Commented Jun 7, 2021 at 14:22
1
\$\begingroup\$

JavaScript (V8), 33 32 bytes

a=>Math.exp(-~a/16-2).toFixed(2)

Try it online!

Thanks to @my pronoun is monicareinstate for -1 byte

\$\endgroup\$
1
1
\$\begingroup\$

cQuents, 24 bytes

:b$)/100
:R100*x_+$/16-2

Try it online!

For some reason, rounding works on the whole line. I would do /100/R100*, but floats went all 9y on me.

\$\endgroup\$
1
\$\begingroup\$

R, 28 bytes

round(exp((scan()-31)/16),2)

Try it online!

There seems to be some controversy about whether trailing zeros must be printed. If so, the following 35 byte solution works:

sprintf("%.2f",exp((scan()-31)/16))
\$\endgroup\$
1
\$\begingroup\$

bc, 40 bytes

scale=2
define f(n){return e((n-31)/16)}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

C (gcc), 35 44 38 36 bytes

Saved a byte thanks to my pronoun is monicareinstate!!!
Saved 2 bytes thanks to Arnauld!!!
Added 10 bytes to fix a bug kindly pointed out by Kjetil S.

f(n){printf("%.2f",exp(-~n/16.-2));}

Try it online!

\$\endgroup\$
5
  • 3
    \$\begingroup\$ Rounding should be inside function f? \$\endgroup\$
    – Kjetil S
    Commented Aug 2, 2020 at 12:58
  • \$\begingroup\$ Ignoring rounding, which should be added, 34 bytes (assuming I didn't make a dumb mistake) \$\endgroup\$ Commented Aug 2, 2020 at 12:59
  • \$\begingroup\$ @KjetilS. Oops, missed that - fixed! :-) \$\endgroup\$
    – Noodle9
    Commented Aug 2, 2020 at 14:05
  • 3
    \$\begingroup\$ Do you really need the \n? \$\endgroup\$
    – Arnauld
    Commented Aug 2, 2020 at 15:23
  • \$\begingroup\$ @Arnauld Of course not - thanks! :D \$\endgroup\$
    – Noodle9
    Commented Aug 2, 2020 at 17:05
1
\$\begingroup\$

Japt, 12 11 bytes

-1 byte thanks to @Shaggy

Me°U/G-2 x2

Try it

Explanation

Me°U/G-2 x2
Me            //  exp(
  °U          //      (U + 1)
    /G-2      //              / 16 - 2
              //  )
          x2  //  round to 2 decimal digits
\$\endgroup\$
1
  • \$\begingroup\$ 16 can be G. \$\endgroup\$
    – Shaggy
    Commented Aug 2, 2020 at 17:18
1
\$\begingroup\$

Python 3, 52 36 35 bytes

Saved a whopping 16 17 bytes thanks to Jonathan Allan!!!

lambda n:round(1.0644944**(n-31),2)

Try it online!

\$\endgroup\$
7
  • 3
    \$\begingroup\$ @petStorm I disagree, "The final output in dog years must be a decimal, rounded to 2 digits." states nothing about necessitating trailing zeros (and that's assuming it means 2dp rather than 2sf). Furthermore, many answers will give no trailing zero, e.g. 0.5 when given 20. \$\endgroup\$ Commented Aug 2, 2020 at 14:52
  • 2
    \$\begingroup\$ lambda n:round(math.exp(-~n/16-2),2) saves 4 \$\endgroup\$ Commented Aug 2, 2020 at 15:24
  • 1
    \$\begingroup\$ If we can't assume n is an integer we can't use ~; if we can assume n is an integer (in \$[1,122]\$) we can do lambda n:round(2.71828**((n-31)/16),2) for 38. \$\endgroup\$ Commented Aug 2, 2020 at 16:36
  • \$\begingroup\$ ...actually, lambda n:round(1.06449445**(n-31),2) would work for 36. \$\endgroup\$ Commented Aug 2, 2020 at 16:48
  • \$\begingroup\$ @JonathanAllan Oh wow, that's great - thanks! :D \$\endgroup\$
    – Noodle9
    Commented Aug 2, 2020 at 17:02
1
\$\begingroup\$

MathGolf, 19 bytes

T-☻/e▬♪*i♂‼/%5≥+♀∩*

If only MathGolf had a round builtin.. :/
6 bytes are used for the actual formula, 13 for rounding to 2 decimals, haha.

I/O both as a float.

Try it online.

Explanation:

T-            # Subtract 31 from the (implicit) input-float
              #  i.e. 50.0 → 19.0
  ☻/          # Divide it by 16
              #  → 1.1875
    e▬        # Push 2.718281828459045 to the power this value
              #  → 3.2788737679386735
♪*            # Multiply it by 1000
              #  → 3278.8737679386735
  i           # Convert it to an integer, truncating the decimal values
              #  → 3278
   ♂          # Push 10
    ‼         # Apply the following two commands separated to the stack:
     /        #  Integer-division
      %       #  Modulo
              #   → 327 and 8
       5≥     # Check if the modulo-10 result (the last digit) is >= 5
              # (1 if truthy; 0 if falsey)
              #   → 327 and 1
         +    # Add that to the division-by-10 result
              #   → 328
          ♀∩  # Push 1/100
            * # Multiply that to the integer
              #   → 3.28
              # (note: `♀/` cannot be used, because it would act as integer division)
              # (after which the entire stack is output implicitly as result)
\$\endgroup\$
1
\$\begingroup\$

Rust, 38 bytes

|n|print!("{:.2}",((n-31.)/16.).exp())

Try it online

\$\endgroup\$
1
\$\begingroup\$

Charcoal, 20 bytes

﹪%.2fX¹·⁰⁶⁴⁴⁹⁴⁴⁵⁻N³¹

Try it online! Link is to verbose version of code. Numeric constant stolen from @JonathanAllan. Explanation:

                N      Input as a number
               ⁻ ³¹    Subtract literal 31
     X¹·⁰⁶⁴⁴⁹⁴⁴⁵        Raise literal 1.06449445 to that power
﹪%.2f                   Format using literal format string `%.2f`
                        Implicitly print
\$\endgroup\$
1
\$\begingroup\$

Zsh, 50 bytes

zmodload zsh/mathfunc
printf %.2f $[16*log($1)+31]

Try it Online!

Gives "dog years" per the original refs and examples. For example, the "ScienceFocus" article gives 2 examples, and the "Cell Systems" paper gives 1 example, as tabulated:
dog age | equivalent human age
actual years | approx. "dog years"
1 | ~30
4 | ~52
12 | ~70

Do programmers ever read requirements?

\$\endgroup\$
1
  • 1
    \$\begingroup\$ This was my first question, and I wrote it in a bit of a hurry, so it is bad and not very well researched. Thanks for the help, and nice answer. \$\endgroup\$
    – Razetime
    Commented Dec 12, 2020 at 6:40
1
\$\begingroup\$

05AB1E, 12 bytes

>16/Ížrsm2.ò

Try it online!

>16/Ížrsm2.ò  # full program
          .ò  # round...
     žr       # 2.718281828459045...
       sm     # to the power of...
              # implicit input...
>             # plus 1...
   /          # divided by...
 16           # literal...
    Í         # minus 2...
          .ò  # to...
         2    # literal...
          .ò  # decimal places
              # implicit output
\$\endgroup\$
0
\$\begingroup\$

HP‑41C series, 18 B

You must place \$n\$ on top of the stack first (a. k. a. the X register). Then you can XEQ (execute) the following program:

01♦LBL "Y"         5 Bytes    global label requires 4 + (length of string) Bytes
   NULL            1 Byte     invisible Null byte before numbers
02 31              2 Bytes    X ≔ 31;  Y ≔ 𝘯
03 −               1 Byte     X ≔ 𝘯 − 31
   NULL            1 Byte     invisible Null byte before numbers
04 16              2 Bytes    place the value 16 on top of the stack; X ≔ 16
05 ∕               1 Byte     X ≔ (𝘯 − 31) ∕ 16
06 E↑X             1 Byte     𝘦 raised to the power of X
07 FIX 2           2 Bytes    show (up to) two place after the radix point
08 RND             1 Byte     round the value
09 RTN             1 Byte     `RTN` does not affect local label search

The fixed decimal point display is always rounded. However, the display settings do not affect the internally stored numbers. To ensure all digits after the second decimal place are zero, too, RND (round) is applied.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.