문자열을 힐버트 커브로 매핑


27

일부 문자열을 2D 공간, 프랙탈 스타일에 매핑합시다. 당신의 임무는 힐버트 커브 를 계산하고 그것을 따라 문자열을 배치하는 것입니다.

힐버트 커브, 반복 1 ~ 8

태스크

이 작업은 한 줄짜리 입력 문자열을 가져와 그것을 포함하기에 충분히 큰 힐베르트 곡선을 따라 배치하는 것 입니다. 바이트 수를 최대한 줄이십시오. 이 결국!

정황

  • 공백으로 채워질 틈이 있지만 줄 끝에 패딩이 필요하지 않습니다.
  • 선의 시작은 왼쪽 상단에 있고 끝은 왼쪽 하단에 있어야합니다.
  • 프로그램이나 기능을 만들 수 있습니다.
  • 새로운 테스트 사례가 나타날 수 있으므로 아무 것도 하드 코딩하지 마십시오!

보너스

참고 : 보너스는 -50% & -20% on 100B= -20% on 50B또는 -50% on 80B= 와 같이 쌓 40B입니다.

  • -50 % 입력이 여러 줄 문자열 인 경우 원래 입력을 만들려면 프로세스를 반대로하십시오. 보너스에 대한 테스트 케이스 : 기존의 것을 사용하십시오 (보너스 테스트 케이스 포함).
  • -20 % 출력에서 ​​불필요한 공백을 모두 제거하는 경우 (예 : 줄 끝).
  • -5 % 글로벌 네임 스페이스를 오염시키지 않으면 (내가 무슨 뜻인지 알 것이다!)

테스트 사례

abcdefghijklmn

adef
bchg
 nij
 mlk


The quick brown fox jumps over the lazy dog.

Thn f ju
 ewooxpm
qckr rs 
ui btevo
    hlaz
    e  y
      do
      .g

공백 제거 보너스의 경우 :

No  hitespac  her 

Noher

hesc
itpa

리더 보드

답변이 표시되도록하려면 다음 마크 다운 템플릿을 사용하여 헤드 라인으로 답변을 시작하십시오.

# Language Name, N bytes

N제출물의 크기는 어디에 있습니까 ? 당신은 당신의 점수를 향상시킬 경우에, 당신은 할 수 있습니다 를 통해 눈에 띄는에 의해, 헤드 라인에 오래된 점수를 유지한다. 예를 들어 :

# Ruby, <s>104</s> <s>101</s> 96 bytes

헤더에 여러 숫자를 포함하려는 경우 (예 : 점수가 두 파일의 합계이거나 인터프리터 플래그 페널티를 별도로 나열하려는 경우) 실제 점수가 헤더 의 마지막 숫자 인지 확인하십시오 .

# Perl, 43 + 2 (-p flag) = 45 bytes

언어 이름을 링크로 만들어 리더 보드 스 니펫에 표시 될 수도 있습니다.

# [><>](http://esolangs.org/wiki/Fish), 121 bytes

누구든지 더 많은 테스트 케이스를 만들 수 있다면 감사하겠습니다.
wizzwizz4

문자는 곡선의 꼭짓점으로 표시되어야합니까?
flawr

No..hitespac..her.점이 공백 인 경우 보너스에 대한 더 나은 테스트 사례가됩니다. (그리고 현재, 테스트 케이스는 후행 누락 .)
마틴 청산

L 시스템 접근 방식을 사용하는 경우 http : // codegolf / questions / 48697 / ascii-l-system-renderer 를 시도 할 수도 있습니다 . 답을 골라내는 데 도움이 될 수 있습니다.
wizzwizz4

답변:


7

CJam, 119 117 113 112 109 * 0.5 * 0.8 = 43.6 바이트

1 바이트를 절약 해 준 Dennis에게 감사합니다.

시작은 ...

{+e`W<e~}:F;q_N-,4mLm]0aa{4\#4e!1=f*\:G[zGGW%zW%G].ff+2/{~.+~}%}@:L/\_N&{N/]z:z:~$1f>sS}{4L#' e]f{f=SF}N*N}?F

정방향 변환을 테스트합니다 . 역변환을 테스트합니다.

커브를 생성하는 더 짧은 방법이 있다고 확신합니다 ...

설명

먼저 여러 곳에서 필요하기 때문에 배열 끝에서 일부 요소를 자르는 함수를 정의합니다. 스택 위에 배열과 요소 (별도의 배열 내부)가 필요합니다.

{
  +  e# Append the element to the array.
  e` e# Run-length encode.
  W< e# Discard last run.
  e~ e# Run-length decode.
}:F; e# Store in F and discard.

이제 코드의 대부분은 필요한 힐버트 커브의 크기를 결정하고 요소를 커브를 따라 인덱스하는 2D 배열로 구성합니다. 나는 다음 관찰에 근거하여 이것을 구성한다.

2x2 Hilbert 곡선을 고려하십시오.

01
32

4x4 힐버트 곡선은 다음과 같습니다.

0345
1276
ed89
fcba

각 사분면에서 최소값을 빼고 시각적 선명도를 위해 조금씩 분리하면 다음과 같이 나타납니다.

03 01
12 32

21 01
30 32

이 패턴은 모든 크기에 적용됩니다. 이는 4 개의 사분면으로 a) 현재 레벨의 전치, b) 현재 레벨 자체, c) 대각 대각선을 따른 전치, d)를 다시 사용하여 현재 레벨에서 다음 레벨을 구성 할 수 있음을 의미합니다 현재 레벨 자체 그런 다음 현재 레벨 크기의 0, 1, 3, 2 배를 각각 오프셋합니다.

q           e# Read input.
_N-         e# Make a copy and remove all linefeeds.
,4mLm]      e# Take that string's length's logarithm with base 4, rounded up.
            e# This is the Hilbert curve level we need.
0aa         e# Push [[0]] as the level-0 Hilbert curve.
{           e# Store the Hilbert curve level in L. Then for each i from 0 to L-1...
  4\#       e#   Compute 4^i. This is the offset of the four quadrants.
  4e!1=     e#   Get [0 1 3 2] as the second permutation returned by 4e!.
  f*        e#   Multiply each of them by the offset.
  \:G       e#   Swap with the Hilbert curve so far and call it G.
  [         e#   Create an array with...
    z       e#     The transpose of G.
    G       e#     G itself.
    GW%zW%  e#     The anti-diagonal transpose of G.
    G       e#     G itself.
  ]
  .ff+      e#   Add the appropriate offsets to the indices in each of the four quadrants.
  2/        e# Split into a 2x2 grid.
  {         e# Map this onto each pair of quadrants...
    ~       e#   Dump both quadrants on the stack.
    .+      e#   Concatenate them line by line.
    ~       e#   Dump the lines on the stack.
  }%        e# Since this is a map, the lines will automatically be collected in an array.
}@:L/

마지막으로,이 힐버트 지수 곡선을 사용하여 입력에 적절한 변형을 적용합니다.

\_        e# Swap the curve with the input and make another copy.
N&{       e# If the input contains linefeeds, execute the first block, else the second...
  N/      e#   Split the input into lines. The stack now has a grid of indices and a grid
          e#   of characters.
  ]z:z:~  e#   This is some weird transposition magic which zips up the indices with the
          e#   corresponding characters from both grids, and finally flattens the grid
          e#   into a linear list of index/character pairs. Those cells that don't have
          e#   characters due to trimmed whitespace in the input will be turned into
          e#   arrays containing only an index.
  $       e#   Sort the pairs (which sorts them by indices).
  1f>     e#   Discard the indices.
  s       e#   Flatten the result into a single string.
  S       e#   Leave a space on the stack to be trim trailing spaces later.
}{        e# or...
  4L#     e#   Compute the size of the Hilbert curve.
  ' e]    e#   Pad the input to that size with spaces.
  f{      e#   Map this block over lines of the curve, passing the padding input as an
          e#   additional parameter...
    f=    e#     For each index in the current line, select the appropriate character
          e#     from the padded input.
    SF    e#     Trim spaces from the end of the line.
  }
  N*      e#   Join the lines with linefeed characters.
  N       e#   Leave a linefeed on the stack to be trim trailing linefeeds later.
}?
F         e# We left either a space or a linefeed on stack... trim that character from
          e# the end of the string.

3

파이썬 3 467 434 423 457 451 426 386 374 342 291 304 * 80 % * 95 %가 = 231.04 바이트

이것이 작동하는 방식은 Lindenmayer 시스템을 사용하여 Hilbert 곡선을 만들고 문자열 배열을 따라 왼쪽, 오른쪽 및 앞으로 지시를 따릅니다. 골프를 더 잘 할 수있는 방법은 여러 가지가 있습니다. 특히 조건부와 문자열 배열에서. (나는 시도 [" "*p for i in range(p)]했지만 문자열은 항목 할당을 지원하지 않습니다 (분명히). 작동하도록하려면 조인을 제거 할 수 있습니다)

편집 : Dennis 덕분에 일부 조건부 골프를 쳤습니다 . 그리고 나는 줄의 배열을 골라 내었다. 그리고 위의 예제와 비교하여 결과가 바뀌 었으므로 바이트가 변경되지 않았습니다.

편집 : 공백 제거 보너스를 구현했습니다.

편집 : 6 바이트 이상 공백 제거 코드의 버그가 수정되었습니다.

편집 : 이 답변은 글로벌 네임 스페이스를 오염시키지 않기 때문에 wizzwizz4 here 에 따르면 5 % 보너스를받습니다 .

편집 :g 증가 및 감소 방법 이 변경되었습니다 . 이제 eval()와를 사용 str.translate합니다.

편집 : 이 답변은 이제 기능 대신 프로그램입니다.

편집 : 이전 골프의 일부 버그가 수정되었습니다.

s=input();m=(len(bin(len(s)-1))-1)//2;t=eval("[' ']*2**m,"*2**m);t[0][0],*s=s;x=y=g=0;b="A";exec("b=b.translate({65:'-BF+AFA+FB-',66:'+AF-BFB-FA+'});"*m)
while s:
 c,*b=b;g+=(c<"-")-(c=="-")
 if"B"<c:x,y=[[x+1-g%4,y],[x,y+g%4-2]][g%2];t[x][y],*s=s
print("\n".join(''.join(i).rstrip()for i in t).rstrip())

언 골프 드 :

# hilbert(it) is now implemented in the code with exec("b=b.translate")

def hilbert(it):
    s="A"
    n=""
    for i in range(it):
        for c in s:
            if c == "A":
                n += "-BF+AFA+FB-"
            elif c == "B":
                n += "+AF-BFB-FA+"
            else:
                n += c
        s=n;n=""
    return s

def string_to_hilbert(string):
    length = len(string)
    it = (len(bin(length-1))-1)//2
    hil = hilbert(it)
    pow_2 = 2**it
    # we use eval("[' ']*pow_2,"*pow_2) in the code, but the following is equivalent
    output = [[" "for j in range(pow_2)] for i in range(pow_2)]
    output[0][0] = string[0]
    x = 0
    y = 0
    heading = 0
    while string: # while there are still characters in string
        char, *hil = hil
        if char == "-": heading = heading - 1
        elif char == "+": heading = heading + 1
        elif char == "F":
            if heading % 4 == 3: y += 1
            elif heading % 4 == 2: x -= 1
            elif heading % 4 == 1: y -= 1
            else: x += 1
            output[x][y], *string = string
    array = [''.join(i).rstrip()for i in output]
    array = "\n".join(array).rstrip()
    print(array)
    return

5 % 보너스에 대해 궁금합니다. 변수가 파이썬에서 자동으로 로컬입니까?
edc65

@ edc65 나는 도전자에게 비슷한 것을 물었다 : chat.stackexchange.com/transcript/240?m=28529277#28529277 . 희망이 조금 도움이됩니다. 그렇지 않은 경우 채팅으로 토론을 계속할 수 있습니다.
Sherlock9

2

루비, 358 356 344 322 319 * 80 % * 95 % = 242.44 바이트

이것은 내 파이썬 코드가 루비로 번역되었습니다. 루비로 더 많은 답변을 작성해야합니다. 골프를 즐기기에 알맞은 언어입니다.

편집 : 이 질문에서 함수의 이름을 지정할 필요가 없다는 것을 잊었습니다.

편집 : 이 답변은 글로벌 네임 스페이스를 오염시키지 않으므로 wizzwizz4에 따르면 5 % 보너스를 얻 습니다..

->s{l=s.size;m=((l-1).bit_length+1)/2;x=2**m;t=(1..x).map{[" "]*x};t[0][0]=s[0];x=y=g=z=0;d=1;b=?A;m.times{b=b.split("").map{|c|c==?A?"-BF+AFA+FB-":c==?B?"+AF-BFB-FA+":c}.join("")};(c=b[z];z+=1;g+=c<?-?1:c==?-?-1:0;(g%2>0?y+=g%4-2:x+=1-g%4;t[x][y]=s[d];d+=1)if c>?B)while d<l;puts (t.map{|i|(i*'').rstrip}*"\n").rstrip}

언 골프 드 :

def map_string(string)
  len = string.size
  m = ((len-1).bit_length+1)/2
  pow = 2**m
  output = (1..pow).map{[" "]*pow}
  output[0][0] = s[0]
  x = y = heading = char_index = 0
  chars_in_output = 1
  b = ?A
  m.times do |j|
    a = b.split("").map do |char|
      if char == "A"
        "-BF+AFA+FB-"
      else if char == "B"
        "+AF-BFB-FA+"
      else
        char
      end
    end
    b = a.join("")
  end
  while chars_in_output < len
    char = b[char_index]
    char_index += 1
    if char == "-"
      heading += -1
    else if char == "+"
      heading += 1
    else if char == "F"
      if heading % 2 == 0
        y += heading % 4 - 2
      else
        x += 1 - heading % 4
      end
    end
    output[x][y] = string[char_index]
    char_index += 1
  end
  return (output.map{|i|(i*'').rstrip}*"\n").rstrip

이 코드는 코드 라이센스 하에서 이중 라이센스입니까? GPL에 따라 릴리스 된 파생 작업을 생성하고 싶습니다 (GPL 호환 라이센스가 모두 작동하지만). 현재 CC BY-SA 3.0으로 출시되었습니다.
wizzwizz4

@ wizzwizz4 여기에서 채팅하십시오 : chat.stackexchange.com/rooms/56405/…
Sherlock9

1

자바 스크립트 (ES6), 227-20 % : 181.6 바이트

m=>{for(n=1<<((33-Math.clz32(m.length-1))/2),t='',y=0;y<n;y++,t+=`
`)for(x=0;x<n;x++,t+=m[h]||' ')for(u=y,v=x,h=0,s=n;s>>=1;q||(p&&(u=s+~u,v=s+~v),[u,v]=[v,u]))h+=s*s*(3*!!(p=u&s)^!!(q=v&s));return t.replace(/ +$/mg,'').trim()}

5 % 보너스 받기

m=>{for(var n=1<<((33-Math.clz32(m.length-1))/2),t='',x,y=0;y<n;y++,t+=`
`)for(x=0;x<n;x++,t+=m[h]||' ')for(var p,q,u=y,v=x,h=0,s=n;s>>=1;q||(p&&(u=s+~u,v=s+~v),[u,v]=[v,u]))h+=s*s*(3*!!(p=u&s)^!!(q=v&s));return t.replace(/ +$/mg,'').trim()}

241 * 0.8 * 0.95 : 183.16 더 큰

덜 골프

m=>
{
  // calc the size of the bounding square, clz32 is a bit shorter than ceil(log2()
  n = 1<<( (33-Math.clz32(m.length-1)) / 2); 
  t = '';
  for(y = 0; y < n; y++) 
  {
    for(x = 0 ; x < n; x++)
    {
      // for each position x,y inside the square
      // get the index postion in the hilbert curve
      // see https://en.wikipedia.org/wiki/Hilbert_curve (convert x,y to d)
      for(u=y, v=x, h=0, s=n; s >>= 1; )
      {
        h += s*s*(3 * !!(p = u & s) ^ !!(q = v & s));
        q || (p && (u = s+~u, v = s+~v),[u,v]=[v,u])
      }
      // add char at given index to output  
      t += m[h]||' '; // blank if beyond the length of m
    }
    t += '\n'; // add newline add end line
  }
  return t.replace(/ +$/mg,'').trim() // to get the 20% bonus
}  

테스트

F=m=>{for(n=1<<((33-Math.clz32(m.length-1))/2),t='',y=0;y<n;y++,t+=`
`)for(x=0;x<n;x++,t+=m[h]||' ')for(u=y,v=x,h=0,s=n;s>>=1;q||(p&&(u=s+~u,v=s+~v),[u,v]=[v,u]))h+=s*s*(3*!!(p=u&s)^!!(q=v&s));return t.replace(/ +$/mg,'').trim()}

function Test() { O.textContent = F(I.value) }

Test()
#I { width: 90% }
#O { border: 1px solid #ccc}
<input id=I oninput='Test()' value='The quick brown fox jumps over the lazy dog.'>
<pre id=O></pre>


var5 % 보너스를 받기 위해 s를 추가 할 가치가 있습니까?
wizzwizz4

var s,x,y,u,v,t,p,q,n,h아니오 가치가 없습니다 @ wizzwizz4
edc65

당신은 var각각의 첫 사용 전에 넣을 수 있습니다 ... 아, 그것은 더 나쁩니다.
wizzwizz4

@ wizzwizz4 전부, 어쩌면 당신은 요점이 있습니다 ... 나는 노력하고 있습니다 ... 아니오. 너무 나쁨
edc65
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.