Làm một số tuyết!


18

Nhiệm vụ của bạn: tạo ra một bông tuyết Koch đến độ sâu thứ n. Bạn không cần phải tạo ra một bông tuyết Koch hoàn chỉnh, chỉ cần một bên của tam giác bắt đầu. Wikipedia về mảnh bong bóng của Koch: https://en.wikipedia.org/wiki/Koch_snowflower .

Quy tắc:

  • Chương trình phải tạo ra một mặt của bông tuyết Koch đến độ sâu thứ n.
  • Đầu ra phải là ASCII.
  • Bạn có thể tạo ra toàn bộ bông tuyết; Điều này là không bắt buộc.
  • Quy tắc tiêu chuẩn cho đầu vào / đầu ra và sơ hở và công cụ áp dụng.
  • Khoảng trắng không quan trọng, miễn là tất cả các ký tự ở đúng vị trí so với nhau.
  • Mã ngắn nhất sẽ thắng!

Các trường hợp thử nghiệm:

n = 0:

__

n = 1:

__/\__

n = 2:

      __/\__
      \    /
__/\__/    \__/\__

n = 3:

                        __/\__
                        \    /
                  __/\__/    \__/\__
                  \                /
                  /_              _\
                    \            /
      __/\__      __/            \__      __/\__
      \    /      \                /      \    /
__/\__/    \__/\__/                \__/\__/    \__/\__

Tôi hy vọng điều này có ý nghĩa. Lưu ý rằng trong mỗi trường hợp thử nghiệm, fractal có thể được chia thành ba phần bằng nhau về chiều dài. Cũng lưu ý rằng chiều rộng của mỗi bông tuyết gấp ba lần chiều rộng của thế hệ trước của bông tuyết.


FYI, đã đồng ý rằng đây không phải là một bản sao của điều này .
Đồng chí SparklePony

Tôi không nghĩ rằng bạn đã xác định một cách thích hợp biểu diễn ASCII thích hợp của đường cong thứ n là gì.
orlp

Tôi không chắc chắn tỷ lệ có ý nghĩa. Không dupe được sử dụng __/\__với hai gạch chân, làm cho mỗi lần lặp lại lớn gấp 3 lần so với lần trước. Chỉ sử dụng một gạch chân dường như sẽ tạo ra mâu thuẫn bắt đầu trở nên thực sự khó xử trong n = 3. Ví dụ, các phần bên ngoài có chiều rộng 12 trong khi phần giữa chỉ có chiều rộng 10, do hậu quả của /__\ quá chật chội. Và thậm chí trước đó bạn đã _mở rộng gấp đôi chiều rộng /\ .
Ørjan Johansen

Tôi nghĩ rằng /__\ là phần duy nhất thực sự gây tử vong - phần dưới cần phải đi, bởi vì chúng cần phải ở cùng vị trí với /\ . Khi đã xong, mọi thứ có thể mở rộng gấp 3 lần từ n = 1 trở đi (nhưng n = 0 không phù hợp.)
Ørjan Johansen

Than ôi, không, phần giữa vẫn có chiều rộng không khớp với các phần bên ngoài, bằng chứng là n = 3 có chiều rộng 52 chứ không phải 54 = 2 * 3 ^ 3. Hãy thử một trong những thứ này . Tôi đã bao gồm các phiên bản lộn ngược với các phần chỉ hiển thị từ n = 4 hoặc n = 5 - chúng khác với các phiên bản hướng lên trong đó phần dưới được bỏ đi.
Ørjan Johansen

Câu trả lời:


10

Haskell , 308 300 299 byte

Chỉnh sửa:

  • -4 byte: Thay đổi zipWith(+)để zipWith(-)điều chỉnh mã hóa và offsets đã thoát khỏi tất cả các dấu hiệu phủ định.
  • -1 byte: Điều chỉnh thêm mã hóa cho phép loại bỏ một số tên biến #bằng cách sử dụng r=reversethay vì khớp mẫu trực tiếp.
  • -2 byte: Sử dụng toán tử thay vì chữ và số cho zipWith(-).
  • -1 byte: Xác định o=[0,0]để rút ngắn các hằng danh sách.
  • -1 byte: Hợp nhất hai nhánh của ?.
import Data.List
k n=0?sort(o#(f=<<scanl1(+)(iterate(>>=(:[1,4,1]))[6]!!n)))
x?l@(([_,w],c):r)|x>w='\n':0?l|0<1=([2..w-x]>>" ")++[c|w>x]++w?r
_?_=""
w#((c,l):m)=(l&w,c):r l&(l&w)#m
_#_=[]
f x=zip"_/\\_/\\"([id,r]<*>[0:1:o,[0,1,0,1],o++[1,1]])!!mod x 6<$[1,3..gcd 3x]
(&)=zipWith(-)
r=reverse
o=[0,0]

Hãy thử trực tuyến! (Đáng buồn thay, bất cứ điều gì lớn hơn n = 3 đều bị gói ghém khủng khiếp và không thể đọc được, nhưng bạn có thể sao chép nó sang một chương trình khác để xem nó.)

Biến thể

Làm thế nào nó hoạt động

  • klà hàm chính, nó lấy Int nvà trả về a String.
  • iterate(>>=(:[1,4,1]))[6]tạo ra một danh sách vô hạn chứa, với mỗi n, các ngã rẽ giữa các dòng liên tiếp trong lần lặp đường cong đó, kiểu đồ họa rùa, như các số trên danh nghĩa giữa 05. Mỗi lần lặp chỉ là lần lặp trước với các lượt được 1,4,1xen kẽ. Lý do duy nhất mà các danh sách phụ bắt đầu 6thay vì 0là để thực hiện các gcdmẹo trong fcông việc bằng cách tránh f 0.
  • scanl1(+)chuyển đổi các ngã rẽ thành các hướng "tuyệt đối", lên tới modulo 6. A 0có nghĩa là phải, sau đó mỗi số cao hơn là 60 độ ngược chiều kim đồng hồ so với trước. (Chà, sẽ là 60 độ nếu đây là bản vẽ phù hợp thay vì ASCII.)
  • f chuyển đổi một hướng tuyệt đối thành một danh sách các cặp (ký tự, mã hóa bù) mã hóa các ký tự để thêm vào đường cong (đối với các hướng ngang, nó tạo ra hai cặp, nếu không là một) và cách thay đổi vị trí tương đối.
  • Các #lặp điều hành thông qua các danh sách trước đó của (nhân vật, bù đắp mã hóa) cặp, tạo ra (nhân vật phối hợp,) cặp thực tế.
  • Nguyên tắc mã hóa:
    • Một ký tự từ _/\danh nghĩa đại diện cho một dòng được vẽ từ một góc bắt đầu thông qua một ô hình chữ nhật đến một góc kết thúc khác.
    • Các tọa độ ô có dạng [y,x], từ trên xuống dưới, từ trái sang phải, để chúng sắp xếp theo thứ tự chúng tôi muốn in chúng. Cột dựa trên 1. Danh sách được sử dụng thay vì bộ dữ liệu cho số học vectơ ngắn hơn với (&)=zipWith(-).
    • Một góc được biểu thị với cùng tọa độ [y,x]với ô ở phía trên bên trái của nó. Điều này đảm bảo rằng tất cả các độ lệch từ một góc tới các ô lân cận của nó là không âm, tránh các hằng số âm.
    • Tuy nhiên, tọa độ góc được truyền xung quanh phủ định để cho phép tất cả các phép toán vectơ được trừ thay vì bổ sung, điều này tránh tất cả các dấu hiệu rõ ràng khác.
    • Danh sách mã hóa bù là [y1,x1,x2,y2]vị trí [y1,x1]tọa độ bù từ góc bắt đầu đến ô ký tự và [y2,x2]là phần bù từ góc cuối đến ô ký tự. Điều này có nghĩa là:
      • Danh sách mã hóa cho các hướng 3.. 5chỉ là mặt trái của danh sách cho 0.. 2, cho phép chúng được tạo với [id,r]<*>.
      • Tất cả số học vectơ cần thiết có thể được thực hiện bằng cách sử dụng (&)=zipWith(-)với danh sách mã hóa hoặc ngược lại.
  • Sau khi sắp xếp danh sách các cặp (tọa độ, ký tự), chúng được chuyển đến ?, tạo ra kết quả cuối cùng Stringtừ chúng.
    • In x?l@(([_,w],c):r) xlà tọa độ x của ký tự trước được hiển thị trên dòng này hoặc 0nếu ở đầu dòng; llà toàn bộ danh sách hiện tại, wlà tọa độ x của ký tự tiếp theo được thêm vào, clà ký tự và rlà danh sách còn lại.
    • Ở giai đoạn này, tọa độ y không còn cần thiết nữa. Bởi vì mỗi dòng chứa các ký tự và ký tự đầu tiên của mỗi dòng nằm ở bên trái của cuối dòng trước, nên bắt đầu các dòng mới bằng cách kiểm tra xem tọa độ x có giảm không.
    • Underscore có giá trị ASCII lớn hơn \/, do đó, nó được sắp xếp sau cùng nếu nó trùng với một ký tự khác ở cùng vị trí. Do đó, một dấu gạch dưới dự phòng được phát hiện bằng cách kiểm tra tọa độ x đã được lặp lại.

Đẹp! Tôi sẽ chấp nhận điều này nếu không có thêm hoạt động nào cho câu hỏi này ngày hôm nay.
Đồng chí SparklePony
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.