Hilbert eğrisine dize eşleştir


27

Bazı karakter dizilerini 2d uzaya fraktal stille eşleştirelim. Senin görevin bir Hilbert eğrisi hesaplamak ve onun üzerine bir dize koymak.

Hilbert eğrisi, 1'den 8'e kadar yinelemeler

Görev

Görev, tek satırlık giriş dizesini almak ve onu içine alacak kadar büyük, ancak daha büyük olmayacak şekilde bir Hilbert eğrisi boyunca yerleştirmektir . Bayt sayısını olabildiğince düşük tutmaya çalışın; Bu ise sonuçta!

Koşullar

  • Boşluklarla doldurulması gereken boşluklar, ancak satırların sonunda doldurma gerekli değildir.
  • Çizginin başlangıcı sol üst köşede ve son sol alt köşede olmalıdır.
  • Bir program veya işlev oluşturabilirsiniz.
  • Ortaya çıkan bazı yeni test durumları olabilir, bu nedenle hiçbir şeyi kodlamayın!

Bonuslar

Not: Bonuslar yığını böyle: -50% & -20% on 100B= -20% on 50Bveya -50% on 80B= 40B.

  • -50% Giriş çok satırlı bir dize ise, orijinal girişi oluşturma işlemini tersten izleyin. Bonus için test durumları: sadece mevcut olanları kullanın (bonus test durumları dahil!)
  • % -20 Gereksiz tüm boşlukları çıktıdan çıkarırsanız (örneğin bir satırın sonunda).
  • -5% Eğer küresel isim alanını kirletmiyorsanız (ne demek istediğimi biliyorsunuz!)

Test durumları

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

Ve boşluk-sıyırma bonusu için:

No  hitespac  her 

Noher

hesc
itpa

Liderler Sıralaması

Cevabınızın göründüğünden emin olmak için, lütfen aşağıdaki Markdown şablonunu kullanarak cevabınızı bir başlık ile başlatın:

# Language Name, N bytes

Gönderinizin Nbüyüklüğü nerede ? Puanınızı artırmak varsa, olabilir onları içinden vurarak, başlığa eski hesapları tutmak. Örneğin:

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

Başlığınıza birden fazla sayı eklemek istiyorsanız (örneğin, puanınız iki dosyanın toplamı olduğundan veya tercüman bayrağı cezalarını ayrı ayrı listelemek istediğiniz için), gerçek puanın başlıktaki son sayı olduğundan emin olun :

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

Dil adını, daha sonra büyük afiş snippet'inde görünecek bir bağlantı da yapabilirsiniz:

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

Birileri biraz daha testis yapabilirse, bu memnuniyet duyar.
wizzwizz4

Öyleyse, charactes eğrinin köşeleriyle mi temsil edilmeli?
kusur

No..hitespac..her.noktaların boşluk olduğu yerlerde, bonus için daha iyi bir test durumu olacaktır. (Ve şu anda, test davasında sondaki eksik .)
Martin Ender

L sistemi yaklaşımını kullanıyorsanız, http: // codegolf / questions / 48697 / ascii-l-system-renderer'ı da denemek isteyebilirsiniz . Cevaplarını doldurmana yardımcı olabilir.
wizzwizz4

Yanıtlar:


7

CJam, 119 117 113 112 109 * 0.5 * 0.8 = 43.6 bayt

1 byte tasarruf için Dennis teşekkürler.

İşte bir başlangıç ​​...

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

İleri dönüşümü test edin . Ters dönüşümü test edin.

Eminim eğriyi oluşturmanın daha kısa bir yolu vardır ...

açıklama

İlk olarak, bazı elementleri bir dizinin sonundan kırpmak için bir fonksiyon tanımladım, çünkü birkaç yerde buna ihtiyacım var. Diziyi ve elemanı (ayrı bir dizinin içinde) yığının üstüne bekler.

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

Şimdi kodun çoğunluğu gerekli Hilbert eğrisinin boyutunu belirler ve bunu elemanların eğri boyunca indekslendiği 2D dizisi olarak yapılandırır. Bunu aşağıdaki gözlemlere dayanarak yapıyorum:

2x2 Hilbert eğrisini göz önünde bulundurun:

01
32

4x4 Hilbert eğrisi şöyledir:

0345
1276
ed89
fcba

Her bir kadrandan minimum değeri çıkarırsak (ve onları görsel netlik için biraz ayırırsak), şunları elde ederiz:

03 01
12 32

21 01
30 32

Bu desen herhangi bir boyut için tutar. Bu, bir sonraki seviyeyi dört kadran olarak kullanarak mevcut seviyeden inşa edebileceğimiz anlamına gelir: a) mevcut seviyenin devri, b) mevcut seviyenin kendisi, c) köşegen boyunca geçiş, d) tekrar Mevcut seviyenin kendisi. Ve sonra onları sırasıyla geçerli seviyenin boyutunun 0, 1, 3, 2 katı kadar dengeledik.

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/

Son olarak, girdilere uygun dönüşümü uygulamak için bu Hilbert indeks eğrisini kullanıyoruz:

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

Bunun çalışması, Hilbert eğrisini bir Lindenmayer sistemi kullanarak yapıyorum ve bir dizi dizi boyunca sol, sağ ve ileri talimatları izliyorum. Yine de, bunun daha iyi golf oynayabileceği pek çok yol var; Özellikle koşullu olarak ve dizgelerin dizilişinde. (Denedim[" "*p for i in range(p)] ancak dizeler öğe atamasını desteklemiyor (görünüşe göre). Bunu işe alabilirsem, katılmaktan da kurtulabilirdim)

Düzenleme: Dennis sayesinde bazı koşulların golf oynadı . Ve dizgilerin dizisine girdim. Ve bir bayt olmayan değişiklik çünkü sonuçlar yukarıdaki örneklere göre aktarıldı.

Düzenleme: Beyazlık-sıyırma bonusu uygulandı.

Düzenleme: Boşluk-sıyırma kodumda altı baytlık bir hata düzeltildi

Düzenle: Bu cevap küresel isim alanını kirletmediğinden, burada wizzwizz4'e göre% 5 bonus kazanıyorum .

Düzenleme: Nasıl değiştig artırılıp azaltılacağını değiştirdi. Şimdi eval()ve kullanarakstr.translate .

Düzenle: Bu cevap şimdi bir işlev yerine bir programdır.

Düzenleme: Bir önceki golfün bazı hataları düzeltildi.

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 bonus hakkında merak ediyorum. Python'da değişkenler otomatik olarak yerel midir?
edc65

@ edc65 Buradaki soruna benzer bir şey sordum: chat.stackexchange.com/transcript/240?m=28529277#28529277 . Umarım bu biraz yardımcı olur. Olmazsa, tartışmaya sohbete devam edebiliriz.
Sherlock9

2

Ruby, 358 356 344 322 319 * 80% * 95% = 242.44 bayt

Bu benim Ruby'ye aktarılan Python kodum. Ruby'de daha fazla cevap yazmalıyım. Golf oynamak için iyi bir dil.

Düzenleme: Bu soruda işlevlerin adlandırılmasına gerek olmadığını unuttum.

Düzenleme: Bu cevap küresel isim alanını kirletmediğinden, burada wizzwizz4'e göre% 5 bonus kazanıyorum .

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

Bu kod bir kod lisansı altında çift lisanslı mı? GPL kapsamında yayınlanan bir türev çalışma yapmak istiyorum (GPL uyumlu lisans bununla çalışsa da). Halen CC BY-SA 3.0 altında yayınlanmıştır.
wizzwizz4


1

JavaScript (ES6), 227 -% 20: 181.6 bayt

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 bonus kazanmaya çalışıyorum

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 daha büyük

Daha az golf oynadı

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
}  

Ölçek

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 bonus almak için s eklemeye değer mi ?
wizzwizz4

var s,x,y,u,v,t,p,q,n,hhayır değmez @ wizzwizz4
edc65 17

varHer birini ilk kullanımdan önce koyabilirsiniz ... Ah, bu daha da kötü.
wizzwizz4

@ wizzwizz4 Sonuçta, belki bir noktaya var ... Deniyorum ... hayır. Çok kötü
edc65
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.