Déterminer les dimensions d'un rectangle pivoté

14

Cette pile Snippet dessine un crénelage rectangle blanc sur un fond noir des paramètres donnés ses dimensions, la position, l' angle et les dimensions de la grille:

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

La représentation du texte a XXpartout où il y a un pixel noir dans l'image et ..partout où il y a un pixel blanc. (Il semble écrasé s'ils le sont Xet ..)

Écrivez un programme qui prend la représentation textuelle d'un rectangle produit par l'extrait de code et génère la largeur et la hauteur approximatives du rectangle, toutes deux à ± 7% de la largeur et de la hauteur réelles .

Votre programme doit fonctionner efficacement pour tous les rectangles possibles qui peuvent être dessinés par l'extrait de code, avec les contraintes suivantes:

  • La largeur et la hauteur du rectangle sont au minimum de 24.
  • La largeur et la hauteur de la grille sont au minimum de 26.
  • Le rectangle ne touche jamais ni ne sort des limites de la grille.

Ainsi, le rectangle d'entrée peut avoir n'importe quelle rotation, position et dimension, et la grille peut avoir n'importe quelle dimension, tant que les trois contraintes ci-dessus sont respectées. Notez qu'à l'exception des dimensions de la grille, les paramètres d'extrait peuvent être des flottants.

Détails

  • Prenez le rectangle de texte brut en entrée ou prenez le nom de fichier d'un fichier qui contient le rectangle de texte brut (via stdin ou ligne de commande). Vous pouvez supposer que le rectangle de texte a une nouvelle ligne de fin.
  • Vous pouvez supposer que le rectangle de texte est constitué de deux caractères ASCII imprimables distincts autres que Xet .si vous le souhaitez. (Les sauts de ligne doivent rester des sauts de ligne.)
  • Affichez la largeur et la hauteur mesurées sous forme d'entiers ou de flottants sur stdout dans n'importe quel ordre (car il n'y a aucun moyen de déterminer lequel correspond réellement à quel paramètre). Tout format qui montre clairement les deux dimensions est très bien, par exemple D1 D2, D1,D2, D1\nD2, (D1, D2), etc.
  • Au lieu d'un programme, vous pouvez écrire une fonction qui prend le rectangle de texte sous forme de chaîne ou le nom de fichier et imprime le résultat normalement ou le renvoie sous forme de chaîne ou de liste / tuple avec deux éléments.
  • N'oubliez pas que XXou ..est un «pixel» du rectangle, pas deux.

Exemples

Ex. 1

Paramètres: grid w:60 grid h:34 w:40 h:24 x:0 y:0 θ:12(valeurs par défaut de l'extrait)

Contribution

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

Exemples de sorties

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

Ex. 2

Paramètres: grid w:55 grid h:40 w:24.5 h:24 x:-10.1 y:2 θ:38.5

Contribution

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

Exemples de sorties

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

Notation

Le code le plus court en octets gagne. Tiebreaker est le poste le plus voté.

Loisirs de Calvin
la source
Une solution ne doit-elle pas répondre aux exigences de précision pour être acceptée? Celui que vous avez accepté est loin pour certaines valeurs d'entrée.
Reto Koradi

Réponses:

6

Matlab, 226 octets

L'idée est simple: j'essaie d'abord de savoir à quel point le rectangle a été tourné, puis de tourner l'image en conséquence de sorte que le rectangle soit droit. Ensuite, je résume simplement tous les pixels dans les colonnes de ligne et j'essaie de compter combien de sommes sont supérieures à la moyenne (seuillage simple) pour déterminer la largeur et la hauteur. Cette méthode simple fonctionne de manière étonnamment fiable.

Comment détecter l'angle?

J'essaie simplement chaque étape (un degré chacune) et je fais la somme le long des colonnes et j'obtiens un vecteur de sommes. Lorsque le rectangle est droit, je ne devrais idéalement obtenir que deux changements brusques de ce vecteur de sommes. Si le carré est sur la pointe, les changements sont très progressifs. Je n'utilise donc que la première dérivée et j'essaie de minimiser le nombre de «sauts». Ici vous pouvez voir un tracé du critère que nous essayons de minimiser. Notez que vous pouvez voir les quatre minima qui correspondent aux quatre orientations verticales possibles.

critère de minimisation

Réflexions complémentaires: je ne sais pas combien il pourrait être joué car la recherche d'angle exténuante prend beaucoup de caractères et je doute que vous puissiez si bien y parvenir avec des méthodes d'optimisation intégrées, car comme vous pouvez le voir, il existe de nombreux minima locaux que nous ne recherchons pas. Vous pouvez facilement améliorer la précision (pour les grandes images) en choisissant une taille de pas plus petite pour l'angle et en ne recherchant que 90 ° au lieu de 360 ​​° afin de pouvoir remplacer0:360 par0:.1:90 ou quelque chose comme ça. Mais de toute façon, pour moi, le défi était plus de trouver un algorithme robuste plutôt que de jouer au golf et je suis sûr que les entrées des langues de golf laisseront ma soumission loin derrière =)

PS: Quelqu'un devrait vraiment dériver une langue de golf de Matlab / Octave.

Les sorties

Exemple 1:

 25    39

Exemple 2:

 25    24

Code

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

Non 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))])
flawr
la source
7

CJam, 68 65 64 octets

Cela peut être joué un peu plus ..

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

Comment ça fonctionne

La logique est assez simple, si vous y réfléchissez.

Tout ce dont nous avons besoin dans les X.combinaisons d' entrée est de 3 coordonnées de deux côtés adjacents. Voici comment nous les obtenons:

First

Dans n'importe quelle orientation du rectangle, le premier .dans l'ensemble de l'entrée va être l'un des coins. Par exemple..

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

Ici, le premier . est dans la 2 ème ligne, 8 ème colonne.

Mais ce n'est pas ça, nous devons faire un ajustement et ajouter la largeur de la .piste sur cette ligne aux coordonnées pour obtenir les coordonnées de l'extrémité droite.

Second

Si nous transposons le rectangle ci-dessus (pivoté sur les nouvelles lignes), le coin inférieur gauche prend la place de l'étape ci-dessus. Mais ici, nous ne compensons pas la .longueur de course car nous aurions souhaité obtenir de toute façon la coordonnée inférieure gauche du bord (qui sous forme transposée sera toujours la première rencontrée). )

Rest two

Pour les deux autres coordonnées, il suffit de retourner horizontalement le rectangle et d'effectuer les deux étapes ci-dessus. Un des coins ici sera commun aux deux premiers.

Après avoir obtenu les 4, nous faisons simplement quelques calculs simples pour obtenir les distances.

Maintenant, ce n'est pas la méthode la plus précise, mais elle fonctionne bien dans la marge d'erreur et bien pour toutes les orientations possibles du rectangle.

Expansion de code (peu obsolète)

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

Essayez-le en ligne ici

Optimiseur
la source
Essayez une taille de grille de 50x50, une taille de rectangle de 45x45 et un angle -2. L'erreur est d'environ 28%. J'ai essayé une approche similaire (c'était mon idée initiale, avant de voir la vôtre), et la rendre suffisamment précise s'avère plus délicate que prévu, en particulier si les côtés sont proches de l'horizontale / verticale. Fonctionne très bien s'ils sont plus proches de la diagonale. Je pense que cela nécessite soit plus de logique (par exemple aussi la recherche d'extrêmes dans la direction diagonale), soit une approche entièrement différente.
Reto Koradi
@RetoKoradi Oh. C'est simplement parce que tous les angles négatifs ont besoin du .réglage de la largeur sur la deuxième coordonnée, au lieu du premier. Réparera. Devrait être courte.
Optimizer
1
@RetoKoradi devrait être corrigé maintenant.
Optimizer
Essayez le rectangle 40x24 avec l'angle 0.
Reto Koradi
@RetoKoradi Bons points. Non accepté pour l'instant.
Calvin's Hobbies
5

Python 3, 347 337 octets

Cela s'est avéré plus difficile que prévu. Travail en cours ...

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

Définit une fonction fprenant la chaîne comme argument et imprimant le résultat dans STDOUT.

Pyth, 87 84 82 81 75 72 71 octets

(POSSIBLEMENT INVALIDE, ENQUÊTE QUAND JE RETOURNE À LA MAISON)

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

Way encore trop long. Fondamentalement, un port du précédent. Aimer .ala distance euclidienne de Pyth . Prend l'entrée via STDIN et donne la sortie via STDOUT. S'attend à ce que le caractère non rectangle soit en minuscules x(enfin, tout ce qui a une valeur ASCII 98 ou plus).

Algorithme

Les deux utilisent le même algorithme. Je commence essentiellement par un tableau contenant le centre de masse de la zone rectangulaire. J'ajoute ensuite trois points au tableau de tous les points du rectangle, en choisissant toujours celui avec la somme maximale des distances aux points déjà dans le tableau. Le résultat est toujours trois points dans différents coins du rectangle. Je calcule ensuite les trois distances entre ces trois points et je prends les deux plus courtes.

PurkkaKoodari
la source
La solution Pyth ne fonctionne pas du tout. Les deux exemples de l'OP donnent les résultats [33.0, 59.0]au lieu de [40, 24]et [39.0, 54.0]au lieu de [24.0, 24.5].
Jakube
@Jakube Weird. Je vais enquêter une fois à la maison. Malheureusement, je suis en voyage de classe en Laponie jusqu'au 9 juin.
PurkkaKoodari
Je ne voudrais pas appeler un voyage en Laponie malheureusement ;-)
Jakube
0

Python 2, 342 octets

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

Cela s'est inspiré de l'algorithme de @ Pietu1998. Il prend l'idée de déterminer un coin comme le point le plus éloigné du centre, mais en diffère:

  • Je détermine le deuxième coin comme le point avec le plus grand produit croisé avec le vecteur du centre au premier coin. Cela donne le point avec la plus grande distance de la ligne du centre au premier coin.
  • Il n'est pas nécessaire de rechercher un troisième coin, car il s'agit simplement de l'image miroir du deuxième coin par rapport au centre.

Le code suit donc cette séquence:

  • La première boucle se trouve sur les lignes en entrée et crée une liste rde points rectangulaires.
  • La deuxième boucle calcule la moyenne de tous les points du rectangle, donnant le centre du rectangle.
  • La troisième boucle trouve le point le plus éloigné du centre. Ceci est le premier virage. En même temps, il soustrait le centre des points de la liste, de sorte que les coordonnées des points soient relatives au centre pour le calcul restant.
  • La quatrième boucle trouve le point avec le plus grand produit croisé avec le vecteur au premier coin. Ceci est le deuxième virage.
  • Imprime la distance entre le premier coin et le deuxième coin, et la distance entre le premier coin et l'image miroir du deuxième coin.
  • 1.0est ajouté aux distances car les calculs de distance d'origine utilisent des indices de pixels. Par exemple, si vous avez 5 pixels, la différence entre l'index du dernier et du premier pixel n'était que de 4, ce qui nécessite une compensation dans le résultat final.

La précision est assez bonne. Pour les deux exemples:

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

Python 2, 272 octets

Publier cela comme une réponse distincte car il s'agit d'un algorithme entièrement différent de mon précédent:

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

Cette approche n'identifie pas du tout les coins. Il est basé sur l'observation que la taille (largeur et hauteur) du cadre de délimitation et la zone du rectangle pivoté sont suffisantes pour déterminer la largeur et la hauteur du rectangle.

Si vous regardez une esquisse, il est assez facile de calculer la largeur ( wb) et la hauteur ( hb) du cadre de sélection avec w/ hla taille du rectangle et pl'angle de rotation:

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

wbet hbpeut être extrait directement de l'image. On peut également extraire rapidement la surface totale adu rectangle en comptant le nombre de ..pixels. Puisque nous avons affaire à un rectangle, cela nous donne l'équation supplémentaire:

a = w * h

Nous avons donc 3 équations avec 3 inconnues ( w, het p), ce qui est suffisant pour déterminer les inconnues. Le seul inconvénient est que les équations contiennent des fonctions trigonométriques, et au moins avec ma patience et mes compétences en mathématiques, le système ne peut pas être facilement résolu analytiquement.

Ce que j'ai implémenté, c'est une recherche par force brute de l'angle p. Une fois pdonnée, les deux premières équations ci-dessus deviennent un système de deux équations linéaires, qui peuvent être résolues pour wet 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))

Avec ces valeurs, nous pouvons alors comparer w * havec la zone mesurée du rectangle. Les deux valeurs seraient idéalement égales à un moment donné. Cela ne se produira bien sûr pas en mathématiques à virgule flottante.

La valeur de w * hdiminue à mesure que l'angle augmente. Nous commençons donc à l'angle 0,0, puis incrémentons l'angle par petits pas jusqu'à ce que la première fois w * hsoit inférieure à la zone mesurée.

Le code ne comporte que deux étapes principales:

  1. Extraire la taille du cadre de sélection et de la zone du rectangle de l'entrée.
  2. Boucle sur les angles candidats jusqu'à ce que le critère de terminaison soit atteint.

La précision de la sortie est bonne pour les rectangles dont la largeur et la hauteur sont sensiblement différentes. Il devient quelque peu incertain avec des rectangles presque carrés et tournés de près de 45 degrés, effaçant à peine l'obstacle d'erreur de 7% pour l'exemple de test 2.

Le bitmap de l'exemple 2 semble en fait légèrement étrange. Le coin gauche semble étrangement terne. Si j'ajoute un pixel de plus dans le coin gauche, il a l'air mieux (pour moi) et donne une bien meilleure précision pour cet algorithme.

Reto Koradi
la source