Mon triangle a besoin de plus de nœuds


20

Considérons le triangle équilatéral standard, avec des nœuds étiquetés à l'aide de coordonnées barycentriques :

Nous pouvons transformer ce triangle à 3 nœuds en un triangle à 6 nœuds en ajoutant une nouvelle ligne de 3 sommets (un de plus que ce qui était présent sur un côté du triangle d'origine à 3 nœuds), supprimer tous les bords internes (mais pas les nœuds internes) et normaliser les coordonnées:

entrez la description de l'image ici

Répéter le processus pour passer d'un triangle à 6 nœuds à un triangle à 10 nœuds, ajouter une ligne de 4 sommets (là encore, un de plus que ce qui était présent sur un côté du triangle d'origine à 6 nœuds), supprimer tous les bords internes (mais pas les nœuds internes ) et renormaliser les coordonnées:

entrez la description de l'image ici

Ce processus peut être répété indéfiniment. Le but de ce défi est donné un nombre entier Nreprésentant le nombre de fois que ce processus a été effectué, sortie tous les nœuds pour le triangle associé en coordonnées barycentriques.

Contribution

Votre programme / fonction doit prendre en entrée un seul entier non négatif Nreprésentant le nombre de fois où ce processus a été appliqué. Notez que pour N=0, vous devez sortir le triangle d'origine avec 3 nœuds.

L'entrée peut provenir de n'importe quelle source (paramètre de fonction, stdio, etc.).

Production

Votre programme / fonction doit sortir tous les nœuds en coordonnées barycentriques normalisées. L'ordre des nœuds n'a pas d'importance. Un nombre peut être spécifié sous forme de fraction (réduction de fraction non requise) ou nombre à virgule flottante. Vous pouvez également générer des vecteurs "à l'échelle" pour spécifier un nœud. Par exemple, les 3 sorties suivantes sont équivalentes et autorisées:

0.5,0.5,0

1/2,2/4,0

[1,1,0]/2

Si vous utilisez une sortie en virgule flottante, votre sortie doit être précise à 1% près. La sortie peut être vers n'importe quel récepteur souhaité (stdio, valeur de retour, paramètre de retour, etc.). Notez que même si les coordonnées barycentriques sont uniquement déterminées par seulement 2 nombres par nœud, vous devez sortir les 3 nombres par nœud.

Exemples

Les exemples de cas sont formatés comme suit:

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

où la première ligne est l'entrée N, et toutes les lignes suivantes forment un nœud x,y,zqui doit être dans la sortie exactement une fois. Tous les nombres sont donnés sous forme de nombres à virgule flottante approximatifs.

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

Notation

C'est le golf de code; le code le plus court en octets gagne. Des échappatoires standard s'appliquent. Vous pouvez utiliser n'importe quel module intégré souhaité.


Vous dites " Si vous utilisez une sortie en virgule flottante ". Quelles alternatives existe-t-il? Des fractions? Si oui, doivent-ils être réduits? Qu'en est-il des vecteurs à l'échelle comme [1,2,3]/6?
Peter Taylor

Oui, toutes ces alternatives sont autorisées. Je mettrai à jour l'énoncé du problème.
helloworld922

Réponses:


7

CJam (22 octets)

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

Il s'agit d'un bloc (fonction) anonyme qui prend Nla pile et laisse un tableau de tableaux de doubles sur la pile. Démo en ligne

Dissection

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

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

5

Python 3, 87 octets

Il s'agit en fait d'un commentaire sur la solution de TheBikingViking mais je n'ai pas assez de réputation pour les commentaires.

On peut économiser quelques octets en itérant uniquement sur les variables i,jet en utilisant le fait qu'elles s'ajoutent à la troisième 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 octets

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

Il s'agit d'une fonction sans nom prenant un seul argument entier. La sortie est une liste de listes de fractions exactes (réduites).

Génère tous les 3-tuples de multiples 1/(N+1)compris entre 0 et 1, inclus, puis sélectionne ceux dont la somme est 1 (comme requis par les coordonnées barycentriques).


4

05AB1E , 10 octets

ÌL<¤/3ãDOÏ

Explication

Ì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

Essayez-le en ligne


Puisque ¤consomme le tableau, pourquoi /divise-t-il le tableau par cela? Est-ce qu'il "se souvient" de la dernière valeur surgie et l'utilise si nécessaire?
Luis Mendo

@LuisMendo: ¤est l'une des rares commandes qui n'apparaissent pas et ne consomment pas de la pile. Il pousse le dernier élément de la liste tout en laissant la liste sur la pile.
Emigna



Oh bien sûr! Merci pour les explications
Luis Mendo

3

MATL , 17 octets

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

Essayez-le en ligne!

Explication

L'approche est la même que dans les autres réponses:

  1. Générez le tableau [0, 1/(n+1), 2/(n+1), ..., 1], où nest l'entrée;
  2. Générez tous les 3-tuples avec ces valeurs;
  3. Ne gardez que ceux dont la somme est 1.

Plus précisement:

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

Méduse , 37 33 octets

Merci à Zgarb d'avoir économisé 4 octets.

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

Essayez-le en ligne!

Comme mes réponses CJam de Mathematica et Peter, cela génère un ensemble de tuples candidats, puis ne sélectionne que ceux qui totalisent 1. Je ne suis pas encore entièrement satisfait de la disposition, et je me demande si je peux enregistrer quelques octets avec des crochets ou des fourches, mais je vais devoir examiner cela plus tard.


1

Perl 6: 50 40 octets

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

Renvoie une séquence de listes à 3 éléments de nombres rationnels (exacts).

Explication:

  • $_
    Paramètre implicitement déclaré du lambda.
  • 0, 1/($_ + 1) ... 1
    Utilise l'opérateur de séquence ...pour construire la séquence arithmétique qui correspond aux valeurs de coordonnées possibles.
  • [X] EXPR xx 3
    Prend le produit cartésien de trois copies d'EXPR, c'est-à-dire génère tous les 3-tuples possibles.
  • grep *.sum == 1, EXPR
    Filtrez les tuples avec une somme de 1.

1

Rubis, 62

Je serais surpris si cela ne pouvait pas être amélioré:

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

En prenant les conseils latents dans le puzzle, cela calcule les options du deuxième nœud en fonction du premier et du troisième nœud en soustrayant les deux premiers.



0

Python 3, 106 octets

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

Une fonction qu'ils saisit via un argument et imprime une liste de listes de flottants dans STDOUT.

Python n'est pas bon dans les produits cartésiens ...

Comment ça fonctionne

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

Essayez-le sur Ideone


0

En fait , 15 octets

Cela utilise un algorithme similaire à celui de la réponse Python de TheBikingViking . Suggestions de golf bienvenues. Essayez-le en ligne!

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

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


0

JavaScript (Firefox 30-57), 88 81 octets

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

Renvoie un tableau de tableaux de nombres à virgule flottante. Edit: 7 octets enregistrés en calculant directement la troisième coordonnée. J'ai essayé d'éliminer le ifen calculant ydirectement la plage de mais cela a coûté un octet supplémentaire:

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

À la fin, vous avez écrit [x/n,y/n/z/n], avez-vous oublié une virgule?
kamoroso94

@ kamoroso94 Vous avez raison, j'ai tapé la dernière virgule, merci de me l'avoir fait savoir.
Neil
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.