Build this pyramid

21

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.

Misha Lavrov

Posted 2017-11-24T19:53:00.377

Reputation: 4 846

Answers

7

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).

user76250

Posted 2017-11-24T19:53:00.377

Reputation:

14 bytes – caird coinheringaahing – 2017-11-27T19:55:40.643

6

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;

Titus

Posted 2017-11-24T19:53:00.377

Reputation: 13 814

1Shouldn't you set P to X*70+Y instead? – Misha Lavrov – 2017-11-24T21:31:20.820

4

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!

PattuX

Posted 2017-11-24T19:53:00.377

Reputation: 361

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! – caird coinheringaahing – 2017-11-25T01:08:51.530

You could shorten a**2 to a*a to save a byte. – Luke – 2017-11-25T14:04:28.857

Wow, thats a simple one. Thanks. – PattuX – 2017-11-25T22:02:02.867

3

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);}

PrincePolka

Posted 2017-11-24T19:53:00.377

Reputation: 653

I think it should be z/y+1 in the 1-indexed version. – Titus – 2017-11-26T11:30:09.867

@Titus I don't see why, it complies with OP's question as is – PrincePolka – 2017-11-26T21:50:52.897

3

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!

xnor

Posted 2017-11-24T19:53:00.377

Reputation: 115 687

This also worked for C, thanks – PrincePolka – 2017-11-26T21:46:50.893

2

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.

Neil

Posted 2017-11-24T19:53:00.377

Reputation: 95 035

2

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!

Jonah

Posted 2017-11-24T19:53:00.377

Reputation: 8 729

(#~~:&a:)->a:-.~ – FrownyFrog – 2017-11-25T22:16:56.113

@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.

– Jonah – 2017-11-26T05:40:55.417

1

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.

Zgarb

Posted 2017-11-24T19:53:00.377

Reputation: 39 083