눈 좀 내놔!


18

임무 : n 번째 깊이까지 코흐 눈송이를 생성합니다. 완전한 코흐 눈송이를 만들 필요는 없습니다. 시작 삼각형의 한 면일뿐입니다. 코흐 조각에 위키 백과 : https://en.wikipedia.org/wiki/Koch_snowflake .

규칙 :

  • 프로그램은 Koch 눈송이의 한쪽을 n 번째 깊이까지 생성해야합니다.
  • 출력은 ASCII 여야합니다.
  • 눈송이 전체를 생성 있습니다 . 필요하지 않습니다.
  • 입 / 출력 및 허점 및 재료에 대한 표준 규칙이 적용됩니다.
  • 모든 문자가 서로에 대해 올바른 위치에 있으면 공백은 중요하지 않습니다.
  • 최단 코드 승리!

테스트 사례 :

n = 0 :

__

n = 1 :

__/\__

n = 2 :

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

n = 3 :

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

이것이 의미가 있기를 바랍니다. 각 테스트 사례에서 프랙탈은 길이가 같은 세 부분으로 나눌 수 있습니다. 또한 각 눈송이의 너비는 이전 세대 눈송이의 너비의 3 배입니다.


참고로,이 중 속는 아니라는 것을 동의했다 .
스파클 포니 동지

n 번째 Koch 곡선의 적절한 ASCII 표현이 무엇인지 적절하게 정의하지 않았다고 생각합니다.
orlp

비율이 의미가 있는지 확실하지 않습니다. 중복되지 않은 __/\__두 개의 밑줄을 사용 하여 각 반복을 이전보다 3 배 크게 일관되게 만들었습니다. 하나의 밑줄 만 사용하면 모순이 n = 3에서 어색해지기 시작하는 것 같습니다. 중간 부분의 결과로서 만 폭 (10)를 갖는다 예 외측 부분 (12)이 폭 /__\ 그 너무 좁아서된다. 그리고 그 전에도 _너비 /와 너비의 두 배로 확장했습니다 \ .
Ørjan Johansen 2016 년

나는 /_and _\ 가 유일한 치명적인 부분 이라고 생각합니다 . 밑줄은 /and와 같은 위치에 있어야하기 때문에 가야합니다 \ . 이 작업이 완료되면 n = 1부터 3 배까지 확장 할 수 있습니다 (그러나 n = 0이 맞지 않습니다)
Ørjan Johansen 2016.

아아, 아니오, 중간 부분은 여전히 ​​바깥 부분과 일치하지 않습니다 .54 = 2 * 3 ^ 3이 아닌 너비 52를 갖는 n = 3에 의해 입증됩니다. 한보십시오 이를 . 나는 n = 4 또는 n = 5로만 나타나는 부분이있는 거꾸로 된 버전을 포함했습니다-밑줄이 떨어지는 위쪽 버전과 다릅니다.
Ørjan Johansen 2016 년

답변:


10

하스켈 , 308 300 299 바이트

편집 :

  • -4 바이트 : 변경 zipWith(+)zipWith(-)와 조정 인코딩 및 오프셋은 모든 부정 기호를 제거 얻었다.
  • -1 바이트 : 인코딩을 추가 조정하면 직접 패턴 일치 대신 여러 변수 이름을 #삭제할 수있었습니다 r=reverse.
  • -2 바이트 :에 대해 영숫자 대신 연산자 사용 zipWith(-).
  • -1 바이트 : o=[0,0]목록 상수를 짧게 정의 합니다.
  • -1 바이트 :의 두 가지를 병합 ?합니다.
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]

온라인으로 사용해보십시오! (슬프게도 n = 3보다 큰 것은 엄청나게 줄 바꿈되어 읽을 수 없지만 다른 프로그램에 복사하여 볼 수 있습니다.)

변형

작동 원리

  • k주요 함수이며, Int na를 반환하고 a를 반환합니다 String.
  • iterate(>>=(:[1,4,1]))[6]각 n 에 대해 곡선 반복에서 연속 선 사이 의 회전 , 거북이 그래픽 스타일을 명목상 0및 사이의 숫자로 포함하는 무한 목록을 생성합니다 5. 각 반복은 턴이 1,4,1인터리브 된 이전 반복입니다 . 서브리스트 6대신에 시작하는 유일한 이유는 피하는 방법으로 트릭 0을 만드는 것 입니다.gcdff 0
  • scanl1(+)회전을 모듈로 6까지 "절대"방향으로 변환합니다. A 0는 오른쪽을 의미하며, 그보다 높은 각 숫자는 이전보다 반 시계 방향으로 60 도입니다. (이것이 ASCII가 아닌 적절한 그림이라면 60 도입니다.)
  • f 절대 방향을 곡선에 추가 할 문자 (수평 방향의 경우 두 쌍을 생성하고 그렇지 않으면 하나를 생성)를 인코딩하는 (문자, 오프셋 인코딩) 쌍 목록으로 변환하고 상대 위치가 어떻게 변경되는지를 변환합니다.
  • #실제 (좌표, 캐릭터)를 생성 쌍 (문자 인코딩 오프셋) 쌍의리스트를 이전의 조작을 반복.
  • 인코딩 원리 :
    • _/\명목상 의 문자 는 시작 모서리에서 직사각형 셀을 통해 다른 끝 모서리로 그려진 선을 나타냅니다.
    • 셀 좌표의 형식 [y,x]은 위에서 아래로, 왼쪽에서 오른쪽으로, 인쇄하려는 순서대로 정렬됩니다. 열은 1부터 시작합니다. 으로 짧은 벡터 산술을 위해 튜플 대신 목록이 사용됩니다 (&)=zipWith(-).
    • 모서리는 [y,x]셀의 왼쪽 위와 동일한 좌표 로 표시됩니다 . 이렇게하면 코너에서 인접 셀까지의 모든 오프셋이 음수가 아니므로 음수가 아닙니다.
    • 그러나 모퉁이 좌표는 부정으로 전달되어 모든 벡터 연산이 더하기 대신 빼기를 허용하므로 다른 모든 명시 적 부호를 피할 수 있습니다.
    • 오프셋 부호화 목록은 [y1,x1,x2,y2]여기서 [y1,x1]상기 문자 셀 시작 모서리로부터 오프셋 좌표와 [y2,x2]상기 문자 셀의 단부 모서리로부터 오프셋된다. 이것은 다음을 의미합니다.
      • 부호화 나열 방향에 대해 3.. 5단지 대한리스트의 역이다 0.. 2, 이들을 생성 할 수 있도록 [id,r]<*>.
      • 필요한 모든 벡터 산술은 (&)=zipWith(-)인코딩 목록 또는 그 반대로 사용하여 수행 할 수 있습니다 .
  • (좌표, 문자) 쌍의 목록을 정렬 한 후로 전달되어 ?최종 결과를 생성 String합니다.
    • In x?l@(([_,w],c):r) x은이 줄에 표시된 이전 문자의 x 좌표입니다 0. l전체 현재 목록, w추가 할 다음 문자의 x 좌표 c, 문자 및 r나머지 목록입니다.
    • 이 단계에서 y 좌표는 더 이상 필요하지 않습니다. 모든 줄은 문자를 포함하고 모든 줄의 첫 번째 문자는 이전 줄의 끝 왼쪽에 있으므로 x 좌표가 감소했는지 확인하여 새 줄의 시작을 감지합니다.
    • 밑줄은 \and 보다 큰 ASCII 값 /을 가지므로 같은 위치에있는 다른 문자와 겹치면 마지막으로 정렬됩니다. 따라서 x 좌표가 반복되었는지 확인하여 중복 밑줄이 감지됩니다.

좋은! 오늘이 질문에 더 이상 활동이 없으면 이것을 수락합니다.
스파클 포니 동지
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.