Chuỗi ánh xạ tới đường cong Hilbert


27

Hãy ánh xạ một số chuỗi thành không gian 2d, kiểu fractal. Nhiệm vụ của bạn là tính toán một đường cong Hilbert và đặt một chuỗi dọc theo nó.

Đường cong Hilbert, lặp lại 1 đến 8

Bài tập

Nhiệm vụ là lấy chuỗi đầu vào một dòng và đặt nó dọc theo một đường cong Hilbert đủ lớn để chứa nó, nhưng không lớn hơn. Cố gắng làm cho số byte càng thấp càng tốt; Rốt cuộc đây !

Điều kiện

  • Bất kỳ khoảng trống nào được đệm bằng khoảng trắng, nhưng không cần đệm ở cuối dòng.
  • Điểm bắt đầu của dòng nên ở góc trên bên trái và kết thúc ở góc dưới bên trái.
  • Bạn có thể tạo một chương trình hoặc chức năng.
  • Có thể có một số trường hợp thử nghiệm mới xuất hiện, vì vậy đừng mã hóa bất cứ thứ gì!

Tiền thưởng

Lưu ý: Phần thưởng xếp chồng như thế này: -50% & -20% on 100B= -20% on 50Bhoặc -50% on 80B= 40B.

  • -50% Nếu đầu vào là một chuỗi nhiều dòng, đảo ngược quá trình để tạo đầu vào ban đầu. Các trường hợp kiểm tra cho phần thưởng: chỉ cần sử dụng các trường hợp hiện có (bao gồm các trường hợp kiểm tra phần thưởng!)
  • -20% Nếu bạn loại bỏ tất cả các khoảng trắng không cần thiết khỏi đầu ra (ví dụ: ở cuối dòng).
  • -5% Nếu bạn không làm ô nhiễm không gian tên toàn cầu (bạn hiểu ý tôi là gì!)

Các trường hợp thử nghiệm

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

Và đối với phần thưởng tước khoảng trắng:

No  hitespac  her 

Noher

hesc
itpa

Bảng xếp hạng

Để đảm bảo rằng câu trả lời của bạn hiển thị, vui lòng bắt đầu câu trả lời của bạn bằng một tiêu đề, sử dụng mẫu Markdown sau:

# Language Name, N bytes

nơi Nlà kích thước của trình của bạn. Nếu bạn cải thiện điểm số của mình, bạn có thể giữ điểm số cũ trong tiêu đề, bằng cách đánh bại chúng thông qua. Ví dụ:

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

Nếu bạn muốn bao gồm nhiều số trong tiêu đề của mình (ví dụ: vì điểm của bạn là tổng của hai tệp hoặc bạn muốn liệt kê riêng các hình phạt cờ của thông dịch viên), hãy đảm bảo rằng điểm thực tế là số cuối cùng trong tiêu đề:

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

Bạn cũng có thể đặt tên ngôn ngữ thành một liên kết mà sau đó sẽ hiển thị trong đoạn trích bảng xếp hạng:

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

Nếu bất cứ ai có thể làm thêm một số testcase, điều đó sẽ được đánh giá cao.
wizzwizz4

Vì vậy, các charactes nên được đại diện bởi các đỉnh của đường cong?
flawr

No..hitespac..her.trong đó các dấu chấm là khoảng trắng sẽ là trường hợp thử nghiệm tốt hơn cho phần thưởng. (Và hiện tại, trường hợp thử nghiệm bị thiếu dấu vết .)
Martin Ender

Nếu bạn đang thực hiện phương pháp hệ thống L, bạn cũng có thể muốn thử http: // codegolf / question / 48697 / ascii-l-system-renderer . Nó có thể giúp bạn đánh golf câu trả lời của bạn.
wizzwizz4

Câu trả lời:


7

CJam, 119 117 113 112 109 * 0,5 * 0,8 = 43,6 byte

Cảm ơn Dennis vì đã tiết kiệm 1 byte.

Đây là một khởi đầu ...

{+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

Kiểm tra biến đổi về phía trước . Kiểm tra biến đổi nghịch đảo.

Tôi chắc chắn có một cách ngắn hơn để tạo đường cong ...

Giải trình

Đầu tiên, tôi định nghĩa một hàm để cắt một số phần tử từ cuối một mảng, bởi vì tôi cần nó ở một vài nơi. Nó mong đợi mảng và phần tử (bên trong một mảng riêng) ở trên cùng của ngăn xếp.

{
  +  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.

Bây giờ, phần lớn mã xác định kích thước của đường cong Hilbert cần thiết và xây dựng nó thành mảng 2D trong đó các phần tử là các chỉ số dọc theo đường cong. Tôi xây dựng điều này dựa trên quan sát sau đây:

Hãy xem xét đường cong Hilbert 2x2:

01
32

Đường cong Hilbert 4 x 4 là:

0345
1276
ed89
fcba

Nếu chúng ta trừ đi giá trị tối thiểu từ mỗi góc phần tư (và tách chúng ra một chút cho rõ ràng trực quan), chúng ta sẽ nhận được:

03 01
12 32

21 01
30 32

Mẫu này giữ cho bất kỳ kích thước. Điều đó có nghĩa là chúng ta có thể xây dựng cấp độ tiếp theo từ cấp độ hiện tại, bằng cách sử dụng như bốn góc phần tư: a) chuyển vị của cấp độ hiện tại, b) chính cấp độ hiện tại, c) chuyển đổi dọc theo đường chéo, d) một lần nữa mức độ hiện tại chính nó. Và sau đó chúng tôi bù cho chúng lần lượt 0, 1, 3, 2 lần kích thước của mức hiện tại.

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/

Cuối cùng, chúng tôi sử dụng đường cong chỉ số Hilbert này để áp dụng phép biến đổi phù hợp cho đầu vào:

\_        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

Python 3, 467 434 423 457 451 426 386 374 342 291 304 * 80% * 95% = 231.04 byte

Cách thức hoạt động này là tôi tạo đường cong Hilbert bằng hệ thống Lindenmayer và làm theo các hướng dẫn bên trái, phải và chuyển tiếp dọc theo một chuỗi các chuỗi. Có lẽ có nhiều cách để chơi golf tốt hơn; đặc biệt là trong các điều kiện và trong việc tạo ra các chuỗi. (Tôi đã cố gắng [" "*p for i in range(p)]nhưng các chuỗi không hỗ trợ gán vật phẩm (rõ ràng). Nếu tôi có thể làm điều đó hoạt động, tôi cũng có thể thoát khỏi tham gia)

Chỉnh sửa: Chơi golf một số điều kiện với lời cảm ơn đến Dennis . Và tôi đánh gôn xuống dãy dây. Và một sự thay đổi không có byte bởi vì các kết quả đã được chuyển đổi so với các ví dụ ở trên.

Chỉnh sửa: Đã thực hiện phần thưởng tước khoảng trắng.

Chỉnh sửa: Đã sửa lỗi trong mã tước khoảng trắng của tôi để có thêm sáu byte

Chỉnh sửa: Vì câu trả lời này không gây ô nhiễm không gian tên toàn cầu, tôi nhận được 5% tiền thưởng, theo wizzwizz4 tại đây .

Chỉnh sửa: Thay đổi cách gtăng và giảm. Hiện đang sử dụng eval()str.translate.

Chỉnh sửa: Câu trả lời này bây giờ là một chương trình thay vì một chức năng.

Chỉnh sửa: Đã sửa một số lỗi từ golf trước đó.

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())

Ung dung:

# 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

Tò mò về tiền thưởng 5%. Các biến có tự động cục bộ trong Python không?
edc65

@ edc65 Tôi đã hỏi người viết thử thách một điều tương tự ở đây: chat.stackexchange.com/transcript/240?m=28529277#28529277 . Hy vọng rằng sẽ giúp một chút. Nếu không, chúng ta có thể tiếp tục thảo luận trong trò chuyện.
Sherlock9

2

Ruby, 358 356 344 322 319 * 80% * 95% = 242,44 byte

Đây là mã Python của tôi được phiên mã sang Ruby. Tôi nên viết nhiều câu trả lời hơn trong Ruby. Đó là một ngôn ngữ tốt để chơi golf.

Chỉnh sửa: Tôi quên rằng các chức năng không cần phải được đặt tên trong câu hỏi này.

Chỉnh sửa: Vì câu trả lời này không gây ô nhiễm không gian tên toàn cầu, tôi nhận được 5% tiền thưởng, theo wizzwizz4 tại đây .

->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}

Ung dung:

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

Mã này có được cấp phép kép theo giấy phép mã không? Tôi muốn sản xuất một tác phẩm phái sinh được phát hành theo GPL (mặc dù mọi giấy phép tương thích GPL sẽ hoạt động với điều này). Nó hiện đang được phát hành theo CC BY-SA 3.0.
wizzwizz4

@ wizzwizz4 Trò chuyện tại đây: chat.stackexchange.com/rooms/56405/ tàng
Sherlock9

1

JavaScript (ES6), 227 - 20%: 181,6 byte

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()}

Đang cố gắng để nhận được 5% tiền thưởng

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: lớn hơn 183,16

Ít chơi gôn

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
}  

Kiểm tra

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>


Nó có đáng để thêm vars để nhận 5% tiền thưởng không?
wizzwizz4

var s,x,y,u,v,t,p,q,n,hkhông, nó không có giá trị @ wizzwizz4
edc65

Bạn chỉ có thể đặt vartrước lần sử dụng đầu tiên của mỗi ... Ồ, điều đó thậm chí còn tệ hơn.
wizzwizz4

@ wizzwizz4 tất cả, có lẽ bạn có một điểm ... tôi đang cố gắng ... không. Quá tệ
edc65
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.