Caixa de areia
Para os propósitos da tarefa atual, um cubo de comprimento unitário é renderizado em projeção oblíqua com símbolos ASCII da seguinte maneira:
+-----+
/ /|
+-----+ |
| | +
| |/
+-----+
+
para os vértices.-
para as arestas X. O comprimento da unidade ao longo de X é representado por cinco-
entre dois vértices.|
para as bordas em Y. O comprimento da unidade ao longo de Y é representado por dois|
entre dois vértices./
para as arestas Z. O comprimento da unidade ao longo de Z é representado por um/
entre dois vértices.- Os vértices são desenhados apenas onde todos os três planos se cruzam.
- As arestas são desenhadas apenas onde exatamente dois planos se cruzam.
Quando uma face de unidade é extrudada, ela é deslocada pelo comprimento da unidade de sua posição original e quatro novas arestas são criadas para cada direção (positiva e negativa).
Você pode pensar na extrusão como desenhar os eixos de um sistema de coordenadas cartesianas 3D em que cada eixo é representado como um cuboide com seção transversal 1x1 e comprimento n
distante de (0,0,0)
Extrudado por 1 ao longo de X:
+-----------------+
/ /|
+-----------------+ |
| | +
| |/
+-----------------+
Tarefa
Dados três números para os eixos XYZ, faça a extrusão simétrica das faces de um cubo de unidade pelas quantidades indicadas e renderize o resultado com os símbolos ASCII, conforme especificado acima.
Entrada
x, y, z - números não negativos - comprimentos de extrusão para os respectivos eixos. 0 significa que não há extrusão. A entrada pode ser três números, uma lista de três números, um triplo, uma string ou qualquer coisa que seja conveniente para você.
Saída
O desenho ASCII do cubo após a extrusão. Os espaços de espera à esquerda e à direita são permitidos.
Casos de teste
X Y Z
0 0 0
+-----+
/ /|
+-----+ |
| | +
| |/
+-----+
1 0 0
+-----------------+
/ /|
+-----------------+ |
| | +
| |/
+-----------------+
0 0 1
+-----+
/ /|
/ / |
/ / +
/ / /
/ / /
+-----+ /
| | /
| |/
+-----+
1 1 0
+-----+
/ /|
+-----+ |
+---| | +-----+
/ | |/ /|
+-----+ +-----+ |
| | +
| |/
+-----+ +-----+
| | +
| |/
+-----+
2 0 1
+-----+
/ /|
+-----------+ +-----------+
/ /|
+-----------+ +-----------+ |
| / /| | +
| +-----+ | |/
+---------| | +-----------+
| |/
+-----+
1 1 1
+-----+
/ /|-+
+-----+ |/|
+---| | +-----+
/ | |/ /|
+-----+-----+-----+ |
| / /| | +
| +-----+ | |/
+---| | +-----+
| |/| +
+-----+ |/
+-----+
Critérios de vitória
A solução mais curta em bytes em todos os idiomas vence. Por favor, adicione uma breve descrição do método usado e seu código.
Respostas:
JavaScript (ES6),
525 ... 475 471459 bytesGuardado 13 bytes graças a @Neil
Recebe entrada como uma matriz
[X,Y,Z]
. Retorna uma matriz de caracteres.Experimente online!
Quão?
Etapas do desenho
A saída consiste em 15 lados, desenhados em uma ordem específica.
Implementação
A função de desenho ég . Funciona com os seguintes parâmetros:
Os vértices são sempre desenhados. Dependendo do valor de outro parâmetroc , as arestas são desenhadas ou apagadas.
Set=0 , a função desenha um lado frontal:
Set=1 , desenha um lado superior:
Set=2 , desenha um lado direito:
Para resumir, um lado é totalmente descrito com:
Portanto, precisamos armazenar os 10 parâmetros a seguir para cada lado:
Abaixo estão os parâmetros dos 15 lados que precisam ser desenhados:
We force all values into the range[0..9] by applying the following operations:
It results in 15 numbers of exactly 10 decimal digits, which are stored as 15 groups of 7 digits in base 36.
For instance, the first side is encoded as
4032070460
and stored as1uol9h8
.fonte
Array(W*2+9).fill` `
saves a byte.APL (Dyalog Classic),
162161132130 bytesTry it online!
(1 + 4*cx + 2*cy + cz) mod 16
wherecx
,cy
,cz
are the number of same-value "rods" along axis x,y,z, i.e. vectors along that axis that consist of the same value: 0 0 or 1 1. we make an exception if the subarray is all-zero (or all-one - those don't matter) and we consider its number 0 instead of 28-|/+
thanks Scott Milner for spotting that some
+
s rendered as?
sfonte
Charcoal, 325 bytes
Try it online! Link is to verbose version of code. Explanation:
Input the extrusions, but premultiply them to save bytes.
If at least two of the extrusions are zero, then simply draw a cuboid of dimensions (2x+1, 2y+1, 2z+1). Otherwise:
Print the left extrusion, if any.
Print the down extrusion, if any.
Print the back extrusion, if any.
The remaining extrusions all meet at this point (which doesn't get drawn until the very end!)
Print the front extrusion, if any, taking care to erase parts of the left and down extrusions that may overlap.
Print the up extrusion, if any, taking care to erase parts of the back and left extrusions that may overlap.
Print the right extrusion, if any, taking care to erase parts of the down and back extrusions that may overlap.
Draw the joins between the latter extrusions.
fonte
Charcoal,
195164144 bytesTry it online! Link is to verbose version of code. I'm posting this as a separate answer as it uses a completely different approach to drawing the extrusion. Explanation:
Input the extrusions and calculate half the size of the enclosing cuboid, but in integer arithmetic because Charcoal's ranges are always integers. The origin of the output maps to the centre of the original unit cube.
Loop over all coordinates within (including the boundary) the cuboid containing the extrusion.
Jump to the output position corresponding to those coordinates.
From the given coordinates, peek in all eight diagonal directions to determine whether the extrusion overlaps in that direction. The peeked coordinates are checked that they still lie within the cuboid, and then the number of axes in which the coordinate lies within the original cube must be greater than 1. Note that since the cube has an odd display height, the Y-axis values that are peeked are integers while the other axes use fractional coordinates.
Consider the number of directions in which the extrusion overlaps. There are five cases of interest where we want to print something, as in the case of zero, that means that this is empty space and we don't want to print anything, while in the case of eight, that means that this is inside the extrusion and anything we did print would be overprinted by a layer nearer the eye point.
If the extrusion only overlaps in one direction then this is an outer corner and we need to output a
+
.If the extrusion overlaps in two directions then this is an outer edge. Which sort of edge is determined from the separation between the two overlaps; 6 and 7 are rear-facing edges and will get overwritten, 4 is a diagonal edge, 2 is a vertical edge and 1 is a horizontal edge. (I actually calculate 7 minus the separation as it seems to be easier to do.)
If the extrusion overlaps in three directions then this is an inner corner in the case where one of the extrusions is zero and we need to output a
+
.If the extrusion overlaps in four directions then there are two cases: faces (any direction), and inner corners in the case with three positive extrusions. In the latter case there are an odd number of overlaps towards the viewer.
If the extrusion overlaps in six directions then this is an inner edge. It works like the complement of an outer edge except that we're only interested when one of the two empty spaces is the direction towards the eye point (the last entry in the array).
fonte
K (ngn/k), 172 bytes
Try it online!
obligatory k rewrite of my apl solution
same algorithm, except that 3d->2d rendering is done with (the k equivalent of) scatter index assignment instead of creating 2d matrices for each 3d element and mixing them
fonte
ngn/apl
perfrom in comparison to yourDyalog APL
solution?⍤
) and stencil (⌺
)