Tantangan ASCII-art heksplosif


20

Dalam permainan strategi "Hexplode" , pemain secara bergantian menempatkan token pada papan heksagonal. Setelah jumlah token sama dengan jumlah petak yang berdekatan, petak itu hexplodes , dan memindahkan semua token di atasnya ke tetangga sekitarnya. Anda dapat memainkan game online di sini .

Saya suka game ini, tetapi terkadang sulit untuk mengetahui dengan pasti berapa banyak token yang dipasang pada ubin tertentu; Saya selalu menghitung jumlah tetangga. Akan sangat nyaman jika saya memiliki seni ASCII untuk membantu saya mengingat berapa banyak token yang dipasang di setiap ubin.

Anda perlu menulis sebuah program atau fungsi yang mengambil bilangan bulat positif sebagai masukan, dan menghasilkan ini representasi ASCII dari segi enam ukuran N . Setiap ubin akan menjadi jumlah tetangga yang dimiliki ubin. Karena 1 adalah kasus sudut aneh dengan nol tetangga, Anda hanya perlu menangani input yang lebih besar dari 1.

Anda dapat mengambil nomor ini dalam format apa pun yang wajar, seperti STDIN, argumen fungsi, argumen baris perintah, dari file, dll. Outputnya juga dapat dalam format apa pun yang masuk akal, seperti mencetak ke STDOUT, menulis ke file, mengembalikan daftar string, string yang dipisahkan baris baru, dll.

Berikut adalah beberapa contoh output untuk 5 input pertama:

2)

 3 3
3 6 3
 3 3


3)

  3 4 3
 4 6 6 4
3 6 6 6 3
 4 6 6 4
  3 4 3


4)

   3 4 4 3
  4 6 6 6 4
 4 6 6 6 6 4
3 6 6 6 6 6 3
 4 6 6 6 6 4
  4 6 6 6 4
   3 4 4 3

5)

    3 4 4 4 3
   4 6 6 6 6 4
  4 6 6 6 6 6 4
 4 6 6 6 6 6 6 4
3 6 6 6 6 6 6 6 3
 4 6 6 6 6 6 6 4
  4 6 6 6 6 6 4
   4 6 6 6 6 4
    3 4 4 4 3

6)

     3 4 4 4 4 3
    4 6 6 6 6 6 4
   4 6 6 6 6 6 6 4
  4 6 6 6 6 6 6 6 4
 4 6 6 6 6 6 6 6 6 4
3 6 6 6 6 6 6 6 6 6 3
 4 6 6 6 6 6 6 6 6 4
  4 6 6 6 6 6 6 6 4
   4 6 6 6 6 6 6 4
    4 6 6 6 6 6 4
     3 4 4 4 4 3

Dan polanya berlanjut dengan cara yang serupa. Seperti biasa, celah standar berlaku, dan jawaban dengan byte-count terendah akan dinobatkan sebagai pemenang!

Papan peringkat

Berikut ini adalah Stack Snippet untuk menghasilkan leaderboard biasa dan gambaran umum pemenang berdasarkan bahasa.

Untuk memastikan bahwa jawaban Anda muncul, silakan mulai jawaban Anda dengan tajuk utama, menggunakan templat Penurunan harga berikut:

# Language Name, N bytes

di mana Nukuran kiriman Anda. Jika Anda meningkatkan skor Anda, Anda bisa menyimpan skor lama di headline, dengan mencoretnya. Contohnya:

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

Jika Anda ingin memasukkan beberapa angka dalam tajuk Anda (mis. Karena skor Anda adalah jumlah dari dua file atau Anda ingin membuat daftar hukuman penterjemah secara terpisah), pastikan bahwa skor sebenarnya adalah angka terakhir di tajuk:

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

Anda juga dapat membuat tautan nama bahasa yang kemudian akan muncul di cuplikan papan peringkat:

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


1
Terkait (tetapi bertanya tentang proses daripada jumlah tetangga).
trichoplax

1
Saya tergoda untuk belajar Hexagony hanya demi tantangan ini. ;)
Kevin Cruijssen

Jawaban:


11

MATL , 39 37 byte

4*3-:!G:+o~YRtP*!tPw4LY)vtI5&lZ+47+*c

Cobalah online! Atau verifikasi semua kasus uji .

Penjelasan

Saya dapat menggunakan konvolusi lagi!

Pertimbangkan input n = 3. Kode pertama membangun matriks ukuran 4*n-3× ndengan menambahkan vektor kolom [1; 2; ...; 9]ke vektor baris [1, 2, 3]dengan siaran. Ini berarti menghitung array array 2D dari semua penambahan berpasangan:

 2  3  4
 3  4  5
 4  5  6
 5  6  7
 6  7  8
 7  8  9
 8  9 10
 9 10 11
10 11 12

Mengganti angka genap dengan 1dan angka ganjil dengan 0memberikan pola kotak-kotak

1 0 1
0 1 0
1 0 1
0 1 0
1 0 1
0 1 0
1 0 1
0 1 0
1 0 1

Ini akan digunakan untuk menghasilkan (bagian dari) kisi heksagonal. Yang akan mewakili poin di grid, dan nol akan mewakili spasi.

Sudut kanan atas dihapus dengan memusatkan semua entri di atas "diagonal" utama dari matriks:

1 0 0
0 1 0
1 0 1
0 1 0
1 0 1
0 1 0
1 0 1
0 1 0
1 0 1

Elemen-bijaksana mengalikan matriks ini dengan versi membalik secara vertikal itu sendiri menghilangkan sudut kanan bawah juga. Transposing kemudian memberi

1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0
0 0 1 0 1 0 1 0 0

Ini mulai terlihat seperti segi enam. Dengan menggunakan simetri, kisi diperpanjang untuk menghasilkan bagian atas:

0 0 1 0 1 0 1 0 0
0 1 0 1 0 1 0 1 0
1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0
0 0 1 0 1 0 1 0 0

Sekarang kita perlu mengganti setiap entri sama dengan satu dengan jumlah tetangga. Untuk ini kami menggunakan konvolusi dengan lingkungan 3 × 5 (yaitu, kernel adalah matriks 3x5). Hasil,

2 3 4 5 5 5 4 3 2
4 5 7 7 8 7 7 5 4
4 6 7 8 7 8 7 6 4
4 5 7 7 8 7 7 5 4
2 3 4 5 5 5 4 3 2

memiliki dua masalah (yang akan diselesaikan nanti):

  1. Nilai telah dihitung untuk semua posisi, sedangkan kita hanya membutuhkannya pada posisi yang ada di kisi nol-satu.
  2. Untuk masing-masing posisi itu, hitungan tetangga mencakup titik itu sendiri, sehingga tidak aktif 1.

Kode sekarang menambah 47setiap nilai yang dihitung. Ini sesuai dengan pengurangan 1untuk menyelesaikan masalah (2) dan menambahkan 48(ASCII untuk '0'), yang mengubah setiap angka ke titik kode karakter terkait.

Matriks yang dihasilkan kemudian dikalikan dengan salinan kisi nol-satu. Ini memecahkan masalah (1) di atas, membuat titik-titik yang bukan bagian dari kisi heksagonal sama dengan nol lagi:

 0  0 51  0 52  0 51  0  0
 0 52  0 54  0 54  0 52  0
51  0 54  0 54  0 54  0 51
 0 52  0 54  0 54  0 52  0
 0  0 51  0 52  0 51  0  0

Akhirnya, array angka ini dilemparkan ke array char. Zero chars ditampilkan sebagai spasi, yang memberikan hasil akhir:

  3 4 3  
 4 6 6 4 
3 6 6 6 3
 4 6 6 4 
  3 4 3  

15

JavaScript (ES6), 118 117 byte

n=>[...Array(m=n+--n)].map((_,i,a)=>a.map((_,j)=>(k=j-(i>n?i-n:n-i))<0?``:k&&++j<m?i/2%n?6:4:3+!i%n).join` `).join`\n`

Dimana \nmewakili karakter baris baru literal. Penjelasan: Misalkan n=4. Kita mulai dengan kotak digit yang dipisahkan oleh spasi berikut:

0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0

Yang pertama |n-i| 0dihapus, tetapi spasi tetap:

   0 0 0 0
  0 0 0 0 0
 0 0 0 0 0 0
0 0 0 0 0 0 0
 0 0 0 0 0 0
  0 0 0 0 0
   0 0 0 0

Segi enam instan! Kemudian cukup untuk menghitung nilai yang sesuai di tempat masing-masing 0dengan memeriksa apakah kita berada di baris dan / atau kolom pertama atau terakhir. Sunting: Disimpan 1 byte berkat @Arnauld.


Menggunakan beberapa formula Anda, saya sampai pada versi 107 byte dengan untuk / console.log ():n=>{for(i=n+--n;i--;)console.log(' '.repeat(l=i>n?i-n:n-i)+(j=3+!l%n)+` ${l-n?6:4}`.repeat(2*n-l-1)+' '+j)}
Arnauld

@Arnauld saya suka itu 3+!i%n!
Neil

7

Python 2, 125 123 byte

def h(n):m=n-1;t=[' '*(m-r)+' '.join(('46'[r>0]*(r+m-1)).join('34'[r%m>0]*2))for r in range(n)];print'\n'.join(t+t[-2::-1])

Tes ada di ideone

Berjalan melalui bagian atas ke baris tengah, for r in range(n), membangun string:
- membuat dua sudut atau dua sisi, '34'[r%m>0]*2;
- mengisi dengan bergabung mereka dengan berulang '6'atau '4', '46'[r>0]*(r+m-1);
- bergabung dengan sudut dan tepi dengan ' ';
- mengawali dengan spasi, ' '*(m-r);

Lalu cetak ini dan itu refleksi di baris tengah bergabung dengan baris baru, print'\n'.join(t+t[-2::-1])


4

Python 2, 96 byte

n=input();m=n-1
while n+m:n-=1;j=abs(n);c='34'[0<j<m];print' '*j+c+' '+'46  '[j<m::2]*(2*m+~j)+c

Ini terlihat sangat berantakan dan agak golf ...


3

Java, 375 363 361 339 329 317 293 byte

interface J{static void main(String[]r){int i=0,k,h=Integer.decode(r[0]),a=1,l,n=0;for(;i++<h*2-1;n+=a){if(n==h-1)a=-1;String s="";for(k=0;k<n+h;k++,s+=" ")s+=n==0?k==0||k==n+h-1?3:4:k!=0&&k!=n+h-1?6:n==h-1?3:4;l=(h*4-3-s.trim().length())/2;System.out.printf((l==0?"%":"%"+l)+"s%s\n","",s);}}}

Tidak disatukan

interface J {
    static void main(String[] r) {
        int i = 0, k, h = Integer.decode(r[0]), a = 1, l, n = 0;
        for (; i++ < h * 2 - 1; n += a) {
            if (n == h - 1) {
                a = -1;
            }
            String s = "";
            for (k = 0; k < n + h; k++, s += " ") {
                s += n == 0 ? k == 0 || k == n + h - 1 ? 3 : 4 : k != 0 && k != n + h - 1 ? 6 : n == h - 1 ? 3 : 4;
            }
            l = (h * 4 - 3 - s.trim().length()) / 2;
            System.out.printf((l == 0 ? "%" : "%" + l) + "s%s\n", "", s);
        }
    }
}

Penggunaan :

$ java J 5
    3 4 4 4 3     
   4 6 6 6 6 4    
  4 6 6 6 6 6 4   
 4 6 6 6 6 6 6 4  
3 6 6 6 6 6 6 6 3 
 4 6 6 6 6 6 6 4  
  4 6 6 6 6 6 4   
   4 6 6 6 6 4    
    3 4 4 4 3

Saya yakin bahwa blok if-else yang bersarang yang mengerikan dapat ditulis ulang menjadi lebih kecil tetapi saya tidak dapat mengetahuinya saat ini. Setiap saran dipersilahkan :-)

Memperbarui

  • Mengikuti saran Kevin Cruijssen dan menggunakan decode alih-alih parseInt.
  • Menulis ulang beberapa ifs dengan menggunakan operator ternary.
  • Lebih banyak operator ternary.
  • Operator terar Moar! Saya pikir saya telah menciptakan monster!
  • Menulis ulang blok if-else tentang pencetakan.

1
Saya belum melihat dengan seksama pada metode yang Anda gunakan sendiri, tetapi beberapa tips golf kecil untuk kode Anda saat ini: Integer.parseIntbisa di -golf Integer.decode. l=(h*4-3-s.trim().length())/2;if(l==0)bisa bermain golf if((l=(h*4-3-s.trim().length())/2)==0). Juga, itu benar-benar dapat diterima untuk hanya memposting metode tanpa kelas (kecuali jika pertanyaan menyatakan sebaliknya), jadi void f(int i){...use i...}alih-alih interface J{static void main(String[]r){...i=Integer.decode(r[0])...use i...}, itu akan menyelamatkan Anda beberapa byte juga. Ketika saya memiliki lebih banyak waktu, saya akan mencari lebih jauh.
Kevin Cruijssen

@KevinCruijssen: Terima kasih atas saran Anda. l=(h*4-3-s.trim().length())/2;if(l==0)sebenarnya panjangnya sama dengan if((l=(h*4-3-s.trim().length())/2)==0).
Master_ex

2

05AB1E , 44 byte

FN_i4ë6}ð«¹ÍN+×ðìN_N¹<Q~i3ë4}.ø¹<N-ð×ì})¦«»

Penjelasan

Karena bagian atas dan bawah segi enam dicerminkan, kita hanya perlu membuat bagian atas.
Jadi untuk input X kita perlu menghasilkan baris X. Itulah yang dilakukan loop utama.

F                                        }

Kemudian kita lakukan bagian tengah baris.
Ini adalah 4 untuk baris pertama dan 6 untuk sisanya (karena kami hanya melakukan bagian atas).
Kami menggabungkan angka ini dengan spasi karena pola akan membutuhkan jarak antar angka.

N_i4ë6}ð«

Kami kemudian mengulangi string ini X-2 + N kali, di mana N adalah baris saat ini yang diindeks 0 dan menambahkan karakter spasi di sisi kiri.

¹ÍN+×ðì

Setelah ini saatnya untuk sudut. Mereka akan menjadi 3 untuk baris pertama dan terakhir dan 4 untuk baris tengah.

N_N¹<Q~i3ë4}.ø

Sekarang kita perlu memastikan baris berbaris dengan benar dengan menambahkan spasi di depan setiap baris. Jumlah spasi yang ditambahkan adalah X-1-N .

¹<N-ð×ì

Sekarang setelah bagian atas grid selesai, kita tambahkan baris ke daftar, buat salinan terbalik dan hapus item pertama dari salinan itu (karena kita hanya perlu baris tengah satu kali), lalu gabungkan kedua daftar ini menjadi satu dan mencetak.

)¦«»

Cobalah online!

Solusi tambahan, juga 44 byte:

ÍÅ10.øvN_i4ë6}ð«¹ÍN+×ðìyi4ë3}.ø¹<N-ð×ì})¦«»

2

Ruby, 87 byte

Fungsi anonim mengambil n sebagai argumen dan mengembalikan array string.

->n{(1-n..n-=1).map{|i|j=i.abs
" "*j+(e=j%n>0?"4 ":"3 ")+["6 ","4 "][j/n]*(2*n-1-j)+e}}

Tidak digabungkan dalam program uji

Masukan melalui stdin. Menulis seluruh bentuk menjadi stdout. Cukup jelas.

f=->n{
  (1-n..n-=1).map{|i|            #reduce n by 1 and iterate i from -n to n
    j=i.abs;                     #absolute magnitude of i
    " "*j+                       #j spaces +
    (e=j%n>0?"4 ":"3 ")+         #start the string with 3 or 4 +
    ["6 ","4 "][j/n]*(2*n-1-j)+  #2*n-1-j 6's or 4`s as appropriate +
    e                            #end the string with another 3 or 4
  }
}

puts f[gets.to_i]

1

V , 60 byte

Àé x@aA4 xr3^.òhYpXa 6^òkyHç^/:m0
Pç 3.*6/^r4$.
òÍ6 4./6

Cobalah online!

Ini terlalu lama. Ini hexdump, karena ini mengandung karakter yang tidak patut dicetak:

0000000: c0e9 2078 4061 4134 201b 7872 335e 2ef2  .. x@aA4 .xr3^..
0000010: 6859 7058 6120 361b 5ef2 6b79 48e7 5e2f  hYpXa 6.^.kyH.^/
0000020: 3a6d 300a 50e7 2033 2e2a 362f 5e72 3424  :m0.P. 3.*6/^r4$
0000030: 2e0a f2cd 3620 9334 852e 2f36            ....6 .4../6

1

Racket, 487 byte

(λ(n c e o)(let((sp(append(range(- n 1)-1 -1)(reverse(range(- n 1)0 -1))))
(mm(append(range(- n 2)(-(+ n(- n 1))2))(range(-(+ n(- n 1))2)(-(- n 1)2)-1)))
(r""))(for((i sp)(j mm))(define str"")(for((ss i))(set! str(string-append str" ")))
(set! str(string-append str(if(or(= i 0)(= i(- n 1))(= i(* 2(- n 1))))c e)" "))
(for((jj j))(set! str(string-append str(if(= j(- n 2))e o)" ")))(set! r(if(or(= i 0)
(= i(- n 1))(= i(* 2(- n 1))))c e))(set! str(string-append str r))(displayln str))))

Pengujian:

(f 4 "3" "4" "6") 

   3 4 4 3
  4 6 6 6 4
 4 6 6 6 6 4
3 6 6 6 6 6 3
 4 6 6 6 6 4
  4 6 6 6 4
   3 4 4 3

(f 5 "o" "*" "-") 

    o * * * o
   * - - - - *
  * - - - - - *
 * - - - - - - *
o - - - - - - - o
 * - - - - - - *
  * - - - - - *
   * - - - - *
    o * * * o

Versi detail:

(define(f1 n c e o)
  (let ((sp(append(range(sub1 n) -1 -1)
                  (reverse(range(sub1 n) 0 -1))))
        (mm(append(range(- n 2)(-(+ n(sub1 n)) 2))
                  (range(-(+ n(sub1 n)) 2)(-(sub1 n)2) -1) ))
        (r ""))
    (for((i sp)(j mm))
      (define str "")
      (for((ss i))(set! str(string-append str " ")))
      (set! str(string-append str
                              (if(or(= i 0)(= i(sub1 n))
                                    (= i(* 2(sub1 n)))) c e)
                              " "))
      (for((jj j))
        (set! str(string-append str
                                (if(= j(- n 2)) e o)
                                " ")))
      (set! r(if(or(= i 0)
                   (= i(sub1 n))
                   (= i(* 2(sub1 n)))) c e))
      (set! str(string-append str r))
      (displayln str))))
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.