22
\$\begingroup\$

Your pyramid

The pyramid I want you to build is made entirely of cubes. It has 24 layers, and the Nth layer from the top contains N2 cubes arranged in an N by N square. The pyramid looks like this:

The pyramid

To build the pyramid, you will need a supply of cubes. You are given 4900 cubes arranged in a 70 by 70 square that looks like this:

The square

(Okay, I admit that the picture of the square is entirely unnecessary.)

Since 12 + 22 + 32 + ... + 242 = 702, you have exactly the right number of cubes to build the pyramid. All you have to do is tell me where each cube should go.

Your task

You should pick an arbitrary bijection between the cubes in the square and the cubes in the pyramid. (It would be nice if your answer said which of the 4900! different bijections you're using.)

Then, write a function or program that does the following:

  • Given the location of a cube in the 70 by 70 square (as a pair of coordinates (X,Y)),
  • Output its location in the pyramid (as a triple of coordinates (A,B,C)).

The input and output coordinates can all be either 0-indexed or 1-indexed. Assuming 1-indexed, your input (X,Y) will be a pair of integers between 1 and 70. Your output (A,B,C) will be a triple of integers; A should be the layer counting from the top (between 1 and 24) and (B,C) should be the coordinates of that cube within that layer (between 1 and A).

For example:

  • the top cube of the pyramid has coordinates (1,1,1).
  • The four corners of the base of the pyramid have coordinates (24,1,1), (24,1,24), (24,24,1), and (24,24,24).
  • If you decide to place the corners of the square at the corners of the pyramid, then on input (70,1) you might give the output (24,24,1).

You may assume you will only be given valid coordinates (X,Y) as input. Correctness is entirely determined by the following rule: two different valid inputs should always give two different valid onputs.

This is : the shortest code wins.

\$\endgroup\$
0

8 Answers 8

7
\$\begingroup\$

Jelly, 15 14 bytes

24p;€$€Ẏ
ḅ70ị¢

Try it online!

This is fairly simple: we construct the list of coordinates of cubes within the pyramid as an actual list. Then all we need to do is biject the input coordinates within the square into an index within the list, which is trivial to do via base conversion.

This submission works either as a full program (taking the coordinates as [x, y] via the first command line argument and outputting on standard output), or as a function, implicitly named 2Ŀ.

Explanation

Constructing the list

We start with the number 24, which is interpreted as a range from 1 to 24 inclusive (because we're trying to use it as though it were a list). Then we iterate over it; that's what the last in the program does. For each element n of the list:

  • We construct the list of pairs x, y where each element comes from 1..n; p constructs a list of pairs given two sets of elements, and because only one value is available here (n), it's implicitly used for both sets, which both therefore become a list from 1..n.
  • We append n (again, the only value we have available) to each element of the list (;€).
  • In order to make the second apply both of these operations to each n (i.e. to create a loop containing two instructions), we use $ to group the two instructions into one.

Finally, we use to flatten the list by one stage, in order to get a list that simply contains all the coordinates in order. It starts like this:

[1, 1, 1], [1, 1, 2], [1, 2, 2], [2, 1, 2], [2, 2, 2], [1, 1, 3], [1, 2, 3], [1, 3, 3], [2, 1, 3], [2, 2, 3], [2, 3, 3], [3, 1, 3], [3, 2, 3], [3, 3, 3], [1, 1, 4], [1, 2, 4], [1, 3, 4], [1, 4, 4], [2, 1, 4], [2, 2, 4], [2, 3, 4], [2, 4, 4], [3, 1, 4], [3, 2, 4], [3, 3, 4], [3, 4, 4], [4, 1, 4], [4, 2, 4], [4, 3, 4], [4, 4, 4], …

and ends with [24, 24, 24].

Indexing the list

We start by converting the input coordinates to a number by interpreting them as a base 70 integer: ḅ70. This gives us a value in the range 71 to 4970 inclusive; all these values are unique mod 4900. indexes into the list modulo the length of the list, so [1, 1] will give us the 71st element, [1, 2] the 72nd element, all the way up to [70, 70] which gives us the 70th element (i.e. the element before the answer for [1, 1]). Finally, we just need a ¢ to tell us which list to index (in this case, it's the list specified by the previous line; that's what ¢ does, run the previous line with no arguments).

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

PHP, 75 82 78 bytes

0-indexed:

set P=X*70+Y then reduce P by A2 while walking down to the correct layer. A-1; P/A; P%A - done.

(reversed: while incrementing A to the correct layer: P=P+A2 then P=P+A*B+C --> X=P/70, Y=P%70)

for($p=$argv[1]*70+$argv[2];$p>=++$a**2;$p-=$a**2);echo$a-1,_,$p/$a|0,_,$p%$a;

Run with php -nr '<code>' <X> <Y>; prints A_B_C.

1-indexed, 82 bytes:

for($p=$argv[1]*70+$argv[2]-71;$p>++$a**2;$p-=$a**2);echo$a,_,$p/$a+1|0,_,$p%$a+1;
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Shouldn't you set P to X*70+Y instead? \$\endgroup\$ Commented Nov 24, 2017 at 21:31
4
\$\begingroup\$

Python, 80 73 72 bytes

First submission, don't be too harsh q:

0-indexed

lambda x,y:[(a-1,b//a,b%a)for a in range(25)for b in range(a*a)][70*x+y]

Creates a list of length 4900 with all pyramind coordinates and returns a different list entry for each input.

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ Welcome to the site and nice first post! There are plenty of Python golfers who'd be willing to try to golf your solution down around here, and I hope you enjoy PPCG! \$\endgroup\$ Commented Nov 25, 2017 at 1:08
  • \$\begingroup\$ You could shorten a**2 to a*a to save a byte. \$\endgroup\$
    – Luke
    Commented Nov 25, 2017 at 14:04
  • \$\begingroup\$ Wow, thats a simple one. Thanks. \$\endgroup\$
    – PattuX
    Commented Nov 25, 2017 at 22:02
3
\$\begingroup\$

Python 2, 64 bytes

x,y=input()
n=-70*x-y
i=1
while n<0:i+=1;n+=i*i
print~-i,n/i,n%i

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ This also worked for C, thanks \$\endgroup\$ Commented Nov 26, 2017 at 21:46
3
\$\begingroup\$

C 89 , 87 , 82 , 71 bytes

Took xnor's Python solution, and removed the linebreak

p(x,y){for(x=-70*y-x,y=1;x<0;x+=++y*y);printf("%d %d %d",~-y,x/y,x%y);}

0-indexed

z;p(x,y){for(x+=y*70+1,y=z=0;z<x;z+=++y*y);z-=x;printf("%d %d %d\n",y-1,z/y,z%y);}

1-indexed

z;p(x,y){for(x+=~-y*70,y=z=1;z<x;z+=++y*y);z-=x-y;printf("%d %d %d\n",y,z/y,z%y+1);}
\$\endgroup\$
2
  • \$\begingroup\$ I think it should be z/y+1 in the 1-indexed version. \$\endgroup\$
    – Titus
    Commented Nov 26, 2017 at 11:30
  • \$\begingroup\$ @Titus I don't see why, it complies with OP's question as is \$\endgroup\$ Commented Nov 26, 2017 at 21:50
2
\$\begingroup\$

Batch, 103 bytes

@set/an=%1*70+%2,i=0
:l
@set/an-=i*i,j=i,i+=1,k=n%%i,l=n/i
@if %l% geq %i% goto l
@echo %j% %k% %l%

0-indexed. Works through each layer starting from the top.

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

J, 37 bytes

-4 bytes thanks to FrownyFrog

(a:-.~,(<:,&.>{@;~&i.)"0 i.25){~70&#.

Fairly straightforward translation of the Jelly method into J. Uses 0 indexing. The top pyramid square is the first. The bottom right corner of the base is the last.

The majority of the code is boilerplate to produce the triple indexed list as a constant. Finding the correct element within that list based on the 2 element input is simply a matter of translating from base 70 with 70&#.

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ (#~~:&a:)->a:-.~ \$\endgroup\$
    – FrownyFrog
    Commented Nov 25, 2017 at 22:16
  • \$\begingroup\$ @FrownyFrog Thanks. As happens often to me in J, I've used that trick before and forgot about it in this case. Btw, you may be interested in this question, which was inspired by this problem. \$\endgroup\$
    – Jonah
    Commented Nov 26, 2017 at 5:40
1
\$\begingroup\$

Husk, 13 bytes

!foEG▲π3Π4B70

Try it online! Indices start from 1.

Explanation

Like some other answers, I construct the full list of pyramid coordinates and simply index into it. I do this by listing all triples [A,B,C] where the numbers are between 1 and 24 (expressed as 4! to save a byte) and keeping those for which A >= max(B,C).

!foEG▲π3Π4B70  Implicit input: a list of two numbers.
          B70  Interpret in base 70.
!              Modular index into the following list:
        Π4      Factorial of 4: 24
      π3        Take range and 3-fold Cartesian power: [[1,1,1],[1,1,2],..,[24,24,24]]
 f              Filter by
  oE            all values are equal
    G▲          in cumulative reduce by maximum.
\$\endgroup\$

Your Answer

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

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