Koch Snowflake - codegolf

21

Krzywa kocha (znany także jako gwiazda Koch i Koch Island) to matematyczna krzywa i jeden z najwcześniejszych fraktalnych krzywych zostały opisane. Opiera się na krzywej Kocha, która ukazała się w artykule z 1904 r. Zatytułowanym „Na ciągłej krzywej bez stycznych, możliwej do zbudowania z geometrii elementarnej” (oryginalny francuski tytuł: „Sur une courbe kontynuacja sans tangente, obtenue par une construction géométrique élémentaire”) przez szwedzki matematyk Helge von Koch.

wprowadź opis zdjęcia tutaj

Oto niektóre ascii reprezentacje różnych iteracji:

n=1
__
\/

n=2
__/\__
\    /
/_  _\
  \/

n=3
      __/\__
      \    /
__/\__/    \__/\__
\                /
/_              _\
  \            /
__/            \__
\                /
/_  __      __  _\
  \/  \    /  \/
      /_  _\
        \/ 

Ponieważ istnieje oczywiście ograniczenie rozdzielczości reprezentacji ascii, musimy powiększyć rozmiar płatka śniegu o współczynnik 3 dla każdej iteracji, aby pokazać dodatkowe szczegóły.

Napisz najkrótszy kod, aby wypisać płatek śniegu w tym samym stylu dla n = 4

Twój program nie powinien pobierać żadnych danych wejściowych.
Twój program powinien zapisać płatek śniegu na konsoli.

gnibbler
źródło
Koch-snowflake .. tag .. to ciekawe .. !! .. wygląda na to, że będziesz strzelał więcej pytań na temat tego tagu :)
Aman ZeeK Verma
5
Za krótki na odpowiedź: wolframalpha.com/input/?i=koch+snowflake+4 : D
Dr. belisarius
1
Czy należy zmienić zaakceptowaną odpowiedź? Teraz są krótsze rozwiązania.
Timwi

Odpowiedzi:

2

Python, 338 bajtów

#coding:u8
print u"碜䄎쀠ࢻ﬊翀蝈⼖㗎芰悼컃뚔㓖ᅢ鄒鱖渟犎윽邃淁挢㇌ꎸ⛏偾࿵헝疇颲㬤箁鴩沬饅앎↳\ufaa4軵몳퍋韎巃๧瓠깡未늳蒤ꕴ⁵ᦸ䥝両䣚蟆鼺伍匧䄂앢哪⡈⁙ತ乸ሣ暥ฦꋟ㞨ޯ⿾庾뻛జ⻏燀䲞鷗﫿".encode("utf-16be").decode("zlib")

Po prostu kolejny exploit unicode

biegać w ideone

TY
źródło
5
W porządku, ale z pewnością spowodowałoby to, że plik źródłowy miałby więcej niż 300 bajtów.
Timwi
link jest zerwany
Chiel ten Brinke
10

Python, 650 612 594 574 znaków

n='\n'
S='_a/G\F I\n'
A=dict(zip(S,('III','   ','__/','  G','\  ','F__','   ','III','')))
B=dict(zip(S,('III','   ','\  ',' aF','/a ','  G','   ','III','')))
C=dict(zip(S,('___','aaa','/  ','GII','II\\','  F','   ','III','')))
def T(s):
 a=b=c=d=r=u''
 for k in s:
    a+=A[k];b+=B[k];c+=C[k]
    if k=='I':a=a[:-3]+('II\\'if'a '==d[1:3]else'GII'if' a'==d[:2]else 3*k)
    d=d[3:]
    if k==n:d=c.replace('____','__/F').replace('aaaa','aa  ').replace('/  a','/a  ').replace('a  F','  aF');r+=a+n+b+n+d+n;a=b=c=''
 return r
print T(T(T('__\n\G\n'))).translate({97:95,71:47,73:32,70:92})

Działa to poprzez rozszerzenie trójkąta za każdym razem o współczynnik 3. Aby to zrobić, musimy śledzić, czy każdy symbol jest lewą czy prawą granicą (np. Sposób /rozwinięcia zależy od tego, która strona /jest wewnątrz). Używamy różnych symboli dla dwóch możliwych przypadków, jak następuje:

_: _, outside on the top
a: _, outside on the bottom
/: /, outside on the left
G: /, outside on the right
\: \, outside on the left
F: \, outside on the right
<space>: inside
I: outside

dZmienna zajmuje się szczególny przypadek, w którym rozprężeniowej aaby przedłużyć do 3x3 w następnym wierszu.

Keith Randall
źródło
+1 za uzyskanie pierwszej odpowiedzi na tablicy. Myślę, że możesz zamienić podwójne spacje na tabulatory w pętli for. Spróbuj także użyć if k <"C" zamiast K == "A" itd. Teraz będę musiał przyjrzeć się bliżej Twojemu algorytmowi :)
gnibbler
Czy nie można usunąć wielu instrukcji if z tablicą asocjacyjną? I może łańcuchowe instrukcje zamiany można skrócić za pomocą tablicy.
Nabb
('acEei',r'_/\\ ')=> ('aecEi','_\/\ ')oszczędza jeszcze 1. Możesz także sprawdzić unicode.translate().
gnibbler
Spowoduje to również wydrukowanie około 18 nowych linii przed płatkiem śniegu, ale przypuszczam, że OP nie określił, czy może być wydrukowane coś innego niż płatek śniegu.
RomanSt
6

16-bitowy kod maszynowy MS-DOS: 199 bajtów

Dekoduj przy użyciu tej strony , zapisz jako plik „koch.com” i uruchom z wiersza poleceń WinXP.

sCAAxo7ajsKLz/OquF9fulwvvUoBM9u+BADoiQDodgDocwDogADobQDoagDodwCK8TLSs0+I98cHDQrGRwIktAnNIf7GOO5+7MNWAVwBYwFsAXoBgwGJB4DDAsOIN/7D6QQA/suIF/7P6R0A/suAPyB1AogH/suIB8OBw/8AiDfpBgD+x4gX/sM4734Ciu84z30Cis/Dg8UIg8UCgf1WAXLzg+0Mw07/dgB0GV/o9v/o5v/o8P/o3f/o2v/o5//o1//o4f9Gww==

Aktualizacja

Oto łatwa do odczytania wersja asemblera:

  ; L-System Description
  ;
  ; Alphabet : F
  ; Constants : +, -
  ; Axiom : F++F++F
  ; Production rules: F -> F-F++F-F 
  ;
  ; Register usage:
  ;                             _        _
  ; bp = direction: 0 = ->, 1 = /|, 2 = |\, 3 = <-, 4 = |/_, 5 = _\|
  ; cl = min y, ch = max y
  ; bl = x (unsigned)
  ; bh = y (signed)
  ; si = max level

  ; clear data
  mov al,20h
  add dh,al
  mov ds,dx
  mov es,dx
  mov cx,di
  rep stosb
  mov ax,'__'
  mov dx,'/\'

  ; initialise variables
  mov bp,Direction0
  xor bx,bx
  mov si,4

  call MoveForward
  call TurnRight
  call TurnRight
  call MoveForward
  call TurnRight
  call TurnRight
  call MoveForward

  mov dh,cl
  xor dl,dl
  mov bl,79
OutputLoop:
  mov bh,dh
  mov w [bx],0a0dh
  mov b [bx+2],24h
  mov ah,9
  int 21h
  inc dh
  cmp dh,ch
  jle OutputLoop  
  ret

Direction0:
  dw MoveRight
  dw MoveUpRight
  dw MoveUpLeft
  dw MoveLeft
  dw MoveDownLeft
  dw MoveDownRight
Direction6:

MoveRight:
  mov w [bx],ax
  add bl,2
  ret

MoveUpRight:
  mov b [bx],dh
  inc bl
  jmp DecBHCheckY

MoveUpLeft:
  dec bl
  mov b [bx],dl
DecBHCheckY:  
  dec bh
  jmp CheckY

MoveLeft:
  dec bl  
  cmp b [bx],20h
  jne MoveLeftAgain
  mov [bx],al
MoveLeftAgain:
  dec bl  
  mov [bx],al
  ret

MoveDownLeft:
  add bx,255
  mov b [bx],dh
  jmp CheckY

MoveDownRight:
  inc bh
  mov b [bx],dl
  inc bl

CheckY:
  cmp bh,ch
  jle NoMaxChange
  mov ch,bh
NoMaxChange:  
  cmp bh,cl
  jge NoMinChange
  mov cl,bh
NoMinChange:  
  ret

TurnRight:
  add bp,8

TurnLeft:
  add bp,2

  cmp bp,Direction6
  jb ret
  sub bp,12
  ret

MoveForward:
  dec si
  push [bp]
  jz DontRecurse
  pop di
  call MoveForward
  call TurnLeft
  call MoveForward
  call TurnRight
  call TurnRight
  call MoveForward
  call TurnLeft
  call MoveForward
DontRecurse:
  inc si
  ret
Skizz
źródło
Abolute magia :), pomóż mi to zrozumieć (przynajmniej podaj link do tego, co zrobiłeś)
Aman ZeeK Verma
@Aman: Wykorzystuje opis systemu L krzywej Kocha do narysowania wyniku. Poziom szczegółowości jest ustawiony w rejestrze SI, chociaż rozmiar jest ograniczony do 252 znaków w wierszu. Musisz zmodyfikować kod drukujący, aby uzyskać wiersze dłuższe niż 79 znaków (tj. Zmień, gdzie zapisuje znaki „\ n $”).
Skizz
można również użyć "scAA...w==".decode("base64")do dekodowania w Python2 (nie działa dla Python3)
gnibbler
+1 teraz, gdy mam maszynę z systemem Windows, na której można go uruchomić. Czy jest jakaś szansa na dołączenie wersji asm?
gnibbler
2
@mellamokb: err, bo może cały kod źródłowy jest dostępny?
Skizz
4

Perl, 176 175 bajtów

Opublikowanie tego jako osobnej odpowiedzi, ponieważ wykorzystuje on binarny plik źródłowy, co może być nieco podstępne. Ale biorąc pod uwagę, że wciąż jest to kod źródłowy Perla , myślę, że to niezwykłe, że wyprzedza rozwiązanie dla kodu maszynowego MS-DOS !

Źródło w postaci zakodowanej w standardzie base64

JF89IsLApwag0dhnMmAmMEcGIAcGQNHYwsDRFLsQ0djCwKcGoNHYwsDRFDdbECYwcRUxe1DCwNEUuxDR2
CI7c14uXiR4PW9yZCQmOyQieCgkeD4+MykucXcoXCAvXyBfXy8gXC8gX18gX1wgLyBfXy9cX18pWyR4Jj
ddXmVnO3NeLnsyN31eJF89cmV2ZXJzZSQmO3l+L1xcflxcL347cHJpbnQkJi4kXy4kL15lZw==

Nieco bardziej czytelny

Zastąp wszystkie wystąpienia /<[0-9a-f]+>/odpowiednimi danymi binarnymi:

# Raw data!
$_="<c2c0a706a0d1d86732602630470620070640d1d8c2c0d114bb10d1d8c2>".
   "<c0a706a0d1d8c2c0d114375b1026307115317b50c2c0d114bb10d1d8>";

# Decode left half of the snowflake (without newlines)
s^.^$x=ord$&;$"x($x>>3).qw(\ /_ __/ \/ __ _\ / __/\__)[$x&7]^eg;

# Reconstruct the right half and the newlines
s^.{27}^$_=reverse$&;y~/\\~\\/~;print$&.$_.$/^eg

W tej wersji płatek śniegu jest kodowany w następujący sposób:

  • 8 bitów w każdym bajcie jest podzielonych w następujący sposób:

    +---+---+---+---+---+---+---+---+
    |      5 bits       |   3 bits  |
    +---+---+---+---+---+---+---+---+
              R               C
    
  • Rkoduje ciąg spacji. Najdłuższy ciąg ma 27 znaków, więc wszystkie biegi mieszczą się w 5 bitach.

  • Ckoduje sekwencję znaków, które są po prostu wyszukiwane w dosłownej tablicy. (Kiedyś miałem tutaj nieco bardziej szalone kodowania, w których tylko tablica zawierała / \ _, ale kod Perla niezbędny do odkodowania go był dłuższy ...)

  • Jestem szczęśliwy, że dane binarne nie zawiera żadnych "/ 'lub \które potrzebują ucieczki. Nie planowałem tego. Ale nawet gdyby tak było, prawdopodobnie mógłbym właśnie zmienić kolejność elementów w tablicy, aby to naprawić.

  • To niesamowite, jak proste jest to rozwiązanie w porównaniu z dziesiątkami innych rozwiązań, które przeszedłem, zanim to wymyśliłem. Eksperymentowałem z wieloma różnymi kodowaniami bitowymi bardziej złożonymi niż to i nigdy nie przyszło mi do głowy, że prostsze może być tego warte, ponieważ kod Perla do jego dekodowania byłby krótszy. Próbowałem także skompresować powtórzenia w danych przy użyciu zmiennej interpolacji (patrz druga odpowiedź), ale w najnowszej wersji, która nie zyskuje już żadnych znaków.

Timwi
źródło
3

Python, 284

for s in "eJyVkNENACEIQ/+dgg1YiIT9tzgENRyWXM4/pH1tIMJPlUezIiGwMoNgE5SzQvzRBq52Ebce6cr0aefbt7NjHeNEzC9OAalADh0V3gK35QWPeiXIFHKH8seFfh1zlQB6bjxXIeB9ACWRVwo=".decode('base64').decode('zlib').split('\n'):print s+'  '*(27-len(s))+'\\'.join([c.replace('\\','/')for c in s[::-1].split('/')])

Z nieco więcej białych znaków:

for s in "eJyVkNENACEIQ/+dgg1YiIT9tzgENRyWXM4/pH1tIMJPlUezIiGwMoNgE5SzQvzRBq52Ebce6cr0aefbt7NjHeNEzC9OAalADh0V3gK35QWPeiXIFHKH8seFfh1zlQB6bjxXIeB9ACWRVwo=".decode('base64').decode('zlib').split('\n'):
  print s + '  '*(27-len(s)) + '\\'.join([c.replace('\\','/') for c in s[::-1].split('/')])

Lewa strona jest ściśnięta; prawa strona jest odtwarzana z lewej strony.

RomanSt
źródło
3

Perl, 224 223 znaków

use MIME::Base64;$_=decode_base64 wsCnBqDR2GcyYCYwRwYgBwZA0djCwNEUuxDR2MLApwag0djCwNEUN1sQJjBxFTF7UMLA0RS7ENHY;s^.^$x=ord$&;$"x($x>>3).qw(\ /_ __/ \/ __ _\ / __/\__)[$x&7]^eg;s^.{27}^$_=reverse$&;y~/\\~\\/~;print$&.$_.$/^eg

Nieco bardziej czytelny

use MIME::Base64;

# raw binary data in base-64-encoded form as a bareword
$_=decode_base64
    wsCnBqDR2GcyYCYwRwYgBwZA0djCwNEUuxDR2MLApwag0djCwNEUN1sQJjBxFTF7UMLA0RS7ENHY;

# Decode left half of the snowflake (without newlines)
s^.^$x=ord$&;$"x($x>>3).qw(\ /_ __/ \/ __ _\ / __/\__)[$x&7]^eg;

# Reconstruct the right half and the newlines
s^.{27}^$_=reverse$&;y~/\\~\\/~;print$&.$_.$/^eg

Jak to działa

Aby uzyskać wyjaśnienie, jak to działa, zobacz drugą odpowiedź, w której umieszczam to samo w formacie binarnym . Jestem bardzo przykro, że nie jestem faktycznie generowania płatek śniegu Koch, ściskając go po prostu ...

Poprzednie wersje

  • (359) Zakodowałem cały płatek śniegu zamiast tylko lewej połowy. Spacje zostały włączone do kodowania bitów; nie ma jeszcze długości. Użyto kilku zmiennych interpolowanych oraz @_tablicy, do której uzyskano dostęp za pomocą s/\d/$_[$&]/eg. Newlines zostały zakodowane jako !.

  • (289) Pierwsza wersja, która zakodowała tylko lewą połowę płatka śniegu.

  • (267) Pierwsza wersja, w której zastosowano kodowanie długości spacji.

  • (266) Zmień ' 'na $".

  • (224) Zupełnie inna kompresja, zakodowana jako base-64. (Teraz odpowiada wersji binarnej ).

  • (223) Zdałem sobie sprawę, że mogę umieścić nadruk w ostatnim zastępstwie, a tym samym zapisać średnik.

Timwi
źródło