Mój trójkąt potrzebuje więcej węzłów

20

Rozważ standardowy trójkąt równoboczny, z węzłami oznaczonymi za pomocą współrzędnych barycentrycznych :

Możemy przekształcić ten trójkąt z 3 węzłami w trójkąt z 6 węzłami, dodając nową linię 3 wierzchołków (o jeden więcej niż z boku oryginalnego trójkąta z 3 węzłami), usuń wszelkie wewnętrzne krawędzie (ale nie wewnętrzne węzły) i ponownie znormalizować współrzędne:

wprowadź opis zdjęcia tutaj

Powtarzając proces przejścia z trójkąta 6-węzłowego do trójkąta 10-węzłowego, dodaj linię 4 wierzchołków (ponownie, o jeden więcej niż na boku oryginalnego trójkąta 6-węzłowego), usuń wszelkie wewnętrzne krawędzie (ale nie wewnętrzne węzły ) i ponownie znormalizować współrzędne:

wprowadź opis zdjęcia tutaj

Proces ten można powtarzać w nieskończoność. Celem tego wyzwania jest liczba całkowita Nreprezentująca, ile razy ten proces został wykonany, wyprowadzenie wszystkich węzłów dla powiązanego trójkąta we współrzędnych barycentrycznych.

Wejście

Twój program / funkcja powinna przyjąć jako dane wejściowe jedną nieujemną liczbę całkowitą Nreprezentującą ile razy ten proces został zastosowany. Zauważ, że dla N=0powinieneś wygenerować oryginalny trójkąt z 3 węzłami.

Dane wejściowe mogą pochodzić z dowolnego źródła (parametr funkcji, stdio itp.).

Wynik

Twój program / funkcja powinna wypisywać wszystkie węzły w znormalizowanych współrzędnych barocentrycznych. Kolejność węzłów nie ma znaczenia. Liczbę można określić jako ułamek (redukcja ułamka nie jest wymagana) lub liczbę zmiennoprzecinkową. Możesz również wyprowadzać „skalowane” wektory, aby określić węzeł. Na przykład wszystkie 3 z następujących danych wyjściowych są równoważne i dozwolone:

0.5,0.5,0

1/2,2/4,0

[1,1,0]/2

Jeśli używasz wyjścia zmiennoprzecinkowego, twój wynik powinien być dokładny z dokładnością do 1%. Dane wyjściowe mogą być do dowolnego pożądanego ujścia (standard, wartość zwracana, parametr powrotu itp.). Zauważ, że chociaż współrzędne barycentryczne są jednoznacznie określone tylko przez 2 liczby na węzeł, powinieneś wyprowadzić wszystkie 3 liczby na węzeł.

Przykłady

Przykładowe przypadki są sformatowane jako:

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

gdzie pierwszy wiersz jest wejściem N, a wszystkie kolejne wiersze tworzą węzeł, x,y,zktóry powinien znajdować się na wyjściu dokładnie raz. Wszystkie liczby podano jako przybliżone liczby zmiennoprzecinkowe.

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

Punktacja

To jest kod golfowy; najkrótszy kod w bajtach wygrywa. Obowiązują standardowe luki. Możesz użyć dowolnych wbudowanych funkcji.

helloworld922
źródło
Mówisz „ Jeśli używasz wyjścia zmiennoprzecinkowego ”. Jakie są alternatywy? Ułamki? Jeśli tak, to czy należy je zmniejszyć? Co powiesz na skalowane wektory [1,2,3]/6?
Peter Taylor,
Tak, wszystkie te alternatywy są dozwolone. Zaktualizuję instrukcję problemu.
helloworld922,

Odpowiedzi:

7

CJam (22 bajty)

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

Jest to anonimowy blok (funkcja), który przyjmuje Nstos i pozostawia tablicę tablic podwójnych na stosie. Demo online

Sekcja

{         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
źródło
6

Haskell, 53 bajty

f n|m<-n+1=[map(/m)[x,y,m-x-y]|x<-[0..m],y<-[0..m-x]]
Damien
źródło
5

Python 3, 87 bajtów

To rzeczywiście powinien być komentarz do rozwiązania TheBikingViking, ale nie mam wystarczającej reputacji do komentowania.

Można zaoszczędzić kilka bajtów, tylko iterując zmienne i,ji wykorzystując fakt, że z trzecim sumują się 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
źródło
4

Mathematica,  44  43 bajty

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

Jest to funkcja bez nazwy, która przyjmuje pojedynczy argument liczby całkowitej. Dane wyjściowe to lista list dokładnych (zredukowanych) ułamków.

Generuje wszystkie 3-krotności wielokrotności od 1/(N+1)0 do 1 włącznie, a następnie wybiera te, których suma wynosi 1 (zgodnie ze współrzędnymi barycentrycznymi).

Martin Ender
źródło
4

05AB1E , 10 bajtów

ÌL<¤/3ãDOÏ

Wyjaśnienie

Ì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

Wypróbuj online

Emigna
źródło
Skoro ¤pochłania tablicę, dlaczego /dzieli tablicę przez to? Czy „pamięta” tę ostatnią wyskakującą wartość i używa jej w razie potrzeby?
Luis Mendo
@LuisMendo: ¤jest jednym z niewielu poleceń, które nie wyskakują i nie zużywają się ze stosu. Pcha ostatni element listy, pozostawiając listę na stosie.
Emigna
Och, oczywiście! Dziękuję za wyjaśnienia
Luis Mendo
3

MATL , 17 bajtów

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

Wypróbuj online!

Wyjaśnienie

Podejście jest takie samo jak w innych odpowiedziach:

  1. Wygeneruj tablicę [0, 1/(n+1), 2/(n+1), ..., 1], gdzie njest wejście;
  2. Wygeneruj wszystkie 3 krotki z tymi wartościami;
  3. Zatrzymuj tylko tych, których suma jest 1.

Dokładniej:

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
źródło
1

Meduza , 37 33 bajtów

Dzięki Zgarbowi za oszczędność 4 bajtów.

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

Wypróbuj online!

Podobnie jak moje odpowiedzi Mathematica i Peter CJam, generuje zestaw krotek kandydujących, a następnie wybiera tylko te, które sumują się do 1. Nie jestem jeszcze całkowicie zadowolony z układu i zastanawiam się, czy mogę zapisać niektóre bajty za pomocą haków lub widelców, ale będę musiał to sprawdzić później.

Martin Ender
źródło
1

Perl 6: 50 40 bajtów

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

Zwraca sekwencję 3-elementowych list (dokładnych) liczb wymiernych.

Wyjaśnienie:

  • $_
    Deklarowany niejawnie parametr lambda.
  • 0, 1/($_ + 1) ... 1
    Używa operatora sekwencji ...do skonstruowania sekwencji arytmetycznej, która odpowiada możliwym wartościom współrzędnych.
  • [X] EXPR xx 3
    Pobiera kartezjański produkt trzech kopii EXPR, tj. Generuje wszystkie możliwe 3-krotki.
  • grep *.sum == 1, EXPR
    Filtruj krotki o sumie 1.
smls
źródło
1

Ruby, 62

Byłbym zaskoczony, gdyby nie można tego poprawić:

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

Biorąc pod uwagę porady ukryte w układance, oblicza to opcje drugiego węzła na podstawie pierwszego i trzeciego węzła, odejmując pierwsze dwa.

Nie ten Charles
źródło
0

Python 3, 106 bajtów

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

Funkcja pobiera dane wejściowe przez argument i wypisuje listę list liczb zmiennoprzecinkowych do STDOUT.

Python nie jest dobry w kartezjańskich produktach ...

Jak to działa

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

Wypróbuj na Ideone

TheBikingViking
źródło
0

Właściwie 15 bajtów

Wykorzystuje algorytm podobny do tego w odpowiedzi Pythona w TheBikingViking . Sugestie dotyczące gry w golfa mile widziane. Wypróbuj online!

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

Nie golfowany:

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
źródło
0

Ruby, 77 74 bajtów

Inna odpowiedź wykorzystująca algorytm w pythonowej odpowiedzi TheBikingViking . Sugestie dotyczące gry w golfa mile widziane.

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

Kolejny 74-bajtowy algorytm oparty na odpowiedzi Ruby Charlesa .

->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
źródło
0

JavaScript (Firefox 30-57), 88 81 bajtów

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

Zwraca tablicę tablic liczb zmiennoprzecinkowych. Edycja: Zapisano 7 bajtów, obliczając bezpośrednio trzecią współrzędną. Próbowałem wyeliminować if, obliczając ybezpośrednio zasięg, ale kosztowało to dodatkowy bajt:

n=>[for(x of a=[...Array(++n+1).keys()])for(y of a.slice(x))[x/n,(y-x)/n,(n-y)/n]]
Neil
źródło
Na koniec, napisałeś [x/n,y/n/z/n], zapomniałeś przecinka?
kamoroso94
@ kamoroso94 Masz rację, wpisałem ostatni przecinek, dzięki za poinformowanie mnie.
Neil