Mi triángulo necesita más nodos.

20

Considere el triángulo equilátero estándar, con los nodos etiquetados con coordenadas barcéntricas :

Podemos convertir este triángulo de 3 nodos en un triángulo de 6 nodos agregando una nueva línea de 3 vértices (uno más de lo que estaba presente en un lado del triángulo original de 3 nodos), eliminar los bordes internos (pero no los nodos internos) y volver normalizar las coordenadas:

ingrese la descripción de la imagen aquí

Repitiendo el proceso para pasar de un triángulo de 6 nodos a un triángulo de 10 nodos, agregue una línea de 4 vértices (nuevamente, uno más de lo que estaba presente en un lado del triángulo original de 6 nodos), elimine los bordes internos (pero no los nodos internos ) y re-normalizar las coordenadas:

ingrese la descripción de la imagen aquí

Este proceso puede repetirse indefinidamente. El objetivo de este desafío es un número entero que Nrepresenta cuántas veces se ha realizado este proceso, generar todos los nodos para el triángulo asociado en coordenadas barcéntricas.

Entrada

Su programa / función debe tomar como entrada un número entero no negativo que Nrepresente cuántas veces se ha aplicado este proceso. Tenga en cuenta que para N=0, debe generar el triángulo original con 3 nodos.

La entrada puede provenir de cualquier fuente (parámetro de función, stdio, etc.).

Salida

Su programa / función debería generar todos los nodos en coordenadas barcéntricas normalizadas. El orden de los nodos no importa. Un número puede especificarse como una fracción (no se requiere reducción de fracción) o un número de coma flotante. También puede generar vectores "escalados" para especificar un nodo. Por ejemplo, las 3 de las siguientes salidas son equivalentes y están permitidas:

0.5,0.5,0

1/2,2/4,0

[1,1,0]/2

Si usa salida de punto flotante, su salida debe ser precisa dentro del 1%. La salida puede ser a cualquier sumidero deseado (estándar, valor de retorno, parámetro de retorno, etc.). Tenga en cuenta que a pesar de que las coordenadas barcéntricas están determinadas únicamente por 2 números por nodo, debe generar los 3 números por nodo.

Ejemplos

Los casos de ejemplo están formateados como:

N
x0,y0,z0
x1,y1,z1
x2,y2,z2
...

donde la primera línea es la entrada N, y todas las siguientes líneas forman un nodo x,y,zque debería estar en la salida exactamente una vez. Todos los números se dan como números aproximados de coma flotante.

0
1,0,0
0,1,0
0,0,1

1
1,0,0
0,1,0
0,0,1
0.5,0,0.5
0.5,0.5,0
0,0.5,0.5

2
1,0,0
0,1,0
0,0,1
0.667,0,0.333
0.667,0.333,0
0.333,0,0.667
0.333,0.333,0.333
0.333,0.667,0
0,0.333,0.667
0,0.667,0.333

3
1,0,0
0.75,0,0.25
0.75,0.25,0
0.5,0,0.5
0.5,0.25,0.25
0.5,0.5,0
0.25,0,0.75
0.25,0.25,0.5
0.25,0.5,0.25
0.25,0.75,0
0,0,1
0,0.25,0.75
0,0.5,0.5
0,0.75,0.25
0,1,0

Puntuación

Este es el código de golf; el código más corto en bytes gana. Se aplican lagunas estándar. Puede usar los complementos deseados.

helloworld922
fuente
Usted dice " Si usa salida de punto flotante ". ¿Qué alternativas hay? Fracciones? Si es así, ¿tienen que reducirse? ¿Qué tal los vectores escalados [1,2,3]/6?
Peter Taylor
Sí, todas esas alternativas están permitidas. Actualizaré la declaración del problema.
helloworld922

Respuestas:

7

CJam (22 bytes)

{):X),3m*{:+X=},Xdff/}

Este es un bloque anónimo (función) que toma Nla pila y deja una matriz de matrices de dobles en la pila. Demostración en línea

Disección

{         e# Define a block
  ):X     e# Let X=N+1 be the number of segments per edge
  ),3m*   e# Generate all triplets of integers in [0, X] (inclusive)
  {:+X=}, e# Filter to those triplets which sum to X
  Xdff/   e# Normalise
}
Peter Taylor
fuente
6

Haskell, 53 bytes

f n|m<-n+1=[map(/m)[x,y,m-x-y]|x<-[0..m],y<-[0..m-x]]
Damien
fuente
5

Python 3, 87 bytes

En realidad, se supone que esto es un comentario de TheBikingViking a la solución, pero no tengo suficiente reputación para hacer comentarios.

Uno puede guardar unos pocos bytes al iterar solo sobre las variables i,jy usar el hecho de que con el tercero se suman n+1.

def f(n):d=n+1;r=range(n+2);print([[i/d,j/d,(d-i-j)/d]for i in r for j in r if d>=i+j])
Elvorfirilmathredia
fuente
4

Mathematica  44  43 bytes

Select[Range[0,x=#+1]~Tuples~3/x,Tr@#==1&]&

Esta es una función sin nombre que toma un único argumento entero. La salida es una lista de listas de fracciones exactas (reducidas).

Genera todas las 3 tuplas de múltiplos 1/(N+1)entre 0 y 1, inclusive, y luego selecciona aquellos cuya suma es 1 (como lo requieren las coordenadas barcéntricas).

Martin Ender
fuente
4

05AB1E , 10 bytes

ÌL<¤/3ãDOÏ

Explicación

ÌL<          # range(1,n+2)-1
   ¤/        # divide all by last element (n+1)
     3ã      # cartesian product repeat (generate all possible triples)
       DO    # make a copy and sum the triples
         Ï   # keep triples with sum 1

Pruébalo en línea

Emigna
fuente
Dado que ¤consume la matriz, ¿por qué /divide la matriz por eso? ¿"Recuerda" el último valor reventado y lo usa si es necesario?
Luis Mendo
@LuisMendo: ¤es uno de los pocos comandos que no aparece y consume de la pila. Empuja el último elemento de la lista mientras deja la lista en la pila.
Emigna
Hm? Ese no parece ser el caso
Luis Mendo
¡Oh por supuesto! Gracias por las explicaciones
Luis Mendo
3

MATL , 17 bytes

2+:qGQ/3Z^t!s1=Y)

Pruébalo en línea!

Explicación

El enfoque es el mismo que en otras respuestas:

  1. Genere la matriz [0, 1/(n+1), 2/(n+1), ..., 1], donde nestá la entrada;
  2. Genere todas las 3 tuplas con esos valores;
  3. Conserve solo aquellos cuya suma es 1.

Más específicamente:

2+     % Take input and add 2: produces n+2
:q     % Range [0 1 ... n+1]
GQ/    % Divide by n+1 element-wise: gives [0, 1/(n+1), 2/(n+1)..., 1]
3Z^    % Cartesian power with exponent 3. Gives (n+1)^3 × 3 array. Each row is a 3-tuple
t      % Duplicate
!s     % Sum of each row
1=     % Logical index of entries that equal 1
Y)     % Use that index to select rows of the 2D array of 3-tuples
Luis Mendo
fuente
1

Medusa , 37 33 bytes

Gracias a Zgarb por guardar 4 bytes.

p
*%
# S
`
=E   S
`/
1+r#>>i
   3

Pruébalo en línea!

Al igual que mis respuestas de Mathematica y Peter CJam, esto genera un conjunto de tuplas candidatas y luego selecciona solo aquellas que suman 1. No estoy completamente satisfecho con el diseño todavía, y me pregunto si puedo guardar algunos bytes con ganchos o tenedores, pero tendré que investigar eso más tarde.

Martin Ender
fuente
1

Perl 6: 50 40 bytes

{grep *.sum==1,[X] (0,1/($_+1)...1)xx 3}

Devuelve una secuencia de listas de 3 elementos de números racionales (exactos).

Explicación:

  • $_
    Parámetro declarado implícitamente de la lambda.
  • 0, 1/($_ + 1) ... 1
    Utiliza el operador de secuencia ...para construir la secuencia aritmética que corresponde a los posibles valores de coordenadas.
  • [X] EXPR xx 3
    Toma el producto cartesiano de tres copias de EXPR, es decir, genera todas las 3 tuplas posibles.
  • grep *.sum == 1, EXPR
    Filtra las tuplas con una suma de 1.
smls
fuente
1

Rubí, 62

Me sorprendería si esto no se puede mejorar en:

->x{0.step(1,i=1.0/(x+1)){|a|0.step(1-a,i){|b|p [a,b,1-a-b]}}}

Tomando el consejo latente en el rompecabezas, esto calcula las opciones del segundo nodo basadas en el primero, y el tercer nodo restando los dos primeros.

No es que Charles
fuente
0

Python 3, 106 bytes

def f(n):r=range(n+2);print([x for x in[[i/-~n,j/-~n,k/-~n]for i in r for j in r for k in r]if sum(x)==1])

Una función que toman entrada a través de argumentos e imprime una lista de listas de flotantes en STDOUT.

Python no es bueno en productos cartesianos ...

Cómo funciona

def f(n):                         Function with input iteration number n
r=range(n+2)                      Define r as the range [0, n+1]
for i in r for j in r for k in r  Length 3 Cartesian product of r
[i/-~n,j/-~n,k/-~n]               Divide each element of each list in the product
                                  by n+1
[x for x in ... if sum(x)==1]     Filter by summation to 1
print(...)                           Print to STDOUT

Pruébalo en Ideone

TheBikingViking
fuente
0

En realidad , 15 bytes

Esto utiliza un algoritmo similar al de la respuesta de Python de TheBikingViking . Sugerencias de golf bienvenidas. Pruébalo en línea!

u;ur♀/3@∙`Σ1=`░

Sin golf:

u;                Increment implicit input and duplicate.
  ur              Range [0..n+1]
    ♀/            Divide everything in range by (input+1).
      3@∙         Take the Cartesian product of 3 copies of [range divided by input+1]
         `Σ1=`    Create function that takes a list checks if sum(list) == 1.
              ░   Push values of the Cartesian product where f returns a truthy value.
Sherlock9
fuente
0

JavaScript (Firefox 30-57), 88 81 bytes

n=>[for(x of a=[...Array(++n+1).keys()])for(y of a)if(x+y<=n)[x/n,y/n,(n-x-y)/n]]

Devuelve una matriz de matrices de números de punto flotante. Editar: guardado 7 bytes calculando la tercera coordenada directamente. Intenté eliminar el ifmediante el cálculo del rango de ydirectamente pero me costó un byte adicional:

n=>[for(x of a=[...Array(++n+1).keys()])for(y of a.slice(x))[x/n,(y-x)/n,(n-y)/n]]
Neil
fuente
Al final, usted escribió [x/n,y/n/z/n], ¿olvidó una coma?
kamoroso94
@ kamoroso94 Tienes razón, escribí la última coma, gracias por hacérmelo saber.
Neil