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.


Koch-snowflake .. tag .. to ciekawe .. !! .. wygląda na to, że będziesz strzelał więcej pytań na temat tego tagu :)
— Aman ZeeK Verma


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


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.


+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

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.


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.


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.