Meningkatkan Diamond Tiling

27

Setiap segi enam biasa dapat diberi ubin dengan berlian, misalnya seperti:

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

Kami akan mempertimbangkan ubin di atas ukuran 1(karena sisi berlian terbuat dari satu /atau \masing - masing). Ukuran ubin yang sama 2akan terlihat seperti:

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

Tugas Anda adalah untuk menerima ubin seni ASCII (ukuran 1) seperti input, bersama dengan bilangan bulat positif N(dalam desimal atau unary), menentukan ukuran output yang diinginkan. Anda kemudian harus menampilkan versi yang ditingkatkan dari ubin yang sama.

Perhatikan bahwa segi enam bisa berukuran berapa saja dan sekecil 1x1x1 (mengandung tiga berlian).

Baik input maupun output tidak boleh mengandung spasi tambahan, atau spasi lebih banyak dari yang diperlukan untuk menyelaraskan bentuk segi enam. Baik input dan output secara opsional dapat memuat satu baris baru (pilihan ini tidak harus sama untuk input dan output).

Anda dapat menulis sebuah program atau fungsi, mengambil input melalui STDIN (atau alternatif terdekat), argumen baris perintah atau argumen fungsi dan mengeluarkan hasilnya melalui STDOUT (atau alternatif terdekat), nilai pengembalian fungsi atau parameter function (out).

Ini adalah kode golf, jadi jawaban tersingkat (dalam byte) dalam kemenangan.

Contoh Memiringkan

Berikut ini beberapa masukan yang dapat Anda gunakan untuk menguji kiriman Anda.

 __
/_/\
\_\/

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

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

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

Cuplikan berikut berisi keluaran yang sesuai untuk input yang N = 1masuk N = 6.

Martin Ender
sumber
20
Saya melihat Anda tertarik pada berlian sekarang karena Anda punya satu di sebelah nama pengguna Anda.
user12205
3
@ace: Anda tahu apa yang mereka katakan: berlian adalah sahabat moderator.
Alex A.
Saya pikir saya tahu jawabannya, tapi saya harap saya salah: Memimpin garis kosong akan dianggap sebagai ruang terdepan, yang Anda nyatakan sebagai ilegal? Solusi awal saya memiliki N-1jalur kosong terdepan. :(
Reto Koradi
@RetoKoradi Memang, tidak ada baris baru. Maaf.
Martin Ender
1
Saya pikir. Harganya sekitar 10 byte. Tidak seburuk kelihatannya ketika saya pertama kali mengenali masalahnya.
Reto Koradi

Jawaban:

8

CJam, 85 79 76 72 byte

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

Ukurannya harus di baris pertama. Dan berliannya mengikuti.

Tidak bermain golf dengan baik ... Dan setengah dari karakter datang dari detail.

Penjelasan (dari versi sebelumnya)

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.
jimmy23013
sumber
10

Python 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

Output pada kasus uji.

Jadi, apa yang terjadi di sini?

Gagasan utamanya adalah bahwa setiap karakter dalam dokumen asli meledak menjadi satu n*nblok. Misalnya, untuk n = 4, /bisa jadi

   /
  /
 /
/___

Karakter asli muncul sekali di setiap baris, dan ada padding di kedua sisi. Di sini, di sebelah kiri, dan _di sebelah kanan. Hanya baris bawah yang bisa diisi oleh '_'; sisanya selalu ' '.

Kesulitan utama adalah bahwa bantalan di sebelah kanan dapat bergantung pada simbol yang akan datang. Secara khusus, '/ 'memiliki padding berbeda dari '/_', jadi kita perlu melihat ke depan. Selain itu, untuk menghindari spasi tambahan, kita harus mencatat bahwa kita berada pada simbol terakhir dan menahan diri dari bantalan di sebelah kanan.

Kami mengatasi kedua masalah ini dengan hanya menempel di sebelah kiri karakter saat ini. Ketika kami melakukannya, kami juga melakukan padding kanan dari karakter sebelumnya menggunakan simbol padding saat ini. Jadi, kami mencetak padding kanan yang terutang dari char sebelumnya, padding kiri dari char saat ini, kemudian char saat ini. Kami juga menyimpan jumlah padding "hutang" yang harus dibayar oleh arang berikutnya.

Sekarang mari kita membahas kodenya.

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

String input adalah sdan faktor skala adalah n. Kami pergi baris demi baris, mencetak nbaris untuk setiap baris input W, dengan salinan diindeks j=n,n-1,...,2,1. Baris pertama hanya disalin sekali, yang kita capai dengan menginisialisasi jke 1 tetapi mengubahnya ke nsetiap loop.

Kami beralih melalui jalur input, mengumpulkan jalur untuk dicetak O. Pertama, kami mencari karakter padding yang sesuai q, yang merupakan garis bawah jika kita berada di garis bawah dan karakter saat ini atau sebelumnya adalah garis bawah, dan sebaliknya spasi.

Kemudian, kami memutuskan jumlah bantalan untuk diletakkan di sebelah kiri ( e). Untuk /, itu j-1(berkurang dengan menurunnya jumlah baris-salinan), dan pelengkap n-juntuk \. Kami memperlakukan karakter lain dengan cara yang sama. Sebagai contoh, meskipun _sepertinya memberikan deretan ngaris bawah, sebenarnya memberi garis bawah tunggal, diisi oleh garis bawah di sebelah kiri dan kanan. Ini tampaknya tidak efisien, tetapi ini memungkinkan kita bekerja dengan _dan dalam kerangka kerja yang sama seperti /dan \Posisi garis bawah "pusat" tidak masalah, jadi kami menyamakannya dan dengan \; Pilihan ini juga membuat baris atas bekerja tanpa casing khusus.

Selanjutnya, kita tambahkan ke string output. Kami telah menemukan simbol padding q, dan jumlah padding saat ini e, tetapi kami juga perlu mengingat hutang padding ddari simbol sebelumnya. Jadi, kami tambahkan q*(e+d). Kemudian, kita menambahkan simbol saat ini c, kecuali kita perlu menghindari garis bawah pada baris non-bawah, yang kita perbaiki dengan mengubah garis bawah menjadi simbol bantalan.

Akhirnya, kami mencatat jumlah utang padding, yang melengkapi n+~djumlah padding kiri saat ini. Kami juga merekam simbol saat ini p, sehingga nanti kami akan tahu apakah simbol sebelumnya adalah _.

Tidak
sumber
3

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

edc65
sumber
3

Python 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

6 byte berkat Sp3000.

Panggil mdengan argumen pertama menjadi berlian sebagai string, dan argumen kedua nomor pengulangan.

Ini didasarkan pada urutan penggantian string 3 langkah:

  • Pertama, ganti garis bawah dengan spasi 2n-1 atau garis bawah, tergantung pada garis.
  • Kedua, ganti /\dengan / \, dengan jumlah ruang intervening dari 2 menjadi 2 * (n-1) melewati garis.
  • Ketiga, ganti \/dengan \ /, dengan jumlah ruang intervensi mulai dari 2 * (n-1) ke 2 di atas garis.

Lalu, ada berbagai mucking tentang untuk mendapatkan ruang terdepan yang benar, dan untuk mendapatkan garis pertama yang benar.

Perhatikan bahwa baris terakhir dari program harus berupa tab, bukan 4 spasi. Penurunan harga tidak mendukung tab.

isaacg
sumber
Dua golf: (i+(n-i+~i)*(d[-1]>f)) --> [i,n+~i][d[-1]>f]dan Anda hanya menggunakan '_'sekali, jadi Anda membuang satu byte untuk mendefinisikannya.
Sp3000
3

Python, 272 238 228 243 byte

Versi yang diperbarui, sekarang mengambil string tunggal sebagai input, bukan urutan string. Juga menghapus spasi spasi yang ada di versi sebelumnya. Sayangnya perubahan ini menambah ukuran.

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

Versi dengan spasi putih, dan pernyataan dipecah menjadi unit yang lebih kecil untuk dibaca:

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

Pendekatan dasar di sini adalah:

  1. Ulangi semua baris dalam input.
  2. Untuk setiap baris, lilitkan pada ukuran output N, buat garis output di setiap iterasi loop. Ada kasus khusus untuk baris pertama, di mana hanya baris output terakhir yang dihasilkan, untuk menghindari menghasilkan baris kosong di awal output.
  3. Ganti setiap karakter di baris dengan Nkarakter, di mana:
    • Setiap ruang diganti dengan Nspasi.
    • Setiap garis bawah diganti dengan Nspasi untuk N -1iterasi loop pertama , dan Nmenggarisbawahi untuk iterasi loop terakhir.
    • Garis miring dan garis miring berlapis dengan N - 1spasi atau garis bawah.

Bagian yang paling sulit di sini adalah bahwa padding untuk garis miring / garis miring menggunakan spasi atau garis bawah tergantung pada karakter input berikutnya (untuk garis miring) atau sebelumnya (untuk garis miring terbalik). Itu tampaknya tidak cocok dengan strategi substitusi string.

Apa yang saya lakukan untuk menyelesaikan ini adalah saya pertama kali mengganti dua kombinasi karakter tertentu dengan karakter yang berbeda, sehingga saya dapat memperlakukannya secara berbeda selama penggantian yang sebenarnya. Misalnya, /_diganti dengan (_. Setelah ini, (secara efektif "garis miring diikuti oleh garis bawah", yang kemudian dapat diganti.

Program utama yang digunakan untuk menguji fungsi:

import sys
import Golf

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

Golf.d(t, n)
Reto Koradi
sumber
1
n-1-kadalahn+~k
rekursif
Untuk kepentingan pengungkapan penuh: Saya baru saja menemukan bahwa solusi saya menghasilkan beberapa ruang tambahan. Karena itu tidak diizinkan dalam definisi output, itu tidak memenuhi persyaratan. Dalam kasus terburuk, saya harus menambahkan .rstrip()9 karakter lagi. Saya harap saya bisa melakukan yang lebih baik, dan juga menemukan cara untuk memotong 5 karakter.
Reto Koradi
Sepertinya format input Anda tidak diperbolehkan. sys.stdinbukan parameter input yang diijinkan - Anda perlu memanipulasi string itu sendiri.
isaacg
Baik Anda dapat menggunakan sys.stdindan int(sys.argv[1])tetapi Anda tidak akan mendapatkannya secara gratis dengan mengharapkan mereka akan rangedimasukkan sebagai variabel (jika itu adalah permainan yang adil, maka Anda juga bisa mengharapkan alias untuk dan mengganti` dan apa pun yang Anda harus ditetapkan sebelumnya) .
Martin Ender
@ MartinBüttner Dikatakan bahwa saya dapat mengambil input sebagai argumen fungsi. Bukankah ini yang saya lakukan di sini? Saya akan mengubah argumen fungsi ke daftar string. Apakah itu baik-baik saja? Ini tidak jauh berbeda, karena keduanya stdindan daftar string adalah urutan string.
Reto Koradi
1

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

Gabungan input STDIN dan ARGV. Contoh:

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

Ruby 236 237

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

Tes online: http://ideone.com/e6XakQ

Ini adalah kode sebelum bermain golf:

-> 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
}
Cristian Lupascu
sumber