자바 스크립트 ES6, 738 바이트
((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')
조정없이 대부분의 브라우저와 노드에서 작동하는 ES5 이하 버전은 다음과 같습니다. 827 바이트
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 '))
코드는 익명 함수를 반환합니다. 매개 변수로는 다음과 같은 점으로 구성된 배열을 사용 [[0,1],[2,3],[4,5]]
합니다. 그것을 사용하려면 그 var f=
앞에 배치 하거나 명령 줄에서 사용 (process.argv[2].replace(/ /g,'').slice(1,-1).split(')(').map((x)=>x.split(',')))
하려면 끝에 추가 하고 다음과 같이 호출하십시오node convpol.js '(1,2)(3,4)(5,6)'
도전 해 주셔서 감사합니다! 참조 구현이 없으므로 이것이 정확하다는 것을 증명할 수는 없지만 적어도 포인트 목록의 순열에 대해서는 일관성이 있습니다. 디버깅 코드가있는 버전, 심지어 비활성화 된 버전이 기하 급수적으로 시간이 지남에 따라 너무 느리기 때문에 이것이 효과가 있다고 생각하지 않았습니다. 어쨌든 골프를하기로 결심했고 내 컴퓨터에서 50 포인트 동안 2 초 미만으로 떨어 졌다는 것을 알게되어 기뻤습니다. 1 분에 약 130 포인트를 계산할 수 있습니다.
이 알고리즘은 Graham scan 과 유사하지만 어디에서나 빈 볼록 껍질을 검색해야한다는 점이 다릅니다.
설명
다음은 알고리즘 작동 방식에 대한 고급 개요입니다. 이 알고리즘의 핵심은 포인트를 둘러싸 지 않는 반 시계 방향의 볼록 루프를 검색하는 것입니다. 절차는 다음과 같습니다.
- 한 쌍의 점과 다른 모든 점의 목록으로 시작하십시오.
- 현재 포인트 쌍이 목록의 임의의 포인트를 정확히 통과하면 중지하십시오.
- 다각형을 오목하게 만들기 때문에 현재 쌍의 시계 방향으로 모든 점을 필터링합니다.
- 남은 모든 포인트에 대해 다음을 수행하십시오.
- 이 점에서 체인의 첫 번째 점까지의 선이 시계 반대 방향으로 점을 통과하거나 둘러싸는 경우 다각형이 점을 둘러싸 기 때문에이 점을 건너 뜁니다.
- 이 점을 체인에 추가하고 1 단계부터 현재 체인 및 점 목록과 함께 반복합니다.
- 남은 점이없고 체인에 최소 3 개의 점이있는 경우 유효한 볼록 다각형입니다. 이 다각형의 가장 큰 영역을 기억하십시오.
또한 최적화로 체인의 초기 쌍을 확인 된 상태로 기록하므로이 쌍을 가진 가장 큰 다각형이 이미 발견되었으므로 체인의 어느 곳에서나이 쌍을 본 후에 검색하면 즉시 검색을 중지 할 수 있습니다.
이 알고리즘은 다각형을 두 번 찾지 않아야하며 실험적으로이를 확인했습니다.