19
\$\begingroup\$

The gravitational binding energy of a planet is the amount of energy required to separate every tiny piece of it so that no piece will orbit or collide with another piece. For a uniform sphere, Wikipedia gives this formula:

$$E = \frac{3GM^2}{5R}$$

Where G is the gravitational constant (6.672e-11 m3•kg-1•s-2), M is mass, and R is the radius.

I could make this challenge about merely calculating this in Joules (kg•m2•s-2), but… that would be boring. And besides, not everyone understands Joules.

So instead, let's convert it into the following units:

  • Kilotons of TNT (4.184 trillion Joules, shorthand kilotons)
  • Hiroshima nuclear weapons (62.76 trillion Joules, shorthand nukes)
  • Hostess™ Twinkies (560,000 Joules, shorthand twinkies)
  • Kilowatt-hours (exactly 3.6 million Joules, shorthand kWh)
  • Kilograms of mass-energy (1 kg mass-energy = 299,792,4582 Joules, shorthand kg)

So, take in the following input:

  • mass in kilograms
  • radius in meters
  • one of six distinct inputs representing the unit to use

And output the binding energy in the specified units. Append the shorthand unit to the end of the output.

Rules

  • The shorthand for Joules is J.
  • Arbitrary whitespace is allowed, as long as it doesn't split the shorthand unit or the number.
  • Scientific notation is allowed, in whatever format your language uses.
  • You only need 4 significant figures. Floating points are highly recommended.
  • Blah blah shortest answer in bytes.

Test Cases

Generated with this spreadsheet.

Mass (kg)   Radius (m)  J           kilotons    nukes       twinkies    kWh         kg
3.302E+23   2440000     1.789E+30   4.275E+17   2.850E+16   3.194E+24   4.969E+23   1.990E+13
4.869E+24   6052000     1.568E+32   3.748E+19   2.499E+18   2.800E+26   4.356E+25   1.745E+15
5.974E+24   6371000     2.242E+32   5.360E+19   3.573E+18   4.004E+26   6.229E+25   2.495E+15
6.419E+23   3390000     4.866E+30   1.163E+18   7.753E+16   8.689E+24   1.352E+24   5.414E+13
1.899E+27   69911000    2.065E+36   4.935E+23   3.290E+22   3.687E+30   5.736E+29   2.298E+19
5.685E+26   58232000    2.222E+35   5.310E+22   3.540E+21   3.968E+29   6.172E+28   2.472E+18
8.683E+25   25360000    1.190E+34   2.845E+21   1.896E+20   2.125E+28   3.306E+27   1.324E+17
1.024E+26   24620000    1.705E+34   4.075E+21   2.717E+20   3.045E+28   4.736E+27   1.897E+17
1.311E+22   1186000     5.801E+27   1.387E+15   9.244E+13   1.036E+22   1.611E+21   6.455E+10
1.989E+30   696300000   2.274E+41   5.436E+28   3.624E+27   4.062E+35   6.318E+34   2.531E+24
7.350E+22   1737000     1.245E+29   2.976E+16   1.984E+15   2.223E+23   3.458E+22   1.385E+12

Inspired by Powering the Death Star with Twinkies by Scott Manley.

\$\endgroup\$
6
  • \$\begingroup\$ what do you mean by "default to joules"? does that mean that the output unit will not always be given in the input? \$\endgroup\$
    – hyper-neutrino
    Nov 27, 2017 at 2:02
  • 9
    \$\begingroup\$ also, I love how there's actually a name for the amount of energy needed to completely annihilate a thing :P \$\endgroup\$
    – hyper-neutrino
    Nov 27, 2017 at 2:03
  • \$\begingroup\$ can we take the output unit as any of 6 distinct inputs? otherwise it's a cumbersome I/O format and those are discouraged \$\endgroup\$
    – hyper-neutrino
    Nov 27, 2017 at 2:06
  • \$\begingroup\$ @HyperNeutrino sure, but you still need the shorthand in the output. \$\endgroup\$
    – Nissa
    Nov 27, 2017 at 2:16
  • 2
    \$\begingroup\$ @StephenLeppik "one of six distinct inputs representing the unit to use" - can those distinct inputs be 4.184, 62.76, etc? \$\endgroup\$
    – ngn
    Nov 30, 2017 at 18:50

10 Answers 10

17
+50
\$\begingroup\$

JavaScript (ES6), 78 bytes

Takes input as 3 distinct variables (mass, radius, unit).

(m,r,u)=>m*m/r/[8987e9,56,6276e6,,4184e5,1e-4,360][parseInt(u,30)%7]/2498e11+u

Test cases

The following snippet runs all test cases in the provided spreadsheet.

let f=

(m,r,u)=>m*m/r/[8987e9,56,6276e6,,4184e5,1e-4,360][parseInt(u,30)%7]/2498e11+u

console.log(
  [
    '3.302e+23 2440000   1.789e+30 4.275e+17 2.850e+16 3.194e+24 4.969e+23 1.990e+13',
    '4.869e+24 6052000   1.568e+32 3.748e+19 2.499e+18 2.800e+26 4.356e+25 1.745e+15',
    '5.974e+24 6371000   2.242e+32 5.360e+19 3.573e+18 4.004e+26 6.229e+25 2.495e+15',
    '6.419e+23 3390000   4.866e+30 1.163e+18 7.753e+16 8.689e+24 1.352e+24 5.414e+13',
    '1.899e+27 69911000  2.065e+36 4.935e+23 3.290e+22 3.687e+30 5.736e+29 2.298e+19',
    '5.685e+26 58232000  2.222e+35 5.310e+22 3.540e+21 3.968e+29 6.172e+28 2.472e+18',
    '8.683e+25 25360000  1.190e+34 2.845e+21 1.896e+20 2.125e+28 3.306e+27 1.324e+17',
    '1.024e+26 24620000  1.705e+34 4.075e+21 2.717e+20 3.045e+28 4.736e+27 1.897e+17',
    '1.311e+22 1186000   5.801e+27 1.387e+15 9.244e+13 1.036e+22 1.611e+21 6.455e+10',
    '1.989e+30 696300000 2.274e+41 5.436e+28 3.624e+27 4.062e+35 6.318e+34 2.531e+24',
    '7.350e+22 1737000   1.245e+29 2.976e+16 1.984e+15 2.223e+23 3.458e+22 1.385e+12'
  ]
  .map((l, n) => {
    [m, r, ...res] = l.match(/\S+/g).map(Number);

    return 'Test case #' + -~n + ' -> ' + (
      ['J', 'kilotons', 'nukes', 'twinkies', 'kWh', 'kg']
      .every((u, i) => +(+f(m, r, u).split(u).join``).toExponential(3) === +res[i])
      ? 'OK' : 'FAIL'
    )
  })
)

How?

This is quite similar to @ColeraSu's C answer, with a JS-friendly hash function that works on the whole unit string.

Unit       | Parsed as (*) | Base-30 -> Dec. | mod 7
-----------+---------------+-----------------+------
"J"        | "j"           | 19              | 5        (*):
"kilotons" | "kilotons"    | 451052545318    | 4          Because we're parsing as Base-30,
"nukes"    | "n"           | 23              | 2          characters [u-z] (and anything
"twinkies" | "t"           | 29              | 1          after them) are simply ignored.
"kWh"      | "k"           | 20              | 6
"kg"       | "kg"          | 616             | 0
\$\endgroup\$
0
7
\$\begingroup\$

Jelly, 78 bytes

²×⁽LÐ÷ȷ14÷⁴÷5÷⁵ị“¤Fðẏẏż“?A⁺ẏẏż“¬ŀż“8Ƙż“¡uþ³⁾ẉṿÆ“¡’¤;⁵ị“ÞṠlT“¡ṁæ-“;ØḲ“ȧ¹“ṫD“}»¤

Try it online!

Stuff to do with strings isn't really Jelly's type of challenge...

-7 bytes thanks to user202729 (thanks for helping me not get beaten by JavaScript :D)

\$\endgroup\$
2
  • \$\begingroup\$ Yeah, now you're tied with JS and still not on top either. \$\endgroup\$
    – Nissa
    Nov 27, 2017 at 14:40
  • \$\begingroup\$ @StephenLeppik At least I'm not getting beaten :D and shush 05AB1E is inherently better at string challenges :P \$\endgroup\$
    – hyper-neutrino
    Nov 27, 2017 at 14:50
6
\$\begingroup\$

05AB1E, 56 54 bytes

Takes input as unit, radius, mass

6n56•G*•x619+•Oć•4°z)•1¡‡•S°*"Wwigu"I1èkè*2498T>°P/*¹J

Try it online!

Saved 2 bytes thanks to Erik the outgolfer (base 255 encode 4184 and 6276).

\$\endgroup\$
0
6
\$\begingroup\$

C, 113 bytes

Hash the second character, using the trailing '\0' of "J". Inline array in C is used.

Note we need to multiply the second M last, or it will overflow to inf.

f(m,r,c)float m,r;char*c;{printf("%e%s",m/r/(float[]){1e-4,360,6276e6,8987e9,56,4184e5}[c[1]%36%7]/2498e11*m,c);}

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ +1. Not sure if possible, but f(m,r,char*c)float m,r{…} would save some bytes. Also, the semicolon after printf is optional \$\endgroup\$
    – caylee
    Nov 27, 2017 at 6:03
  • \$\begingroup\$ @xanoetux Which compiler do you use? Both don't work on my machine though. \$\endgroup\$
    – Colera Su
    Nov 27, 2017 at 8:25
  • \$\begingroup\$ I'm using GCC. Untested, but I'm quite sure about the last semicolon. (will test later) \$\endgroup\$
    – caylee
    Nov 27, 2017 at 14:27
4
\$\begingroup\$

APL (Dyalog Unicode), 153 71 69 bytes

op←{⍺,⍨40032E¯15÷÷/8987E13 36E5 6276E10 56E4 4184E9 1['gWuw '⍳⊃1↓⍺]⍵⍺⍺⍵}

Try it online!

Thanks to @Adám for absolutely crushing my old answer into this one. Thanks to @ngn for 2 bytes.

This 'function' is actually an operator called op. All the values for the measurement units were transformed to scientific notation.

How it works:

{⍺,⍨40032E¯15÷÷/8987E13 36E5 6276E10 56E4 4184E9 1['gWuw '⍳⊃1↓⍺]⍵⍺⍺⍵}
                                                             1↓⍺         ⍝ take the measurement unit without the first letter (because it is ambiguous)
                                                            ⊃            ⍝ picks the first element returned by 
                                                           ⍳             ⍝ Dyadic ⍳ota, which finds the index of
                                                  'gWuw '                ⍝ each of these characters
                                                 [             ]         ⍝ square brackets indicate the index
               8987E13 36E5 6276E10 56E4 4184E9 1                        ⍝ of the element of this vector (1-indexed) which will be used as the divisor for
            ÷/                                                  ⍵⍺⍺⍵     ⍝ dividing by the left operand (⍺⍺) and the right argument squared.
    40032E¯15÷                                                           ⍝ then divide this number by the result
 ⍺,⍨                                                                     ⍝ and append the measurement unit
\$\endgroup\$
0
3
\$\begingroup\$

Python 3, 112 106 108 101 Bytes

lambda m,r,u:str(40032e-19*m*m/r/{'':1e-4,'i':4184e5,'u':6276e6,'w':56,'W':360,'g':8987e9}[u[1:2]])+u

Pretty straight forward. Uses Python's e notation. Uses a dict that distinguishes unit based on the second letter and divides by the corrosponding value. u[1:2] is basically u[1], expect it returns '' instead of an error (which I only learned now). Then applies the formula with a few simplifications.

edit: down to 106 thanks to totallyhuman, back to 108 because of new nukes value and down to 101 thanks to Colera Su.

Try it online!

\$\endgroup\$
0
3
\$\begingroup\$

Excel (Office 365), 106 101 97 bytes

Assuming cell A1 is the mass, A2 is the radius, and B1 is the unit, written as the shorthand for the output.

=40032E-19*A1^2/(A2*SWITCH(MID(B1,2,1),"u",6276E6,"w",56,"W",360,"g",89876E8,"i",4184E5,1E-4))&B1

Excel, 130 bytes

Old-fashioned Excel doesn't have the SWITCH function, so you have

=40032E-15*A1^2/(A2*IF(B1="J",1,IF(B1="nukes",6276E10,IF(B1="twinkies",56E4,IF(B1="kWh",36E5,IF(B1="kg",299792E3^2,4184E9))))))&B1
\$\endgroup\$
2
  • \$\begingroup\$ You can save 2 bytes by substituting 299792E3^2 with 89876E12 (Still accurate enough for question requirements.) Divide all values by 1000 saves another 2: =40032E-19*A1^2/(A2*SWITCH(MID(B1,2,1),"u",6276E6,"w",56,"W",360,"g",89876E8,"i",4184E5,1E-4))&B1 \$\endgroup\$
    – Wernisch
    Dec 1, 2017 at 13:10
  • \$\begingroup\$ Hey, just want to throw it out there that the Switch() function is available to desktop copies of Excel, and was introduced with Office 2016. \$\endgroup\$ Dec 1, 2017 at 21:44
1
\$\begingroup\$

Ruby , 83 82 bytes

->m,r,u{"#{40032E-18*m*m/r/[36E2,56,8987E9,1E-3,4184E6,6276E7][u.sum*3%71%6]} "+u}

Uses a custom hash to index a LUT for the units (i * k mod m formula). The numbers were found using brute-force.

\$\endgroup\$
0
\$\begingroup\$

Excel, 94 bytes

Takes Mass from A1, Radius from B1, Unit in C1. Look up on 2*Code(Unit) + Length(Unit) modulo 11.

=4.0032E-15*A1^2/B1/CHOOSE(MOD(2*CODE(C1)+LEN(C1),11),,4184E5,,,6276E6,1E-4,89876E8,360,56)
\$\endgroup\$
0
\$\begingroup\$

Jelly,  59  54 bytes

Saved 5 bytes thanks to @ChartZBelatedly

I just wanted to try another weird method to convert the units. But the rest of the code is probably badly golfed.

⁵OẒḄ%9ị56,4184ȷ5,8987ȷ9,360,0,6276ȷ6,ȷ-4
²÷÷2498ȷ11÷¢⁵

Try it online!

How?

We build a 'signature' of a unit string out of the primality of its ASCII codes. We interpret it as a binary value and apply a modulo to get the final index in the lookup table.

⁵OẒḄ%9ị[...]    - helper link to convert the unit to a hardcoded constant
⁵               - the 3rd input        e.g. "kilotons"
 O              - to ASCII codes       --> [107, 105, 108, 111, 116, 111, 110, 115]
  Ẓ             - is prime?            --> [1, 0, 0, 0, 0, 0, 0, 0]
   Ḅ            - binary -> decimal    --> 128
    %9          - modulo 9             --> 2
      ị[...]    - get value from table --> 418400000

²÷÷2498ȷ11÷¢⁵   - main link taking the mass, the radius and the unit
²               - square the mass
 ÷              - divide by the radius
  ÷2498ȷ11      - divide by 2498e11
          ÷¢    - divide by the unit constant, invoking the helper link as a nilad
            ⁵   - append the unit

The helper link gives the following indices for each unit:

unit     | ASCII codes                     | is prime?       | bin -> dec | mod 9
---------+---------------------------------+-----------------+------------+------
J        | 74                              | 0               |      0     |   0
kilotons | 107,105,108,111,116,111,110,115 | 1,0,0,0,0,0,0,0 |    128     |   2
nukes    | 110,117,107,101,115             | 0,0,1,1,0       |      6     |   6
twinkies | 116,119,105,110,107,105,101,115 | 0,0,0,0,1,0,1,0 |     10     |   1
kWh      | 107,87,104                      | 1,0,0           |      4     |   4
kg       | 107,103                         | 1,1             |      3     |   3
\$\endgroup\$
2
  • \$\begingroup\$ The [ and ] are unnecessary. Additionally, the can be removed and the ÆP has a 1 byte alias: . Finally, if the number on the left of ȷ is 1, it can be omitted. -5 bytes \$\endgroup\$ Apr 4, 2021 at 15:51
  • \$\begingroup\$ @ChartZBelatedly Thank you! \$\endgroup\$
    – Arnauld
    Apr 4, 2021 at 20:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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