Island Golf # 1: Circumnavigation

43

Ini adalah yang pertama dari serangkaian tantangan Island Golf. Tantangan selanjutnya

Diberi nama pulau dalam seni ASCII, menghasilkan jalur yang optimal untuk mengelilingi pulau itu.

Memasukkan

Input Anda akan berupa kotak persegi panjang yang terdiri dari dua karakter, mewakili tanah dan air. Dalam contoh di bawah ini, tanah adalah #dan air adalah ., tetapi Anda dapat mengganti dua karakter berbeda yang Anda inginkan.

...........
...##......
..#####....
..#######..
.#########.
...#######.
...#####.#.
....####...
...........

Akan selalu ada setidaknya satu ubin tanah. Ubin tanah semuanya akan bersebelahan (yaitu hanya ada satu pulau). Ubin air juga akan bersebelahan (yaitu tidak ada danau). Perbatasan luar dari grid semua akan menjadi ubin air. Ubin tanah tidak akan terhubung secara diagonal: yaitu, Anda tidak akan pernah melihat sesuatu seperti itu

....
.#..
..#.
....

Keluaran

Kode Anda harus menampilkan kisi yang sama, dengan navigasi keliling terpendek di atasnya. Pada contoh di bawah ini, jalur navigasi keliling digambar o, tetapi Anda dapat mengganti karakter apa pun asalkan berbeda dari karakter tanah dan air Anda.

Sebuah mengelilingi adalah kurva tertutup sederhana, ditarik sepenuhnya pada ubin air, yang sepenuhnya mengelilingi semua ubin tanah di grid. Koneksi diagonal yang diperbolehkan. Misalnya, ini adalah penjelajahan dari pulau di atas (tetapi bukan yang terpendek):

.ooooo.....
o..##.oo...
o.#####.o..
o.#######o.
o#########o
ooo#######o
..o#####.#o
..oo####..o
....oooooo.

Panjang navigasi mengelilingi dihitung sebagai berikut: Untuk setiap pasangan ubin yang berdekatan di jalan, jika mereka terhubung secara horizontal atau vertikal, tambahkan 1; jika mereka terhubung secara diagonal, tambahkan √2. Panjang jalur di atas adalah 22 + 7√2 (≈ 31,9).

Sebuah terpendek mengelilingi adalah mengelilingi dengan panjang sesingkat mungkin. Program Anda harus menampilkan satu jalur yang memenuhi kondisi ini. Untuk sebagian besar pulau, akan ada beberapa kemungkinan solusi. Berikut adalah satu solusi untuk pulau di atas, dengan panjang 10 + 13√2 (≈ 28,4):

...oo......
..o##oo....
.o#####oo..
.o#######o.
o#########o
.o.#######o
..o#####.#o
...o####.o.
....ooooo..

Detail

Solusi Anda mungkin merupakan program atau fungsi lengkap . Salah satu input dan output metode standar yang dapat diterima.

Input dan output Anda mungkin berupa string multiline atau daftar string. Jika bahasa Anda memiliki tipe karakter yang berbeda dari string karakter tunggal, Anda dapat mengganti "daftar karakter" untuk "string" dalam kalimat sebelumnya. Jika bahasa Anda perlu memasukkan tinggi dan / atau lebar kisi, Anda dapat melakukannya. Output Anda mungkin (secara opsional) memiliki satu baris baru. Seperti disebutkan di atas, Anda dapat menggunakan tiga karakter berbeda sebagai pengganti #.o(harap tentukan dalam kiriman Anda karakter mana yang Anda gunakan).

Uji kasus

A. Pulau dengan navigasi berkeliling terpendek yang unik:

...
.#.
...

.o.
o#o
.o.

......
.####.
......

.oooo.
o####o
.oooo.

......
......
..##..
...#..
......
......

......
..oo..
.o##o.
..o#o.
...o..
......

.......
.#####.
...#...
...#...
.#####.
.......

.ooooo.
o#####o
o..#..o
o..#..o
o#####o
.ooooo.

.......
...#...
...#...
.#####.
...#...
...#...
.......

...o...
..o#o..
.o.#.o.
o#####o
.o.#.o.
..o#o..
...o...

.......
.#####.
.##..#.
..#..#.
.......

.ooooo.
o#####o
o##..#o
.o#..#o
..oooo.

B. Contoh pulau dengan beberapa solusi yang memungkinkan:

........
....##..
...####.
..###...
.#####..
.#####..
..##....
........

Output yang mungkin:

....oo..
...o##o.
..o####o
.o###.o.
o#####o.
o#####o.
.o##oo..
..oo....

....oo..
...o##o.
..o####o
.o###.o.
o#####o.
o#####o.
.o##.o..
..ooo...

....oo..
...o##o.
..o####o
.o###..o
o#####.o
o#####o.
.o##oo..
..oo....

....oo..
...o##o.
..o####o
.o###..o
o#####.o
o#####o.
.o##.o..
..ooo...

C. Kasus uji besar sebagai Intisari


Ini adalah : kode terpendek dalam setiap bahasa menang.

DLosc
sumber
1
Navigasi terpendek untuk kasus uji ke-3 adalah pola 'roti' dalam Permainan Kehidupan Conway!
Kamerad SparklePony

Jawaban:

18

Mathematica (versi 9), 165 byte

Fungsi bagus dan pendek ConvexHullMeshyang digunakan Greg Martin hanya diperkenalkan di Mathematica versi 10, jadi saya pikir saya akan berusaha tanpanya, menggunakan Mathematica kuno saya versi 9. Namun saya berhasil membuatnya sedikit lebih pendek! Ini adalah fungsi yang mengambil dan mengembalikan daftar string (dengan ., #dan osebagai simbol).

""<>#&/@("o"MorphologicalTransform[MorphologicalComponents[#,Method->"ConvexHull"],Max[#(1-#[[2,2]])CrossMatrix@1]&]+"#"#/.{0->"."})&[Characters@#/.{"."->0,"#"->1}]&

Penjelasan:

  • Pertama, Characters@# /. {"."->0, "#"->1}mengubah input menjadi matriks 0s dan 1s.
  • "o"MorphologicalTransform[MorphologicalComponents[#,Method->"ConvexHull"],Max[#(1-#[[2,2]])CrossMatrix@1]&]+"#"#kemudian menggunakan kemampuan pemrosesan gambar Mathematica yang kuat (tapi sangat byte-berat ...) untuk pertama-tama mengisi lambung cembung pulau (yang merupakan bentuk yang akan Anda dapatkan jika Anda merentangkan seutas tali di sekitarnya), dan kemudian mengambil batasnya. Kami kemudian mengalikan matriks ini dengan string "o"untuk mendapatkan matriks 0s dan "o"s (terima kasih kepada kemampuan adaptasi Matematika yang mengesankan tentang jenis), dan menambahkan ini ke "#"kali matriks pulau.
  • Terakhir, ""<>#& /@ (... /. {0->"."})ubah matriks "o"s, s, "#"dan 0s ini menjadi matriks "o"s, "#"s dan "."s, dan gabungkan setiap baris menjadi string.

Ketika kami menguji ini pada contoh B , kami mendapatkan output

{"....oo..",
 "...o##o.",
 "..o####o",
 ".o###..o",
 "o#####o.",
 "o#####o.",
 ".o##oo..",
 "..oo...."}

[Sunting, terima kasih kepada Greg Martin:] Jika kami diizinkan menggunakan array karakter alih-alih daftar string, kami dapat memangkasnya hingga 144 byte:

"o"MorphologicalTransform[MorphologicalComponents[#,Method->"ConvexHull"],Max[#(1-#[[2,2]])CrossMatrix@1]&]+"#"#/.{0->"."}&[#/.{"."->0,"#"->1}]&
Bukan pohon
sumber
1
Bagus sekali! Saya tidak pernah tahu tentang MorphologicalComponents[#, Method->"ConvexHull"] :) Anda dapat menyimpan lebih banyak byte dengan mengasumsikan bahwa input sudah dibagi menjadi karakter, dan dengan mengembalikan array karakter 2D juga.
Greg Martin
@GregMartin, saya tidak tahu tentang penggunaannya MorphologicalComponentssampai hari ini!
Bukan pohon
Mathematica novice here: bagaimana saya memanggil fungsi ini? Saya mencoba f[{"...",".#.","..."}]dan mendapatkan beberapa kesalahan.
DLosc
@Dosc, Fungsi adalah segalanya, bukan hanya f. (Yah, sebenarnya itu adalah barang setelah titik koma.) Untuk memanggil fungsi, ketik semuanya ke dalam jendela Mathematica, diikuti oleh [, input Anda, dan ], sehingga akan terlihat seperti f@m_:=m(1-m[[2,2]]) . . . #/.{"."->0,"#"->1}]&[{"...", ".#.", "..."}](diringkas untuk ruang).
Bukan pohon
@Dosc, Yah, itu karena kodenya rusak. Saya pikir saya sudah memperbaikinya sekarang! (Saya tidak tahu apa yang terjadi di sana; maaf ...)
Bukan sebatang pohon
11

(Tapi pilihlah solusi Notatree , lebih baik!)

Mathematica, 168 byte

(x_~n~y_:=Min[Norm[x-#]&/@y];i=#;p=i~Position~#&;t=p["#"|"."]~Select~#&;(i~Part~##="o")&@@@t[#~n~t[ConvexHullMesh[Join[s=p@"#",#+{.1,.1}&/@s]]~RegionMember~#&]==1&];i)&

Fungsi murni mengambil array karakter 2D sebagai input dan mengembalikan array karakter 2D. Versi yang lebih mudah dibaca:

1  (x_~n~y_ := Min[Norm[x - #] & /@ y];
2  i = #; p = i~Position~# &; 
3  t = p["#" | "."]~Select~# &;
4  (i~Part~## = "o") & @@@ 
5    t[#~n~
6      t[ConvexHullMesh[
7        Join[s = p@"#", # + {.1, .1} & /@ s]]
8      ~RegionMember~# &] == 1 &];
9  i) &

Baris 1 mendefinisikan fungsi nyang menghasilkan jarak (terkecil) antara titik xdi pesawat dan satu set ytitik lainnya. Baris 2 menginisialisasi variabel ike input, baik untuk menyelesaikan ambiguitas currying nanti dan untuk dapat memodifikasinya untuk menghasilkan output akhirnya; baris 2 juga mendefinisikan fungsi pyang mengembalikan koordinat semua kemunculan inputnya i.

Pada baris 3, p["#" | "."]mewakili setiap koordinat tunggal dari peta input (karena semua karakternya adalah salah satu "#"atau "."), jadi tadalah fungsi yang memilih hanya koordinat yang memenuhi properti yang belum ditentukan. Pada baris 4, i~Part~## = "o"akan mengubah banyak entri ike karakter "o"; karakter-karakter itu akan dipilih dari himpunan koordinat yang mungkin menurut item pada baris 5-8. Dan baris 9 baru mengembalikan jawaban setelah dihitung.

Oke, infrastruktur sudah selesai, sekarang untuk perhitungan yang sebenarnya. ConvexHullMeshadalah built-in Mathematica untuk menghitung lambung cembung dari satu set poin (poligon cembung terkecil yang mengandung titik-titik itu). Secara moral, ini harus "mengisi" teluk-teluk kecil dan teluk-teluk pulau (yang s = p@"#"), untuk mengesampingkan mereka dari navigasi pusat kami. Ada sedikit masalah dengan ConvexHullMeshkapan kumpulan poin itu berada dalam satu garis (terima kasih, test case # 2), yang kami selesaikan dengan menambahkan versi yang sedikit diimbangi suntuk dirinya sendiri di baris 7. Output ini adalah poligon, jadi baris 7 -9 (t[...~RegionMember~# &]) menghasilkan daftar titik dengan koordinat bilangan bulat dalam poligon itu. Akhirnya, garis 5 dan akhir garis 9 menghitung semua titik yang berada pada jarak tepat 1 (karenanya bukan 0) dari kumpulan titik integer ini; set yang menjadi jalur mengelilingi.

Di bawah ini adalah output untuk test case besar di tautan OP. Perhatikan di kiri atas, pilihan-pilihan yang tidak biasa kapan pergi ke barat versus barat daya mengisyaratkan fakta bahwa itu membayangi garis kemiringan tak terlihat -2/3 antara dua semenanjung (kata segmen garis menjadi bagian dari batas lambung cembung).

........................
.............o..........
...........oo#ooooooo...
..........o#.#.##...#o..
........oo.#.#.###.##o..
.......o..########.##o..
.....oo...############o.
...oo#....############o.
..o#.###.##############o
.o##.##################o
.o####################o.
.o.##################.o.
.o##################..o.
.o..################..o.
o###################..o.
o#####################o.
o.##################.o..
o####################o..
o#...##############.o...
o##...#############o....
o#.....###....#oooo.....
.oooooo#ooooooo.........
.......o................
Greg Martin
sumber
Apakah Mathematica biasanya mewakili string sebagai array karakter 1D? Jika tidak, maka Anda harus mengambil / mengembalikan array string 1D sebagai gantinya. (Juga, menantikan penjelasan! Saya tidak berpikir saya akan dapat menjalankan ini tanpa memiliki Mathematica, kan?)
DLosc
Mathematica memiliki tipe data string, tetapi tampaknya array karakter juga valid untuk keperluan situs ini (yaitu, saya mempelajari ini ketika saya mulai di PPCG, tapi saya lupa legalitas mengapa). Ya, sayangnya, Mathematica tidak bebas dan karenanya tidak dapat diakses oleh banyak orang :(
Greg Martin
1
@GregMartin Saya selalu mencoba solusi Mathematica di sandbox.open.wolframcloud.com
ovs
Konsensus saat ini mengatakan bahwa daftar string karakter tunggal tidak dapat digunakan sebagai pengganti string. Sejauh yang saya tahu, "karakter" di Mathematica hanyalah string karakter tunggal, seperti dalam Python. Situasinya berbeda dalam bahasa seperti Jawa, yang memiliki charjenis yang berbeda ; dalam hal ini, sebuah chararray dapat digunakan sebagai pengganti string.
DLosc
1
Begini cara saya membacanya: Jawaban utama yang diunggah diposting pada tahun 2014. Jawaban yang saya tautkan dipasang pada tahun 2016, sebagai upaya untuk memperjelas ambiguitas dalam jawaban sebelumnya. Jadi saya membaca skor negatif pada jawaban yang lebih baru ketika orang-orang berkata, "Tidak, kami tidak ingin jawaban yang lebih tua berarti bahwa daftar string single-char tidak apa-apa." Tapi terlepas dari meta, saya melarang daftar string single-char dalam pertanyaan ini (dan saya mengklarifikasi kata-kata untuk mencerminkan itu).
DLosc
10

Python 3, 779 byte (indentasi dengan tab)

Ini adalah keseluruhan program. Bunyinya input dari stdin dan mencetaknya ke stdout. Stdin harus diakhiri dengan EOF. Contoh dijalankan dengan input besar: https://ideone.com/XIfYY0

import itertools,sys
L=list
C=itertools.count
d=L(map(L,filter(None,sys.stdin.read().split('\n'))))
X=len(d[0])
Y=len(d)
R=range
def P(r):return all(d[y][x]=='.'for x,y in r)
def S(f):
    for n in C(0):
        if P(f(n)):l=n
        else:break
    for n in C(l+1):
        if P(f(n)):return l,n
def f(V,a,*b):return L(eval('lambda '+a+':('+i+')',V)for i in b)
V=locals()
def D(n):
    y=min(n,Y-1);x=n-y
    while y>=0and x<X:yield(x,y);x+=1;y-=1
def E(n):
    x=max(0,n-Y);y=x+Y-n
    while y<Y and x<X:yield(x,y);x+=1;y+=1
F=f(V,'p','(p,y)for y in R(0,Y)','(x,p)for x in R(0,X)')+[D,E]
r=f(V,'x,y','x','y','x+y','x-y+Y')
B=L(map(S,F))
for x in R(0,X):
    for y in R(0,Y):
        z=L(zip(r,B))
        if all(g(x,y)in R(a,b+1)for g,(a,b)in z)and any(g(x,y)in e for g,e in z):d[y][x]='o'
print('\n'.join(''.join(x)for x in d))

Idenya sederhana: ia menghitung batas oktagonal terkecil, dan menarik sel-sel yang ada di dalam semua batas yang dikomputasi dan memotong setidaknya satu ujung.

Lera
sumber
1
Anda tidak perlu menggunakannya sys.stdinsebagai input. input(), mendapatkan multiline akan melakukan pekerjaan dan biaya lebih sedikit byte
Dead Possum
2
Mungkin dapat menggantikan R(0,x)denganR(x)
ceilingcat
+1 karena tidak menggunakan built-in.
Robert Fraser
1
Bagus! Beberapa tips golf lagi: hemat masing-masing 5 byte dengan menggunakan lambdas untuk mendefinisikan Pdan f; L(generator expression)=> [generator expression]; F,, rdan Btampaknya hanya digunakan satu kali saja dan dengan demikian dapat diuraikan.
DLosc
8

JavaScript (ES6), 369 343 byte

f=s=>(a=s.split`
`.map(s=>[...s]),m=Array(8),a.map((b,i)=>b.map((c,j)=>c>'#'||[i-j,i,j+i,j,j-i,-i,-i-j,-j].map((d,k)=>d>m[k]||(m[k]=d-1)))),[o,p,q,r,t,u,v,w]=m,g=(i,j,k,l,...p)=>i-k|j-l?a[i][j]=g(i+(k>i)-(k<i),j+(l>j)-(l<j),k,l,...p):1/p[0]?g(k,l,...p):'o',g(p,p-o,p,q-p,q-r,r,r-t,r,-u,t-u,-u,u-v,w-v,-w,o-w,-w,p,p-o),a.map(b=>b.join``).join`
`)

Penjelasan: String dipecah menjadi array karakter (Saya tidak jelas apakah input array karakter dapat diterima). Array kemudian diulang dan posisi semua kotak tanah berada. Garis berlari diberikan oleh persamaan x - y = o, x = p, x + y = q, y = r, y - x = t, -x = u, -x - y = v, -y = wditentukan sedemikian rupa sehingga memungkinkan parameter maksimum dipilih mana semua kebohongan tanah di luar garis. Ini memiliki efek melampirkan pulau dalam segi delapan. Koordinat sudut-sudut oktagon siap dihitung dari parameter dan sel-sel di tepi diisi. Array kemudian bergabung kembali ke dalam string. Alasan octagon mencukupi adalah sebagai berikut:

   /o#     /o#     /o#
 |/o #   |/o #   |/ o#
 *o###   * o #   *  o#
/|o #   /|o #   /| o#
 |o#     |o#     |o#

Pertimbangkan sudut segi delapan. Di beberapa titik di sepanjang dua sisi jalan akan dibatasi oleh tanah karena kami membangun segi delapan untuk menyentuh tanah sedekat mungkin. Jika tidak ada tanah di sudut itu sendiri, jalan bisa mengambil rute alternatif seperti yang ditunjukkan di sebelah kanan, tetapi itu masih jumlah yang sama dari langkah ortogonal dan diagonal, sehingga jaraknya tidak berubah.

Neil
sumber
Apa yang dilakukan ´ ... p´?
Robert Fraser
@RobertFraser Nama teknisnya adalah susunan array. Namun dalam kasus ini, ia hanya bertindak sebagai rest of argumentsparameter.
Neil
@ Neil Sebenarnya, nama teknis adalah parameter istirahat . Sintaks yang sama digunakan untuk operator spread . (Anda menggunakan keduanya seperti ...pdi tempat yang berbeda.) Penghancuran adalah sesuatu yang lain (meskipun operator spread dapat digunakan dalam penghancuran).
Brian McCutchon
@BrianMcCutchon Anda benar, maksud saya operator spread, tapi tetap saja restrukturisasi berfungsi dalam daftar argumen.
Neil
6

Python 3.5, 224, 263, 234 218 byte

Golf 16 byte lainnya dengan menghilangkan fungsi bersarang dan menjadikannya satu-liner.

def h(s,k=0,i=0):w=s.find('\n')+1;x=s.find('X')-w;k=k or x;d=[1,w+1,w,w-1,-1,-w-1,-w,-w+1]*2;u=s[:k]+'o'+s[k+1:];return['X'>s[k]and i<8and(h(u,k+d[i+2],i+2)or h(u,k+d[i+1],i+1)or h(u,k+d[i],i))or'',s][s[k]>'X'and k==x]

Golf off 29 byte:

def f(s):
 w=s.find('\n')+1;x=s.find('X')-w;d=[1,w+1,w,w-1,-1,-w-1,-w,-w+1]*2
 def h(s,k,i):u=s[:k]+'o'+s[k+1:];return['X'>s[k]and i<8and(h(u,k+d[i+2],i+2)or h(u,k+d[i+1],i+1)or h(u,k+d[i],i))or'',s][s[k]>'X'and k==x]
 return h(s,x,0)

Input adalah string tunggal menggunakan '~' untuk lautan, 'X' untuk tanah, dan 'o' untuk batas. (Menggunakan 'X' menyimpan byte untuk '>' alih-alih '==')

Versi yang kurang golf dengan komentar:

def f(s):
    w=s.find('\n')+1                         # width of one row
    x=s.find('X')-w                          # starting point
    d=[1,w+1,w,w-1,-1,-w-1,-w,-w+1]*2        # delta to add to current index to move in 
                                             # the 8 directions: E, SE, S, SW, W, NW, 
                                             # N, NE. Make it long to avoid
                                             # lots of modulo operations in 
                                             #    the recursive calls

    def h(s,k,i):                            # s is the island string, k the current
                                             # position, i the direction index
        if s[k]>'X'and k==x:                 # if back at the begining,
            return s                         #   return the map

        elif 'X'>s[k] and i<8:               # if there is water here, and haven't
                                             #  looped around,
            u=s[:k]+'o'+s[k+1:]              #  make a new map with an 'o' in the 
                                             #  current spot

            r = h(u,k+d[i+2],i+2)            # try a 90 degree right turn
            if r: return r

            r = h(u,k+d[i+1],i+1)            # try a 45 degree turn
            if r: return r

            r= h(u,k+d[i],i)                 # try straight ahead
            if r: return r

        return ''                            # this path failed

    return h(s,x,0)
RootTwo
sumber
@Dosc diperbaiki. (haruskah saya menghapus jawaban lama?)
RootTwo
Bagus! (Ya, Anda harus menghapus jawaban lama - jika ada yang ingin melihatnya, mereka dapat melihat riwayat revisi pos.)
DLosc
5

C # 7 - 414 369 327 byte

Sunting : beralih ke loop 1D, komputasi, idan jon the fly

Sunting : metode input yang diubah, tabel lookup yang diciutkan, dan beralih ke batas awal yang terdefinisi dengan baik ... dan menghilangkan ruang tak berujung di loop luar terakhir untuk-loop

using C=System.Console;class P{static void Main(){var D=C.In.ReadToEnd().Replace("\r","");int W=D.IndexOf('\n')+1,H=D.Length,z=H,k,q,c;int P()=>z%W*(k%3-1)+z/W*(k/3-1)+H;var B=new int[9];for(;z-->0;)for(k=9;k-->0&D[z]%7<1;)if(B[k]<=P())B[k]=P()+1;for(;++z<H;C.Write(q>9?'o':D[z]))for(q=k=9;k-->0;)q*=(c=P()-B[k])>0?0:c<0?1:2;}}

Cobalah secara Online

Program lengkap, mengambil input ke dalam standar, mencetak ke luar standar, penggunaan #, .dan o. Untuk setiap sel, ia menghitung 'profil' (yang merupakan jarak lebih dari 8 arah (tampaknya menghitung kesembilan untuk kenyamanan, tetapi ini selalu 0), dan mencatat maksimum masing- masing sel . Ia kemudian menulis seluruh peta lagi, dan mengganti sel apa saja yang berada di batas dan tidak di luar dengan 'o' .Komentari yang dikomentari di bawah ini menjelaskan cara kerjanya.

Sesuai jawaban saya untuk Menyelamatkan Angsa dari Kepunahan , ini menghasilkan oktagon terkecil (navigasi mengelilingi dengan wilayah terbesar) yang membatasi pulau.

Catatan : bahwa untuk sekali dalam hidup saya, saya menggunakan sesuatu dari dekade ini, dan kode ini membutuhkan C # 7 untuk dikompilasi. Jika Anda tidak memiliki C # 7, ada satu baris yang perlu diganti, yang ditandai dengan jelas dalam kode.

Contoh penggunaan dan output:

type t7.txt | IslandGolf1.exe

.........ooooooooooo....
........o....#......o...
.......o...#.#.##...#o..
......o....#.#.###.##.o.
.....o....########.##..o
....o.....############.o
...o.#....############.o
..o#.###.##############o
.o##.##################o
o.####################.o
o..##################..o
o.##################...o
o...################...o
o###################...o
o#####################.o
o.##################..o.
o####################o..
o#...##############.o...
o##...#############o....
o#.....###....#...o.....
.o.....#.........o......
..ooooooooooooooo.......

Kode yang diformat dan dikomentari:

using C=System.Console;

class P
{
    static void Main()
    {
        // \n 10
        // # 35
        // . 46
        // o 111


        var D=C.In.ReadToEnd().Replace("\r",""); // map

        int W=D.IndexOf('\n')+1, // width
            H=D.Length, // length
            z=H, // position in map (decomposed into i and j by and for P)
            k, // bound index
            q, // bound distance, and later cell condition (0 -> outside, 8 -> inside, >8 -> on boudary)
            c; // (free), comparison store

        // 'indexes' into a profile for the point z at index k
        // effectively {i=z%W,j=z/W,-i,-j,i+j,j-i,-i-j,i-j,0}[k] (inside order is a bit different) (0 const is always treated as 'inside bounds')
        // each non-zero-const entry describes the distance in one of the 8 directions: we want to maximise these to find the 'outer bounds'
        // the non-zero-const bounds describe 8 lines, together an octogen
        int P()=>z%W*(k%3-1)+z/W*(k/3-1)+H; // new C#7 local method syntax (if you don't have C#7, you can test this code with the line below instead)
        //k=0;System.Func<int>P=()=>z%W*(k%3-1)+z/W*(k/3-1)+H; // old lambda syntax (must pre-assign k to make static checker happy)

        var B=new int[9]; // our current bounds, each is initially null (must only call P() when on a #)
        // B[k] starts off a 0, P() has a +H term, and W+(H/W)<H for W >= 3, so B[k] is assigned the first time we compare it (H-i-j always > 0)

        for(;z-->0;) // for each cell
            for(k=9;k-->0& // for each bound
                D[z]%7<1;) // if this cell is #
                if(B[k]<=P())B[k]=P()+1; // update bound if necessary (add one so that we define the bound _outside_ the hashes)
        // z=-1
        for(;++z<H; // for each cell
                C.Write(q>9?'o':D[z])) // print the cell (if q > 9, then we are on the bounds, otherwise, spit out whatever we were before)
            // check we are not 'outside' any of the bounds, and that we are 'on' atleast one of them
            for(q=k=9;k-->0;) // for each bound
                q*=(c=P()-B[k])>0?0: // outside bound (q=0)    (??0 is cheaper than (int) or .Value)
                    c<0?1: // inside (preserve q)
                    2; // on bound (if q != 0, then q becomes > 9)
    }
}
VisualMelon
sumber
oktagon terbesar? atau terkecil?
Sarge Borsch
@SargeBorsch terima kasih, perbaiki teks.
VisualMelon