10, 10, 10… 희망이 있습니까?


15

머리말

오늘 일찍 900 라운드 양궁을 쏘고 있었을 때 (10은 끝 6 화살표로 끝나고 10은 끝 3 화살표로 끝나며 총 90 화살표와 최대 900 점)이 도전에 대해 생각했습니다.

양궁에서 (FITA가 제공 한 대상 얼굴 (촬영 한 종이)에서 촬영한다고 가정 )에서 각 화살표에 대해 최대 10 점을 청구 할 수 있습니다. 대상 얼굴의 직경이 10 또는 11 개 감소합니다. 서로 안에 중첩되어 있습니다. 내륜에서 바깥쪽으로 10 포인트부터 1 포인트까지 계산됩니다 (11 링의 경우 'X'로 계산되는 보조 최 내측 링이 있습니다.이 링은 10 점이지만 넥타이 끊기 경우에 사용됩니다. 더 높은 값). 관찰 :

FITA 목표 점수

물론 위의 그림에서 볼 수 있듯이 FITA Metric 점수를 참조하고 있습니다. 자세히 보면, 가장 안쪽의 고리가 보일 수 있습니다. 그것은 내가 언급 한 'X'이지만, 보너스와 경쟁하지 않는 한 그것에주의를 기울일 필요는 없습니다.

도전

녹색 (HEX # 00FF00, RGB (0, 255, 0)) 일부 크기의 점으로 점수를 반환합니다. 이미지에 녹색 점 이외의 데이터가 포함되어있을 수 있지만 녹색은 항상 동일한 음영입니다.

정사각형 이미지가 대상면을 나타내고 가장 바깥 쪽 링이 4 점 (상단 중앙, 하단 중앙, 우측 중앙, 왼쪽 중앙)에 닿아 있다고 상상할 수 있습니다. 표현 된 목표면은 항상 같은 비율이 될 것이며, 모든 링은 입력 목표 이미지 너비의 정확히 1/20의 너비를 갖습니다. 예를 들어, 입력 크기가 400px x 400px 인 입력 이미지의 경우 아래 그림과 같이 각 링의 내부 너비가 20px라고 가정 할 수 있습니다.

크 래피 예제 그림

설명

  • 두 개의 분리 된 고리를 만지면 두 개의 고리 중 더 높은 고리가 계산됩니다.
  • 보너스를 시도하지 않는 한 미스 또는 'x'사례를 자동으로 설명 할 필요는 없습니다.
  • 녹색 원이 겹치지 않는다고 가정 할 수 있습니다
  • 해당 녹색 음영의 다른 픽셀이 이미지에 없다고 가정 할 수도 있습니다.
  • 이미지는 PNG, JPEG 또는 PPM 형식입니다 (선택)
  • 이 질문을 게시하기 전에 작성된 경우 외부 이미지 처리 라이브러리가 허용됩니다.
  • 한 대상의 모든 녹색 원의 지름이 같다고 가정 할 수 있습니다
  • 겹치는 원 보너스에 대해 촬영 (ha)하는 경우 이미지에서 하나 이상의 원에 다른 겹치는 부분이 없다고 가정 할 수 있습니다.
  • 표준 허점은 허용되지 않습니다

테스트 사례

다음 두 경우는 각각 52 점 (또는 보너스의 경우 1 'x', 1 미스 로 52) 이어야합니다 .

그리고이 마지막 테스트 사례는 25 점입니다 .

보너스

  • 당신은 또한 (어떤 고리의 밖에서) 미스의 수를 반환하는 경우 -25 바이트
  • X의 양도 반환하는 경우 -30 바이트 (가장 안쪽 x는 이미지 너비의 3/100이고 10은 이미지 너비의 2/100이라고 가정합니다. 1-9 비율은 변경되지 않음)
  • 겹치는 원을 설명하면 -35 % 바이트 수

이것은 코드 골프이므로 최소 바이트가 이깁니다. 즐기세요!


"30은 끝에서 3 개의 화살표로 끝납니다. 총 30 개의 화살표"? 이것이 90 화살표가 아니어야합니까?
DavidC

@DavidCarraher 나는 게시 한대로 그 사실을 깨달았습니다. 수정
globby December

어떤 이미지 형식을 사용할 수 있습니까? PNG? PPM? 우리만의 맞춤 형식? (나는 첫 번째 두 개를 가정하지만 세 번째는 아니지만 설명을 위해 설명 할 것입니다.)
Doorknob

의는冰단순 @Doorknob 단지 JPEG 또는 PNG 가정 해 봅시다
globby

1
가장 어려운 보너스는 보상이 가장 적은 보너스라고 생각합니다.
Justin

답변:


4

처리 2, 448-25 = 423 바이트

int x,y,w,b,v,c,m;color g;PImage i;void setup(){i=loadImage("f.png");w=i.width;size(w,w);g=#00ff00;image(i,0,0);b=v=x=y=c=m=0;loadPixels();while(y*w+x<w*w){if(pixels[y*w+x]==g){f(y,x);if(v>=0)c+=v;else m++;}v=-1;x++;if(x==w){x=0;y++;}}println(c+" "+m);}void f(int k,int l){pixels[k*w+l]=color(0);if(pixels[(k+1)*w+l]==g)f(k+1,l);if(pixels[k*w+l+1]==g)f(k,l+1);if(pixels[k*w+l-1]==g)f(k,l-1);k-=w/2;l-=w/2;b=10-(int)(sqrt(k*k+l*l)/(w/20));if(b>v)v=b;}

이미지 파일에서 읽은 f는 녹색을 찾을 때까지 픽셀을 반복합니다. 그런 다음 중앙에 가장 가까운 점을 결정하여 원을 채 웁니다. 그런 다음 해당 점수를 총계에 더합니다. 점수가 음수이면 미스 카운터에 추가됩니다.

프로그램은 2 개의 숫자를 출력하며, 첫 번째는 점수이고 두 번째는 미스 횟수입니다.

  int x,y,w,b,v,c,m;
  color g;
  PImage i;
void setup()
{
  i=loadImage("f.png");
  w=i.width;
  size(w,w);
  g=#00ff00;
  image(i,0,0);
  b=v=x=y=c=m=0;  
  loadPixels();
  while(y*w+x<w*w)
  {
    if(pixels[y*w+x]==g)
    {
      f(y,x);
      if(v>=0)c+=v;
      else m++;
    }
    v=-1;
    x++;
    if(x==w){x=0;y++;}
  }
  print(c+" "+m);
}

void f(int k,int l)
{
  pixels[k*w+l]=color(0);
 if(pixels[(k+1)*w+l]==g)f(k+1,l);
 if(pixels[k*w+l+1]==g)f(k,l+1);
 if(pixels[k*w+l-1]==g)f(k,l-1); 
 k-=w/2;
 l-=w/2;
 b=10-(int)(sqrt(k*k+l*l)/(w/20));
 if(b>v)v=b;
}

여기에서 처리 할 수 있습니다


4

펄 5 + GD : 225-25 = 200

편집 : 인덱스 PNG에서 픽셀 판독이 잘못된 이유 를 발견 하고 해결 방법을 적용했습니다. 어떤 이유로 GD 라이브러리에서 녹색 픽셀 값은 (4,254,4)로 읽습니다. 이것이 질문에 포함 된 PNG 파일에만 해당되는지 확실하지 않습니다. 줄 바꿈은 아래 코드에서 제거 할 수 있습니다.

use GD;$k=newFromPng GD::Image'-',1;
sub v{/ /;10-int((($'-@x/2)**2+($`-@x/2)**2)**.5/@x*20)}
map{v>0?($r+=v):$%++,fill$k @c,0if 65280==getPixel$k @c=split
}sort{v($_=$b)- v$_=$a}map{//;map"$_ $'",@x}@x=0..width$k-1;
print"$r $%"

입력에서 PNG 이미지를 가져 와서 2 개의 값을 인쇄합니다. 점수 및 누락 수. 예를 들면 다음과 같습니다.

perl arch.pl <arch52.png
52 1

마지막 순간 변경 :

어쨌든에 사용되는 컬러 인덱스를 필요가 있다고 트루 컬러 모드 getPixelfill필요 사용하지하기 때문에 단순히 정수, RGB 값을 인코딩 rgb하고 colorAllocate에 그 인덱스로 변환 할 수 있습니다.

설명:

  • 공백으로 구분 된 정수 쌍으로 모든 픽셀 좌표 목록을 생성합니다.
  • 잠재적 점수를 기준으로 정렬합니다 ( 짧은 표준 매개 변수 대신 sub v매개 변수를 사용함 $_).
  • 녹색 인 경우 가장 높은 점수를받은 픽셀부터 시작하여 각 픽셀에 대해 결과에 추가하고 해당 위치를 검은 색으로 채 웁니다.

이미지가 아닙니다. @ bubalou의 대답은 제대로 # 00FF00과 색상을 읽고
globby

@ globby 이미지에서 색상이 올바른지 알고 있지만 (이미지 편집 소프트웨어로 확인) 색상 공간을 자르는 동일한 메타 정보가있을 수도 있습니다.
nutki December

혹시. 그래도 이상합니다
globby

3

하스켈 -579-25 = 554603-25-30 576-25-30 = 521 바이트

전략:

  • 모든 픽셀에 대해 (d, x, y) 트리플의 목록을 만듭니다 (d는 중심까지의 거리입니다)
  • 거리별로 목록을 정렬
  • 가장 큰 거리로 시작 : 작은 이웃에서 픽셀이 유일한 녹색 픽셀 인 경우 목록 L에서 거리를 유지하고 그렇지 않으면 어둡게합니다.
  • 거리 목록 L에서 점수를 계산

(52,1,1)를 들어 테스트 이미지의 출력은 3 배 (점수, 누락, X) 입니다.

중심에 가장 가까운 원의 픽셀이 다른 원의 3 픽셀 내에 있으면 프로그램이 실패 할 수 있습니다.

import Data.List
import Codec.Picture
import Codec.Picture.RGBA8
import Codec.Picture.Canvas
z=fromIntegral
f(e,x,y)(v,h)|and$j x y:[not$j a b|a<-[x-3..x+3],b<-[y-3..y+3],not(a==x&&b==y)]=(v,e:h)|1<2=(setColor x y(PixelRGBA8 0 0 0 0)v,h)
 where j n m|PixelRGBA8 0 255 0 _<-getColor n m v=0<1|0<1=0>1
d k r(h,i,j)|r>10*k=(h,i+1,j)|r<k*3/5=(h+10,i,j+1)|1<2=(10-(floor$r/k)+h,i,j)
main=do
 i<-readImageRGBA8 "p.png"
 let(Right c)=imageToCanvas i;s=canvasWidth c;q=[3..s-4];(_,g)=foldr f(c,[])$sort[(sqrt$(z x-z s/2)^2+(z y-z s/2)^2,x,y)|x<-q,y<-q]
 print$foldr(d$z s/20)(0,0,0)g

팁 : all id또한.와 동일합니다. 패턴 가드로 and구현할 수 있습니다jj n m|PixelRGBA8 0 255 0 _<-getColor n m v=0<1|0<1=0>1
자랑스런 Haskeller

@ proudhaskeller : 예, 감사합니다!
nimi

2

수학 -371386-25 = 361

보다 최적의 솔루션. 내 파이썬 솔루션보다 훨씬 빠르게 답변을 계산합니다.

i=IntegerPart;c=i/@((NestList[#+.01&,.1,10]~Prepend~1)*100);g[m_]:=Last@@c~Position~#-1&/@(i@Round@Last@#&/@(#*100&/@Riffle[RGBColor/@NestList[#+.01&,{.1,.1,.1},10],Table[Disk[{0,0},n],{n,1,.1,-.1}]]~Graphics~{ImageSize->ImageDimensions[m],PlotRangePadding->None}~ImageMultiply~ChanVeseBinarize[m,"TargetColor"->Green]~ComponentMeasurements~"Max"/.Rule[a_,b_]:>b))//{Total@#,#~Count~0}&

PIL이 포함 된 Python-간단하고 최적화되지 않은 솔루션, 961 바이트

이것은 단순히 문제를 해결하는 데 어리석은 접근법을 보여주기위한 것입니다. 처음 2 개의 테스트 사례를 실행하는 데 ~ 2 분이 걸리고, 빠르게 구성되고, 리소스를 많이 사용하며, 알고리즘 적으로 복잡한 서클 탐지기 때문에 시스템에서 세 번째를 실행하는 데 ~ 20 분이 걸립니다. 그럼에도 불구하고, 최적의 골프는 아니지만 요구 사항을 충족합니다. 이미지에 녹색이 많을수록 실행 시간이 더 오래 걸립니다.

from PIL import Image,ImageDraw
a=lambda x,y,w,h:filter(lambda x:0<=x[0]<w and 0<=x[1]<h,[(x-1,y-1),(x,y-1),(x+1,y-    1),(x-1,y),(x,y),(x+1,y),(x-1,y+1),(x,y+1),(x+1,y+1)])
def b(c):
 d=0,255,0;e,f=c.size;g=c.load();h,i=[],[];j=Image.new("RGB",(e,f));k=ImageDraw.Draw(j)
 for l in range(e):
  for m in range(e):
   n=g[l,m][:-1]
   if n==d and(l,m)not in i:
    o=[(l,m)];p=[];q=1
    while q:
     q=0;r=o[:]
     for s in o:
      t=filter(lambda x:g[x[0],x[1]][:-1]==d and(x[0],x[1]) not in r,a(s[0],s[1],e,f))
      if t:
       r+=t
       if len(t)<8:
        p+=[s]
       q=1
     o=r
    h+=[p]
    for u in o:
     i+=[u]
   i+=[(l,m)]
 p=map(lambda x:"#"+str(x)*6,'123456789ab');v=0;k.rectangle((0,0,e,f),fill=p[0])
 for n in p[1:]:
  w=e/20*v;x=e-w;k.ellipse((w,w,x,x),fill=n);v+=1
 y=j.load();z=0
 for l in h:
  v=[]
  for m in l:
   s=y[m[0],m[1]]
   if s not in v:
    v+=[s]
  v=max(v);z+=p.index("#"+''.join(map(lambda x:hex(x)[2:],v)))
 return z

PIL 이미지 객체를 가져 와서 점수를 반환합니다.

필요한 단계 :

  1. 녹색 원을 비효율적으로 격리
    • n녹색 픽셀 인 경우 일부 픽셀의 모든 이웃을 찾아 원에 추가합니다.
    • 이웃이 8 개인 픽셀을 필터링하여 대략적인 윤곽선 결정
  2. 대상 표현 그리기
    • 빈 캔버스 만들기
    • 독특한 색상의 배경을 그리십시오 (미스를 쉽게 구현할 수 있음)
    • 고유 한 색상으로 중첩 된 타원 그리기
  3. 원 아래에있는 대상의 색상을 결정하여 각 원의 점수 영역을 결정하십시오.
  4. 높은 점수 영역을 선택하고 (여러 개가있는 경우) 총점에 점수를 추가합니다
  5. 합계를 반환

파이썬 함수 a는 다음과 같이 쓸 수 있습니다a=lambda x,y,w,h:[(X,Y)for X in(x-1,x,x+1)for Y in(y-1,y,y+1)if w>X>-1<Y<h]
ovs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.