Javascript ES6, 738 octets
((V,C,L,r,k,n,A,G,F,e,i,j,q)=>p=>{p=p.map((p,i)=>({i:i,x:p[0],y:p[1]}));A=(f,p,a,b,v,i)=>{for(i=p[n],v=V(a,b);i--;)if(f(v,V(a,p[i])))return 1};G=(p,i,a)=>{for(i=p[n]-1,a=C(p[i],p[0]);i--;)a+=C(p[i],p[i+1]);if((a/=2)>r)r=a};F=(p,s,l,f,a,b,v)=>(l=s[n],f=s[0],a=s[l-2],b=s[l-1],e[a.i][b.i]||A((a,b)=>C(a,b)?0:a.x<0==b.x<0&&a.y<0==b.y<0&&L(a)>L(b),p,a,b)?0:(p=(v=V(a,b),p[k](x=>C(v,V(a,x))>=0)),A((a,b)=>C(a,b)>0,p,b,f)?0:(p.map(q=>F(p[k](r=>q!==r),[...s,q])),s[2]&&!p[n]&&!e[b.i][f.i]?G(s):0)));e=p.map(x=>p.map(y=>x===y));for(i=p[n];i--;){for(j=i;j--;){q=p[k]((p,x)=>x-i&&x-j);F(q,[p[i],p[j]]);F(q,[p[j],p[i]]);e[i][j]=e[j][i]=1}}console.log(r)})((a,b)=>({x:b.x-a.x,y:b.y-a.y}),(a,b)=>a.x*b.y-a.y*b.x,v=>v.x*v.x+v.y*v.y,0,'filter','length')
Voici une version ES5 ou moins qui devrait fonctionner dans la plupart des navigateurs et des nœuds sans peaufiner: 827 octets
eval("(%V,C,L,r,k,n,A,G,F,e,i,j,q){@%p){p=p.map(%p,i){@{i:i,x:p[0],y:p[1]}});A=%f,p,a,b,v,i){for(i=p[n],v=V(a,b);i--;)if(f(v,V(a,p[i])))@1};G=%p,i,a){for(i=p[n]-1,a=C(p[i],p[0]);i--;)a+=C(p[i],p[i+1]);if((a/=2)>r)r=a};F=%p,s,l,f,a,b,v){@(l=s[n],f=s[0],a=s[l-2],b=s[l-1],e[a.i][b.i]||A(%a,b){@C(a,b)!=0?0:a.x<0==b.x<0&&a.y<0==b.y<0&&L(a)>L(b)},p,a,b)?0:(p=(v=V(a,b),p[k](%x){@C(v,V(a,x))>=0})),A(%a,b){@C(a,b)>0},p,b,f)?0:(p.forEach(%q){@F(p[k](%r){@q!==r}),s.concat([q]))}),s[2]&&p[n]==0&&!e[b.i][f.i]?G(s):0)))};e=p.map(%x,i){@p.map(%y,j){@i==j})});for(i=p[n];i--;){for(j=i;j--;){q=p[k](%p,x){@x!=i&&x!=j});F(q,[p[i],p[j]]);F(q,[p[j],p[i]]);e[i][j]=e[j][i]=1}}console.log(r)}})(%a,b){@{x:b.x-a.x,y:b.y-a.y}},%a,b){@a.x*b.y-a.y*b.x},%v){@v.x*v.x+v.y*v.y},0,'filter','length')".replace(/%/g,'function(').replace(/@/g,'return '))
Le code renvoie une fonction anonyme. En tant que paramètre, il prend un tableau de points, comme [[0,1],[2,3],[4,5]]
. Pour l'utiliser, vous pouvez le placer var f=
avant, ou si vous souhaitez l'utiliser à partir de la ligne de commande, ajoutez (process.argv[2].replace(/ /g,'').slice(1,-1).split(')(').map((x)=>x.split(',')))
à la fin et appelez-le commenode convpol.js '(1,2)(3,4)(5,6)'
Merci pour le défi! Comme il n'y a pas d'implémentation de référence, je ne peux pas prouver que c'est correct, mais c'est cohérent au moins pour les permutations de la liste de points. Je ne pensais presque pas que cela allait fonctionner, car les versions avec le code de débogage, même désactivées, étaient beaucoup trop lentes avec une augmentation exponentielle du temps. J'ai quand même décidé de jouer au golf et j'étais ravi de voir qu'il était tombé à moins de 2 secondes pour 50 points sur ma machine. Il peut calculer environ 130 points en 1 minute.
L'algorithme est similaire au balayage Graham , sauf qu'il doit rechercher des coques convexes vides partout.
Explication
Voici un aperçu de haut niveau du fonctionnement de l'algorithme. La viande de cet algorithme recherche simplement des boucles convexes dans le sens antihoraire qui ne renferment pas de point. La procédure ressemble à ceci:
- Commencez avec une paire de points et une liste de tous les autres points.
- Si la paire de points actuelle passe exactement par n'importe quel point de la liste, arrêtez.
- Filtrez tous les points dans le sens horaire de la paire actuelle, car ils rendraient le polygone concave.
- Pour tous les points restants, procédez comme suit:
- Si une ligne allant de ce point au premier point de la chaîne passe par ou englobe des points dans le sens inverse des aiguilles d'une montre, sautez ce point, car tous les polygones entoureraient le point.
- Ajoutez ce point à la chaîne, reprenez à partir de l'étape 1 avec la chaîne actuelle et la liste des points.
- S'il n'y avait plus de points et que la chaîne a au moins 3 points, c'est un polygone convexe valide. N'oubliez pas la plus grande zone de ces polygones.
De plus, à titre d'optimisation, nous enregistrons la paire initiale de la chaîne comme vérifiée, de sorte que toute recherche ultérieure après avoir vu cette paire n'importe où dans la chaîne peut immédiatement arrêter la recherche, car le plus grand polygone avec cette paire a déjà été trouvé.
Cet algorithme ne devrait jamais trouver un polygone deux fois, et je l'ai vérifié expérimentalement.