Wygeneruj spiralę Padovan ASCII

22

To jest wersja ASCII tego wyzwania . Początkowy post został oddzielony na żądanie przez Martina Endera

Wprowadzenie

Podobnie jak Sekwencja Fibonacciego, Sekwencja Padovana ( OEIS A000931 ) jest sekwencją liczb, która jest wytwarzana przez dodanie poprzednich terminów w sekwencji. Wartości początkowe są zdefiniowane jako:

P(0) = P(1) = P(2) = 1

Warunki: 0, 1 i 2 są 1. Relacja powtarzalności jest podana poniżej:

P(n) = P(n - 2) + P(n - 3)

W ten sposób uzyskuje się następującą sekwencję:

1, 1, 1, 2, 2, 3, 4, 5, 7, 9, 12, 16, 21, 28, 37, 49, 65, 86, 114, 151, 200, 265, 351, ...

Używanie tych liczb jako długości boków trójkątów równobocznych daje fajną spiralę, gdy umieścisz je wszystkie razem, podobnie jak Spirala Fibonacciego:

wprowadź opis zdjęcia tutaj

Zdjęcie dzięki uprzejmości Wikipedia


Zadanie

Twoim zadaniem jest napisanie programu, który odtworzy tę spiralę według sztuki ASCII, z danymi wejściowymi odpowiadającymi temu terminowi. Ponieważ trójkąta o długości boku 1 (1 znak) nie da się dobrze przedstawić w ASCII, długości boków zostały rozszerzone o współczynnik 2. Zatem trójkąt o długości boku 1 jest w rzeczywistości tak przedstawiony:

 /\
/__\

Na przykład, jeśli dane wejściowe wynosiły 5 (5 termin), dane wyjściowe powinny wynosić:

   /\
  /  \
 /    \
/______\
\      /\
 \    /__\ 
  \  /\  /
   \/__\/

Pierwsze 5 wyrazów to 1, 1, 1, 2, 2, więc trójkąt miał długość boku 2, 2, 2, 4, 4 z powodu rozszerzenia. Kolejny przykład dla wejścia 8:

     __________
   /\          /\
  /  \        /  \
 /    \      /    \
/______\    /      \
\      /\  /        \
 \    /__\/          \
  \  /\  /            \
   \/__\/______________\
    \                  /
     \                /
      \              /
       \            /
        \          /
         \        /
          \      /
           \    /
            \  /
             \/

Zasady

  • Musisz wydrukować wynik, a wejście musi być liczbą całkowitą odpowiadającą liczbie terminów
  • Dopuszczalne są końcowe i wiodące znaki nowej linii, dozwolone są także końcowe spacje po wierszach
  • Twoje zgłoszenie musi być w stanie obsłużyć co najmniej do 10. kadencji (9)
  • Twoje zgłoszenie musi być pełnym programem lub funkcją, która pobiera dane wejściowe i drukuje wynik
  • Dopuszczalne są obroty wyjścia, w wielokrotnościach 60 stopni, ale rozmiar trójkątów musi pozostać taki sam, wraz z reprezentacją
  • Dozwolone jest również poruszanie się w lewo
  • Standardowe luki są zabronione

Możesz założyć, że dane wejściowe będą> 0 i że podany zostanie prawidłowy format danych wejściowych.

Punktacja

To jest , więc wygrywa najkrótszy kod w bajtach. Szczęśliwego Nowego Roku wszystkim!

Andrew Li
źródło
1
mój język Turtlèd może pobierać dane wejściowe z bazy 10 i przetwarzać je dobrze, ale to wyzwanie byłoby o wiele łatwiejsze, gdyby dane wejściowe były przyjmowane jako jednoargumentowe. czy byłoby to dozwolone?
Destructible Lemon
1
@DestructibleWatermelon Tak. Dane wejściowe muszą być po prostu liczbą całkowitą, w jakiejś formie.
Andrew Li
fajne. Zacznę nad tym pracować
Destructible Lemon
3
poczekaj, to wciąż bardzo trudne
Destructible Lemon

Odpowiedzi:

13

Befunge, 871 836 798 bajtów

&00p45*:10p20p030p240p050p060p9010gp9110gp1910gp1-91+10gpv
<v-g03+g06*2g041g055_v#!:%6:p06p05+p04g05g06:g04<p*54+292<
->10g:1\g3+:70p110gv >:5- #v_550g:01-\2*40g+1-30g
/\110:\-g03:\1:g055 _v#!-4:<vp01:-1g01-g03-1\-
^1<v07+1:g07< p08p < >:1-#v_550g:01-\40g+60g+1-30g-50g>v
 _0>p80gp:5-|v1\+66\:p\0\9:$<:p02:+1g02-g03+g06-\g04\1:<
0v|-g00:+1$$<>\p907^>p:!7v>3-#v_550g:30g+:30p1\0\-
1>10g+::0\g3-:70p\0^^07<v<>50#<g::30g+:30p-1-01-\
v >\$0gg> :1+10gg1- #v_^>0g10gg*+\:!2*-70g2+10gv>:#->#,"_"$#1_:1#<p
+1+g03$_^#`gg011+3:+3<g07\+*2+*`0:-\gg01+5g07:g<>1#,-#*:#8>#4_$#:^#
>55+,p30g40p10gg10g1>#v_
#v:#p0$#8_:$#<g!#@_0^ >
 >>:180gg`>>#|_:2+80gg:!v
3+^g\0p08:<vgg08+2::+3<$_100p1-v>g,\80gg+\80gp:2+90g:!01p\80gp
!#^_80g:1+^>\180gg`+!#^_20g80g`
5*g10!g09p04-1-\0\+g04:gg08:p09<^3`0:gg08+1:::$$_1#!-#\\:,#\<g

Wypróbuj online!

Jak to często bywa w Befunge, sztuczka wymyśla algorytm, który pozwala nam renderować wzór od góry do dołu, ponieważ po prostu nie jest możliwe, aby najpierw zapisać go w pamięci przy ograniczonej dostępnej przestrzeni.

Działa to najpierw poprzez zbudowanie prostej struktury danych reprezentującej krawędzie potrzebne do narysowania spirali. Drugi etap następnie analizuje tę strukturę od góry do dołu, renderując fragmenty krawędzi wymagane dla każdej linii wyjścia.

Korzystając z tej techniki, możemy obsłużyć do n = 15 w implementacji referencyjnej, zanim zaczniemy mieć problem z przepełnieniem w 8-bitowych komórkach pamięci. Tłumacze o większym rozmiarze komórki powinni móc obsłużyć do n = 25 przed wyczerpaniem się pamięci.

James Holderness
źródło
to imponujące ... ale czy potrafisz czytać te programy? lol dla mnie to wygląda tak losowo. jak buduje strukturę danych? jakiej struktury danych używa? dzięki!
don bright
1

idź, 768 bajtów

func 卷(n int){
    数:=0
    p:=[]int{1,1,1}
    for i:=3;i<n;i++ {p=append(p,p[i-2]+p[i-3])}
    宽:=p[len(p)-1]*10+10
    素:=make([]int,宽*宽)
    for 数=range 素 {素[数]=32}
    for i:=0;i<数;i+=宽 {素[i]=10}
    态:=[]int{1,1,宽/2,宽/2,92}
    表:=[70]int{}
    s:="SRSQTSPQQ!QOQP~QQQQQQSQR~ORQR!OPOPTSQRQ$QPPQNQPPPXQQQQQQRRQXQRRRNOQPQ$"
    for i:=range s {表[i]=int(s[i])-33-48}
    表[49],表[59]=48,48
    for i:=0;i<4*n;i++ {
        梴:=p[i/4]*2
        if 态[1]==0 {梴=梴*2-2}
        for k:=0;k<梴;k++ {
            址:=(态[2]+态[3]*宽)%len(素)
            if 素[址]==32 {素[址]=态[4]}
            态[2]+=态[0]
            态[3]+=态[1]
        }
        数=((态[0]+1)*2+态[1]+1)*5
        if i%4>2 {数+=35}
        for k:=0;k<5;k++ {态[k]+=表[数+k]}
    }
    for i:=0;i<宽*宽;i++ {fmt.Printf("%c",rune(素[i]))}
}

To oczywiście nie jest optymalne, ale nie jest to zły początek. Wiem, że jest to trochę proste jak na standardy gry w golfa, ale było fajnie i mam nadzieję, że nie przeszkadza mi, jeśli zostawię jakieś uwagi przyszłej jaźni.

Jak to działa

Zasadniczo symuluję „rysującego żółwia”, jak w LOGO, na siatce pikseli ASCII, ale żółw może wykonać tylko te trzy polecenia:

rt   - right turn, turn 120 degrees right (1/3 of a Turn)
rth  - right turn half, turn  60 degrees right (1/6 of a Turn)
fd n - forward, go forward n steps, drawing a trail of _, /, or \

Teraz dla każdego trójkąta idę w ten sposób, gdzie P jest 2x n-ta liczba Padovana:

fd P
rt
fd P
rt 
fd P
rt
fd P
rth

Czwarta „fd” oznacza, że ​​śledzę pierwszą stronę każdego trójkąta. Pomaga to wrócić do dobrego punktu wyjścia do następnego trójkąta. Pół skrętu w prawo upewnia się, że następny trójkąt będzie we właściwej orientacji.


Aby zagrać w żółwia, przechowuję 5 zmiennych stanu w tablicy 态: x pozycja, y pozycja, x prędkość, y prędkość i „runa rysująca”. W każdej klatce animacji x + = x prędkość, y + = y prędkość, a runa jest rysowana.

Potem ustawiam tabelę 表, która mówi, jak wykonać turę. Kod kierunkowy jest trudny ze względu na sposób działania grafiki ASCII. Nie jest to prosty ruch jak na ekranie pikselowym. Kierunek żółwia, określony przez prędkość xiy, decyduje o zmianach koniecznych do uzyskania właściwego skrętu.

Aby obrócić, patrzy na bieżącą prędkość xiy i łączy je w indeks.

xv = x velocity, yv = y velocity. 
i.e. a turtle facing down and to the right has 
xv of 1, and yv of 1. It can only face 6 
different directions. Formula is (xv+1)*2+yv+1

xv  yv    index
-1  -1    0
-1   0    1
-1   1    2
 1  -1    4
 1   0    5
 1   1    6

Ten indeks służy do wyszukiwania zestawu 5 wartości w tabeli 表. Te 5 wartości z tabeli 表 są następnie dodawane do każdej z 5 zmiennych w stanie 态. Żółw jest następnie skutecznie obracany i gotowy do następnego „fd”.

Po drugie, połowa skrętu w prawo, jest osobna sekcja tabeli 表. Jest to kompensowane przez 7 * 5 lub 35 wpisów z pierwszej tabeli w 表.

Na koniec wykonałem proste kodowanie liczb całkowitych tabeli na ciąg ascii.

Wiem, że mógłbym „zaoszczędzić bajty”, usuwając Hanzi, ale jak już powiedziałem, nie jest to optymalne i istnieje więcej możliwości gry w golfa ... Usunę je, gdy nie będzie żadnej innej możliwej optymalizacji. Ci Hanzi faktycznie mają luźne znaczenie w oparciu o ich rzeczywiste znaczenie i chociaż nie znam chińskiego, pomaga mi to myśleć o programie.

数  index number
宽  screen width
素  pixel data
梴  length of side of triangle
态  current state
址  address of pixel
表  state transition table

Aby przetestować kod, potrzebujesz pełnego pliku golang z tym nagłówkiem

package main
import "fmt"

i ta stopka

func main ()  {
    for i := 0; i<15; i++ {
       卷(i)
    }
}

dzięki

Don Bright
źródło