ASCII 파도바 나선형 생성


22

도전 의 ASCII 버전입니다 . Martin Poster가 요청 당 초기 게시물을 분리했습니다.

소개

피보나치 수열과 유사하게 파도바 수열 ( OEIS A000931 )은 수열에 이전 항을 추가하여 생성되는 수열입니다. 초기 값은 다음과 같이 정의됩니다.

P(0) = P(1) = P(2) = 1

0, 1, 2 번째 항은 모두 1입니다. 반복 관계는 다음과 같습니다.

P(n) = P(n - 2) + P(n - 3)

따라서 다음과 같은 시퀀스가 ​​생성됩니다.

1, 1, 1, 2, 2, 3, 4, 5, 7, 9, 12, 16, 21, 28, 37, 49, 65, 86, 114, 151, 200, 265, 351, ...

이 숫자를 정삼각형의 측면 길이로 사용하면 피보나치 나선과 같이 모두 함께 배치 할 때 멋진 나선을 얻을 수 있습니다.

여기에 이미지 설명을 입력하십시오

Wikipedia의 이미지 제공


태스크

당신의 임무는 ASCII 용어 로이 나선을 재현하는 프로그램을 작성하는 것입니다. 측면 길이 1 (1 문자)의 삼각형을 ASCII로 멋지게 표현할 수 없기 때문에 측면 길이가 2의 배수로 확장되었습니다. 따라서 측면 길이 1의 삼각형은 실제로 다음과 같이 표시됩니다.

 /\
/__\

예를 들어, 입력이 5 (5 번째 항) 인 ​​경우 출력은 다음과 같아야합니다.

   /\
  /  \
 /    \
/______\
\      /\
 \    /__\ 
  \  /\  /
   \/__\/

처음 5 개의 항은 1, 1, 1, 2, 2이므로 삼각형은 팽창으로 인해 측면 길이 2, 2, 2, 4, 4를 가졌습니다. 입력 8의 다른 예 :

     __________
   /\          /\
  /  \        /  \
 /    \      /    \
/______\    /      \
\      /\  /        \
 \    /__\/          \
  \  /\  /            \
   \/__\/______________\
    \                  /
     \                /
      \              /
       \            /
        \          /
         \        /
          \      /
           \    /
            \  /
             \/

규칙

  • 결과를 인쇄해야하며 입력은 용어 번호에 해당하는 정수 여야합니다.
  • 후행 및 선행 개행이 허용되며, 라인 이후의 후행 공백도 허용됩니다.
  • 귀하의 제출물은 최소한 10 학기 (9)까지 처리 할 수 ​​있어야합니다.
  • 제출물은 입력을 받고 결과를 인쇄하는 전체 프로그램 또는 기능이어야합니다
  • 출력 회전은 60 도의 배수로 허용되지만 삼각형의 크기는 표현과 함께 동일하게 유지되어야합니다.
  • 반 시계 방향으로도 이동 가능
  • 표준 허점 은 금지되어 있습니다

입력이> 0이고 올바른 형식의 입력이 있다고 가정 할 수 있습니다.

채점

이것은 이므로 바이트 단위의 가장 짧은 코드가 이깁니다. 새해 복 많이 받으세요!


1
내 언어 Turtlèd는 기본 10 입력을 가져 와서 잘 처리 할 수 ​​있지만 단항 입력으로 입력하면이 도전이 훨씬 쉽습니다. 허용 될까요?
Destructible Lemon

1
@DestructibleWatermelon 예. 입력은 일종의 정수 형식이어야합니다.
Andrew Li

시원한. 지금 작업을 시작하겠습니다
Destructible Lemon

3
실제로 기다린다 그것은 여전히 ​​정말 어렵다
Destructible Lemon

답변:


13

Befunge, 871 836 798 바이트

&00p45*:10p20p030p240p050p060p9010gp9110gp1910gp1-91+10gpv
<v-g03+g06*2g041g055_v#!:%6:p06p05+p04g05g06:g04<p*54+292<
->10g:1\g3+:70p110gv >:5- #v_550g:01-\2*40g+1-30g
/\110:\-g03:\1:g055 _v#!-4:<vp01:-1g01-g03-1\-
^1<v07+1:g07< p08p < >:1-#v_550g:01-\40g+60g+1-30g-50g>v
 _0>p80gp:5-|v1\+66\:p\0\9:$<:p02:+1g02-g03+g06-\g04\1:<
0v|-g00:+1$$<>\p907^>p:!7v>3-#v_550g:30g+:30p1\0\-
1>10g+::0\g3-:70p\0^^07<v<>50#<g::30g+:30p-1-01-\
v >\$0gg> :1+10gg1- #v_^>0g10gg*+\:!2*-70g2+10gv>:#->#,"_"$#1_:1#<p
+1+g03$_^#`gg011+3:+3<g07\+*2+*`0:-\gg01+5g07:g<>1#,-#*:#8>#4_$#:^#
>55+,p30g40p10gg10g1>#v_
#v:#p0$#8_:$#<g!#@_0^ >
 >>:180gg`>>#|_:2+80gg:!v
3+^g\0p08:<vgg08+2::+3<$_100p1-v>g,\80gg+\80gp:2+90g:!01p\80gp
!#^_80g:1+^>\180gg`+!#^_20g80g`
5*g10!g09p04-1-\0\+g04:gg08:p09<^3`0:gg08+1:::$$_1#!-#\\:,#\<g

온라인으로 사용해보십시오!

Befunge의 경우와 마찬가지로 트릭에는 패턴을 위에서 아래로 렌더링 할 수있는 알고리즘이 제공됩니다. 제한된 공간을 사용하여 먼저 메모리에 패턴을 렌더링하는 것은 불가능하기 때문입니다.

이것이 작동하는 방법은 먼저 나선형을 그리는 데 필요한 가장자리를 나타내는 간단한 데이터 구조를 구축하는 것입니다. 그런 다음 두 번째 단계는 해당 구조를 위에서 아래로 구문 분석하여 각 출력 라인에 필요한 가장자리 조각을 렌더링합니다.

이 기술을 사용하면 8 비트 메모리 셀에서 오버플로 문제가 발생하기 전에 참조 구현에서 최대 n = 15를 지원할 수 있습니다. 셀 크기가 더 큰 인터프리터는 메모리가 부족하기 전에 최대 n = 25를 지원할 수 있어야합니다.


그것은 매우 인상적이지만 ...이 프로그램을 읽을 수 있습니까? 나에게 그것은 너무 무작위로 보인다. 데이터 구조를 어떻게 구축합니까? 어떤 종류의 데이터 구조를 사용합니까? 감사!
밝게 돈

1

768 바이트

func 卷(n int){
    数:=0
    p:=[]int{1,1,1}
    for i:=3;i<n;i++ {p=append(p,p[i-2]+p[i-3])}
    宽:=p[len(p)-1]*10+10
    素:=make([]int,宽*宽)
    for 数=range 素 {素[数]=32}
    for i:=0;i<数;i+=宽 {素[i]=10}
    态:=[]int{1,1,宽/2,宽/2,92}
    表:=[70]int{}
    s:="SRSQTSPQQ!QOQP~QQQQQQSQR~ORQR!OPOPTSQRQ$QPPQNQPPPXQQQQQQRRQXQRRRNOQPQ$"
    for i:=range s {表[i]=int(s[i])-33-48}
    表[49],表[59]=48,48
    for i:=0;i<4*n;i++ {
        梴:=p[i/4]*2
        if 态[1]==0 {梴=梴*2-2}
        for k:=0;k<梴;k++ {
            址:=(态[2]+态[3]*宽)%len(素)
            if 素[址]==32 {素[址]=态[4]}
            态[2]+=态[0]
            态[3]+=态[1]
        }
        数=((态[0]+1)*2+态[1]+1)*5
        if i%4>2 {数+=35}
        for k:=0;k<5;k++ {态[k]+=表[数+k]}
    }
    for i:=0;i<宽*宽;i++ {fmt.Printf("%c",rune(素[i]))}
}

이것은 물론 최적은 아니지만 나쁜 시작은 아닙니다. 나는 그것이 골프 표준에 대해 약간 간단하다는 것을 알고 있지만, 재미 있었고 미래의 자기 자신에 대한 메모를 남길 경우 마음에 들지 않기를 바랍니다.

작동 원리

기본적으로 ASCII 픽셀 그리드에서 로고와 같은 '그리기 거북이'를 시뮬레이션하지만 거북이는 다음 세 가지 명령 만 수행 할 수 있습니다.

rt   - right turn, turn 120 degrees right (1/3 of a Turn)
rth  - right turn half, turn  60 degrees right (1/6 of a Turn)
fd n - forward, go forward n steps, drawing a trail of _, /, or \

이제 각 삼각형에 대해 P는 n 번째 파도바 숫자의 2 배입니다.

fd P
rt
fd P
rt 
fd P
rt
fd P
rth

네 번째 'fd'는 각 삼각형의 첫 번째면을 다시 추적한다는 의미입니다. 이것은 다음 삼각형을위한 좋은 출발점으로 돌아 오는 데 도움이됩니다. 반 오른쪽 회전은 다음 삼각형이 올바른 방향이되도록합니다.


거북이를 골프화하기 위해 5 개의 상태 변수를 배열 态 : x 위치, y 위치, x 속도, y 속도 및 '그리기 룬'에 저장합니다. 각 애니메이션 프레임에서 x + = x 속도, y + = y 속도 및 룬이 그려집니다.

그런 다음 실제로 턴을 수행하는 방법을 알려주는 표 表를 설정했습니다. ASCII 코드가 작동하는 방식 때문에 턴 코드는 까다 롭습니다. 픽셀 디스플레이에서와 같이 간단한 움직임이 아닙니다. x와 y 속도에 의해 결정되는 거북이의 방향에 따라 회전이 올바르게 보이도록 필요한 변화가 결정됩니다.

돌리려면 현재 x 및 y 속도를보고이를 인덱스로 결합합니다.

xv = x velocity, yv = y velocity. 
i.e. a turtle facing down and to the right has 
xv of 1, and yv of 1. It can only face 6 
different directions. Formula is (xv+1)*2+yv+1

xv  yv    index
-1  -1    0
-1   0    1
-1   1    2
 1  -1    4
 1   0    5
 1   1    6

이 인덱스는 테이블 表에서 5 개의 값을 찾는 데 사용됩니다. 그런 다음 표 表의 5 개 값이 상태 态의 5 개 변수 각각에 추가됩니다. 거북이는 효과적으로 회전하여 다음 'fd'를 준비합니다.

오른쪽 차례의 절반 인 rth의 경우 表 테이블의 별도 섹션이 있습니다. 表의 첫 번째 테이블에서 7 * 5 또는 35 개의 항목으로 오프셋됩니다.

마지막으로 테이블의 정수를 ASCII 문자열로 간단한 인코딩했습니다.

Hanzi를 제거하여 바이트를 저장할 수 있다는 것을 알고 있지만 말했듯이 이것이 최적이 아니며 더 많은 골프가 가능합니다 ... 다른 가능한 최적화가 없으면 제거 할 것입니다. 실제로한지의 실제 의미에 따라 의미가 느슨하며 중국어를 모르더라도 프로그램에 대한 생각을하는 데 도움이됩니다.

数  index number
宽  screen width
素  pixel data
梴  length of side of triangle
态  current state
址  address of pixel
表  state transition table

코드를 테스트하려면이 헤더와 함께 전체 golang 파일이 필요합니다

package main
import "fmt"

이 바닥 글

func main ()  {
    for i := 0; i<15; i++ {
       卷(i)
    }
}

감사

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.