단어를 삼각형으로 나선형으로 만드십시오!

Sep 02 2020

도전

길이에 상관없이 문자열이 주어지면 중앙에서 나선형으로 나선 삼각형으로 쓰십시오. 예를 들어 다음과 abcdefghijklmnop같습니다.

   g  
  fah
 edcbi
ponmlkj

또는 더 명시 적으로 :

원하는 경우 시계 반대 방향으로 나선형으로 대신 할 수 있습니다.

   g  
  haf
 ibcde
jklmnop

또는 균일하게 공백을 추가합니다.

      g   

    f a h 

  e d c b i  

p o n m l k j 

입력 문자는 ASCII이지만 공백을 포함 할 수 있습니다. 또한 문자 수가 완전한 정사각형 ( Hello World!) 이 아닐 수 있습니다 .

  W
  Ho
oller
   !dl

몇 가지 더 엣지 케이스. 2 문자 입력 ab:

 a
  b

3 글자 입력 abc:

 a
 cb

절차 설명

위의 예가 명확하지 않은 경우 프로세스에 대한 절차 설명은 다음과 같습니다.

  1. 첫 편지를 적어 두십시오.
  2. 대각선 아래로 오른쪽으로 이동합니다 (예 :이 방향 \). 따라서에서 시작했다면 (0,0)이제 (1, -1)에있게됩니다. 두 번째 편지를 내려 놓으십시오.
  3. 한 번에 한 칸씩 왼쪽으로 이동하여 각 칸에 문자를 떨어 뜨려 총 3 칸을 만듭니다. 즉,에 편지를 드롭 (0,-1), (-1,-1)하고 (-2, -1).
  4. 다음으로 대각선으로 위로 이동하고 오른쪽 /두 칸 으로 이동 하여 (-1,0)(0,1).
  5. 이제 현재 위치가 기존 문자에 왼쪽에서 오른쪽으로 인접 해있는 한 계속해서 대각선으로 아래로 오른쪽으로 이동하는 것으로 돌아가서 문자를 단계 및 드롭합니다.
  6. 다음으로 다시 왼쪽으로 이동 /하여 기존 문자에 대각선으로 인접 해있는 한 계속해서 문자를 단계 및 드롭합니다 .
  7. /현재 위치가 기존 문자에 왼쪽에서 오른쪽으로 인접 해있는 한 문자를 한 단계 씩 이동하여 다시 오른쪽으로 대각선으로 이동 합니다.
  8. 모든 문자를 다 사용할 때까지 5-7 단계를 반복합니다.

더 많은 예

규칙

  • 코드 골프, 표준 규칙이 적용됩니다.
  • 후행 공백이나 줄 바꿈은 괜찮습니다.
  • 삼각형의 모양이 유지되는 한 일관된 선행 공백이나 줄 바꿈도 괜찮습니다.

답변

8 KevinCruijssen Sep 02 2020 at 15:48

05AB1E , 24 20 15 13 바이트

2Iā¨t·îŽOGsèΛ

-7 이식에 의해 바이트 @Neil 의 숯 응답을 사용하여, @att을 의 식 ' 그래서뿐만 아니라 둘 다 찬성 투표 할 수 있는지 확인하십시오!

온라인으로 시도하십시오. 없기 때문에 테스트 스위트는, 내장은 이전 내용을 유지하고 재설정 할 수있는 방법이없는 ( 이 그것이 어떻게 보이는지 없습니다 .

설명:

2              # Push a 2
 I             # Push the input-string
  ā            # Push a list in the range [1,length] (without popping)
   ¨           # Remove the last value to change the range to [1,length)
    t          # Take the square-root of each value
     ·         # Double each
      î        # Ceil each
       ŽOG     # Push compressed integer 6136
          s    # Swap so the list is at the top of the stack again
           è   # Index each value (0-based and modulair) into the 6136
            Λ  # Pop all three and use the Canvas builtin,
               # after which the result is implicitly output immediately afterwards

내이 05AB1E 팁을 참조하십시오 (섹션 얼마나 큰 정수를 압축하는 방법을? ) 이유를 이해하는 ŽOG것입니다 6136.

Canvas 내장은 세 가지 인수를 사용하여 모양을 그립니다.

  • 그릴 문자 / 문자열 :이 경우 입력
  • 그릴 선의 길이 : 2이 경우
  • 그릴 방향 : [3,6,6,6,1,1,3,3,3,6,6,6,6,6,6,6,1,1,1,1,3,...].

Canvas 내장에 대한 설명은 아래의 원래 답변을 참조하십시오. 길이 목록이 선행하는 아래 프로그램과 달리, 여기에서는 단일 길이의 2.


원래 24 20 바이트 답변 :

ā·Ð·s>ø.ι˜DŠOð׫₆1ªΛ

선행 / 후행 공백과 줄 바꿈을 포함합니다 (입력이 길수록 공백 / 줄 바꿈이 더 많음).

온라인으로 시도하십시오. 내장이 이전 내용을 유지하고 재설정 할 방법이 없기 때문에 테스트 스위트 가 없습니다 ( 테스트 케이스가 서로 위에 그려지 는 모습 ).

설명:

ā           # Push a list in the range [1, length] of the (implicit) input (without popping)
            #  i.e. "Hello World!" → "Hello World!" and [1,2,3,4,5,6,7,8,9,10,11,12]
 ·          # Double each value in this list
            #  → [2,4,6,8,10,12,14,16,18,20,22,24]
  Ð         # Triplicate it
   ·        # Double each value of the top copy
            #  → [4,8,12,16,20,24,28,32,36,40,44,48]
    s       # Swap to get the other copy
     >      # Increase each by 1
            #  → [3,5,6,9,11,13,15,17,19,21,23,25]
      ø     # Create pairs of the top two lists
            #  → [[4,3],[8,5],[12,7],[16,9],[20,11],[24,13],[28,15],[32,17],[36,19],[40,21],[44,23],[48,25]]
       .ι   # Interleave it with the third list
            #  → [2,[4,3],4,[8,5],6,[12,7],8,[16,9],10,[20,11],12,[24,13],14,[28,15],16,[32,17],18,[36,19],20,[40,21],22,[44,23],24,[48,25]]
         ˜  # Flatten
            #  → [2,4,3,4,8,5,6,12,7,8,16,9,10,20,11,12,24,13,14,28,15,16,32,17,18,36,19,20,40,21,22,44,23,24,48,25]
D           # Duplicate this list of integers
 Š          # Triple-swap, so the stack order is list,input,list
  O         # Pop and sum the top list
            #  → 636
   ð×       # Create a string of that many spaces
     «      # And append it to the string
₆           # Push builtin 36
 1ª         # Convert it to a list of digits, and append 1: [3,6,1]
Λ           # Use the Canvas builtin with these three arguments,
            # after which the result is implicitly output immediately afterwards

Canvas 내장은 세 가지 인수를 사용하여 모양을 그립니다.

  • 그릴 문자 / 문자열 :이 경우 입력, 후행 공백이 추가됨
  • 그릴 선의 길이 : 목록 [2,4,3,4,8,5,6,12,7,8,16,9,10,20,11,...]
  • 그릴 방향 : [3,6,1]. \ 범위의 숫자$[0,7]\$ 각각은 특정 방향을 나타냅니다.
7   0   1
  ↖ ↑ ↗
6 ← X → 2
  ↙ ↓ ↘
5   4   3

따라서이 [3,6,1]경우에는 \$[↘,←,↗]\$.

다음은 출력에 대한 단계별 설명입니다 ( "Hello_World!"여기서는 입력 을 예로 사용합니다).

1 단계 : "He"방향으로 2 자 ( ) 그리기 3↘:

H
 e

2 단계 : "llo"방향으로 4-1 자 ( ) 그리기 6←:

  H
olle

3 단계 : "_W"방향으로 3-1 자 ( ) 그리기 1↗:

  W
 _H
olle

4 단계 : "orl"방향으로 4-1 자 ( ) 그리기 3↘:

  W
 _Ho
oller
     l

5 단계 : "d! "방향으로 8-1 자 ( ) 그리기 6←:

   W
  _Ho
 oller
    !dl

기타 모든 후행 공백에 대해서도 마찬가지입니다.

Canvas 내장에 대한 자세한 설명은이 05AB1E 팁을 참조하십시오.

14 att Sep 02 2020 at 11:56

Wolfram 언어 (Mathematica) , 99 바이트

sPrint@@@Array[s[[4# #-2#+1-#2&@@If[Abs@#2<2#,!##,#-Abs@#2|-#2]]]/._@__->" "&,2{L=Tr[1^s],L},-L]

온라인으로 시도하십시오!

각 위치의 인덱스를 직접 계산합니다. 데카르트 좌표에서 \$\operatorname{index}(x,y)=\textit{offset}+\begin{cases}2y(2y+1)-x,&|x|<-2y\\ 2\left(y+|x|\right)\left(2\left(y+|x|\right)+1\right)+x,&\text{else}\end{cases}\$

여기서 \$\textit{offset}\$ "첫 번째"문자의 색인입니다 (Mathematica에서는 1).

문자 목록을 입력으로받습니다.


이전 페이지 접근 123 122 109 107 바이트

Print@@@Normal@SparseArray[i=0;p=2Length@#;(p+=ReIm[I[2+I,1-I][[⌈2√i++⌉~Mod~4-1]]-1])->#&/@#,2p," "]&

온라인으로 시도하십시오!

i이전 문자 에 대한 (1- 인덱싱 된) 번째 문자 의 방향은 \ 로 계산할 수 있습니다.$\Big\lceil2\sqrt i\Big\rceil\bmod 4\$:

  • 1 : ↗
  • 2 : ↘
  • 3,0 : ←
9 Neil Sep 02 2020 at 07:00

차콜 , 37 36 21 바이트

GH✳✳E⊖LθI§4174⌈⊗₂⊕ι²θ

온라인으로 시도하십시오! deverbosifier가 ✳σ대신 출력 ✳✳하여 올바르게 실행되지 않는 유효하지 않은 간결한 코드를 생성 하기 때문에 자세한 링크 가 없지만 작동하면 PolygonHollow(Directions(Map(Decremented(Length(q)), Cast(AtIndex("4174", Ceiling(Doubled(SquareRoot(Incremented(i)))))))), 2, q);. @KevinCruijssen의 05AB1E 솔루션에서 영감을 얻었지만 @att의 공식을 사용하여 방향을 생성합니다. 설명:

       θ                Input string
      L                 Length
     ⊖                  Decremented
    E                   Map over implicit range
                  ι     Current index (0-indexed)
                 ⊕      Incremented (i.e. 1-indexed)
                ₂       Square rooted
               ⊗        Doubled
              ⌈         Ceiling
         §4174          Cyclically index to find direction
        I               Cast to integer
  ✳✳                    Convert to directions
GH                 ²θ   Draw path using input string

경로 그리기 명령은 시작으로 한 n-1문자를 그리고 배열의 각 방향에 대해 문자를 그립니다 . 불행히도 대각선 방향을 나타내는 단일 문자열이 없으므로 대신 정수를 사용해야합니다. 0오른쪽 에서 시작하여 시계 방향으로 45 ° 씩 증가합니다.

이전 37 바이트 솔루션 :

≔⮌⪪S¹θFLθF³F§⟦⊕⊗ι⁺³×⁴ι⊗⊕ι⟧κ¿θ✳⁻⁷׳κ⊟θ

온라인으로 시도하십시오! 링크는 자세한 코드 버전입니다. 설명:

≔⮌⪪S¹θ

입력을 문자로 분할하고 목록을 반대로합니다.

FLθ

충분히 많이 반복하십시오.

F³

삼각형의 각면을 반복합니다.

F§⟦⊕⊗ι⁺³×⁴ι⊗⊕ι⟧κ

측면의 크기에 대한 루프.

¿θ

아직 인쇄 할 항목이 있는지 확인하십시오.

✳⁻⁷׳κ⊟θ

적절한 방향으로 다음 문자를 인쇄하십시오.

7 MatthewJensen Sep 02 2020 at 07:04

JavaScript (V8) , 222 바이트

s=>(g=(a,b,n=1)=>b?g([(c=(b+' '.repeat(n*8)).slice(0,n*8))[n*6-1],...[...a,c.slice(0,n*4-1)].map((l,i)=>c[n*6+i]+l+c[n*6-2-i])],b.slice(n*8),n+1):a)([s[0]],s.slice(1)).reduce((p,l,i,a)=>p+' '.repeat(a.length-i-1)+l+`
`,'')

온라인으로 시도하십시오!

확실히 더 많이 골프를 칠 수 있습니다.
재귀 알고리즘을 사용하여 출력을 삼각형 '레이어'로 분할합니다. 여기서 각 레이어는 이전 삼각형의 완전한 랩 (3 변)입니다.

미 골프

s=>(g=(a,b,n=1)=> // g is a recursive function; a: previous; b: rest; n: increment
  b ? // if there is more string to wrap
    g([ // wrap b around a as a triangle and recurse
        (c=(b+' '.repeat(n*8)).slice(0,n*8))[n*6-1],
        ...[...a,c.slice(0,n*4-1)].map((l,i)=>c[n*6+i]+l+c[n*6-2-i])
      ],
      b.slice(n*8),
      n+1)
  :a // otherwise return the triangle
  )
  ([s[0]],s.slice(1)) // run the function with the first letter and the rest
  .reduce((p,l,i,a)=>p+' '.repeat(a.length-i-1)+l+'\n','') // step the triangle to make it look like it is meant to
7 Arnauld Sep 02 2020 at 19:09

JavaScript (ES8), 137 바이트

문자 배열이 필요합니다. 문자열을 반환합니다.

이 버전은 @att 에서 사용하는 공식을 기반으로 하며 JS에서 골프 친화적으로 수정되었습니다.

a=>a.map((c,n)=>(m[y+=~(d=2*n**.5-1/n)%4%3?d&++x/x||-1:!x--]=m[y]||[...''.padEnd(x)])[x]=c,m=[],x=y=a.length)&&m.map(r=>r.join``).join`
`

온라인으로 시도하십시오! (원시 출력)

온라인으로 시도하십시오! (추가 공백이 제거됨)

어떻게?

위치 \$n\$캐릭터, 방향 \$0\le d\le 2\$ 다음과 같이 계산할 수 있습니다.

$$d=\left(\left\lfloor2\sqrt{n}+1-\frac{1}{n}\right\rfloor\bmod 4\right)\bmod 3$$

실제 JS 구현은 다음과 같습니다.

~(2 * n ** 0.5 - 1 / n) % 4 % 3

어떤 평가됩니다에 \$0\$, \$-1\$또는 \$-2\$.


자바 스크립트 (ES8)  163  157 바이트

문자 배열이 필요합니다. 문자열을 반환합니다.

a=>a.map(c=>((m[y]=m[y]||[...''.padEnd(x)])[x]=c,j%3%2?x--:y+=!!++x-j%3,k?k--:k=(n=j/3<<1)+(j++%3||n+2)),m=[],j=k=0,x=y=a.length)&&m.map(r=>r.join``).join`
`

온라인으로 시도하십시오! (원시 출력)

온라인으로 시도하십시오! (추가 공백이 제거됨)

어떻게?

이것은 매트릭스에 의해 문자의 출력 특성을 그리는 오히려 단순 알고리즘 \$m[\:]\$, 위치 추적 \$(x,y)\$펜의 방향 \$\{0,1,2\}\$그리고 숫자 \$k\$ 다음 방향 변경 전에 그릴 문자 수.

다음 표에 따라 이동합니다.

 direction | moving towards | distance
-----------+----------------+----------
     0     | South-East     |  2t + 1       (t = turn number)
     1     | West           |  4t + 3
     2     | North-East     |  2t + 2

다음을 제공합니다.

t = 0     t = 1        t = 2            t = 3

                                          2       
                         2               2.       
            2           2.              2..0      
  2        2.          2..0            2....0     
 2X       2.X0        2..X.0          2...X..0    
1110     2....0      2......0        2........0   
        11111110    2........0      2..........0  
                   111111111110    2............0 
                                  1111111111111110

JS 구현에서는 방향을 명시 적으로 저장하지 않습니다. 대신, 우리는 카운터를 사용 \$j\$\ 에서 출발$0\$\$+\infty\$사용 \$j\bmod 3\$현재 방향을 파악합니다. 우리는 또한 회전 수 있지만 계산을 저장하지 않습니다 \$n=2\cdot\lfloor j/3\rfloor\$, \ 값 사용$j\$ 방향 변경을 설명하기 위해 증가 하기 전에 (즉, \$n\$\와 같음$2(t-1)\$대신 \$2t\$방향이 \$0\$).

따라서 다음 표는 다음과 같습니다.

     j mod 3     |  (j + 1) mod 3  |                     | new starting
 (old direction) | (new direction) |    new distance     | value for k
-----------------+-----------------+---------------------+--------------
        2        |        0        | (n + 2) + 1 = n + 3 |     n + 2
        0        |        1        |      2n + 3         |    2n + 2
        1        |        2        |       n + 2         |     n + 1

그리고 해당 식 업데이트 \$k\$:

k = (n = j / 3 << 1) + (j++ % 3 || n + 2)

좌표는 다음으로 업데이트됩니다.

j % 3 % 2 ?          // if the direction is 1:
  x--                //   decrement x
:                    // else:
  y += !!++x - j % 3 //   increment y if the direction is 0
                     //   or decrement y if it's 2
                     //   increment x in both cases
5 att Sep 04 2020 at 00:19

R , 205 153 147 136 132 126 바이트

-52 Dominic van Essen에서.
주세페에서 -4.
-4 Giuseppe 덕분에 다시.
-5 Dominic van Essen 덕분에

function(s,n=nchar(s))for(y in(x=-n:n)*2)cat(ifelse((i=(t=y-2*(r=abs(x))*!r<y)*t-t-2*(r<y)*x+x+1)>n," ",substring(s,i,i)),"
")

온라인으로 시도하십시오!

4 DLosc Sep 03 2020 at 09:31

Pip -l , 70 바이트

sMC:Y#ax:w:y/2-/2Ly*2L++i/2{I++v<ys@w@x:a@vi%4%3?++x&i%4=1?--w++w--x}s

온라인으로 시도하십시오!

...이 괴물을 자세히 설명하고 싶은지 모르겠습니다. 기본 아이디어는 공간이 너무 큰 2D 배열 ( sMC:#a)을 생성 한 다음 입력 문자열의 문자를 적절한 인덱스 ( s@w@x:a@v) 의 배열에 넣는 것 입니다. 나머지 코드는 "적절한 인덱스"가 무엇인지 파악합니다.


대체 접근 방식, 77 바이트 :

a.:sX#aW<|a{UpaWa^@YxNl?v+1++v%2?v*2+1vl:xNl?RV^p.:lv%2?lPEpl.^pAEx}RVsX,#l.l

온라인으로 시도하십시오!

삼각형을 줄 목록으로 작성하고 목록의 앞 / 끝에 줄을 추가하고 각 줄의 앞 / 끝에 문자를 추가하는 과정을 번갈아 가며 만듭니다. 나는이 방법이 더 짧을 수 있기를 바랐지만 지금까지는 그렇지 않은 것 같습니다.

4 Bubbler Sep 03 2020 at 13:54

J , 60 바이트

4 :'x(<"1(#x)++/\(3|4|>.2*%:i.#x){<:3 3#:3 2 8)}y',~' '"0/,~

온라인으로 시도하십시오!

Jonah의 도전이기 때문에 필수 J 답변입니다.

"배열 내의 특정 위치를 값으로 대체"는 동사가 아니라 부사이기 때문에 기차에서있는 그대로 사용할 수 없으므로 명시 적 인라인 동사로 래핑됩니다.

att의 공식 을 사용 하여 방향을 구성합니다.

작동 원리

NB. input: a string (character vector) of length n

,~' '"0/,~  NB. create a large enough canvas (blank matrix of size 2n*2n)
        ,~  NB. concatenate two copies of self
       /    NB. outer product by...
  ' '"0     NB.   a constant function that returns blank per character
,~          NB. concatenate two copies of self

4 :'...'  NB. a dyadic explicit verb, where x is the input string and
          NB. y is the canvas generated above
x(...)}y    NB. replace some places of y by contents of x...
3|4|>.2*%:i.#x  NB. formula by att (gives 0, 1, or 2 per index)
(...){          NB. select the directions based on the above...
<:3 3#:3 2 8    NB. the matrix (0 -1)(-1 1)(1 1) i.e. L/RU/RD
(#x)++/\        NB. take cumulative sum (giving coords to place each char)
                NB. and add n to all elements
<"1             NB. enclose each row to satisfy the input format of }
4 DominicvanEssen Sep 02 2020 at 20:06

R , 270 265 252 243 232 227 225 바이트

마지막으로 2 개의 문자를 더 제거하여 합계를 삼각형 형태로 표현할 수있는 숫자로 만들었습니다 (여기에 표시된대로). 코드를 실행하려면 일반적으로 형식을 지정해야합니다 (TIO의 예에서와 같이). '•'는 줄 바꿈 ( \n) 문자를 나타냅니다 .

              f
             unc
            tion(
           s,`~`=c
          bind,m=ma
         trix){n=nch
        ar(s)+1;p=m(,
       n^2,2);while(T<
      n){a=4*F;p[T+0:a,
     ]=c(F:-F,(-F:F)[-1]
    )~0:a-2*F;p[T+a+-2:a+
   3,]=(F=F+1)~(b=2*F-1):-
  b;T=T+2*a+4};m=m(" ",n,n)
 ;m[p[2:n-1,]+b+1]=el(strspl
it(s,''));apply(m,1,cat,"•")}

온라인으로 시도하십시오!

이 접근 방식은 att의 접근 방식에 의해 포괄적으로 벗어 났지만 위안으로서 다른 현재 답변도 삼각형으로 표현할 수 없습니다 ...

각 문자의 좌표를 구성한 다음이를 사용하여 문자를 빈 행렬에 넣는 방식으로 작동합니다.

댓글 :

triangle=
function(s){n=nchar(s)          # n is the number of letters
s=el(strsplit(s,''))            # first split the string into individual letters
p=matrix(,2,n^2)                # initialize p as a 2-row matrix to hold the coordinates
                                # (with plenty of columns so that we've enough to go all 
                                # the way round the outermost triangle)
                                # now, F is the current loop, starting at 0
while(T<=n){                    # T is the current letter index
a=4*F+1                         # a=the size of the 'arch' (number of letters going up & over)
p[,T+1:a-1]=                    # set the coordinates for the arch letters...
  rbind(                        # ...(rbind combines rows for y & x coordinates)...
    c(F:-F,(-F:F)[-1]),         # ...to y = F..-F, and then -F+1..F (so: up & then down again)
    1:a-2*F-1)                  # ...and x = across the arch from -2*F to +2*F
a=a+2                           # a=now the width of the base = size of arch + 2
p[,T+a+1:a-3]=                  # now set the coordinates of the base letters...
  rbind(                        #
    F+1,                        # ... base y = row F+1
    (b=2*F+1):-b)               # ... and x = goes (backwards) from 2*F+1..-2*F-1
T=T+2*a-2                       # update the current letter index
F=F+1}                          # increment the loop
p=p[,1:n]                       # delete any excess coordinates
p=p-min(p)+1                    # re-zero the coordinates to remove negatives
m=matrix(" ",b<-max(p),b)       # create a new matrix filled with " "
m[t(p)]=s                       # and fill it with the letters at the right positions
n=apply(m,1,cat,"               # finally, print each row
")}
2 user Sep 03 2020 at 01:33

스칼라, (322) 318 바이트

s=>((s zip Seq.unfold((0,0,0->0)){case(r,n,y->x)=>Option.when(n<s.size){val(c,t)=(math.sqrt(n).toInt%2,r+1-math.abs(x.sign))
(y->x,(t,n+1,(y+(c-1)*(1-t%2*2),x+1-c*2)))}}groupBy(_._2._1)toSeq)sortBy(_._1)map(_._2.sortBy(_._2._2)map(_._1)mkString)zipWithIndex)map{t=>" "*(math.sqrt(s.size).toInt-t._2)+t._1}mkString "\n"

Scastie에서 사용해보세요 (TIO에서는 작동하지 않음).

1 KjetilS. Sep 06 2020 at 10:57

Perl 5 , 163 바이트

sub f{                    #newlines and indentation added here for readability. 
  $_=' 'x1e3; @L=(51,$a=-1,-49)x($p=225); for$c(pop=~/./g){
    $P=$p+$L[1]; $a++>0&&s/^(.{$P}) /$1$c/s&&($p=$P,$a=0,shift@L)||substr$_,$p+=$L[0],1,$c
  }
  s/.{50}/$&\n/gr
}

요컨대, 방향을 바꿀 때가 아니라면 현재 방향의 입력에서 다음 문자를 추가합니다.

온라인으로 시도하십시오!