다이아몬드 타일링 확장


27

정규 육각형은 다음과 같이 다이아몬드로 바둑판 식으로 배열 할 수 있습니다.

   ______
  /_/_/\_\
 /_/\_\/\_\
/\_\/_/\/_/\
\/_/\_\/_/\/
 \_\/_/\_\/
  \_\_\/_/

우리는 위의 타일 크기를 고려할 것입니다 1(다이아몬드 측면이 하나 /또는 \각각 만들어지기 때문에 ). 같은 크기의 타일 2은 다음과 같습니다.

      ____________ 
     /   /   /\   \  
    /___/___/  \___\ 
   /   /\   \  /\   \  
  /___/  \___\/  \___\ 
 /\   \  /   /\  /   /\  
/  \___\/___/  \/___/  \ 
\  /   /\   \  /   /\  /
 \/___/  \___\/___/  \/ 
  \   \  /   /\   \  /
   \___\/___/  \___\/ 
    \   \   \  /   /
     \___\___\/___/ 

당신의 임무는 원하는 출력의 크기를 지정 1하는 양의 정수 N(10 진수 또는 단항) 와 함께 ASCII 아트 타일링 (size )을 입력으로받는 것 입니다. 그런 다음 동일한 바둑판 식으로 확대 된 버전을 출력해야합니다.

점을 유의 육각형이 어떤 크기와 1x1x1 작게 (세 개의 다이아몬드를 포함) 할 수있다.

입력과 출력 모두 후행 공백이나 육각형 모양을 정렬하는 데 필요한 것보다 많은 선행 공백을 포함해서는 안됩니다. 입력과 출력 모두 단일 후행 줄 바꿈을 선택적으로 포함 할 수 있습니다 (이 선택은 입력과 출력에 대해 동일 할 필요는 없습니다).

STDIN (또는 가장 가까운 대안), 명령 행 인수 또는 함수 인수를 통해 입력을 받고 STDOUT (또는 가장 가까운 대안), 함수 리턴 값 또는 함수 (out) 매개 변수를 통해 결과를 출력하는 프로그램 또는 함수를 작성할 수 있습니다.

이것은 코드 골프이므로 가장 짧은 대답 (바이트)이 이깁니다.

타일링 예제

다음은 제출물을 테스트하는 데 사용할 수있는 소수의 입력 타일입니다.

 __
/_/\
\_\/

  ____
 /_/\_\
/\_\/_/\
\/_/\_\/
 \_\/_/

   ______
  /_/_/\_\
 /_/\_\/\_\
/\_\/_/\/_/\
\/_/\_\/_/\/
 \_\/_/\_\/
  \_\_\/_/

    ________
   /_/\_\_\_\
  /\_\/\_\_\_\
 /\/_/\/_/_/\_\
/\/\_\/_/_/\/\_\ 
\/\/_/\_\_\/\/_/
 \/\_\/_/\_\/_/
  \/\_\_\/_/_/
   \/_/_/_/_/

다음 스 니펫에는를 N = 1통한 입력에 대한 해당 출력이 포함되어 있습니다 N = 6.


20
사용자 이름 옆에 다이아몬드가 있으므로 다이아몬드에 관심이있는 것으로 보입니다.
user12205

3
@ace : 당신은 그들이 말하는 것을 알고 있습니다 : 다이아몬드는 중재자의 가장 친한 친구입니다.
Alex A.

나는 대답을 알고 있다고 생각하지만 내가 틀렸다는 것을 희망한다. 빈 줄을 선행하는 것이 선행 공간으로 간주되어 불법으로 선언 했습니까? 내 초기 솔루션에는 N-1빈 줄이 있습니다. :(
Reto Koradi

@RetoKoradi 사실, 새로운 줄 바꿈이 없습니다. 죄송합니다.
마틴 엔더

1
나는 생각했다. 약 10 바이트가 들었습니다. 내가 처음 문제를 인식했을 때보 다 나쁘지 않았습니다.
Reto Koradi 0시 46 분

답변:


8

CJam, 85 79 76 72 바이트

li:Tlf*NqN/T,f{ff{"_/"2$#_1<@+*~ST*@t}:+z{S+e`);e~{"_ "/"__"*W%}T2**N}/}

크기는 첫 번째 줄에 있어야합니다. 그리고 다이아몬드가 이어집니다.

골프를 잘하지 못합니다 ... 그리고 캐릭터의 절반은 세부 사항에서 나왔습니다.

설명 (이전 버전)

li:T            e# Read the size and save to T.
qN/             e# Read and split to lines.
\,fm*           e# Convert each character X to [X 0] [X 1]... [X T(]
{~              e# For each [X I] in each line:
    ST*         e# T spaces.
    \           e# I.
    "_\\"3$#    e# If X is '_, '\ or '/, return Y = 0, 1, -1 respectively.
    _W>@+       e# If it was '_ or '\, increase I by one.
    *(          e# I * Y - 1.
    @t          e# Set the character at that position to X.
}f%
:z:+            e# Make the returned lists from each iteration across T lines.
{S+e`);e~N+}%   e# Boring details to remove trailing spaces and append a newline.
T(>(\s          e# Boring details to extract the first line and only work on others.
{_{"_ "/"__"*W%}2*_@=!}g
                e# Boring details to make underlines expand left and right.

10

파이썬 2, 164

def g(s,n,j=1):
 for W in s.split("\n"):exec"O=p='';d=0\nfor c in W:q=' _'[j*'_'in p+c];e=[n-j,j-1][c=='/'];O+=q*(e+d)+[c,q][c>'^'];p=c;d=n+~e\nprint O;j-=1;"*j;j=n

테스트 사례에 대한 출력.

무슨 일이야?

주요 아이디어는 원본의 각 캐릭터가 n*n블록 으로 날아가는 것 입니다. 예를 들어, N = 4에 대한, /될 수도

   /
  /
 /
/___

원래 문자는 각 줄에 한 번 표시되며 양쪽에 패딩이 있습니다. 여기서,의 왼쪽에, 그리고 그리고 _오른쪽에. 맨 아래 행만 채울 수 있습니다 '_'. 나머지는 항상 ' '입니다.

가장 어려운 점은 오른쪽의 패딩이 다가오는 기호에 따라 달라질 수 있다는 것입니다. 구체적으로와 '/ '다른 패딩이 '/_'있으므로 미리 봐야합니다. 또한 후행 공백을 피하기 위해 마지막 기호에 있고 오른쪽에 패딩을 삼가야합니다.

현재 캐릭터의 왼쪽에 패딩만으로 이러한 문제를 극복합니다. 그렇게 할 때 현재 패딩 기호를 사용하여 이전 문자에서 오른쪽 여백을 수행합니다. 따라서 이전 문자에서 가져온 오른쪽 패딩, 현재 문자에서 왼쪽 패딩, 현재 문자에서 인쇄합니다. 우리는 또한 다음 문자가 지불해야 할 패딩 금액 "채무"를 저장합니다.

이제 코드를 살펴 보겠습니다.

def g(s,n,j=1):
    for W in s.split("\n"):
        while j:
            O=p='';d=0
            for c in W:
                q=' _'[j*'_'in p+c]
                e=[n-j,j-1][c=='/']
                O+=q*(e+d)+[c,q][c>'^']
                p=c
                d=n+~e
            print O;j-=1;
        j=n

입력 문자열은 s이고 스케일 팩터는 n입니다. 우리는 한 줄씩 가서 n각 입력 줄마다 줄을 인쇄 W하고 복사본은 색인으로 묶습니다 j=n,n-1,...,2,1. 첫 번째 줄은 한 번만 복사되므로 j1 로 초기화 하고 n각 루프로 변경하면됩니다 .

입력 라인을 반복하여 인쇄 할 라인을 누적합니다 O. 먼저, 적절한 패딩 문자를 알아냅니다. q우리가 결론에 있고 밑줄 또는 현재 문자가 밑줄이면 밑줄이며 그렇지 않으면 공백입니다.

그런 다음 왼쪽에 넣을 패딩 양을 결정합니다 ( e). 들면 /, 그것의 j-1, 상보 (라인 카피 수 감소에 따라 감소) n-j를위한이 \. 다른 캐릭터도 같은 방식으로 취급합니다. 예를 들어, _한 줄의 n밑줄을 주는 것처럼 보이지만 실제로 왼쪽과 오른쪽의 밑줄로 채워진 단일 밑줄을 제공합니다. 이것은 비효율적 인 것 같지만 그것은 우리가 함께 작동 할 수 _같은 프레임 워크 /\우리가하고 덩어리 때문에, 중요하지 않습니다 "중앙"밑줄의 위치 로를 \; 이 선택은 또한 특별한 케이싱없이 맨 윗줄이 작동하도록합니다.

다음으로 출력 문자열에 추가합니다. 패딩 심볼 q과 현재 패딩 금액 e을 알아 냈지만 d이전 심볼 의 패딩 부채를 기억해야합니다 . 그래서 우리는을 추가 q*(e+d)합니다. 그런 다음 c아래쪽이 아닌 행에서 밑줄을 피해야한다는 점을 제외하고 현재 기호를 추가합니다 . 밑줄을 패딩 기호로 변환하여 수정합니다.

마지막으로 패딩 빚 금액을 기록합니다 n+~d. 또한 현재 심볼을에 기록하여 p나중에 이전 심볼이 있는지 여부를 알 수 _있습니다.


3

자바 스크립트 ( ES6 ) 274 281 289 338

// GOLFED
F=(b,n)=>{
b=b[R='replace'](/ |_/g,c=>c[T='repeat'](n))[R](/_(?=[\\\/])/g,'_'[T](n))[R](/\/\\/g,`/${'  '[T](n-1)}\\`)
.split('\n');
for(i=l=b.length*n-n+1;--i;)
b[i]=i%n?b[i+1][R](/_/g,' ')[R](/\/ ?/g,' /')[R](/ \\(.)?/g,'\\$1$1')
:' '[T](i>l/2?n-1:0)+b[i/n];
return b.join('\n')}


// UNGOLFED
U=(b,n)=>{
  b=b
  .replace(/ |_/g,c=>c.repeat(n))
  .replace(/_(?=[\/\\])/g,'_'.repeat(n))
  .replace(/\/\\/g,`/${'  '.repeat(n-1)}\\`)
  .split('\n');
  for(i=l=b.length*n-n+1;--i;)
  {
    if(i%n)
     b[i]=b[i+1]
     .replace(/_/g,' ')
     .replace(/\/ ?/g,' /')
     .replace(/ \\/g,'\\ ').replace(/ +$/,'')
     .replace(/ \\(.)?/g,'\\$1$1')
    else {
      b[i]=b[i/n]
      if(i>l/2)b[i]=' '.repeat(n-1)+b[i];
    }
  }
  return b.join('\n')
}

//TEST

test=[
' __\n/_/\\\n\\_\\/',
'  ____\n /_/\\_\\\n/\\_\\/_/\\\n\\/_/\\_\\/\n \\_\\/_/',
'   ______\n  /_/_/\\_\\\n /_/\\_\\/\\_\\\n/\\_\\/_/\\/_/\\\n\\/_/\\_\\/_/\\/\n \\_\\/_/\\_\\/\n  \\_\\_\\/_/',
'    ________\n   /_/\\_\\_\\_\\\n  /\\_\\/\\_\\_\\_\\\n /\\/_/\\/_/_/\\_\\\n/\\/\\_\\/_/_/\\/\\_\\\n\\/\\/_/\\_\\_\\/\\/_/\n \\/\\_\\/_/\\_\\/_/\n  \\/\\_\\_\\/_/_/\n   \\/_/_/_/_/'
]

test.forEach(t=>{
  var row = '<td>'+t+'<td>'
  for(rr=2;rr<5;rr++)
    row += '<td>'+F(t,rr)+'</td>'
  OUT.innerHTML += '<tr>'+row+'</tr>'
})
td {
  font-family: monospace;
  white-space: pre;
}
(better full page)
<table id=OUT></table>


3

파이썬 2 217 211 195 194 190

b,f,s='\/ '
R=str.replace
def m(g,n,z=1):
 for d in g.split('\n'):
    for i in range(z):a=z+~i;print[i,a][d[-1]>f]*s+R(R(R(R(d,s,s*n),'_','_ '[i<z-1]*(z+n-1)),f+b,f+s*2*i+b),b+f,b+s*2*a+f);z=n

Sp3000 덕분에 6 바이트

전화 m첫 번째 인수는 문자열, 두 번째 인수 반복 번호와 다이아몬드 인 상태.

이는 3 단계 문자열 교체 시퀀스를 기반으로합니다.

  • 먼저 줄에 따라 밑줄을 2n-1 공백 또는 밑줄로 바꿉니다.
  • 둘째, 대체 /\하여 / \라인 위에 2 * (N-1) (2)로부터가는 공백의 수.
  • 셋째, 대체 \/하여 \ /라인 위에 2 * 2 (N-1)로가는 공백의 수.

그런 다음 선행 공간을 확보하고 첫 번째 줄을 올바르게 설정하려는 다양한 방법이 있습니다.

프로그램의 마지막 줄은 4 칸이 아닌 탭이어야합니다. 마크 다운은 탭을 지원하지 않습니다.


두 개의 골프 : (i+(n-i+~i)*(d[-1]>f)) --> [i,n+~i][d[-1]>f]당신은 '_'한 번만 사용 하므로 정의하는 바이트를 낭비합니다.
Sp3000

3

파이썬, 272 238 228 243 바이트

업데이트 된 버전은 이제 문자열 시퀀스 대신 단일 문자열을 입력으로 사용합니다. 또한 이전 버전에 있던 후행 공백을 제거합니다. 불행히도 이러한 변경은 크기를 증가시킵니다.

s,u,f,b=' _/\\'
r=str.replace
def d(t,n,j=1):
 for p in t.split('\n'):
  for k in range(n-j,n):m,v=n+~k,'_ '[k<n-1];print r(r(r(r(r(r(r(r(p,f+u,'(_'),u+b,'_)'),s,s*n),u,v*n),f,s*m+f+s*k),'(',v*m+f+v*k),b,s*k+b+s*m),')',v*k+b+v*m).rstrip();j=n

공백이있는 버전과 문장은 가독성을 위해 더 작은 단위로 나뉩니다.

s, u, f, b = ' ', '_', '/', '\\'
def d(t, n):
    j = n - 1
    for p in t:
        for k in range(j, n):
            m, v = n - 1 - k, '_ '[k < n - 1]
            q = p[:-1]
            q = q.replace(f + u, '(_')
            q = q.replace(u + b, '_)')
            q = q.replace(s, s * n)
            q = q.replace(u, v * n)
            q = q.replace(f, s * m + f + s * k)
            q = q.replace('(', v * m + f + v * k)
            q = q.replace(b, s * k + b + s * m)
            q = q.replace(')', v * k + b + v * m)
            print q
            j = 0

기본 접근 방식은 다음과 같습니다.

  1. 입력 된 모든 라인을 반복합니다.
  2. 각 라인에 대해 출력 크기를 N반복하여 각 루프 반복에서 출력 라인을 생성하십시오. 출력 시작시 빈 줄이 생성되는 것을 피하기 위해 첫 번째 줄에는 마지막 출력 줄만 생성되는 특별한 경우가 있습니다.
  3. 줄의 각 문자를 N문자로 바꾸십시오.
    • 각 공간은 공백으로 대체됩니다 N.
    • 각 밑줄은 N첫 번째 N -1루프 반복을 위한 공백 으로 대체되고 N마지막 루프 반복을위한 밑줄로 대체됩니다 .
    • 슬래시와 백 슬래시는 N - 1공백이나 밑줄 로 채워집니다 .

여기서 가장 까다로운 부분은 슬래시 / 백 슬래시 용 패딩이 다음 (슬래시 용) 또는 이전 (백 슬래시 용) 입력 문자에 따라 공백 또는 밑줄을 사용한다는 것입니다. 그것은 문자열 대체 전략에 잘 맞지 않는 것 같습니다.

이 문제를 해결하기 위해 먼저 특정 두 문자 조합을 다른 문자로 바꾸어 실제 대체 중에 다르게 처리 할 수 ​​있습니다. 예를 들어 /_으로 바뀝니다 (_. 그 후에 (는 효과적으로 "슬래시 다음에 밑줄"이 표시되며 그에 따라 대체 될 수 있습니다.

기능 테스트에 사용되는 주요 프로그램 :

import sys
import Golf

n = int(sys.argv[1])
t = ''.join(sys.stdin).rstrip()

Golf.d(t, n)

1
n-1-k입니다n+~k
재귀

완전한 공개를 위해 : 방금 내 솔루션이 약간의 공백을 생성한다는 것을 알았습니다. 출력 정의에서는 허용되지 않으므로 요구 사항을 충족하지 않습니다. 최악의 경우 .rstrip()9자를 더 추가해야합니다 . 나는 더 잘 할 수 있기를 바랍니다. 또한 5자를 잘라내는 방법을 찾았습니다.
Reto Koradi

입력 형식이 허용되지 않는 것 같습니다. sys.stdin허용되는 입력 매개 변수가 아닙니다. 문자열 자체를 조작해야합니다.
isaacg

그럼 당신은 사용할 수 있습니다 sys.stdinint(sys.argv[1])(당신은 또한 별칭 기대할 수, 즉 공정한 게임이라면 그들이 변수로 전달 될 것으로 예상하여 무료로 그들을 얻을 거 아니에요하지만 range당신이 미리 정의 할 필요가 어떤 다른과 replace` 등) .
Martin Ender 2016 년

@ MartinBüttner 입력을 함수 인수로 취할 수 있다고 말합니다. 내가 여기서 뭐하는거야? 어쨌든 함수 인수를 문자열 목록으로 변경하려고했습니다. 괜찮을까요? stdin문자열 목록과 문자열 목록이 모두 문자열 시퀀스 이므로 크게 다르지 않습니다 .
Reto Koradi

1

펄, 132

#!perl -p
INIT{$f=pop}s!.!$&x$f!ge;s! $!! while s!\\+\K\\|/(/)! $1!;
for$x(2..m!/!*$f){print y!_! !r;s!\\.?! \\!g;s!./(.)?!/$1$1!g;s!_ !__!g}

STDIN 및 ARGV 입력을 결합했습니다. 예:

$ perl ~/hex.pl <~/hex.txt 3
         __________________
        /     /     /\     \
       /     /     /  \     \
      /_____/_____/    \_____\
     /     /\     \    /\     \
    /     /  \     \  /  \     \
   /_____/    \_____\/    \_____\
  /\     \    /     /\    /     /\
 /  \     \  /     /  \  /     /  \
/    \_____\/_____/    \/_____/    \
\    /     /\     \    /     /\    /
 \  /     /  \     \  /     /  \  /
  \/_____/    \_____\/_____/    \/
   \     \    /     /\     \    /
    \     \  /     /  \     \  /
     \_____\/_____/    \_____\/
      \     \     \    /     /
       \     \     \  /     /
        \_____\_____\/_____/

1

루비 236237

->i,z{i.split(?\n).map{|l|z.times.map{|y|l.size.times.map{|i|z.times.map{|x|c=l[i]
z<y+2&&(l[i-1..i]=='_\\'||l[i..i+1]=='/_')&&o=?_
(c<?!||(x==y&&c==?\\)||(z==y+1&&c>?^)||(x+y+1==z&&c==?/))&&o=c
o||' '}.join}.join.rstrip}-['']}.join ?\n}

온라인 테스트 : http://ideone.com/e6XakQ

이것은 골프 전의 코드입니다.

-> diamond, zoom {
  diamond.split(?\n).map do |l|
    zoom.times.map do |y|
      l.size.times.map do |i|
        zoom.times.map do |x|
          out_char = crt_char = l[i]

          out_char = ' '

          # _ has to be continued under / or \
          if zoom == y+1 && l[i-1..i]=='_\\'
            out_char = ?_
          end
          if zoom == y+1 && l[i..i+1]=='/_'
            out_char = ?_
          end

          # logic to "zoom" \, / and _ characters 
          out_char = crt_char if crt_char == ' '
          out_char = crt_char if x==y && crt_char == ?\\  
          out_char = crt_char if zoom==y+1 && crt_char == ?_
          out_char = crt_char if x+y+1==zoom && crt_char == ?/

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