How much present did you get for Christmas?

Yes, how much, not how many...

As we all know, a large present is far better than a small one. Therefore, the value of the presents should always be measured in total volume, not number of presents, weight, or even combined price.

As it's frowned upon to compare the amount of presents one gets, you don't want a long script that's easily seen and read by others at the Christmas party. Therefore you need to keep the number of bytes in your script at a minimum.

Your task is simple: Create a program that takes a list of dimensions as input, on any suitable format, and outputs the combined volume of your presents. The dimension of each present will either be a set of three numbers, or a single number. If the input is three numbers (L, W, H), the present is a cuboid of dimensions L x W x H. If it's a single number (R), the present is a sphere of radius R.

Rules:

• It can be either a full program or a function
• The input can be in any convenient format
• If desirable, a sphere may be represented by a number followed by two zeros
• A cuboid will always have all non-zero dimensions.
• The output should be a single decimal number
• Additional output is accepted as long as it's obvious what the answer is
• Output must have at least two digits after the decimal point
• The output can be in standard form / scientific notation if the number is larger than 1000.
• In case your language doesn't have a Pi-constant, the answer should be accurate up to 9999.99.

Examples:

((1,4,3),(2,2,2),(3),(4,4,4))
197.0973    // (1*4*3 + 2*2*2 + 4/3*pi*3^3 + 4*4*4)

(5)
523.5988

(5,0,0)
523.5988


The Stack Snippet at the bottom of this post generates the catalog from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.

## Language Name, N bytes


where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

## Ruby, <s>104</s> <s>101</s> 96 bytes


If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

## Perl, 43 + 2 (-p flag) = 45 bytes


You can also make the language name a link which will then show up in the snippet:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


var QUESTION_ID=67027,OVERRIDE_USER=44713;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

• No lady gets hat in one of those funny cylindrical boxes? – manatwork Dec 18 '15 at 12:10
• @manatwork, no, all ladies will get bowler hats, and you can easily fit those in a sphere =P – Stewie Griffin Dec 18 '15 at 12:13
• I assume (5) is just partial example and our code only has to handle ((5)). – manatwork Dec 18 '15 at 12:51
• If our language of choice does not have a Pi constant, how much precision is required? – Dennis Dec 18 '15 at 13:26
• @manatwork, + and * are OK as long as they don't mean addition and multiplication (or other operations) in the language you're using. – Stewie Griffin Dec 18 '15 at 13:35

Jelly, 19 18 bytes

Zµ*3×1420÷339Ḣo@PS


Try it online!

Unfortunately, Jelly does not have a π constant yet, and the vectorizer doesn't handle floats properly.

To overcome these issues, instead of multiplying by 4π/3, we multiply by 1420 and divide by 339. Since 1420 ÷ 339 = 4.18879056… and 4π/3 = 4.18879020…, this is sufficiently precise to comply with the rules.

The newest version of Jelly could accomplish this task in 14 bytes, with better precision.

Zµ*3×240°Ḣo@PS


Try it online!

How it works

Zµ*3×1420÷339Ḣo@PS  Left argument: A, e.g., [[1, 2, 3], [4, 0, 0]]

Z                   Zip A; turn A into [[1, 4], [2, 0], [3, 0]].
µ                  Begin a new, monadic chain with zip(A) as left argument.
*3                Cube all involved numbers.
×1420           Multiply all involved numbers by 1420.
÷339       Divide all involved numbers by 339.
This calculates [[4.19, 268.08], [33.51, 0], [113.10, 0]]
Ḣ      Head; retrieve the first array.
This yields [4.19, 268.08].
P   Take the product across the columns of zip(A).
This yields [6, 0].
o@    Apply logical OR with swapped argument order to the results.
This replaces zeroes in the product with the corresponding
results from the left, yielding [6, 268.08].
S  Compute the sum of the resulting numbers.


The non-competing version uses ×240° instead of ×1420÷339, which multiplies by 240 and converts the products to radians.

q[x]=4/3*pi*x^^3
q x=product x
sum.map q


Usage example: sum.map q $[[1,4,3],[2,2,2],[3],[4,4,4]] -> 197.09733552923254. How it works: For each element of the input list: if it has a single element x calculate the volume of the sphere, else take the product. Sum it up. • Is this way of counting bytes generally valid? I would have said p=sum.map q (and then told to use p on a list of lists of numbers) – Leif Willerts Dec 19 '15 at 13:52 • @LeifWillerts: There's a recent topic on meta which allows unnamed functions that relay on global definitions. sum.map q is an unnamed function that depends on q, so I guess it's fine. – nimi Dec 19 '15 at 23:19 Pyth, 19 18 bytes sm|*Fd*.tC\ð7^hd3Q  1 byte thanks to Dennis Demonstration Input format is list of lists: [[1,4,3],[2,2,2],[3,0,0],[4,4,4]]  It simply multiplies the dimensions together to calculate the cube volume. If that comes out to zero, it calculates the sphere volume. The sphere constant, 4/3*pi is calculated as 240 degrees in radians. .t ... 7 converts an input in degrees to radians, and C\ð calculates the code point of ð, which is 240. Python 2, 86 70 bytes lambda i:sum(x[0]*x[1]*x[2]if len(x)>1 else x[0]**3*4.18879for x in i)  • I get your byte count as 86, how did you get yours? – wnnmaw Dec 18 '15 at 13:53 • Additionally, you can save bytes by just manually putting in a value for pi, you can use up to 3.14159265358979323 to break even – wnnmaw Dec 18 '15 at 13:54 • @wnnmaw I forgot to count the import -.- – TFeld Dec 18 '15 at 13:59 • I believe your hardcoded value for pi is a bit off :) – wnnmaw Dec 18 '15 at 15:45 • @wnnmaw That's not Pi; it's 4Pi/3. – Dennis Dec 18 '15 at 16:06 Mathematica, 34 bytes Tr[1.##&@@@(#/.{r_}:>{4r^3/3Pi})]&  An unnamed function which takes a nested list of lengths and returns the volume as a real number. We first replace single values with the volume of the corresponding sphere with /.{r_}:>{4r^3/3Pi}. Then we multiply up the contents of each list with 1.##&@@@. Finally we compute the sum as the trace of the vector with Tr[...]. JavaScript (ES6), 56 l=>l.map(([x,y,z])=>t+=y?x*y*z:x*x*x*4/3*Math.PI,t=0)&&t  The more sensible .reduce version is 1 byte longer l=>l.reduce((t,[x,y,z])=>t+(y?x*y*z:x*x*x*4/3*Math.PI),0)  • You could save a couple of bytes by using 4.11879 in place of 4/3*Math.PI, as that should be accurate enough to qualify. – ETHproductions Dec 20 '15 at 23:05 • @ETHproductions yes, but In case your language doesn't have a Pi-constant, and my language has a PI constant, so I don't know if it qualifies – edc65 Dec 21 '15 at 7:39 Python, 49 bytes lambda l:sum(a*b*c or a**3*4.18879for a,b,c in l)  Uses the representation of spheres as (a,0,0). Treated as a cuboid, this has volume 0, in which case the sphere volume is used instead. I'm not clear on how accurate the constant needs to be, so I hope this is enough. MATL, 20 bytes it!ptbw~)3^4*3/XT*hs  Input format is a matrix in which each row describes a cube or a sphere. A sphere is defined by only the first number in that row; the other two numbers are zero. So the first example from the challenge would be: [1 4 3; 2 2 2; 3 0 0; 4 4 4]  This uses the current release of the language, 2.0.2, which is earlier than this challenge. Examples: >> matl it!ptbw~)3^4*3/XT*hs > [1 4 3; 2 2 2; 3 0 0; 4 4 4] 197.0973355292326 >> matl it!ptbw~)3^4*3/XT*hs > [5 0 0] 523.5987755982989  Explanation: i % input matrix t! % duplicate and transpose: each object is now a column p % product of elements in each column t % duplicate b % bubble up top-third element in stack w % swap top two elements in stack ~ % logical 'not'. This gives logical index of speheres ) % reference () indexing. This is a logical-linear index to get sphere radii 3^4*3/XT* % formula for volume of spehere; element-wise operations h % horizontal concatenation s % sum  Prolog, 115 100 bytes Code: []*0. [[L,W,H]|T]*V:-W=0,X is 4*pi*L^3/3,T*Y,V is X+Y;X is L*W*H,T*Y,V is X+Y. p(L):-L*V,write(V).  Explained: []*0. [[L,W,H]|T]*V:-W=0, % When 2nd dimension is 0 X is 4*pi*L^3/3, % Calc volume of sphere T*Y, % Recurse over list V is X+Y % Sum volumes ; % When we have a cube X is L*W*H, % Calc cube volume T*Y % Recurse over list V is X+Y. % Sum volumes p(L):-L*V, % Get combined volume of list of lists write(V). % Print volume  Examples: p([[1,4,3],[2,2,2],[3,0,0],[4,4,4]]). 197.09733552923257 p([[5,0,0]]). 523.5987755982989  Try it online here Edit: saved 15 bytes by defining a dyadic predicate. Perl, 52 47 bytes s/,/*/g||s@$@**3*4.18879@,$\+=eval for/\S+/g}{  46 + 1 for -p (that's been common; let me know if it's different here and I'll update) Usage: put in a file and echo 1,4,3 2,2,2 3 4,4,4 | perl -p x.pl With comments: s/,/*/g # x,y,z becomes x*y*z || # if that fails, s@$@**3*1420/339@      # x becomes x**3 * 1420/339
,                      #
$\+=eval # evaluate the expression and accumulate for/\S+/g # iterate groups of non-whitespace }{ # -p adds while(<>){...}continue{print}; resets$_


update 47 Thanks to @Dennis for saving some bytes using this trick.

• s/,/*/g||s@$@**3*4.18879@,$\+=eval for/\S+/g;}{ saves a few bytes. – Dennis Dec 19 '15 at 16:51
• @Dennis Thanks! I tried with $\ before but resetting $_ cost as much. Still unclear as to why $_ is reset in a new block, though.. Is $_ block-local in while(<>){}? – Kenney Dec 19 '15 at 17:14
• Yes, $_ is the default variable of the current scope. In the END block, it is undefined. – Dennis Dec 19 '15 at 17:17 CJam, 24 21 bytes q~{3*)4P*3/*+3<:*}%:+  Test it here. Explanation q~ e# Read and evaluate input. { e# Map this block over the list of presents... 3* e# Repeat the list of lengths 3 times. This will expand cuboids to 9 elements e# and spheres to three copies of the radius. ) e# Pull off the last element. 4P*3/* e# Multiply by 4 pi / 3. + e# Add it back to the list of lengths. 3< e# Truncate to 3 elements. This is a no-op for spheres, which now have three e# elements [r r 4*pi/3*r] but discards everything we've done to cuboids, such e# that they're reduced to their three side lengths again. :* e# Multiply the three numbers in the list. }% :+ e# Sum all the individual volumes.  PowerShell, 67 Bytes ($args|%{($_,((,$_*3)+4.18879))[$_.count-eq1]-join'*'})-join'+'|iex  Some black magic happening here. I'll try to walk through it smoothly. We first take our input, expected as individual comma-delimited arrays e.g. (1,4,3) (2,2,2) (3) (4,4,4), and pipe that into a loop |%{}. Inside the loop, we first check whether $_, the particular array we're considering, has only one item and use that to index into an array (essentially a shorter if/else construction). If it's more than one item, suppose (1,4,3) as input, we execute the first half, which is simply to spit out the array via $_, such as (1,4,3). Otherwise, we create a new dynamic array consisting of the element three times with (,$_*3) and tack on an approximation of 4/3rd*Pi. For input (3), this will result in (3,3,3,4.18879) output.

Yes, PowerShell has a Pi constant, accessed via .NET call [math]::PI, but that's longer and I don't want to use it. :p

Regardless, we concatenate that output array with asterisks via -join'*', so "1*4*3". Once we're completely through the loop, we now have a collection of strings. We -join'+' all those together for our addition, and iex the expression to calculate the result.

Phew.

Ruby, 58 characters

->b{b.reduce(0){|t,s|a,b,c=*s;t+(c ?a*b*c :a**3*4.18879)}}


Sample run:

2.1.5 :001 ->b{b.reduce(0){|t,s|a,b,c=*s;t+(c ?a*b*c :a**3*4.18879)}}[[[1,4,3],[2,2,2],[3],[4,4,4]]]
=> 197.09733


Ruby, 50 characters

Improvement idea shamelessly stolen from edc65's JavaScript answer.

->b{t=0;b.map{|a,b,c|t+=c ?a*b*c :a**3*4.18879};t}


Sample run:

2.1.5 :001 > ->b{t=0;b.map{|a,b,c|t+=c ?a*b*c :a**3*4.18879};t}[[[1,4,3],[2,2,2],[3],[4,4,4]]]
=> 197.09733


Japt, 27 22 bytes

N®r*1 ª4/3*M.P*Zg ³} x


Takes input as space-separated arrays. Try it online!

How it works

N®   r*1 ª 4/3*M.P*Zg ³  } x
NmZ{Zr*1 ||4/3*M.P*Zg p3 } x

// Implicit: N = array of input arrays
NmZ{   }  // Map each item Z in N to:
Zr*1      //  Reduce Z with multiplication.
||4/3*M.P //  If this is falsy, calculate 4/3 times Pi
*Zg p3    //  times the first item in Z to the 3rd power.
x         // Sum the result.
// Implicit: output last expression


R, 70 bytes

function(l)sum(mapply(function(x)prod(x*!!1:3)*4.18879^is.na(x[2]),l))


Try it online!

Pip, 23 bytes

{$*a|4/3*PI*@a**3}MSg^s  There's a couple ways to give input to this program. It can take each present as a command-line argument of three space-separated numbers (which will need to be wrapped in quotes: pip.py present.pip "1 4 3" "3 0 0"). Alternately, specify the -r flag and give each present as a line of stdin consisting of three space-separated numbers. Try it online! How?  g is list of cmdline args (or lines of stdin, if using -r flag) s is space, PI is what it says on the tin (implicit) g^s Split each argument on spaces, so we have a list of lists { }MS Map this function to each sublist and sum the results:$*a                      Fold the list on * (i.e. take the product)
|                     Logical OR: if the above value is zero, use this value instead:
4/3*PI*              4/3 pi, times
@a            First element of the list
**3         Cubed
Autoprint the result


Perl 5, 142 bytes

Run with -p in the command line, and type numbers delimited with a comma, like so:

5,0,0 or (5,0,0)

would produce

523.598820058997

There is no pi keyword in Perl. This is, in most cases, accurate to the significant figures specified, however even if I typed in all the figures of pi I know, it wouldn't be very accurate for some calculations. So I left it with 3.1415. I'm unsure if this is acceptable or not.

Code:

@a=$_=~/(\d+,*)/g;$_=0;@n = map(split(/\D/),@a);for($i=0;$i<$#n;$i+=3){$x=$n[$i];$n[$i+1]==0?$_+=1420/339*$x**3:$_+=($x*$n[$i+1]*$n[\$i+2]);}


Edited for greater precision on the advice of Dennis, who is better at basic mathematics than I, and from a suggestion by MichaelT to save bytes whilst remaining precise.

• 1. How would you parse 1511? 2. 3.1415 is neither rounded properly nor sufficiently precise. If my calculations are correct, the error must not be greater than 0.0000017. 3. (4/3)*3.1415 can be replaced with a single float. – Dennis Dec 18 '15 at 15:54
• 1. The OP says we may assume trailing zero's for spheres (which is in fact the example input I provided), 2. I don't know what calculations you're using, but sure, I'll increase the precision, and 3. good suggestion, I missed that one. Thanks! – Codefun64 Dec 18 '15 at 15:58
• I don't have the resources in front of me at the moment, though I wonder if doing 1420/339 would give you a few bytes back with a reasonable approximation. (this is 4/3 * 355/113). The difference between the fraction and the value you have is is -8.49130615e-8 – user12166 Dec 18 '15 at 16:08
• @MichaelT That is the most interesting thing. Do you have a script that finds the smallest fractional representation of numbers? ;) – Codefun64 Dec 18 '15 at 16:09
• Codefun64 I just worked off of the other common approximation for pi. 22/7 isn't within enough tolerance, so I glanced at en.wikipedia.org/wiki/Approximations_of_%CF%80 an used the next one to see if it had a tolerance better than what @Dennis was asking for. – user12166 Dec 18 '15 at 16:11

Lua, 115 104 bytes

function f(a)b=0 for i=1,#a do c=a[i]b=b+(1<#c and c[1]*c[2]*c[3]or(4/3)*math.pi*c[1]^3)end return b end


Straightforward solution, I have to wrap the pseudo-ternary operation <condition> and <non-false> or <value if false> in parenthesis else b would sum with both areas.

Input must be in the form array={{1,4,3},{2,2,2},{3},{4,4,4}} and the result can be seen by executing print(f(array)).

05AB1E, 18 16 bytes

εDgi3m4žq*3/*]PO


Try it online.

Explanation:

ε                # Map each inner list of the (implicit) input to:
D               #  Duplicate the current inner list
gi             #  Is the length 1 (is it an R):
3m           #   Take the duplicated current item and take its cube
#    i.e. [3] → [27]
žq         #   PI
4*       #   Multiplied by 4
3/     #   Divided by 3
#    → 4.1887902047863905
*    #   And multiply it with the current cubed R
#    [27] and 4.1887902047863905 → [113.09733552923254]
]                # Close both the if and map
P               # Take the product of each inner list
#  i.e. [[1,4,3],[2,2,2],[113.09733552923254],[4,4,4]]
#   → [12,8,113.09733552923254,64]
O              # Take the total sum (and output implicitly)
#  i.e. [12,8,113.09733552923254,64] → 197.09733552923254


R, 38 36 bytes

function(x,y=4*pi/3*x,z=x)sum(x*y*z)


Uses default arguments to switch between the cases: with three arguments computes the product, and with one argument computes the sphere formula.

• do you need the f<- and the {}? – Giuseppe Sep 14 '18 at 17:09
• This code does not output correctly for the test case (5,0,0). Also, it does not accommodate the test case where there are multiple presents and the volumes need to be summed together. – Robert S. Sep 14 '18 at 20:11
• For (5,0,0) I get zero — is that not correct? Have edited to use sum (and removed some stuff that wasn't necessary per Giuseppe's suggestion) – JDL Sep 17 '18 at 7:29