# CGAC2022 Day 1: Let's build a chocolate pyramid!

Following last year's event, we're doing Code Golf Advent Calendar 2022!

On each day from today (Dec 1) until Christmas (Dec 25), a Christmas-themed challenge will be posted, just like an Advent calendar. It is a free-for-all and just-have-fun-by-participation event, no leaderboards and no prizes for solving them fast or solving them in the shortest code. More details can be found in the link above.

I've got an infinite supply of two kinds of weirdly shaped chocolate:

• White chocolate, a square pyramid of side lengths 1
• Dark chocolate, a regular tetrahedon of side lengths 1

To celebrate the upcoming Christmas, I want to assemble them into a giant chocolate pyramid. When the base of the pyramid is a rectangle of size $$\R \times C\$$, the process to build such a pyramid is as follows:

1. Fill the floor with $$\RC\$$ copies of White chocolate.
2. Fill the gaps between White chocolate with Dark chocolate.
3. Fill the holes between Dark chocolate with White chocolate. Now the top face is a rectangle of size $$\(R-1) \times (C-1)\$$.
4. Repeat 1-3 until the top face has the area of 0.

The diagram below shows the process for $$\2 \times 3\$$. It takes 8 White and 7 Dark chocolate to complete the first floor, and 10 White and 8 Dark for the entire pyramid. Given the width and height of the base rectangle, how many White and Dark chocolate do I need to form the chocolate pyramid?

You may assume the width and height are positive integers. You may output two numbers in any order.

Standard rules apply. The shortest code in bytes wins.

## Test cases

(width, height) -> (white, dark)
(2, 3) -> (10, 8)
(10, 10) -> (670, 660)
(10, 1) -> (10, 9)

• Can we create 2 separate functions, one for black chocolates one for white chocolates? Dec 1, 2022 at 6:31
• @mousetail I'll allow it. Dec 1, 2022 at 6:45

# Vyxal, 14 bytes

gʁ$vεƛΠε∑;:›"Ṡ  Try it Online! The main observation here is that the amount of white chocolate $$\w\$$ and dark chocolate $$\d\$$ in a layer of size (a, b) is: $$w = ab +(a-1)(b-1) = 2ab - a - b + 1\\ d = (a-1)b+(b-1)a = 2ab - a - b$$ In other words, the difference between white chocolate and dark chocolate for a layer is 1  ʁ # Range from 0 to... g # Minimum dimension of input$vε          # Subtract each from the input, creating a list of pairs of bases
ƛ   ;     # Over each base pair [a, b]
Π        # Product ab
ε       # Take the absolute difference - [ab - a, ab - b]
∑      # Sum
:›"  # Create an incremented pair for white
Ṡ # Sum each into the final amounts


# Desmos, 4746 37 bytes

-1 byte thanks to emanresu A

-9 bytes (!!!) thanks to alephalpha

N=min(h,w)
f(w,h)=Nhw-N(NN+2)/3+[N,0]


$$\f(w,h)\$$ takes in the width $$\w\$$ and the height $$\h\$$ and returns a two-element list, with the number of white chocolates in the first element and the number of dark ones in the second element.

Try It On Desmos!

Made my own closed form formula because I figured it would be fun :)

For those who are really curious, here’s some of the scratch work for how I came up with this formula (warning: it’s completely unreadable :P): Scratch work

• You can save a byte by factoring out a N - f(w,h)=N(2/3(NN-1)-Nh-Nw+2hw+[1,0]) Dec 1, 2022 at 4:08
• @emanresuA nice spot! Will update my code Dec 1, 2022 at 4:17
• 2/3(NN-1)-Nh-Nw+2hw -> hw-(NN+2)/3. In fact, since N=min(h,w), Nh+Nw is just hw+NN. Dec 1, 2022 at 4:49
• @alephalpha wtf how did you even spot that.... i'm shocked. updating rn Dec 1, 2022 at 7:04

# PARI/GP, 41 bytes

f(r,c)=if(r*c,[t=r*c+r--*c--,t-1]+f(r,c))


Attempt This Online!

# PARI/GP, 41 bytes

f(r,c)=m=min(r,c);[t=1+3*r*c-m^2,t-3]*m/3


Attempt This Online!

f(r,c)=m=min(r,c);[t=r*c*m+m/3-m^3/3,t-m]


Attempt This Online!

Using the closed form formula.

# R, 42 39 bytes

Edit: -3 bytes thanks to @Giuseppe.

\(r,c)-c(0,m<-min(r,c))+r*c*m+m/3-m^3/3


Attempt This Online!

• 39 bytes; there are a couple of different ways of getting to 39 but this is the one I thought of first. Dec 1, 2022 at 16:04

# Ruby, 41 40 bytes

-1 byte thanks to Sisyphus

->a{r,c=a.sort
[t=r/3+c*r*r-r**3/3,t-r]}


Attempt This Online!

• r**2 is r*r Dec 1, 2022 at 2:02

# C (GCC), 7672 70 bytes

• -4 bytes thanks to Conor O'Brien
• -2 bytes thanks to Keven Cruijssen
#define C(n,c)n(a,b){a=a*b?c*--b+n(a,b):0;}
C(f,a*b+--a)C(g,~-a*b+a--)


Attempt This Online!

f(a,b) returns the number of black chocolates while g(a,b) the number of white chocolates.

• I believe a&&b in each function can be a*b for -2 bytes. You can also use a macro to abstract out most of the boilerplate between the two functions and a creative rewrite, if I'm not mistaken. Attempt This Online! Dec 1, 2022 at 7:28
• (a-1) can be ~-a (relevant tip). Dec 1, 2022 at 8:12
• 57 bytes But I think your implementation is much more interesting!
– jdt
Dec 1, 2022 at 15:18

# Charcoal, 20 19 bytes

Ｉ⁺ΣＥ⌊θΣ⁻Π⁻θι⁻θι⟦⌊θ⁰


Try it online! Link is to verbose version of code. Takes input as a tuple or list of (rows, columns). Explanation:

     θ              Input tuple
⌊               Minimum
Ｅ                Map over implicit range
θ         Input tuple
⁻          Vectorised minus
ι        Current value
Π           Take the product
⁻            Minus
θ      Input tuple
⁻       Vectorised minus
ι     Current value
Σ             Take the sum
Σ                 Take the sum
⟦    List of
θ  Input tuple
⌊   Minimum
⁰ Literal integer 0
Ｉ                   Cast to string
Implicitly print


Edit: Saved 1 byte by porting @Ausername's formula. The best closed form formula I could find was 22 bytes, but adapting one of @alephalpha's versions saves 1 byte:

Ｉ⁻⁻×Πθ⌊θ÷⁻Ｘ⌊θ³⌊θ³⟦⁰⌊θ


Try it online! Link is to verbose version of code. Takes input as a tuple or list of (rows, columns). Explanation:

     θ                  Input tuple
Π                   Product
×                    Multiplied by
θ                Input tuple
⌊                 Minimum
⁻                     Subtract
θ           Input tuple
⌊            Minimum
Ｘ             Raised to power
³          Literal integer 3
⁻              Subtract
θ        Input tuple
⌊         Minimum
÷               (Integer) Divide by
³      Literal integer 3
⁻                      Vectorised subtract
⟦      List of
⁰     Literal integer 0
θ   Input tuple
⌊    Minimum
Ｉ                       Cast to string
Implicitly print


# Jelly, 14 bytes

_ⱮṂ‘PḤ_SƲ€S;ṂÄ


A monadic Link that accepts a list of two integers, the base dimensions, and yields a pair of integers, [dark, white].

Try it online!

## 16 bytes

Probably  beatable with a constructive method, but I like it.

Ṃð‘c3×4+²×IAʋ;⁸Ä


A monadic Link that accepts a list of two integers, the base dimensions, and yields a pair of integers, [dark, white].

Try it online!

### How?

Ṃð‘c3×4+²×IAʋ;⁸Ä - Link: Dimensions
Ṃ                - minimum (Dimensions)
ð               - start a new dyadic chain - f(M=that, Dimensions)
‘              - increment (M)
c3            - choose three -> (M-1)th triangular pyramidal number
×4          - times four (call this Q)
²        -   square (M)
I      -   forward differences (Dimensions) -> [Height-Width]
×       -   multiply -> [M*M*(Height-Width)]
A     -   absolute value -> [M*M*|Height-Width|]
+         - (Q) add (that) -> [dark piece count]
⁸  - chain's left argument -> M
;   - (dark piece count) concatenate (M) -> [dark piece count, M]
Ä - cumulative sums -> [dark piece count, white piece count]


# 05AB1E, 13 bytes

WÝ¨€-DPαOD>‚O


Port of @emanresuA's Vyxal answer, so make sure to upvote him/her as well!

Input as a pair $$\[width,height]\$$; output as a pair $$\[dark,white]\$$.

Explanation:

W             # Get the minimum of the (implicit) input-pair
Ý            # Pop and push a list in the range [0,min]
¨           # Remove the last item to make the range [0,min)
€-         # Subtract each from the (implicit) input-pair
D        # Duplicate this list of pairs
P       # Get the product of each inner pairs
α      # Get the absolute difference with the values in the pairs
O     # Sum each inner pair
D    # Duplicate this list
>   # Increase each inner value by 1
‚  # Pair the two lists together
O # Sum each inner list
# (after which this pair is output implicitly as result [dark,white])


# Pyth, 20 bytes

_-h=SQ
sm+*FQ*F=tMQh


Try it online!

Takes (width, height), outputs (white, dark)

### Explanation

   =SQ            sort the input, set to Q
_-h               output dark - min(Q)

s                 sum of
m          hQ    run min(Q) times:
*FQ             product of elements of Q
=tMQ       decrement each element of Q
*F           product of elements of Q


# Python 3, 83 bytes:

f=lambda r,c,w=0,d=0:f(r-1,c-1,w+r*c+(r-1)*(c-1),d+r*(c-1)+c*(r-1))if r*c else(w,d)


Try it online!

• All (r-1) and (c-1) can be ~-r and ~-c respectively (relevant tip). Dec 1, 2022 at 8:09
• @KevinCruijssen nice. That's -8 right there. Dec 3, 2022 at 5:00

# JavaScript (ES7), 40 bytes

Uses the closed form formula from alephalpha's answer.

Expects (w)(h).

w=>h=>[n=w*h*(w<h?w:w=h)+(w-w**3)/3,n-w]


Try it online!

# Python, 50 bytes

lambda p,q:(y:=(x:=min(p,q))*(3*p*q+1-x*x)//3,y-x)


Attempt This Online!

Same closed formula (@alephalpha's) everybody is using.

# Lil, 59 bytes

on f x do
r:min x
t:(r/3)+(r*r*max x)-(r^3)/3
t,t-r
end


Try it online!

Same as alephalpha.

# Pip-p, 26 bytes

Y Ngy*a*b-y*(y*y+2)/3+[y0]


Try It Online!

• 24 bytes Dec 5, 2022 at 21:15

# APL(Dyalog Unicode), 15 bytes SBCS

⌊××+3÷⍨1 ¯2-⌊×⌊


Try it on APLgolf!

Closed form formula from alephalpha's PARI/GP answer.

# Raku, 49 bytes

{my (\r,\c)=.sort;my \t=-r**3/3+r/3+c*r*r;t,-r+t}


Try it online!

# Perl 5, 68 + 3 (-pla option) = 71 bytes

($i,$j)=@F;{$d+=$k=$i*$j*2-$i---$j--;$w+=$k+1;$i*$j&&redo}$_="$w \$d"


Try it online!

# x86-64 machine code, 26 bytes

92 39 F0 73 01 96 6A 03 59 F7 E1 29 F0 F7 E6 F7 E6 01 F0 F7 F1 AB 29 F0 AB C3


Try it online!

Following the standard calling convention for Unix-like systems (from the System V AMD64 ABI), this takes in RDI an address at which two 32-bit integers will be consecutively placed, for the white number and the dark number, in that order; and takes the width and height in ESI and EDX.

In assembly:

f:  xchg edx, eax    # Switch one argument into EAX.
cmp eax, esi     # Compare the two arguments.
jae s            # Jump if EAX holds the higher value.
xchg esi, eax    # Otherwise, exchange the values.
s:                   # (Now, EAX holds the higher value (which we will call m)
#   and ESI holds the lower value (which we will call n).)
push 3; pop rcx  # Set ECX to 3.
mul ecx          # Multiply EAX by ECX (3), producing 3m.
# (Also, the high half of the product goes in EDX.)
sub eax, esi     # Subtract ESI (n) from EAX, producing -n+3m.
mul esi          # Multiply EAX by ESI (n), producing -n²+3mn.
mul esi          # Multiply EAX by ESI (n), producing -n³+3mn².