Кох Сніжинка - кодовий гольф


21

Сніжинки Коха (також відомі як зірка Коха і острів Кох) є математичним кривої , і один з найбільш ранніх фрактальних кривих , щоб було описано. Він заснований на кривій Коха, яка з'явилася в документі 1904 р. Під назвою "Про суцільну криву без дотичних, сконструйованих за допомогою елементарної геометрії" (оригінальна французька назва: "Sur une curbe continue sans tangente, obtenue par une building géométrique élémentaire") шведський математик Гельге фон Кох.

введіть тут опис зображення

Ось кілька зображень ascii різних ітерацій:

n=1
__
\/

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

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

Оскільки, очевидно, існує обмеження дозволу представлення ascii, ми повинні збільшити розмір сніжинки в 3 рази для кожної ітерації, щоб показати додаткову деталізацію.

Напишіть найкоротший код, щоб вивести сніжинку в одному стилі для n = 4

Ваша програма не повинна приймати жодних даних.
Ваша програма повинна записати сніжинку на консоль.


Ког-сніжинка .. тег .. ось цікаво .. !! .. здається, ви будете запускати більше запитань щодо цього тегу :)
Aman ZeeK Verma

5
Занадто короткий для відповіді: wolframalpha.com/input/?i=koch+snowflake+4 : D
Доктор Белісарій

1
Чи слід змінювати прийняту відповідь? Зараз є більш короткі рішення.
Тімві

Відповіді:


2

Пітон, 338 байт

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

Просто черговий подвиг unicode

бігти на ideone


5
Досить справедливо, але, безумовно, це зробить вихідний файл більше 300 байт.
Тімві

посилання порушено
Chiel ten Brinke

10

Пітон, 650 612 594 574 символів

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

Це працює, розширюючи трикутник на коефіцієнт 3 кожного разу. Для цього нам слід відстежувати, чи є кожен символ лівою чи правою межею (наприклад, як /розширюється, залежить від того, яка сторона /знаходиться всередині). Ми використовуємо різні символи для двох можливих випадків:

_: _, 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

dЗмінний обробляє спеціальний випадок , коли розкладання aповинні поширюватися в 3x3 в наступному рядку.


+1 за отримання першої відповіді на дошці. Я думаю, ви можете замінити подвійні пробіли вкладкою в циклі for. Також спробуйте використовувати, якщо k <"C" замість K == "A" і т. Д. Тепер мені доведеться придивитися до вашого алгоритму :)
gnibbler

Ви не можете видалити безліч, якщо оператори з асоціативним масивом? І, можливо, ланцюгові заяви заміни можна скоротити масивом.
Набб

('acEei',r'_/\\ ')=> ('aecEi','_\/\ ')економить ще 1. Ви також можете перевірити unicode.translate().
гніблер

Це також друкує близько 18 рядків до сніжинки, але я вважаю , що ОП не уточнив , є чи що - небудь інше може бути надруковано , ніж сніжинка.
RomanSt

6

16-бітний код машини MS-DOS: 199 байт

Розшифруйте цей сайт , збережіть як файл 'koch.com' та виконайте з командного рядка 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==

Оновлення

Ось легка для читання версія асемблера:

  ; 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

Скасуйте магію :), будь ласка, допоможіть мені зрозуміти це (принаймні надайте посилання на те, що ви робили)
Аман ZeeK Верма

@Aman: Для отримання результату використовується опис L-системи кривої Коха. Рівень деталізації встановлюється в регістрі СІ, хоча розмір обмежений 252 символами на рядок. Вам потрібно буде змінити код друку, щоб отримати рядки довше 79 символів (тобто змінити, де він пише символи '\ n $').
Скізз

також можна використовувати "scAA...w==".decode("base64")для декодування в Python2 (не працює для Python3)
gnibbler

+1 зараз, коли у мене є машина для роботи з Windows. Ви можете включити версію ASM?
гніблер

2
@mellamokb: помилка, адже, можливо, доступний весь вихідний код?
Скізз

4

Perl, 176 175 байт

Опублікуйте це як окрему відповідь, оскільки він використовує двійковий вихідний файл, який, можливо, трохи хитро. Але враховуючи, що це все-таки Perl вихідний код , я думаю, що це чудово, що він перемагає рішення машинного коду MS-DOS !

Джерело у кодованому base64

JF89IsLApwag0dhnMmAmMEcGIAcGQNHYwsDRFLsQ0djCwKcGoNHYwsDRFDdbECYwcRUxe1DCwNEUuxDR2
CI7c14uXiR4PW9yZCQmOyQieCgkeD4+MykucXcoXCAvXyBfXy8gXC8gX18gX1wgLyBfXy9cX18pWyR4Jj
ddXmVnO3NeLnsyN31eJF89cmV2ZXJzZSQmO3l+L1xcflxcL347cHJpbnQkJi4kXy4kL15lZw==

Дещо легше читати

Замініть всі екземпляри /<[0-9a-f]+>/відповідними бінарними даними:

# 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

У цій версії сніжинка кодується таким чином:

  • 8 біт у кожному байті поділяються так:

    +---+---+---+---+---+---+---+---+
    |      5 bits       |   3 bits  |
    +---+---+---+---+---+---+---+---+
              R               C
    
  • Rкодує пробіл. Найдовший пробіг - 27 символів, тому всі прогони вміщуються в 5 біт.

  • Cкодує послідовність символів, яку просто шукають у прямому масиві. (У мене раніше було трохи божевільніші кодування тут, де містився лише масив / \ _, але код Perl, необхідний для його розшифровки, був довшим ...)

  • Мені пощастило, що двійкові дані не містять жодного "/ 'або \того, що потребує втечі. Я не планував цього. Але навіть якби це було, я, певно, міг би просто змінити порядок елементів у масиві, щоб це виправити.

  • Дивовижно, наскільки просте це рішення порівнюється з десятками інших рішень, які я пройшов, перш ніж я придумав це. Я експериментував з багатьма різними бітовими кодуваннями, складнішими за цю, і мені ніколи не спадало на думку, що простіше може бути варте того, що просто, оскільки код Perl для його розшифровки був би коротшим. Я також намагався стиснути повтори в даних, використовуючи змінну інтерполяцію (див. Іншу відповідь), але з новітньою версією, яка більше не набирає жодних символів.


3

Пітона, 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('/')])

З трохи більше пробілу:

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('/')])

Ліва сторона стискається; правий бік відтворений з лівого боку.


3

Perl, 224 223 символи

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

Дещо легше читати

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

Як це працює

Для пояснення того, як це працює, дивіться іншу відповідь, в якій я розміщую те саме у двійковій формі . Мені дуже шкода , що я на самому ділі не генеруючи сніжинку Коха, просто стискаючи його ...

Попередні версії

  • (359) Зашифрував всю сніжинку замість лише лівої половини. Проміжки були включені в бітове кодування; ще немає тривалості пробігу. Використовували кілька інтерпольованих змінних плюс @_масив, до якого звертався за допомогоюs/\d/$_[$&]/eg . Нові рядки були закодовані як !.

  • (289) Перша версія, що кодувала лише ліву половину сніжинки.

  • (267) Перша версія, що використовувала кодування довжини пробігу для пробілів.

  • (266) Змінити ' 'на$" .

  • (224) Радикально відрізняється стиснення, закодоване як основа-64. (Зараз еквівалентний двійковій версії .)

  • (223) Зрозумів, що я можу помістити друк всередині останнього субстрату і таким чином зберегти крапку з комою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.