Determina le dimensioni di un rettangolo ruotato


14

Questo frammento di stack disegna un rettangolo bianco con alias su uno sfondo nero dato i parametri per le sue dimensioni, posizione, angolo e dimensioni della griglia:

<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>
( Versione JSFiddle )

La rappresentazione del testo ha XXovunque ci sia un pixel nero nell'immagine e ..ovunque ci sia un pixel bianco. (Sembra schiacciato se lo sono Xe ..)

Scrivi un programma che prende la rappresentazione testuale di un rettangolo prodotto dallo snippet e genera la larghezza e l'altezza approssimative del rettangolo, entrambe entro ± 7% della larghezza e dell'altezza effettive .

Il tuo programma dovrebbe funzionare efficacemente per tutti i possibili rettangoli che possono essere disegnati dallo snippet, con i vincoli che:

  • La larghezza e l'altezza del rettangolo sono almeno 24.
  • La larghezza e l'altezza della griglia sono almeno 26.
  • Il rettangolo non tocca mai né esce dai limiti della griglia.

Pertanto, il rettangolo di input può avere qualsiasi rotazione, posizione e dimensioni e la griglia può avere qualsiasi dimensione, purché vengano rispettati i tre vincoli di cui sopra. Si noti che, tranne per le dimensioni della griglia, i parametri dello snippet possono essere float.

Dettagli

  • Prendi il rettangolo di testo non elaborato come input o prendi il nome file di un file che contiene il rettangolo di testo non elaborato (tramite stdin o riga di comando). Si può presumere che il rettangolo di testo abbia una nuova riga finale.
  • Si può presumere che il rettangolo di testo sia composto da due distinti caratteri ASCII stampabili diversi da Xe .se desiderato. (Le nuove righe devono rimanere nuove.)
  • Stampa la larghezza e l'altezza misurate come numeri interi o float su stdout in qualsiasi ordine (poiché non c'è modo di determinare quale sia effettivamente andato con quale parametro). Qualsiasi formato che mostra chiaramente le due dimensioni è soddisfacente, ad esempio D1 D2, D1,D2, D1\nD2, (D1, D2), etc.
  • Invece di un programma, è possibile scrivere una funzione che accetta il rettangolo di testo come una stringa o il nome del file e stampa il risultato normalmente o lo restituisce come una stringa o elenco / tupla con due elementi.
  • Ricorda che XXo ..è un "pixel" del rettangolo, non due.

Esempi

Ex. 1

Parametri: grid w:60 grid h:34 w:40 h:24 x:0 y:0 θ:12(valori predefiniti del frammento)

Ingresso

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

Esempi di output

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

Ex. 2

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

Ingresso

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

Esempi di output

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

punteggio

Vince il codice più breve in byte. Tiebreaker è il post più votato.


Una soluzione non dovrebbe soddisfare i requisiti di precisione per essere accettata? Quello che hai accettato è lontano per determinati valori di input.
Reto Koradi,

Risposte:


6

Matlab, 226 byte

L'idea è semplice: prima provo a scoprire quanto è stato girato il rettangolo, quindi giro l'immagine di conseguenza in modo che il rettangolo sia verticale. Quindi ho semplicemente "riassunto" tutti i pixel nelle colonne della riga con speranza e provo a contare quante delle somme sono superiori alla media (soglia semplice) per determinare la larghezza e l'altezza. Questo semplice metodo funziona in modo sorprendentemente affidabile.

Come posso rilevare l'angolo?

Provo solo ogni passaggio (un grado ciascuno) e sommo lungo le colonne e ottengo un vettore di somme. Quando il rettangolo è verticale, idealmente dovrei ottenere solo due improvvisi cambiamenti in questo vettore di somme. Se il quadrato è sulla punta, le modifiche sono molto graduali. Quindi uso solo la prima derivata e cerco di ridurre al minimo il numero di "salti". Qui puoi vedere una trama del criterio che stiamo cercando di minimizzare. Nota che puoi vedere i quattro minimi che corrispondono ai quattro possibili orientamenti verticali.

criterio di minimizzazione

Ulteriori pensieri: non sono sicuro di quanto si possa giocare a golf poiché l'esauriente ricerca dell'angolo richiede molti caratteri e dubito che tu possa ottenere così bene con metodi di ottimizzazione integrati, perché come puoi vedere ci sono molti minimi locali che non stiamo cercando. È possibile migliorare facilmente la precisione (per immagini di grandi dimensioni) scegliendo una dimensione del gradino più piccola per l'angolo e cercare solo 90 ° anziché 360 ° in modo da poterlo sostituire 0:360con 0:.1:90qualcosa di simile. Ma comunque, per me la sfida era più trovare un algoritmo robusto piuttosto che giocare a golf e sono sicuro che le voci delle lingue del golf lasceranno molto indietro la mia presentazione =)

PS: Qualcuno dovrebbe davvero derivare un linguaggio da golf da Matlab / Octave.

Uscite

Esempio 1:

 25    39

Esempio 2:

 25    24

Codice

golfed:

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

Ungolfed:

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

7

CJam, 68 65 64 byte

Questo può essere giocato un po 'di più ..

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

Come funziona

La logica è piuttosto semplice, se ci pensate.

Tutto ciò di cui abbiamo bisogno dalle X.combinazioni di input sono 3 coordinate di due lati adiacenti. Ecco come li otteniamo:

First

In qualsiasi orientamento del rettangolo, il primo .in tutto l'input sarà uno degli angoli. Per esempio..

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

Qui, il primo .è nella seconda riga, ottava colonna.

Ma non è così, dobbiamo fare alcune regolazioni e aggiungere la larghezza della .corsa su quella linea alle coordinate per ottenere la coordinata dell'estremità giusta.

Second

Se trasponiamo il rettangolo sopra (ruotato su newline), l'angolo in basso a sinistra prende il posto sopra. Ma qui, non compensiamo la .lunghezza della corsa poiché avremmo voluto ottenere comunque la coordinata in basso a sinistra del bordo (che in forma trasposta sarà ancora il primo incontrato .)

Rest two

Per il resto due coordinate, giriamo semplicemente in senso orizzontale, il rettangolo ed eseguiamo i due passaggi precedenti. Uno degli angoli qui sarà comune dai primi due.

Dopo aver ottenuto tutti e 4, facciamo semplicemente alcuni semplici calcoli per ottenere le distanze.

Ora questo non è il metodo più accurato, ma funziona bene entro il margine di errore e bene per tutti i possibili orientamenti del rettangolo.

Espansione del codice (bit obsoleto)

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

Provalo online qui


Prova una dimensione della griglia di 50x50, una dimensione del rettangolo di 45x45 e un angolo -2. L'errore è di circa il 28%. Ho provato un approccio simile (era la mia idea iniziale, prima di vedere la tua), e ottenerlo abbastanza preciso risulta essere più complicato del previsto, in particolare se i lati sono vicini all'orizzontale / verticale. Funziona alla grande se sono più vicini alla diagonale. Penso che ciò richieda una maggiore logica (ad es. Anche la ricerca di estremi nella direzione diagonale) o un approccio completamente diverso.
Reto Koradi,

@RetoKoradi Oh. Questo perché tutti gli angoli negativi richiedono la .regolazione della larghezza sulla seconda coordinata, anziché sulla prima. Risolverà. Dovrebbe essere una soluzione breve.
Ottimizzatore,

1
@RetoKoradi dovrebbe essere risolto ora.
Ottimizzatore

Prova il rettangolo 40x24 con angolo 0.
Reto Koradi,

@RetoKoradi Punti positivi. Per ora non accettato.
Hobby di Calvin il

5

Python 3, 347 337 byte

Questo si è rivelato più difficile di quanto mi aspettassi. Lavori in corso...

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

Definisce una funzione che fprende la stringa come argomento e stampa il risultato su STDOUT.

Pyth, 87 84 82 81 75 72 71 byte

(POSSIBILMENTE INVALIDO, INCHIESTA QUANDO POSSO tornare A CASA)

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

Modo ancora troppo lungo. Fondamentalmente un porto del precedente. Amorevole .adistanza euclidea di Pyth . Riceve input tramite STDIN e fornisce output tramite STDOUT. Si aspetta che il carattere non rettangolare sia in minuscolo x(beh, qualsiasi cosa con valore ASCII 98 o superiore).

Algoritmo

Entrambi utilizzano lo stesso algoritmo. Fondamentalmente inizio con un array contenente il centro di massa dell'area del rettangolo. Aggiungo quindi tre punti all'array di tutti i punti nel rettangolo, scegliendo sempre quello con la somma massima delle distanze dai punti già presenti nell'array. Il risultato è sempre tre punti in diversi angoli del rettangolo. Calcolo quindi tutte e tre le distanze tra questi tre punti e prendo le due più brevi.


La soluzione Pyth non funziona affatto. I due esempi dell'OP forniscono i risultati [33.0, 59.0]anziché [40, 24]e [39.0, 54.0]invece di [24.0, 24.5].
Jakube,

@Jakube Weird. Investigherò una volta tornato a casa. Purtroppo sono in gita scolastica in Lapponia fino al 9 giugno.
PurkkaKoodari,

Purtroppo non chiamerei un viaggio in Lapponia ;-)
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

Questo si è ispirato all'algoritmo di @ Pietu1998. Prende l'idea di determinare un angolo come il punto più lontano dal centro, ma differisce da lì:

  • Determino il secondo angolo come punto con il prodotto incrociato più grande con il vettore dal centro al primo angolo. Ciò fornisce il punto con la distanza maggiore dalla linea dal centro alla prima curva.
  • Non è necessario cercare un terzo angolo, poiché è solo l'immagine speculare del secondo angolo rispetto al centro.

Quindi il codice segue questa sequenza:

  • Il primo ciclo è sopra le linee nell'input e crea un elenco rdi punti rettangolari.
  • Il secondo ciclo calcola la media di tutti i punti del rettangolo, fornendo il centro del rettangolo.
  • Il terzo ciclo trova il punto più lontano dal centro. Questa è la prima curva. Allo stesso tempo, sottrae il centro dai punti nell'elenco, in modo che le coordinate dei punti siano relative al centro per il calcolo rimanente.
  • Il quarto ciclo trova il punto con il prodotto incrociato più grande con il vettore fino al primo angolo. Questa è la seconda curva.
  • Stampa la distanza tra il primo angolo e il secondo angolo e la distanza tra il primo angolo e l'immagine speculare del secondo angolo.
  • 1.0viene aggiunto alle distanze perché i calcoli della distanza originali utilizzano indici di pixel. Ad esempio, se hai 5 pixel, la differenza tra l'indice dell'ultimo e il primo pixel era solo 4, il che richiede una compensazione nel risultato finale.

La precisione è abbastanza buona. Per i due esempi:

$ cat rect1.txt | python Golf.py 
24.5372045919 39.8329756779
$ cat rect2.txt | python Golf.py 
23.803508502 24.5095563412

0

Python 2, 272 byte

Pubblicando questo come una risposta separata poiché è un algoritmo completamente diverso dal mio precedente:

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

Questo approccio non identifica affatto gli angoli. Si basa sull'osservazione che le dimensioni (larghezza e altezza) del rettangolo di selezione e l'area del rettangolo ruotato sono sufficienti per determinare la larghezza e l'altezza del rettangolo.

Se guardi uno schizzo, è abbastanza facile calcolare la larghezza ( wb) e l'altezza ( hb) del riquadro di delimitazione con w/ hla dimensione del rettangolo e pl'angolo di rotazione:

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

wbe hbpuò essere estratto direttamente dall'immagine. Possiamo anche estrarre rapidamente l'area totale adel rettangolo contando il numero di ..pixel. Dato che abbiamo a che fare con un rettangolo, questo ci dà l'equazione aggiuntiva:

a = w * h

Quindi abbiamo 3 equazioni con 3 incognite ( w, he p), che è sufficiente per determinare le incognite. L'unico inconveniente è che le equazioni contengono funzioni trigonometriche e almeno con la mia pazienza e abilità matematiche il sistema non può essere facilmente risolto analiticamente.

Ciò che ho implementato è una ricerca della forza bruta per l'angolo p. Una volta pfornite, le prime due equazioni sopra diventano un sistema di due equazioni lineari, che possono essere risolte per we 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))

Con questi valori, possiamo quindi confrontare w * hcon l'area misurata del rettangolo. I due valori sarebbero idealmente uguali ad un certo punto. Questo ovviamente non accadrà nella matematica in virgola mobile.

Il valore di w * hdiminuisce all'aumentare dell'angolo. Quindi iniziamo dall'angolo 0.0 e quindi incrementiamo l'angolo di piccoli passi fino a quando la prima volta w * hè inferiore all'area misurata.

Il codice ha solo due passaggi principali:

  1. Estrai le dimensioni del rettangolo di selezione e dell'area rettangolare dall'input.
  2. Passa sopra gli angoli candidati fino a raggiungere il criterio di terminazione.

La precisione dell'output è buona per i rettangoli in cui larghezza e altezza sono significativamente diverse. Diventa un po 'incerto con rettangoli che sono quasi quadrati e ruotati vicino a 45 gradi, cancellando appena l'ostacolo dell'errore del 7% per l'esempio di prova 2.

La bitmap per esempio 2 in realtà sembra leggermente strana. L'angolo sinistro sembra sospetto noioso. Se aggiungo un altro pixel nell'angolo sinistro, entrambi sembrano migliori (per me) e offrono una precisione molto migliore per questo algoritmo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.