แผนที่สตริงเพื่อโค้ง Hilbert


27

ลองแมปสตริงบางส่วนกับสเปซ 2 มิติสไตล์แฟร็กทัล งานของคุณคือการคำนวณโค้งฮิลแบร์ตและวางสายตาม

เส้นโค้งของฮิลแบร์ตการวนซ้ำ 1 ถึง 8

งาน

ภารกิจคือการใช้สตริงอินพุตบรรทัดเดียวและวางโครงร่างตามแนวโค้งของฮิลแบร์ตใหญ่พอที่จะเก็บไว้ แต่ไม่ใหญ่กว่า พยายามทำให้จำนวนไบต์น้อยที่สุดเท่าที่จะเป็นไปได้ นี่คือ หลังจากทั้งหมด!

เงื่อนไข

  • ช่องว่างใด ๆ ที่จะถูกเสริมด้วยช่องว่าง แต่ไม่จำเป็นต้องใช้ช่องว่างภายในท้ายบรรทัด
  • จุดเริ่มต้นของบรรทัดควรอยู่ที่มุมบนซ้ายและจุดสิ้นสุดที่มุมล่างซ้าย
  • คุณสามารถสร้างโปรแกรมหรือฟังก์ชั่น
  • อาจมีกรณีทดสอบใหม่ปรากฏขึ้นดังนั้นอย่าฮาร์ดโค้ดอะไรเลย!

โบนัส

หมายเหตุ: โบนัสสแต็คเช่นนี้-50% & -20% on 100B= -20% on 50Bหรือ=-50% on 80B40B

  • -50% ถ้าอินพุตเป็นสตริงหลายบรรทัดให้ย้อนกระบวนการเพื่อสร้างอินพุตดั้งเดิม กรณีทดสอบสำหรับโบนัส: เพียงใช้กรณีที่มีอยู่ (รวมถึงกรณีทดสอบโบนัส!)
  • -20% หากคุณตัดช่องว่างที่ไม่จำเป็นออกจากเอาต์พุต (เช่นที่ส่วนท้ายของบรรทัด)
  • -5% ถ้าคุณไม่สร้างมลภาวะให้กับ namespace ทั่วโลก (คุณรู้ว่าฉันหมายถึงอะไร!)

กรณีทดสอบ

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

และสำหรับโบนัส whitespace-stripping:

No  hitespac  her 

Noher

hesc
itpa

ลีดเดอร์บอร์ด

เพื่อให้แน่ใจว่าคำตอบของคุณปรากฏขึ้นโปรดเริ่มคำตอบด้วยหัวข้อโดยใช้เทมเพลต Markdown ต่อไปนี้:

# 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

ดังนั้นตัวละครควรแสดงด้วยจุดยอดของเส้นโค้ง?
ข้อบกพร่อง

No..hitespac..her.จุดที่เป็นช่องว่างจะเป็นกรณีทดสอบที่ดีกว่าสำหรับโบนัส (และปัจจุบันกรณีทดสอบขาดการติดตาม.)
Martin Ender

หากคุณกำลังใช้วิธี L-ระบบคุณอาจต้องการที่จะลองhttp: // codegolf / คำถาม / 48697 / ascii-L-ระบบ renderer มันสามารถช่วยคุณเล่นกอล์ฟคำตอบของคุณ
wizzwizz4

คำตอบ:


7

CJam, 119 117 113 112 109 * 0.5 * 0.8 = 43.6 ไบต์

ขอบคุณ Dennis ที่ช่วยประหยัด 1 ไบต์

นี่คือจุดเริ่มต้น ...

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

ตอนนี้ส่วนใหญ่ของรหัสกำหนดขนาดของเส้นโค้งฮิลแบร์ตที่ต้องการและสร้างมันเป็นอาร์เรย์ 2 มิติที่องค์ประกอบมีดัชนีตามเส้นโค้ง ฉันสร้างสิ่งนี้ตามข้อสังเกตต่อไปนี้:

พิจารณาโค้ง 2x2 Hilbert:

01
32

เส้นโค้ง 4x4 Hilbert คือ:

0345
1276
ed89
fcba

หากเราลบค่าต่ำสุดจากแต่ละควอแดรนท์ (และแยกเป็นบิตเพื่อความชัดเจนของภาพ) เราจะได้:

03 01
12 32

21 01
30 32

รูปแบบนี้ถือขนาดใดก็ได้ มันหมายความว่าเราสามารถสร้างระดับถัดไปจากปัจจุบันโดยใช้เป็น quadrants สี่: 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

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

วิธีการทำงานนี้คือฉันสร้างโค้ง Hilbert โดยใช้ระบบ Lindenmayer และทำตามคำแนะนำด้านซ้ายขวาและไปข้างหน้าตามชุดของสตริง มีหลายวิธีที่อาจทำให้สนามกอล์ฟดีขึ้นได้ โดยเฉพาะอย่างยิ่งในเงื่อนไขและในการสร้างอาร์เรย์ของสตริง (ฉันพยายามแล้ว[" "*p for i in range(p)]แต่สตริงไม่รองรับการกำหนดไอเท็ม (เห็นได้ชัด) ถ้าฉันสามารถทำงานได้ฉันก็สามารถยกเลิกการเข้าร่วมได้เช่นกัน)

แก้ไข:แข็งแรงเล่นกอล์ฟบางส่วนของเงื่อนไขกับขอบคุณที่เดนนิส และฉันก็ลงไปเรียงแถวของสตริง และไม่มีการเปลี่ยนแปลงไบต์เนื่องจากผลลัพธ์ที่ออกมา transposed เมื่อเทียบกับตัวอย่างข้างต้น

แก้ไข:นำโบนัส whitespace stripping ไปใช้

แก้ไข:แก้ไขข้อผิดพลาดในรหัสของฉันช่องว่างการลอกสำหรับอีกหกไบต์

แก้ไข:เนื่องจากคำตอบนี้ไม่ก่อให้เกิดมลพิษ namespace โลกที่ฉันได้รับโบนัส 5% ตาม wizzwizz4 ที่นี่

แก้ไข:เปลี่ยนวิธีการ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())

Ungolfed:

# 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% ตัวแปรอยู่ใน Python โดยอัตโนมัติหรือไม่?
edc65

@ edc65 ผมถามนักเขียนท้าทายสิ่งที่คล้ายกันที่นี่: chat.stackexchange.com/transcript/240?m=28529277#28529277 หวังว่าจะช่วยได้เพียงเล็กน้อย ถ้าไม่เราสามารถพูดคุยกันต่อในการแชท
Sherlock9

2

Ruby, 358 356 344 322 319 * 80% * 95% = 242.44 ไบต์

นี่คือรหัส Python ของฉัน transpiled เป็น Ruby ฉันควรเขียนคำตอบเพิ่มเติมใน Ruby มันเป็นภาษาที่ดีในการเล่นกอล์ฟ

แก้ไข:ฉันลืมว่าฟังก์ชั่นไม่จำเป็นต้องตั้งชื่อในคำถามนี้

แก้ไข:เนื่องจากคำตอบนี้ไม่ก่อให้เกิดมลพิษ namespace โลกที่ฉันได้รับโบนัส 5% ตาม wizzwizz4 ที่นี่

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

Ungolfed:

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 9

1

JavaScript (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 ที่ใหญ่กว่า

น้อย golfed

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>


จะเป็นการเพิ่มมูลค่าอีกvarหรือไม่ที่จะได้รับโบนัส 5%
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.