Meu triângulo precisa de mais nós

20

Considere o triângulo equilátero padrão, com nós rotulados usando coordenadas baricêntricas :

Podemos transformar esse triângulo de 3 nós em um triângulo de 6 nós adicionando uma nova linha de 3 vértices (um a mais do que estava presente em um lado do triângulo de 3 nós original), remova quaisquer arestas internas (mas não os nós internos) e normalize as coordenadas:

insira a descrição da imagem aqui

Repetindo o processo para ir de um triângulo de 6 nós a um triângulo de 10 nós, adicione uma linha de 4 vértices (novamente, mais um que estava presente em um lado do triângulo de 6 nós original), remova quaisquer arestas internas (mas não os nós internos ) e normalize novamente as coordenadas:

insira a descrição da imagem aqui

Este processo pode ser repetido indefinidamente. O objetivo deste desafio é fornecer um número inteiro que Nrepresenta quantas vezes esse processo foi executado, produzindo todos os nós do triângulo associado em coordenadas baricêntricas.

Entrada

Seu programa / função deve ter como entrada um número inteiro não negativo Nrepresentando quantas vezes esse processo foi aplicado. Observe que N=0, para , você deve gerar o triângulo original com 3 nós.

A entrada pode vir de qualquer fonte (parâmetro de função, stdio, etc.).

Saída

Seu programa / função deve produzir todos os nós em coordenadas baricêntricas normalizadas. A ordem dos nós não importa. Um número pode ser especificado como uma fração (redução de fração não necessária) ou um número de ponto flutuante. Você também pode gerar vetores "dimensionados" para especificar um nó. Por exemplo, todas as três seguintes saídas são equivalentes e permitidas:

0.5,0.5,0

1/2,2/4,0

[1,1,0]/2

Se estiver usando saída de ponto flutuante, sua saída deve ter precisão de 1%. A saída pode ser para qualquer coletor desejado (stdio, valor de retorno, parâmetro de retorno, etc.). Observe que, embora as coordenadas barocêntricas sejam determinadas exclusivamente por apenas 2 números por nó, você deve gerar todos os 3 números por nó.

Exemplos

Casos de exemplo são formatados como:

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

onde a primeira linha é a entrada Ne todas as linhas seguintes formam um nó x,y,zque deve estar na saída exatamente uma vez. Todos os números são dados como números aproximados de ponto flutuante.

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

Pontuação

Isso é código de golfe; o menor código em bytes vence. Aplicam-se brechas padrão. Você pode usar quaisquer embutidos desejados.

helloworld922
fonte
Você diz " Se estiver usando saída de ponto flutuante ". Que alternativas existem? Frações? Se sim, eles precisam ser reduzidos? Que tal vetores escalonados [1,2,3]/6?
Peter Taylor
Sim, todas essas alternativas são permitidas. Vou atualizar a declaração do problema.
precisa saber é o seguinte

Respostas:

7

CJam (22 bytes)

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

Este é um bloco anônimo (função) que assume Na pilha e deixa uma matriz de matrizes de duplas na pilha. Demonstração online

Dissecação

{         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
fonte
6

Haskell, 53 bytes

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

Python 3, 87 bytes

Na verdade, isso deve ser um comentário da TheBikingViking à solução, mas não tenho reputação suficiente para comentários.

Pode-se salvar alguns bytes apenas iterando sobre as variáveis i,je usando o fato de que com o terceiro eles somam 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
fonte
4

Mathematica,  44  43 bytes

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

Esta é uma função sem nome que recebe um único argumento inteiro. Saída é uma lista de listas de frações exatas (reduzidas).

Gera todas as três tuplas de múltiplos 1/(N+1)entre 0 e 1, inclusive, e seleciona aquelas cuja soma é 1 (conforme exigido pelas coordenadas baricêntricas).

Martin Ender
fonte
4

05AB1E , 10 bytes

ÌL<¤/3ãDOÏ

Explicação

Ì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

Experimente online

Emigna
fonte
Como ¤consome a matriz, por que a /divide por isso? Ele "lembra" o último valor que apareceu e o usa, se necessário?
Luis Mendo
@LuisMendo: ¤é um dos poucos comandos que não aparece e consome da pilha. Empurra o último elemento da lista enquanto deixa a lista na pilha.
Emigna
Hum? Isso não parece ser o caso
Luis Mendo
Ah, claro! Obrigado pelas explicações.
Luis Mendo
3

MATL , 17 bytes

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

Experimente online!

Explicação

A abordagem é a mesma que em outras respostas:

  1. Gere a matriz [0, 1/(n+1), 2/(n+1), ..., 1], onde nestá a entrada;
  2. Gere todas as três tuplas com esses valores;
  3. Mantenha apenas aqueles cuja soma é 1.

Mais especificamente:

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
fonte
1

Água-viva , 37 33 bytes

Obrigado ao Zgarb por salvar 4 bytes.

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

Experimente online!

Como minhas respostas do Mathematica e do CJam de Peter, isso gera um conjunto de tuplas candidatas e seleciona apenas aquelas que somam 1. Ainda não estou totalmente satisfeito com o layout e me pergunto se posso salvar alguns bytes com ganchos ou garfos, mas vou ter que investigar isso mais tarde.

Martin Ender
fonte
1

Perl 6: 50 40 bytes

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

Retorna uma sequência de listas de 3 elementos de números racionais (exatos).

Explicação:

  • $_
    Parâmetro implicitamente declarado do lambda.
  • 0, 1/($_ + 1) ... 1
    Usa o operador de sequência ...para construir a sequência aritmética que corresponde aos possíveis valores de coordenadas.
  • [X] EXPR xx 3
    Toma o produto cartesiano de três cópias do EXPR, ou seja, gera todas as três tuplas possíveis.
  • grep *.sum == 1, EXPR
    Filtre as tuplas com uma soma de 1.
smls
fonte
1

Ruby, 62

Ficaria surpreso se isso não puder ser melhorado:

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

Tomando o conselho latente no quebra-cabeça, calcula as opções do segundo nó com base no primeiro e no terceiro nó, subtraindo os dois primeiros.

Não que Charles
fonte
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])

Uma função que recebe entrada por meio de argumento e imprime uma lista de listas de carros alegóricos para STDOUT.

Python não é bom em produtos cartesianos ...

Como 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

Experimente no Ideone

TheBikingViking
fonte
0

Na verdade , 15 bytes

Isso usa um algoritmo semelhante ao da resposta em Python do TheBikingViking . Sugestões de golfe são bem-vindas. Experimente online!

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

Ungolfed:

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
fonte
0

Ruby, 77 74 bytes

Outra resposta usando o algoritmo na resposta Python do TheBikingViking . Sugestões de golfe são bem-vindas.

->n{a=[*0.step(1,i=1.0/(n+1))];a.product(a,a).reject{|j|j.reduce(&:+)!=1}}

Outro algoritmo de 74 bytes baseado na resposta de Not that Charles's Ruby .

->x{y=x+1;z=1.0/y;[*0..y].map{|a|[*0..y-a].map{|b|p [a*z,b*z,(y-a-b)*z]}}}
Sherlock9
fonte
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]]

Retorna uma matriz de matrizes de números de ponto flutuante. Editar: salvou 7 bytes calculando diretamente a terceira coordenada. Tentei eliminar o ifcálculo do intervalo ydiretamente, mas custou um byte extra:

n=>[for(x of a=[...Array(++n+1).keys()])for(y of a.slice(x))[x/n,(y-x)/n,(n-y)/n]]
Neil
fonte
No final, você escreveu [x/n,y/n/z/n], esqueceu uma vírgula?
precisa saber é o seguinte
@ kamoroso94 Você está certo, digitei a última vírgula, obrigado por me avisar.
Neil