Il mio triangolo ha bisogno di più nodi


20

Considera il triangolo equilatero standard, con i nodi etichettati usando coordinate baricentriche :

Possiamo trasformare questo triangolo a 3 nodi in un triangolo a 6 nodi aggiungendo una nuova linea di 3 vertici (uno in più rispetto a un lato del triangolo originale a 3 nodi), rimuovere eventuali bordi interni (ma non nodi interni) e ri normalizzare le coordinate:

inserisci qui la descrizione dell'immagine

Ripetendo il processo per passare da un triangolo a 6 nodi a un triangolo a 10 nodi, aggiungi una linea di 4 vertici (di nuovo, uno in più rispetto a un lato del triangolo originale a 6 nodi), rimuovi eventuali bordi interni (ma non nodi interni ) e normalizzare nuovamente le coordinate:

inserisci qui la descrizione dell'immagine

Questo processo può essere ripetuto indefinitamente. L'obiettivo di questa sfida è dato un numero intero che Nrappresenta quante volte questo processo è stato eseguito, emettendo tutti i nodi per il triangolo associato in coordinate baricentriche.

Ingresso

Il tuo programma / funzione dovrebbe prendere come input un singolo intero non negativo che Nrappresenta quante volte questo processo è stato applicato. Si noti che per N=0, è necessario generare il triangolo originale con 3 nodi.

L'ingresso può provenire da qualsiasi sorgente (parametro funzione, stdio, ecc.).

Produzione

Il tuo programma / funzione dovrebbe generare tutti i nodi in coordinate baricentriche normalizzate. L'ordine dei nodi non ha importanza. Un numero può essere specificato come una frazione (riduzione della frazione non richiesta) o un numero in virgola mobile. È inoltre possibile generare vettori "ridimensionati" per specificare un nodo. Ad esempio, tutti e 3 i seguenti output sono equivalenti e consentiti:

0.5,0.5,0

1/2,2/4,0

[1,1,0]/2

Se si utilizza l'output in virgola mobile, l'output deve essere accurato entro l'1%. L'output può essere su qualsiasi sink desiderato (stdio, valore di ritorno, parametro di ritorno, ecc.). Si noti che anche se le coordinate baricentriche sono determinate in modo univoco solo da 2 numeri per nodo, è necessario generare tutti e 3 i numeri per nodo.

Esempi

I casi di esempio sono formattati come:

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

dove la prima riga è l'input Ne tutte le righe seguenti formano un nodo x,y,zche dovrebbe essere nell'output esattamente una volta. Tutti i numeri sono indicati come numeri approssimativi in ​​virgola mobile.

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

punteggio

Questo è il codice golf; vince il codice più breve in byte. Si applicano scappatoie standard. È possibile utilizzare qualsiasi componente incorporato desiderato.


Si dice " Se si utilizza l'uscita a virgola mobile ". Quali alternative ci sono? Frazioni? In tal caso, devono essere ridotti? Che ne dici di vettori in scala come [1,2,3]/6?
Peter Taylor,

Sì, sono ammesse tutte queste alternative. Aggiornerò la dichiarazione del problema.
helloworld922,

Risposte:


7

CJam (22 byte)

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

Questo è un blocco (funzione) anonimo che accetta Nlo stack e lascia una serie di array di doppi nello stack.Demo online

Dissezione

{         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
}

6

Haskell, 53 byte

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

5

Python 3, 87 byte

Questo dovrebbe in realtà essere un commento alla soluzione di TheBikingViking ma non ho abbastanza reputazione per i commenti.

Si può salvare qualche byte ripetendo solo le variabili i,je usando il fatto che con il terzo si sommano 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])

4

Mathematica,  44  43 byte

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

Questa è una funzione senza nome che accetta un singolo argomento intero. L'output è un elenco di elenchi di frazioni esatte (ridotte).

Genera tutte le 3 tuple di multipli 1/(N+1)compresi tra 0 e 1, inclusi, quindi seleziona quelli la cui somma è 1 (come richiesto dalle coordinate baricentriche).


4

05AB1E , 10 byte

ÌL<¤/3ãDOÏ

Spiegazione

Ì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

Provalo online


Poiché ¤consuma l'array, perché /dividere l'array per quello? "Ricorda" l'ultimo valore spuntato e lo usa se necessario?
Luis Mendo,

@LuisMendo: ¤è uno dei pochi comandi che non viene visualizzato e consumato dallo stack. Spinge l'ultimo elemento dell'elenco lasciando l'elenco in pila.
Emigna,



Oh, certo! Grazie per le spiegazioni
Luis Mendo,

3

MATL , 17 byte

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

Provalo online!

Spiegazione

L'approccio è lo stesso di altre risposte:

  1. Generare l'array [0, 1/(n+1), 2/(n+1), ..., 1], doven l'input;
  2. Genera tutte le 3 tuple con quei valori;
  3. Conserva solo quelli la cui somma è 1.

Più specificamente:

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

1

Medusa , 37 33 byte

Grazie a Zgarb per aver salvato 4 byte.

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

Provalo online!

Come le mie risposte di Mathematica e CJam di Peter, questo genera una serie di tuple candidate e quindi seleziona solo quelle che sommano a 1. Non sono ancora del tutto soddisfatto del layout e mi chiedo se posso salvare alcuni byte con ganci o forchette, ma dovrò esaminarlo più tardi.


1

Perl 6: 50 40 byte

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

Restituisce una sequenza di elenchi a 3 elementi di numeri (esatti) razionali.

Spiegazione:

  • $_
    Parametro dichiarato implicitamente della lambda.
  • 0, 1/($_ + 1) ... 1
    Utilizza l'operatore sequenza ...per costruire la sequenza aritmetica che corrisponde ai possibili valori delle coordinate.
  • [X] EXPR xx 3
    Prende il prodotto cartesiano di tre copie di EXPR, ovvero genera tutte le possibili 3 tuple.
  • grep *.sum == 1, EXPR
    Filtra le tuple con una somma di 1.

1

Ruby, 62

Sarei sorpreso se questo non può essere migliorato su:

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

Prendendo il consiglio latente nel puzzle, questo calcola le opzioni del secondo nodo in base al primo e al terzo nodo sottraendo i primi due.



0

Python 3, 106 byte

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 funzione che accetta input tramite argomento e stampa un elenco di elenchi di float su STDOUT.

Python non è bravo nei prodotti cartesiani ...

Come funziona

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

Provalo su Ideone


0

In realtà , 15 byte

Questo utilizza un algoritmo simile a quello nella risposta Python di TheBikingViking . Suggerimenti di golf benvenuti. Provalo 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.


0

JavaScript (Firefox 30-57), 88 81 byte

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]]

Restituisce una matrice di matrici di numeri in virgola mobile. Modifica: salvato 7 byte calcolando direttamente la terza coordinata. Ho provato a eliminare il ifcalcolando l'intervallo di ydirettamente ma costa un 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]]

Alla fine, hai scritto [x/n,y/n/z/n], hai dimenticato una virgola?
kamoroso94

@ kamoroso94 Hai ragione, ho digitato l'ultima virgola, grazie per avermelo fatto notare.
Neil,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.