21
\$\begingroup\$

From Wikipedia, Gabriel's Horn is a particular geometric figure that has infinite surface area but finite volume. I discovered this definition in this Vsauce's video (starting at 0:22) where I took the inspiration for this problem.

You begin with a cake (a cuboid) of dimension \$x \times y \times z\$. In your first slice of the cake, you will end up with two smaller cakes of dimension \$\frac{x}{2} \times y \times z\$. Next, you will slice only one of the two pieces of cake you sliced previously, and so on. The picture below illustrates this:

enter image description here

Task

I cannot believe that the surface area can grow infinitely even if the volume of the cake stays the same and your task is to prove me that! However, I trust you and if you show me that the first 10 slices of the cake that the surface area is really growing, I will believe you.

You will receive the initial \$x \times y \times z\$ dimension of the cake as input and will output a list of 10 values referring to the total surface area of all cuboids after each consecutive slice.

Specs

  • The cake will always be sliced in half and it will always be sliced in the same dimension.
  • The surface area \$S\$ of a cuboid of dimension \$x \times y \times z\$ is: \$S = 2xy + 2xz + 2yz\$
  • The outputted list should first start with the surface area after no slices (that is, the cuboid original surface area), then 1 slice and so on.
  • The slices are going to be done in the \$x\$ dimension and the test cases below will assume this.
  • The surface area you have to calculate includes all pieces of cake sliced in previous iterations.
  • Input is flexible, read it however you see fit for you.
  • Standard loopholes are not allowed.
  • This is , so the shortest code in bytes wins

Test Cases

Format:
x, y, z --> output

1, 1, 1 --> [6, 8.0, 10.0, 12.0, 14.0, 16.0, 18.0, 20.0, 22.0, 24.0]
1, 2, 3 --> [22, 34.0, 46.0, 58.0, 70.0, 82.0, 94.0, 106.0, 118.0, 130.0]
3, 2, 1 --> [22, 26.0, 30.0, 34.0, 38.0, 42.0, 46.0, 50.0, 54.0, 58.0]
7, 11, 17 --> [766, 1140.0, 1514.0, 1888.0, 2262.0, 2636.0, 3010.0, 3384.0, 3758.0, 4132.0]
111, 43, 20 --> [15706, 17426.0, 19146.0, 20866.0, 22586.0, 24306.0, 26026.0, 27746.0, 29466.0, 31186.0]
1.3, 5.7, 21.2 --> [311.62, 553.3, 794.98, 1036.6599999999999, 1278.3400000000001, 1520.02, 1761.6999999999998, 2003.38, 2245.06, 2486.74]
\$\endgroup\$
7
  • 3
    \$\begingroup\$ Do we assume that the same part is always sliced? Your visual example seems to indicate this, as the rightmost part is always being sliced. Also, what do you mean "ihavenoidea"? This is not a bad idea. :) \$\endgroup\$
    – user100690
    May 20 at 16:04
  • \$\begingroup\$ Yes, @ophact! Well, I enjoy creating problems but I have no idea on how to properly golf, though :) \$\endgroup\$ May 20 at 16:10
  • \$\begingroup\$ Can we take input as [z, y, x] instead of [x, y, z]? \$\endgroup\$ May 20 at 16:41
  • 7
    \$\begingroup\$ Ummm... Given the explanation, the calculation seems more-or-less trivial - each iteration seems to just add 2yz to the previous area, no? \$\endgroup\$ May 20 at 16:43
  • 1
    \$\begingroup\$ Can we output in reverse order? \$\endgroup\$
    – Shaggy
    May 20 at 16:44

18 Answers 18

12
\$\begingroup\$

Jelly, 9 8 bytes

ṙ1×æ.Ɱ⁵Ḥ

Try it online!

Takes input as [z, y, x] as allowed by OP.

-1 byte thanks to Nick Kennedy

We calculate

$$2\left( \begin{matrix} z\times y \\ y\times x \\ x\times z\end{matrix} \right) \cdot \left( \begin{matrix} i \\ 1 \\ 1 \end{matrix} \right) = 2(yzi + yx+xz)$$

for each \$1 \le i \le 10\$

How it works

ṙ1×æ.Ɱ⁵Ḥ - Main link. Takes [z, y, x] on the left
ṙ1       - Rotate once left; [y, x, z]
  ×      - Product; [yz, xy, xz]
      ⁵  - Yield 10
     Ɱ   - For each integer 1 ≤ i ≤ 10:
   æ.    -   Dot product. Pad to [i, 1, 1] and calculate
              [yz, xy, xz] . [i, 1, 1] = yzi+xy+xz
       Ḥ - Double each
\$\endgroup\$
1
  • 4
    \$\begingroup\$ beat me to it and i had 14 lol. dot product is smart here \$\endgroup\$
    – hyper-neutrino
    May 20 at 16:19
8
\$\begingroup\$

Haskell, 37 bytes

(x#y)z=[2*(x*y+x*z+n*y*z)|n<-[1..10]]

Try it online!

The relevant function is (#), which takes as input x, y, z in this order and outputs the areas of the first 10 iterations.

\$\endgroup\$
7
\$\begingroup\$

R >= 4.1.0, 39 28 bytes

\(x,y,z)2*(1:10*y*z+x*y+x*z)

Try it online!

Note the TIO link has function in place of \ since TIO is running an older version of R. However, the functionality is identical.

A function taking x, y and z and returning a vector of the surface areas.

Saved 11 bytes by looking at Delfad0r’s Haskell answer (and so using a much similar formula with no non-operator functions!)

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

Zsh, 43 bytes

eval '<<<$[2*($1*$2+$1*$3+$2*$3*'{1..10}\)]

Try it online!

eval '...'{1..10}\)]: evaluate the command <<<$[2*($1*$2+$1*$3+$2*$3*N)] repeated with 1 to 10 in place of N. No semicolons needed, because <<< can be chained implicitly.

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

Factor, 56 bytes

[ 3dup [ * ] 2tri@ 10 [1,b] [ 4dup * + + 2 * nip ] map ]

Try it online!

Data flow combinator version thanks to @Bubbler

The interesting thing about Factor is you generally have four ways to approach golf: dataflow combinators, stack shuffling, local variables, and "sequence-y" (making heavy use of math.vectors and other sequence words). The thing about dataflow combinators is that despite keeping the data stack static and easier to reason about, they're almost always longer than the other three methods. However, once in a while they will win out over the others for some reason, and it's not always clear which will win until you give them all a try.

Factor, 57 bytes

[| x y z | 10 [1,b] [ y z * * x z * x y * + + 2 * ] map ]

Try it online!

Locals

Factor, 60 bytes

[ 10 [1,b] [ '[ 1 _ 1 ] over 1 rotate v* v. 2 * ] with map ]

Try it online!

"Sequence-y"

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Using 2tri@ instead of locals turned out to save a byte: [ 3dup [ * ] 2tri@ 10 [1,b] [ 4dup * + + 2 * nip ] map ]. \$\endgroup\$
    – Bubbler
    May 25 at 23:24
  • \$\begingroup\$ @Bubbler It's so rare for dataflow combinators to win out. That's so cool! \$\endgroup\$
    – chunes
    May 25 at 23:32
3
\$\begingroup\$

JavaScript (SpiderMonkey), 48 bytes

(x,y,z)=>{for(i=22;i-=2;)print(2*x*(y+z)+i*y*z)}

Try it online!

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

Mathematica, 29 bytes

2*(#*#2+#*#3+#2*#3*Range@10)&

Try it online!

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Welcome to Code Golf, and nice first answer! Be sure to check out our Tips for golfing in Mathematica page for ways you can golf your program. This looks to be a snippet, rather than a full program or a function, which is not allowed. I believe you can fix this by appending a & and changing x, y, z to #, #2 and #3 \$\endgroup\$ May 21 at 10:19
  • \$\begingroup\$ @cairdcoinheringaahing Got it, thanks! Should I convert the header to an active link that displays just the program name, like many other answers do and, if so, how do I do that? \$\endgroup\$
    – theorist
    May 21 at 17:12
  • \$\begingroup\$ Most people use the pre-generated format on Try it online!. If you click on the link symbol on this page, and scroll down to "Code Golf submission", it'll have it preformatted for you :) \$\endgroup\$ May 21 at 17:14
  • \$\begingroup\$ @cairdcoinheringaahing To ensure I'm understanding the site requirements you mentioned, let me ask about the Mathematica answer at codegolf.stackexchange.com/questions/225857/… (HarmonicNumber). Isn't that doubly problematic, because (a)it's not a program; and (b)the input isn't represented? I.e., given what you wrote, wouldn't that have to be HarmonicNumber[#,#2]&? \$\endgroup\$
    – theorist
    May 22 at 3:04
  • 1
    \$\begingroup\$ You can find the full rules by taking a browse through the policy tag on Meta, but in short: we allow either full programs or functions, that actually "take" an input (rather than e.g. assuming it's stored in a variable). As HarmonicNumber is a function that completes that challenge by itself (e.g. f = HarmonicNumber; Print[f[1, 2]] would work), the OP doesn't have to make it "more" of a function by adding something like &. A similar example would be "Get the sum of this list". Rather than doing lambda a:sum(a) (Python), you could just do sum \$\endgroup\$ May 22 at 7:43
2
\$\begingroup\$

JavaScript, 53 bytes

Output is a space delimited string with a leading space.

x=>y=>g=(z,n=11)=>--n?g(z,n)+` `+(n*y*z+x*y+x*z)*2:``

Try it online!

Or 52 bytes using commas instead of spaces:

x=>y=>g=(z,n=11)=>--n?g(z,n)+[,(n*y*z+x*y+x*z)*2]:[]

Try it online!

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

J, 23 bytes

(2*+/+i.@10*1&{)@:*1&|.

Try it online!

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

JavaScript (Node.js), 55 bytes

(x,y,z)=>[...Array(10)].map((_,i)=>2*(++i*y*z+x*y+x*z))

Try it online!

Someone will probably outgolf me with recursion, but I have not yet found a suitable way to do so yet. This is essentially just a port of most people's answers.


JavaScript (Node.js), 53 bytes

(x,y,z)=>[...Array(i=10)].map(_=>2*(x*y+x*z+y*z*i--))

Try it online!

Outputs in reverse order

\$\endgroup\$
1
  • \$\begingroup\$ Output can be reversed. \$\endgroup\$
    – Shaggy
    May 20 at 16:52
2
\$\begingroup\$

Python 3, 51 bytes

lambda x,y,z:[2*(x*y+x*z-~n*y*z)for n in range(10)]

Try it online!

-1 byte thanks to @dingledooper

\$\endgroup\$
2
  • 1
    \$\begingroup\$ @dingledooper but last testcase is non-integer \$\endgroup\$
    – tsh
    May 21 at 3:29
  • 1
    \$\begingroup\$ @tsh Ah thanks. 51 bytes is still possible, I think. \$\endgroup\$ May 21 at 4:20
2
\$\begingroup\$

C (gcc), 70 69 bytes

Saved a byte thanks to EliteDaMyth!!!

f(x,y,z,i)float x,y,z;{for(;++i<11;)printf("%f ",2*(x*y+x*z+i*y*z));}

Try it online!

Prints out the surface areas starting at the beginning.

\$\endgroup\$
1
  • \$\begingroup\$ @EliteDaMyth \$i\$ will be whatever's on the stack, but that's consistently \$0\$ on TIO. So even through it's UB, it works! Which makes it acceptable - thanks! :D \$\endgroup\$
    – Noodle9
    May 21 at 11:19
2
\$\begingroup\$

APL (Dyalog Unicode), 41 bytes

{(A[1]×⍳10)++/1↓A←2×⍵×1⌽⍵}

Try it online!

  • my 1st Apl answer, footer stolen.. Honestly I still can't completely understand it because haven't seen yet the SRC and THIS commands.
  • input as Y Z X vector .
A←2×⍵×1⌽⍵   U store in A input rotated once and multiplied by input and then doubled 
   Obtaining total a,b,c planes surfaces
+/1↓A   U sum of b,c planes which remains always the same
(A[1]×⍳10)+   U added to a plane multiplied by [1..10]range
\$\endgroup\$
2
\$\begingroup\$

Julia 1.x, 32 bytes

(x,y,z)->2(x*y.+x*z.+(1:10)*y*z)

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ nice first answer ! -3 bytes by using the @. macro Try it online! \$\endgroup\$
    – MarcMush
    May 24 at 22:39
  • \$\begingroup\$ -1 more byte by using x$(y,z)=... Try it online! \$\endgroup\$
    – MarcMush
    May 24 at 22:45
  • \$\begingroup\$ and -1 byte again with some reorganizing Try it online! \$\endgroup\$
    – MarcMush
    May 24 at 22:58
1
\$\begingroup\$

Charcoal, 16 bytes

IEχ⊗⁺Σ∕Πθθ×ιΠ…θ²

Try it online! Link is to verbose version of code. Takes an array [z, y, x] as input. Explanation:

  χ                 Predefined variable `10`
 E                  Map over implicit range
     Σ∕Πθθ          Half-area of initial cuboid
    ⁺               Plus
           ι        Number of cuts
          ×         Multiplied by
            Π…θ²    Half-area of each cut
   ⊗                Doubled
I                   Cast to string
                    Implicitly print
\$\endgroup\$
1
\$\begingroup\$

Ruby 2.7+, 39 bytes

->x,y,z{(1..10).map{2.*_1*y*z+x*y+x*z}}

Requires ruby 2.7+ for numbered arguments to work.

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

Raku, 63 bytes

{(^10 »*»([*] @_[1,2]) »+»[+] @_[0,0,1]Z*@_[1,2,2]) »*»2}

Hyper-operators galore here leveraging constant difference between consecutive slicings of 2*y*z:

  • ^10 generates 0..9 ...
  • »*» multiplies each integer in the sequence by ...
  • [*] @_[1,2] is y*z
  • »+» then adds to each of element in the sequence ...
  • [+] @_[0,0,1] Z* @_[1,2,2], which computes x*z + x*y + y*z
  • »*»2 then multiplies the resultant list by 2
\$\endgroup\$
1
\$\begingroup\$

Desmos, 28 bytes

f(x,y,z)=2(xz+xy+[1...10]yz)

Try It On Desmos!

Try It On Desmos! (Prettified)

\$\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.