단어를 삼각형으로 나선형으로 만드십시오!
도전
길이에 상관없이 문자열이 주어지면 중앙에서 나선형으로 나선 삼각형으로 쓰십시오. 예를 들어 다음과 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
절차 설명
위의 예가 명확하지 않은 경우 프로세스에 대한 절차 설명은 다음과 같습니다.
- 첫 편지를 적어 두십시오.
- 대각선 아래로 오른쪽으로 이동합니다 (예 :이 방향
\). 따라서에서 시작했다면(0,0)이제 (1, -1)에있게됩니다. 두 번째 편지를 내려 놓으십시오. - 한 번에 한 칸씩 왼쪽으로 이동하여 각 칸에 문자를 떨어 뜨려 총 3 칸을 만듭니다. 즉,에 편지를 드롭
(0,-1),(-1,-1)하고(-2, -1). - 다음으로 대각선으로 위로 이동하고 오른쪽
/두 칸 으로 이동 하여(-1,0)및(0,1). - 이제 현재 위치가 기존 문자에 왼쪽에서 오른쪽으로 인접 해있는 한 계속해서 대각선으로 아래로 오른쪽으로 이동하는 것으로 돌아가서 문자를 단계 및 드롭합니다.
- 다음으로 다시 왼쪽으로 이동
/하여 기존 문자에 대각선으로 인접 해있는 한 계속해서 문자를 단계 및 드롭합니다 . /현재 위치가 기존 문자에 왼쪽에서 오른쪽으로 인접 해있는 한 문자를 한 단계 씩 이동하여 다시 오른쪽으로 대각선으로 이동 합니다.- 모든 문자를 다 사용할 때까지 5-7 단계를 반복합니다.
더 많은 예
규칙
- 코드 골프, 표준 규칙이 적용됩니다.
- 후행 공백이나 줄 바꿈은 괜찮습니다.
- 삼각형의 모양이 유지되는 한 일관된 선행 공백이나 줄 바꿈도 괜찮습니다.
답변
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 팁을 참조하십시오.
Wolfram 언어 (Mathematica) , 99 바이트
sPrint@@@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 : ←
차콜 , 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§⟦⊕⊗ι⁺³×⁴ι⊗⊕ι⟧κ
측면의 크기에 대한 루프.
¿θ
아직 인쇄 할 항목이 있는지 확인하십시오.
✳⁻⁷׳κ⊟θ
적절한 방향으로 다음 문자를 인쇄하십시오.
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
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
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)),"
")
온라인으로 시도하십시오!
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
온라인으로 시도하십시오!
삼각형을 줄 목록으로 작성하고 목록의 앞 / 끝에 줄을 추가하고 각 줄의 앞 / 끝에 문자를 추가하는 과정을 번갈아 가며 만듭니다. 나는이 방법이 더 짧을 수 있기를 바랐지만 지금까지는 그렇지 않은 것 같습니다.
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 }
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
")}
스칼라, (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에서는 작동하지 않음).
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
}
요컨대, 방향을 바꿀 때가 아니라면 현재 방향의 입력에서 다음 문자를 추가합니다.
온라인으로 시도하십시오!