Tentukan Dimensi dari Kotak yang Diputar

14

Potongan Stack ini menggambar sebuah persegi panjang putih alias pada latar belakang hitam diberikan parameter untuk dimensi, posisi, sudut, dan dimensi grid:

<style>html *{font-family:Consolas,monospace}input{width:24pt;text-align:right;padding:1px}canvas{border:1px solid gray}</style><p>grid w:<input id='gw' type='text' value='60'> grid h:<input id='gh' type='text' value='34'> w:<input id='w' type='text' value='40'> h:<input id='h' type='text' value='24'> x:<input id='x' type='text' value='0'> y:<input id='y' type='text' value='0'> &theta;:<input id='t' type='text' value='12'>&deg; <button type='button' onclick='go()'>Go</button></p>Image<br><canvas id='c'>Canvas not supported</canvas><br>Text<br><textarea id='o' rows='36' cols='128'></textarea><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><script>function toCart(t,a,n,r){return{x:t-n/2,y:r/2-a}}function vtx(t,a,n){return{x:n.x+t*Math.cos(a),y:n.y+t*Math.sin(a)}}function sub(t,a){return{x:t.x-a.x,y:t.y-a.y}}function dot(t,a){return t.x*a.x+t.y*a.y}function inRect(t,a,n,r){var e=sub(a,t),o=sub(a,n),l=sub(a,r),i=dot(e,o),v=dot(e,l);return i>0&&i<dot(o,o)&&v>0&&v<dot(l,l)}function go(){var t=parseInt($("#gw").val()),a=parseInt($("#gh").val()),n=parseFloat($("#w").val()),r=parseFloat($("#h").val()),e={x:parseFloat($("#x").val()),y:parseFloat($("#y").val())},o=Math.PI*parseFloat($("#t").val())/180,l=Math.sqrt(n*n+r*r)/2,i=Math.atan2(r,n),v=vtx(l,o+i,e),h=vtx(l,o+Math.PI-i,e),u=vtx(l,o-i,e),x=$("#c");x.width(t).height(a).prop({width:t,height:a}),x=x[0].getContext("2d");for(var s="",c=0;a>c;c++){for(var f=0;t>f;f++)inRect(toCart(f+.5,c+.5,t,a),v,h,u)?(s+="..",x.fillStyle="white",x.fillRect(f,c,1,1)):(s+="XX",x.fillStyle="black",x.fillRect(f,c,1,1));a-1>c&&(s+="\n")}$("#o").val(s)}$(go)</script>
( Versi JSFiddle )

Representasi teks memiliki di XXmana pun ada piksel hitam dalam gambar dan di ..mana pun ada piksel putih. (Kelihatannya terjepit jika mereka Xdan ..)

Tulis sebuah program yang mengambil representasi teks dari sebuah persegi panjang yang dihasilkan oleh Snippet dan menampilkan perkiraan lebar dan tinggi persegi panjang, baik dalam jarak ± 7% dari lebar dan tinggi aktual .

Program Anda harus bekerja secara efektif untuk semua segiempat yang mungkin dapat ditarik oleh snippet, dengan kendala yang:

  • Lebar dan tinggi persegi panjang minimal 24.
  • Lebar dan tinggi kisi minimal 26.
  • Kotak tidak pernah menyentuh atau keluar dari batas kisi.

Jadi persegi panjang input dapat memiliki rotasi, posisi, dan dimensi, dan grid mungkin memiliki dimensi, selama tiga kendala di atas terpenuhi. Perhatikan bahwa kecuali untuk dimensi kisi, parameter Cuplikan dapat mengapung.

Detail

  • Ambil persegi panjang teks mentah sebagai input atau ambil nama file file yang berisi persegi panjang teks mentah (melalui stdin atau baris perintah). Anda dapat mengasumsikan kotak teks memiliki baris tambahan.
  • Anda dapat mengasumsikan kotak teks dibuat dari dua karakter ASCII yang dapat dicetak selain Xdan .jika diinginkan. (Baris baru harus tetap baris baru.)
  • Keluarkan lebar dan tinggi yang diukur sebagai bilangan bulat atau mengapung ke stdout dalam urutan apa pun (karena tidak ada cara untuk menentukan mana yang benar-benar cocok dengan parameter mana). Format yang jelas menunjukkan dua dimensi baik-baik saja, misalnya D1 D2, D1,D2, D1\nD2, (D1, D2), dll
  • Alih-alih sebuah program, Anda dapat menulis fungsi yang mengambil persegi panjang teks sebagai string atau nama file untuk itu dan mencetak hasilnya secara normal atau mengembalikannya sebagai string atau daftar / tuple dengan dua elemen.
  • Ingat itu XXatau ..satu 'pixel' dari persegi panjang, bukan dua.

Contohnya

Ex. 1

Parameter: grid w:60 grid h:34 w:40 h:24 x:0 y:0 θ:12(Default snippet)

Memasukkan

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX....XXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX............XXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX........................XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..................................XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX............................................XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX....................................................XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..............................................................XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX..........................................................................XXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX................................................................................XXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXX................................................................................XXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXX..................................................................................XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXX..........................................................................XXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX..............................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX....................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX............................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX..................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX........................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXX............XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXX....XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Contoh Keluaran

  • 40 24
  • 24 40
  • [40.0, 24.0]
  • 42.8, 25.68 (+ 7%)
  • 37.2, 22.32 (-7%)

Ex. 2

Parameter: grid w:55 grid h:40 w:24.5 h:24 x:-10.1 y:2 θ:38.5

Memasukkan

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX......XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX............XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..............XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXX..................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXX......................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXX............................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX..............................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX..................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX......................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXX............................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXX................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXX..................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXX......................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XX............................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XX..............................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XX................................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXX..............................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXX..............................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXX............................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXX......................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXX....................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXX................................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXX............................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX......................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX..................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX................................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXX..........................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXX......................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX..................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXX................XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXX..........XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXX......XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Contoh Keluaran

  • 24.0 24.5
  • 25.68 26.215 (+ 7%)
  • 22.32 22.785 (-7%)

Mencetak gol

Kode terpendek dalam byte menang. Tiebreaker adalah pos terpilih tertinggi.

Hobi Calvin
sumber
Tidakkah suatu solusi memenuhi persyaratan presisi yang harus diterima? Yang Anda terima jauh untuk nilai input tertentu.
Reto Koradi

Jawaban:

6

Matlab, 226 byte

Idenya sederhana: Pertama saya mencoba untuk mencari tahu berapa banyak persegi panjang itu berubah, kemudian putar gambar sesuai sedemikian rupa sehingga persegi panjang itu tegak. Lalu saya hanya 'meringkas' semua piksel dalam kolom baris secara serentak dan mencoba menghitung berapa jumlah dari jumlah di atas dari rata-rata (ambang sederhana) untuk menentukan lebar dan tinggi. Metode sederhana ini bekerja sangat andal.

Bagaimana saya bisa mendeteksi sudut?

Saya hanya mencoba setiap langkah (masing-masing satu derajat) dan menjumlahkan sepanjang kolom dan mendapatkan vektor jumlah. Ketika persegi panjang tegak, idealnya saya hanya mendapatkan dua perubahan tiba-tiba dalam vektor jumlah ini. Jika kotak berada di ujung, perubahannya sangat bertahap. Jadi saya hanya menggunakan turunan pertama, dan mencoba untuk meminimalkan jumlah 'lompatan'. Di sini Anda dapat melihat plot kriteria yang kami coba untuk meminimalkan. Perhatikan bahwa Anda dapat melihat empat minimum yang sesuai dengan empat posisi mungkin.

kriteria minimisasi

Pikiran lebih lanjut: Saya tidak yakin berapa banyak yang bisa di-golf karena pencarian sudut yang berlebihan membutuhkan banyak karakter dan saya ragu Anda dapat mencapainya dengan baik dengan metode optimasi bawaan, karena seperti yang Anda lihat ada banyak minimum lokal yang tidak kita cari. Anda dapat dengan mudah meningkatkan akurasi (untuk gambar besar) dengan memilih ukuran langkah yang lebih kecil untuk sudut dan hanya mencari 90 ° daripada 360 ° sehingga Anda dapat menggantinya 0:360dengan 0:.1:90atau dengan cara semacam itu. Tetapi bagaimanapun juga, bagi saya tantangannya adalah lebih menemukan algoritma yang kuat daripada golf dan saya yakin entri dari bahasa golf akan meninggalkan kiriman saya jauh di belakang =)

PS: Seseorang harus benar-benar mendapatkan bahasa golf dari Matlab / Oktaf.

Keluaran

Contoh 1:

 25    39

Contoh 2:

 25    24

Kode

Golf:

s=input('');r=sum(s=='n');S=reshape(s',nnz(s)/r,r)';S=S(:,1:2:end-2)=='.';m=Inf;a=0;for d=0:360;v=sum(1-~diff(sum(imrotate(S,d))));if v<m;m=v;a=d;end;end;S=imrotate(S,a);x=sum(S);y=sum(S');disp([sum(x>mean(x)),sum(y>mean(y))])

Tidak Disatukan:

s=input('');
r=sum(s=='n');              
S=reshape(s',nnz(s)/r,r)'; 
S=S(:,1:2:end-2)=='.';    
m=Inf;a=0;
for d=0:360;                 
    v=sum(1-~diff(sum(imrotate(S,d))));
    if v<m;
        m=v;a=d;
    end;
end;
S=imrotate(S,a);
x=sum(S);y=sum(S');
disp([sum(x>mean(x)),sum(y>mean(y))])
cacat
sumber
7

CJam, 68 65 64 byte

Ini bisa bermain golf sedikit lebih ..

qN/2f%{{:QN*'.#Qz,)mdQ2$>2<".X"f#_~>@@0=?Qz}2*;@@-@@-mhSQWf%}2*;

Bagaimana itu bekerja

Logikanya cukup sederhana, jika Anda memikirkannya.

Yang kita butuhkan dari X.kombinasi input adalah 3 koordinat dari dua sisi yang berdekatan. Inilah cara kami mendapatkannya:

First

Dalam setiap orientasi persegi panjang, yang pertama .di seluruh input akan menjadi salah satu sudut. Sebagai contoh..

XXXXXXXXXXXXXX
XXXXXXX...XXXX
XXXX.......XXX
X............X
XX.........XXX
XXXX...XXXXXXX
XXXXXXXXXXXXXX

Di sini, yang pertama .adalah dalam 2 nd line, 8 th kolom.

Tapi bukan itu, kita harus melakukan beberapa penyesuaian dan menambah lebar . run pada garis itu ke koordinat untuk mendapatkan koordinat ujung kanan.

Second

Jika kita memindahkan persegi panjang di atas (diputar pada baris baru), maka sudut kiri bawah mengambil tempat langkah di atas. Tapi di sini, kami tidak mengkompensasi .panjang lari karena kami ingin mendapatkan koordinat kiri bawah dari ujungnya (yang dalam bentuk transpos akan tetap menjadi yang pertama kali ditemui). )

Rest two

Untuk beristirahat dua koordinat, kita cukup membalik secara horizontal, persegi panjang dan melakukan dua langkah di atas. Salah satu sudut di sini akan menjadi umum dari dua sudut pertama.

Setelah mendapatkan keempat, kita cukup melakukan beberapa matematika sederhana untuk mendapatkan jarak.

Sekarang ini bukan metode yang paling akurat, tetapi bekerja dengan baik dalam margin kesalahan dan juga untuk semua orientasi yang mungkin dari persegi panjang.

Perluasan kode (sedikit kedaluwarsa)

qN/2f%{{:QN*'.#Q0=,)md}:A~1$Q='.e=+QzA@@-@@-mhSQWf%}2*;
qN/2f%                               e# Read the input, split on newlines and squish it
      {   ...   }2*                  e# Run the code block two times, one for each side  
{:QN*'.#Q0=,)md}:A~                  e# Store the code block in variable A and execute it
 :QN*                                e# Store the rows in Q variable and join by newlines
     '.#                             e# Get the location of the first '.'
        Q0=,)                        e# Get length + 1 of the first row
             md                      e# Take in X and Y and leave out X/Y and X%Y on stack
1$Q=                                 e# Get the row in which the first '.' appeared
    '.e=+                            e# Get number of '.' in that row and add it to X%Y
         QzA                         e# Transpose the rows and apply function A to get
                                     e# the second coordinate
            @@-@@-                   e# Subtract resp. x and y coordinates of the two corners
                  mh                 e# Calculate (diff_x**2 + diff_y**2)**0.5 to get 1 side
                    SQWF%            e# Put a space on stack and put the horizontally flipped
                                     e# version of the rows/rectangle all ready for next two
                                     e# coordinates and thus, the second side

Cobalah online di sini

Pengoptimal
sumber
Coba ukuran kotak 50x50, ukuran persegi panjang 45x45, dan sudut -2. Kesalahan sekitar 28%. Saya mencoba pendekatan yang sama (itu adalah ide awal saya, sebelum melihat milik Anda), dan membuatnya cukup akurat ternyata lebih rumit dari yang diharapkan, terutama jika sisi-sisinya dekat dengan horizontal / vertikal. Berfungsi bagus jika mereka lebih dekat ke diagonal. Saya pikir ini memerlukan lebih banyak logika (misalnya juga mencari ekstrem dalam arah diagonal), atau pendekatan yang sama sekali berbeda.
Reto Koradi
@RetoKoradi Oh. Itu hanya karena semua sudut negatif memerlukan .penyesuaian lebar pada koordinat kedua, bukan pertama. Akan memperbaiki. Harus diperbaiki singkat.
Pengoptimal
1
@RetoKoradi harus diperbaiki sekarang.
Pengoptimal
Coba persegi panjang 40x24 dengan sudut 0.
Reto Koradi
@RetoKoradi Poin bagus. Tidak diterima untuk saat ini.
Hobi Calvin
5

Python 3, 347 337 byte

Ini ternyata lebih sulit dari yang saya harapkan. Bekerja dalam proses ...

def f(s):
 l=s.split('\n');r=range;v=sorted;w=len(l[0]);h=len(l);p=[[x,y]for x in r(w)for y in r(h)if'X'>l[y][x]];x,y=[sum(k)/w/h for k in zip(*p)];g=[[x/2,y]];d=lambda a:((a[0]/2-a[2]/2)**2+(a[1]-a[3])**2)**.5
 for i in r(3):g+=v(p,key=lambda c:~-(c in g)*sum(d(j+c)for j in g))[:1]
 print(v(map(d,[g[1]+g[2],g[2]+g[3],g[1]+g[3]]))[:2])

Menentukan fungsi f mengambil string sebagai argumen dan mencetak hasilnya ke STDOUT.

Pyth, 87 84 82 81 75 72 71 byte

(MUNGKIN INVALID, MENYELIDIKAN SAAT AKU MENDAPATKAN RUMAH

Km%2d.zJf<@@KeThTG*UhKUKPSm.adfqlT2ytu+G]ho*t}NGsm.a,kNGJ3]mccsklhKlKCJ

Cara Masih terlalu lama. Pada dasarnya port yang sebelumnya. Mencintai .ajarak Euclidean Pyth . Mengambil input melalui STDIN dan memberikan output melalui STDOUT. Mengharapkan karakter non-persegi panjang menjadi huruf kecil x(baik, apa pun dengan nilai ASCII 98 atau lebih).

Algoritma

Keduanya menggunakan algoritma yang sama. Saya pada dasarnya mulai dengan sebuah array yang berisi pusat massa area persegi panjang. Saya kemudian menambahkan tiga titik ke array semua titik dalam persegi panjang, selalu memilih satu dengan jumlah maksimum jarak ke titik yang sudah ada dalam array. Hasilnya selalu tiga poin di berbagai sudut persegi panjang. Saya kemudian hanya menghitung ketiga jarak antara tiga titik dan mengambil dua yang terpendek.

PurkkaKoodari
sumber
Solusi Pyth tidak bekerja sama sekali. Dua contoh dari OP memberikan hasil [33.0, 59.0]bukan [40, 24]dan [39.0, 54.0]bukan [24.0, 24.5].
Jakube
@ Jakube Weird. Saya akan menyelidiki setelah saya pulang. Sayangnya saya sedang dalam perjalanan kelas ke Lapland sampai 9 Juni.
PurkkaKoodari
Sayangnya saya tidak akan melakukan perjalanan ke Lapland ;-)
Jakube
0

Python 2, 342 byte

import sys
r=[]
h=.0
for l in sys.stdin:w=len(l);r+=[[x*.5,h]for x in range(0,w,2)if l[x:x+2]=='..'];h+=1
x,y=.0,.0
for p in r:x+=p[0];y+=p[1]
n=len(r)
x/=n
y/=n
m=.0
for p in r:
 p[0]-=x;p[1]-=y;d=p[0]**2+p[1]**2
 if d>m:m=d;u,v=p
m=.0
for p in r:
 d=p[0]*v-p[1]*u
 if d>m:m=d;s,t=p
print ((u-s)**2+(v-t)**2)**.5+1,((u+s)**2+(v+t)**2)**.5+1

Ini mengambil inspirasi dari algoritma @ Pietu1998. Dibutuhkan gagasan untuk menentukan satu sudut sebagai titik terjauh dari pusat, tetapi berbeda dari sana:

  • Saya menentukan sudut kedua sebagai titik dengan produk silang terbesar dengan vektor dari tengah ke sudut pertama. Ini memberi titik dengan jarak terbesar dari garis dari pusat ke sudut pertama.
  • Tidak perlu mencari sudut ketiga, karena hanya gambar cermin dari sudut kedua relatif ke tengah.

Jadi kode mengikuti urutan ini:

  • Loop pertama melewati garis di input, dan membangun daftar rtitik persegi panjang.
  • Loop kedua menghitung rata-rata semua titik persegi panjang, memberikan pusat persegi panjang.
  • Loop ketiga menemukan titik terjauh dari pusat. Ini adalah tikungan pertama. Pada saat yang sama, itu mengurangi pusat dari titik-titik dalam daftar, sehingga titik koordinat relatif terhadap pusat untuk sisa perhitungan.
  • Loop keempat menemukan titik dengan produk silang terbesar dengan vektor ke sudut pertama. Ini adalah tikungan kedua.
  • Mencetak jarak antara sudut pertama dan sudut kedua, dan jarak antara sudut pertama dan gambar cermin dari sudut kedua.
  • 1.0ditambahkan ke jarak karena perhitungan jarak asli menggunakan indeks piksel. Misalnya, jika Anda memiliki 5 piksel, perbedaan antara indeks piksel terakhir dan pertama hanya 4, yang membutuhkan kompensasi dalam hasil akhir.

Presisinya cukup bagus. Untuk dua contoh:

$ cat rect1.txt | python Golf.py 
24.5372045919 39.8329756779
$ cat rect2.txt | python Golf.py 
23.803508502 24.5095563412
Reto Koradi
sumber
0

Python 2, 272 byte

Posting ini sebagai jawaban terpisah karena ini merupakan algoritma yang sama sekali berbeda dari yang sebelumnya:

import sys,math
y,a,r=0,0,0
l,t=[1<<99]*2
for s in sys.stdin:
 c=s.count('..')
 if c:a+=c;x=s.find('.')/2;l=min(l,x);r=max(r,x+c);t=min(t,y);b=y+1
 y+=1
r-=l
b-=t
p=.0
w,h=r,b
while w*h>a:c=math.cos(p);s=math.sin(p);d=c*c-s*s;w=(r*c-b*s)/d;h=(b*c-r*s)/d;p+=.001
print w,h

Pendekatan ini tidak mengidentifikasi sudut sama sekali. Hal ini didasarkan pada pengamatan bahwa ukuran (lebar dan tinggi) kotak pembatas dan luas persegi panjang yang diputar cukup untuk menentukan lebar dan tinggi persegi panjang.

Jika Anda melihat sketsa, cukup mudah untuk menghitung lebar ( wb) dan tinggi ( hb) dari kotak pembatas dengan w/ hukuran persegi panjang, dan psudut rotasi:

wb = w * cos(p) + h * sin(p)
hb = w * sin(p) + h * cos(p)

wbdan hbdapat diekstraksi langsung dari gambar. Kami juga dapat dengan cepat mengekstrak total area apersegi panjang dengan menghitung jumlah ..piksel. Karena kita berurusan dengan persegi panjang, ini memberi kita persamaan tambahan:

a = w * h

Jadi kita memiliki 3 persamaan dengan 3 tidak diketahui ( w, hdan p), yang cukup untuk menentukan tidak diketahui. Satu-satunya yang mengecewakan adalah bahwa persamaan tersebut mengandung fungsi trigonometri, dan setidaknya dengan kesabaran dan keterampilan matematika saya, sistem tidak dapat dengan mudah diselesaikan secara analitis.

Apa yang saya terapkan adalah pencarian brute force untuk sudutnya p. Setelah pdiberikan, dua persamaan pertama di atas menjadi sistem dua persamaan linear, yang dapat diselesaikan untuk wdan h:

w = (wb * cos(p) - hb * sin(p)) / (cos(p) * cos(p) - sin(p) * sin(p))
h = (hb * cos(p) - wb * sin(p)) / (cos(p) * cos(p) - sin(p) * sin(p))

Dengan nilai-nilai ini, kita kemudian dapat membandingkan w * hdengan luas persegi yang diukur. Kedua nilai idealnya akan sama di beberapa titik. Ini tentu saja tidak akan terjadi dalam matematika floating point.

Nilai w * hmenurun dengan meningkatnya sudut. Jadi kita mulai dari sudut 0,0, dan kemudian menambah sudut dengan langkah-langkah kecil sampai pertama kali w * hkurang dari area yang diukur.

Kode hanya memiliki dua langkah utama:

  1. Ekstrak ukuran kotak pembatas dan area persegi panjang dari input.
  2. Simpulkan sudut kandidat hingga kriteria terminasi tercapai.

Ketepatan output baik untuk persegi panjang di mana lebar dan tinggi berbeda secara signifikan. Itu menjadi agak rapuh dengan persegi panjang yang hampir kuadrat dan diputar mendekati 45 derajat, hanya nyaris menyelesaikan 7% kesalahan rintangan untuk contoh uji 2.

Bitmap misalnya 2 sebenarnya terlihat sedikit aneh. Sudut kiri terlihat kusam. Jika saya menambahkan satu piksel lagi di sudut kiri, keduanya terlihat lebih baik (bagi saya), dan memberikan presisi yang jauh lebih baik untuk algoritma ini.

Reto Koradi
sumber