16
\$\begingroup\$

Write a program that takes two numbers as its input. The first one is the number of dimensions - 0 for a dot, 1 for a straight line, 2 for a circle, 3 for a sphere. The second number is the radius of the object, or, if it's 1-dimensional, the number itself. Output 0 for 0 dimensions. The output is the length/area/volume of the object.

If we call the first number n, the second one r, and the output x, we get that:

  • for n = 0, x = 1

  • for n = 1, x = 2×r

  • for n = 2, x = r2×π

  • for n = 3, x = (4/3)×r3×π

  • and so on... if you want, though.

Notes:

  • Cases when one or both numbers are negative, or when the first number is not whole, don't need to be covered.

  • The program must not read from any file and the only input are those two numbers.

  • The output should use only numerals (e.g. not "14*pi"), and should be accurate to at least two decimal digits.

  • As for n = 0, you can output 0 if it makes the code shorter.

  • Extra swag for an answer covering even 4 and more-dimensional "spheres"!

  • It's , so the shortest answer in bytes wins!

Examples:

 1 1 -> 2

 2 3 -> 28,27

 3 1 -> 4,19

 3 4,5 -> 381,70

 1 9.379 -> 18.758

 0 48 -> 1
\$\endgroup\$
8
  • 2
    \$\begingroup\$ Yay! I love false MathJax equations in posts! \$\endgroup\$
    – user60199
    Nov 5, 2016 at 10:54
  • 1
    \$\begingroup\$ Not to critic, but I don't see how a line can be considered as a 1d circle... \$\endgroup\$
    – xem
    Nov 5, 2016 at 12:50
  • 10
    \$\begingroup\$ @xem Consider a circle as all points that are within a given distance from the center \$\endgroup\$
    – Luis Mendo
    Nov 5, 2016 at 13:11
  • 3
    \$\begingroup\$ Math types would call these "balls" of various dimensions. The set of points with distance from the origin == r is the sphere, the set of points with distance from the origin <= r is the ball. Then these are 0-ball = point, 1-ball = segment, 2-ball = disk, 3-ball = ball, 4-ball, 5-ball, et c. (listed as "n-ball = common name"). \$\endgroup\$ Nov 5, 2016 at 22:44
  • 3
    \$\begingroup\$ "Output 0 for 0 dimensions" and "for n = 0, x = 1" contradict each other. Could you please choose one (or clarify that both are allowed)? \$\endgroup\$ Nov 6, 2016 at 2:34

19 Answers 19

13
\$\begingroup\$

Mathematica, 18 bytes, up to ~168.15 trillion dimensions

Pi^(a=.5#)/a!#2^#&

Anonymous function. Takes two numbers as input, and returns an inexact number as output. Works with any number of dimensions. Outputs 1. for n = 0. Uses the formula from Volume of an n-ball on Wikipedia.

Explanation

We are attempting to compute πn/2/Γ(n/2 + 1)·Rn, or N[Pi^(n/2)/Gamma[n/2 + 1] R^n] in Mathematica. In our case, # (first argument) is n and #2 (second argument) is R. This leaves us with N[Pi^(#/2)/Gamma[#/2 + 1] #2^#] &, which can be golfed as follows:

N[Pi^(#/2)/Gamma[#/2 + 1] #2^#] &
Pi^(.5#)/Gamma[.5# + 1] #2^# &    (* replace exact with approximate numbers*)
Pi^(.5#)/(.5#)! #2^# &            (* n! == Gamma[n + 1] *)
Pi^(a=.5#)/a! #2^# &              (* replace repeated .5# *)
Pi^(a=.5#)/a!#2^#&                (* remove whitespace *)

and thus, our original program.

\$\endgroup\$
6
  • \$\begingroup\$ Nice answer - that was fast! Just for clarification: To how many digits is the output correct? How many dimensions it's possible to calculate? \$\endgroup\$
    – user60199
    Nov 5, 2016 at 11:42
  • \$\begingroup\$ @RudolfL.Jelínek It outputs to about 5 significant figures, and it works for all n up to 168,146,894,169,516 for r = 1 (albeit with less figures). \$\endgroup\$ Nov 5, 2016 at 11:49
  • \$\begingroup\$ @LegionMammal978 which formula? I'm quite certain you don't use the gamma function there \$\endgroup\$
    – Angs
    Nov 5, 2016 at 11:52
  • \$\begingroup\$ @Angs n! = Γ ( n + 1). \$\endgroup\$ Nov 5, 2016 at 11:54
  • 2
    \$\begingroup\$ Oh, ! works for non-integrals too. Using Mathematica for this almost feels like cheating… :) \$\endgroup\$
    – Angs
    Nov 5, 2016 at 11:59
7
\$\begingroup\$

Jelly, 13 bytes + extra swag

÷2µØP*÷!
ç×*@

Try it online!

Works for any dimension, so long as the fixed value of π yielded by ØP (3.141592653589793) is accurate enough.

How?

÷2µØP*÷! - Link 1: n, r
÷2       - n / 2
  µ      - monadic chain separation
   ØP    - π (3.141592653589793)
     *   - exponentiate: π^(n/2)
       ! - Pi(n/2): Gamma(n/2 + 1)
      ÷  - divide: π^(n/2) / Gamma(n/2 + 1)

ç×*@     - Main link: n, r
ç        - call last link (1) as a dyad: π^(n/2) / Gamma(n/2 + 1)
  *@     - exponentiate with reversed @rguments: r^n
 ×       - multiply: r^n * π^(n/2) / Gamma(n/2 + 1)
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Well done for beating Mathematica! \$\endgroup\$
    – CJ Dennis
    Nov 7, 2016 at 2:25
  • \$\begingroup\$ Congrats, you won! \$\endgroup\$
    – user60199
    Nov 10, 2016 at 17:36
6
\$\begingroup\$

JavaScript (ES6), 45 bytes + extra swag

Recursive formula from wikipedia, should work for any number of dimension

f=(n,r)=>n<2?n?2*r:1:f(n-2,r)*2*Math.PI*r*r/n
\$\endgroup\$
6
\$\begingroup\$

R, 75 40 38 bytes (plus extra swag)

Well, looks like I could golf this down by giving in and using the gamma function rather than recursive functions.

function(n,r)pi^(n/2)/gamma(n/2+1)*r^n

Defines an anonymous function to calculate the volume of an n-dimensional hypersphere of radius r.

Some examples:

1 1 -> 2

0 48 -> 1

2 3 -> 28.27433

3 4.5 -> 381.7035

7 7 -> 3891048

100 3 -> 122051813

Swagless solution, 38 34 bytes

For a few bytes less, you can have an anonymous function that only works for dimensions 1 to 3. Returns numeric(0) for n=0, and NA for n>3. (numeric(0) is a numeric vector of length 0; NA is for "not available".) Performance is otherwise identical to the general solution above.

function(n,r)c(1,pi,4/3*pi)[n]*r^n
\$\endgroup\$
1
  • 1
    \$\begingroup\$ ₊₁ for the SSSSSWWWWWAAAAAAAGGGGGGGGGG! \$\endgroup\$
    – user60199
    Nov 5, 2016 at 13:02
5
\$\begingroup\$

Haskell, 74 65 36 bytes + extra swag

0%r=1
1%r=2*r
n%r=2*pi*r^2/n*(n-2)%r

Recursive formula, works for all dimensions that can be presented exactly as a double-precision floating point number but will loop infinitely for non-integral dimensions. The old version for posteriority's sake:

n%r=(max 1$1-(-1)**n)*(2*pi)^(floor$n/2)*r**n/product[n,n-2..1.1]

Works for all dimensions. Uses the formula from the tau manifesto. product[n,n-2..1.1] is a double factorial hack that won't count zero for n==2

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

JavaScript, 61 51 49 43 bytes

0-3 dimensions are supported because there is no 4th dimension.

Thanks to @Hedi for saving 7 bytes

d=(n,r)=>r**n*(n<2?n+1:Math.PI*(n<3?1:4/3))

Creates function d. Then raises r to the nth power and then multiplies it with a number depending on n using ternary operators. Outputs 1 for n=0

Gives output to at least 2 decimal places (10+ dp)

Here's a snack snippet!

var N = document.getElementById("n");
var R = document.getElementById("r");
N.value="3";//default
R.value="4.5";//default
d=(n,r)=>r**n*(n<2?n+1:Math.PI*(n<3?1:4/3));
var b = document.getElementById("b");
b.onclick = function() {
  var s = document.getElementById("s");
  var n = document.getElementById("n").value;
  var r = document.getElementById("r").value;
  s.textContent = d(parseFloat(n),parseFloat(r));
}
span {border:1px solid black;padding:10px;font-size:30px;}
Value of n: <input id="n" type="number"></input>
Value of r: <input id="r" type="number"></input><br>
<button id="b">Calculate!</button><br><br><br>
<span id="s">THERE IS NO 4TH DIMENSION</span>

\$\endgroup\$
7
  • \$\begingroup\$ Beat my non-posted solution by... by a lot. +1! \$\endgroup\$
    – user60199
    Nov 5, 2016 at 12:07
  • 6
    \$\begingroup\$ what a dumb video… \$\endgroup\$ Nov 5, 2016 at 14:55
  • 1
    \$\begingroup\$ @SargeBorsch At least it proves my point :) \$\endgroup\$
    – user41805
    Nov 5, 2016 at 15:43
  • 2
    \$\begingroup\$ @SargeBorsch Haha yup dumb video - 0:40 3 dimensions that behave in the same way and one that behaves in a different way - At that point he seems to be saying there is a 4th dimension, but no 1st, 2nd or 3rd! \$\endgroup\$ Nov 5, 2016 at 23:35
  • 1
    \$\begingroup\$ @LevelRiverSt Well that was the first result I was on the web ¯\_(ツ)_/¯ \$\endgroup\$
    – user41805
    Nov 6, 2016 at 8:21
3
\$\begingroup\$

MATL, 17 bytes

3:^[2P4*P/3]*1hi)

This works up to 3 dimensions only. Inputs are in reverse order, that is: r, then n.

Try it online!

Consider r=3, n=2 as an example.

3:         % Push array [1 2 3]
           % STACK: [1 2 3]
^          % Take r implicitly, and raise it to [1 2 3] element-wise
           % STACK: [3 9 27]
[2P4*P/3]  % Push array [2 pi 4*pi/3]
           % STACK: [3 9 27], [2 pi 4*pi/3]
*          % Multiply element-wise
           % STACK: [6 28.2743 113.0973]
1h         % Append 1
           % STACK: [6 28.2743 113.0973, 1]
i)         % Input n and use it as modular index into the array. Display implicitly
           % STACK: 28.2743
\$\endgroup\$
2
\$\begingroup\$

Java/C/C++/C#, 69 67 bytes + extra swag!

Edit: Saved 2 bytes thanks to @AlexRacer

A dyadic function - first argument is number of dimensions, second is the radius of the n-ball.

float v(int n,float r){return n<1?1:n<2?2*r:6.283f*r*r*v(n-2,r)/n;}

Recursive formula for the volume of an n-ball: Vn=(2πr2Vn-2)n

Whoa! Java (my test language) beats Scala here, thanks to the terse ?: ternary syntax! This function is syntactically correct in all 4 languages in the heading, and I have tested it with C (MinGW GCC 5.4.0), & C# (VS Ultimate 2016, C# 6.0). I'm assuming that it will work in C++ too, so there. Since this function is pretty much library-independent, it should work in any C-like language with similar syntax.

\$\endgroup\$
2
  • \$\begingroup\$ Wow! I thought I'd never get a Java answer! Got it - thanks! And, as a bonus, it beat some answers and got the extra swag! ₊₁ \$\endgroup\$
    – user60199
    Nov 6, 2016 at 19:30
  • \$\begingroup\$ n==0 can be shortened to n<1 and also n==1 to n<2 \$\endgroup\$
    – AlexRacer
    Nov 6, 2016 at 20:47
2
\$\begingroup\$

Haskell, 52 bytes for tab indent 42 bytes + extra swag

Edit: Saved 10 bytes thanks to @WChargin

A dyadic curried function - first argument is number of dimensions, second is the radius of the n-ball.

v 0 r=1
v 1 r=2*r
v n r=2*pi*r*r*v(n-2)r/n

Recursive formula for the volume of an n-ball: Vn=(2πr2Vn-2)n

Save this as a separate script file and run with GHCi, with a function for testing v for output, e.g., show (v 3 4.5). I did not test this, please let me know if this doesn't work.

Old program with 6.2832 approximation for 2π replaced (50 bytes with tab indent):

let v 0 r=1
    v 1 r=2*r
    v n r=2*pi*r*r*(v(n-2)r)/n

This can be used with GHCi in multiline mode (using :set +m or enclosing the code between :{ & :}, the enclosures being on their own lines. Tester function required.

Static typing with full-program type inference comes into play here, allowing Haskell to do far better than Scala, and approaching Groovy, but not quite beating it thanks to the pattern match instead of a ternary, involving some character repetition.

\$\endgroup\$
3
  • \$\begingroup\$ 51 if using layout directly, 49 if you substitute 2*pi for 6.2832, and 47 if you drop the parentheses around the recursive call: let{v 0 r=1;v 1 r=2*r;v n r=2*pi*r*r*v(n-2)r/n} \$\endgroup\$
    – wchargin
    Nov 7, 2016 at 0:47
  • \$\begingroup\$ …but more typical scoring is to submit as a separate script file; drop the let{} and replace my semicolons with linefeeds to get just 42 bytes (without trailing newline). \$\endgroup\$
    – wchargin
    Nov 7, 2016 at 0:48
  • \$\begingroup\$ @WChargin I've been learning Haskell for a whole 2 days, so thanks for the pointers. I erred on the side of caution with the parentheses as I'm not sure about operator vs function call precedence in Haskell \$\endgroup\$ Nov 7, 2016 at 4:56
2
\$\begingroup\$

Racket 69 bytes (plus extra swag)

Uses recursive formula from https://en.wikipedia.org/w/index.php?title=Volume_of_an_n-ball&section=3#Recursions

Including suggestions by @wchargin

(define(v d r)(match d[0 1][1(* 2 r)][_(/(* 2 pi r r(v(- d 2)r))d)]))

Ungolfed (v=volume, d=dimensions, r=radius):

(define(v d r)
  (match d
    [0 1]
    [1 (* 2 r)]
    [_ (/ (*  2   pi   r   r   (v (- d 2) r)  )
          d)]
    ))

Testing:

(v 1 1)
(v 2 3)
(v 3 1)
(v 3 4.5)
(v 1 9.379)
(v 0 48)

Output:

2
28.274333882308138
4.1887902047863905
381.7035074111599
18.758
1
\$\endgroup\$
5
  • \$\begingroup\$ I highly doubt that this is legitimate: you're using the recursive function without counting its definition in the byte count. That is, the expression that you're scoring as 67 bytes is not valid Racket, as v is unbound (not to mention the other parameters). Surely you need to count the (define(v d r)) as well? This brings you up to 82 bytes… \$\endgroup\$
    – wchargin
    Nov 7, 2016 at 0:37
  • \$\begingroup\$ …but you can shave off four bytes from that by replacing your cond with nested if expressions, bringing you down to 78 bytes with (define(v d r)(if(= d 0)1(if(= d 1)(* 2 r)(*(/(* 2 pi(* r r))d)(v(- d 2)r))))). \$\endgroup\$
    – wchargin
    Nov 7, 2016 at 0:37
  • \$\begingroup\$ …and shave off three more by using a match to get (define(v d r)(match d[0 1][1(* 2 r)][_(*(/(* 2 pi(* r r))d)(v(- d 2)r))])). \$\endgroup\$
    – wchargin
    Nov 7, 2016 at 1:06
  • \$\begingroup\$ Thanks for great suggestions. I am including these in the answer. \$\endgroup\$
    – rnso
    Nov 7, 2016 at 1:19
  • \$\begingroup\$ @wchargin : I could reduce 9 more bytes by repositioning (v (- d 2) r) in formula and by using only "r r" instead of "(* r r)" since it is already in a multiplication formula. \$\endgroup\$
    – rnso
    Nov 8, 2016 at 0:54
1
\$\begingroup\$

Perl, 63 bytes + extra swag

@a=1..2;push@a,6.283/$_*@a[$_-2]for 2..($b=<>);say$a[$b]*<>**$b

Accepts two integers n and r, one at a time, then outputs the n-volume for given radius r of an n-sphere. When n = 0, V = 1, and when n = 1, V = 2r. All further dimensions are calculated by the following formula:

Recursive volume formula

Since rn is the radius's factor in every formula, I leave it out of the base calculation and only apply it at the end.

2π is approximated in the code by 6.283.

\$\endgroup\$
1
  • \$\begingroup\$ Nice and recursive, and ₊₁ for showing the recursive formula. \$\endgroup\$
    – user60199
    Nov 5, 2016 at 19:28
1
\$\begingroup\$

Scala, 53 bytes

{import math._;(n,r)=>pow(r,n)*Seq(1,2,Pi,Pi*4/3)(n)}

Sorry, no extra swag for me :(

Explanation:

{                     //define a block, the type of this is the type of the last expression, which is a function
  import math._;        //import everything from math, for pow and pi
  (n,r)=>               //define a function
    pow(r,n)*             //r to the nth power multiplied by
    Seq(1,2,Pi,Pi*4/3)(n) //the nth element of a sequence of 1, 2, Pi and Pi*4/3
}
\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 39 bytes, no swag

(n,r)=>[1,r+r,a=Math.PI*r*r,a*r*4/3][n]
\$\endgroup\$
1
\$\begingroup\$

Python 3, 76 72 68 bytes + extra swag!

Recursive solution with extra swag!
Returns 0 for n=0

from math import*
f=lambda n,r:n*r*2*(n<2or pi*r/n/n*(f(n-2,r)or 1))

Old approach (1 for n=1):

from math import*
f=lambda n,r:1*(n<1)or r*2*(n<2)or 2*pi*r*r/n*f(n-2,r)

Recursive formula from Wikipedia.

Try it online.

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

Python 3, 56 bytes + extra swag!

Straightforward with extra swag!

from math import*
lambda n,r:pi**(n/2)*r**n/gamma(n/2+1)

Standard formula.

Try it online

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

Scala, 81 79 bytes + extra swag!

Edit: Saved 2 bytes thanks to @AlexRacer

A dyadic function - first argument is number of dimensions, second is the radius of the n-ball.

def v(n:Int,r:Float):Float=if n<1 1 else if n<2 2*r else 6.2832f*r*r*v(n-2,r)/n

Recursive formula for the volume of an n-ball: Vn=(2πr2Vn-2)n

Scala's lack of type inference for return types of recursive functions and function parameters and verbose ternary syntax hurts quite a bit here :(

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

Groovy, 49 47 bytes + extra swag!

Edit: Saved 2 bytes thanks to @AlexRacer

A dyadic function - first argument is number of dimensions, second is the radius of the n-ball.

def v(n,r){n<1?1:n<2?2*r:6.2832*r*r*v(n-2,r)/n}

Recursive formula for the volume of an n-ball: Vn=(2πr2Vn-2)n

Dynamic Typing FTW!

My Scala and Java answers use the same logic, but with static typing so higher byte counts due to type annotations :(. However, Scala and Groovy allow me to omit the return and the semicolon, so that helps the byte count, unlike Java/C...

\$\endgroup\$
1
  • \$\begingroup\$ ₊₁ for the extra SWAG! \$\endgroup\$
    – user60199
    Nov 6, 2016 at 19:22
1
\$\begingroup\$

Lithp, 96 characters + extra swag

Line split in 2 for readability:

#N,R::((if (< N 2) ((? (!= 0 N) (* 2 R) 1)) ((/ (* (* (* (* (f (- N 2) R) 2)
        3.1416) R) R) N))))

Thinking I need to upgrade my parser to require less spaces. Code size would be cut down nicely, especially in that ((/ (* (* (* (* section.

Usage:

% n-circle.lithp
(
    (def f #N,R::((if (< N 2) ((? (!= 0 N) (* 2 R) 1)) ((/ (* (* (* (* (f (- N 2) R) 2) 3.1416) R) R) N)))))
    (print (f 1 1))
    (print (f 2 3))
    (print (f 3 1))
    (print (f 3 4.5))
    (print (f 1 9.379))
    (print (f 0 48))
)

#./run.js n-circle.lithp
2
28.274333882308138
4.1887902047863905
381.7035074111598
18.758
1

Thanks to Rudolf for shaving a few bytes off.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ What about shortening "3.141592653589793" to "3.1416", saving 11 bytes and still fitting into the rules? \$\endgroup\$
    – user60199
    Nov 8, 2016 at 13:40
1
\$\begingroup\$

CJam (27 bytes with extra credit)

{1$_[2dP]*<f*\,:)-2%./1+:*}

Online test suite. This is an anonymous block (function) which takes arguments d r on the stack and leaves the result on the stack.

Dissection

The general n-dimensional formula can be rewritten as

$$\frac{2^{\left\lceil\frac{d}{2}\right\rceil}\pi^{\left\lfloor\frac{d}{2}\right\rfloor} r^d}{d!!}$$

{            e# Begin block: stack holds d r
  1$_[2dP]*< e#   Build a list which repeats [2 pi] d times and take the first d elements
  f*         e#   Multiply each element of the list by r
  \,:)-2%    e#   Build a list [1 ... d] and take every other element starting at the end
  ./         e#   Pointwise divide. The d/2 elements of the longer list are untouched
  1+:*       e#   Add 1 to ensure the list is non-empty and multiply its elements
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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