Tôi hy vọng 10, 10, 10?


15

Lời nói đầu

Khi tôi bắn một viên đạn bắn cung 900 viên vào đầu ngày hôm nay (10 kết thúc ở 6 mũi tên kết thúc và 10 kết thúc ở 3 mũi tên kết thúc, với tổng số 90 mũi tên và số điểm tối đa 900), tôi nghĩ đến thử thách này.

Trong bắn cung (giả sử rằng bạn đang bắn vào mặt mục tiêu do FITA cung cấp [mảnh giấy bạn bắn]), với mỗi mũi tên bạn có thể yêu cầu điểm tối đa là 10. Mặt mục tiêu chứa 10 hoặc 11 vòng đường kính giảm, lồng vào nhau. Từ vòng trong ra ngoài, chúng được tính từ 10 điểm, đến một điểm (và trong trường hợp 11 vòng, có một vòng trong cùng thứ cấp được tính là 'X', được tính là 10 nhưng được sử dụng trong các trường hợp phá vỡ cà vạt như giá trị cao hơn). Quan sát:

Ghi điểm mục tiêu của FITA

Tất nhiên, tôi đang đề cập đến cách tính điểm FITA, như đã thấy trong hình minh họa ở trên. Nếu bạn nhìn kỹ, bạn có thể quan sát vòng trong cùng, đó là một đường chấm mờ, điểm số không được đánh dấu. Đó là 'X' mà tôi đã đề cập, nhưng bạn sẽ không phải chú ý đến điều đó trừ khi cạnh tranh để nhận tiền thưởng.

Thử thách

Tạo một chức năng (hoặc chương trình đầy đủ, nếu ngôn ngữ không hỗ trợ các chức năng), sẽ nhận được một hình ảnh vuông hoàn hảo làm đầu vào (hoặc tên tệp hình ảnh, nếu cần), có chứa một số màu xanh lá cây (HEX # 00FF00, RGB (0, 255, 0)) các chấm có kích thước nào đó và trả về điểm số. Hình ảnh có thể chứa dữ liệu khác với các chấm màu lục , nhưng màu xanh lá cây sẽ luôn có cùng sắc thái.

Bạn có thể tưởng tượng rằng hình ảnh vuông đại diện cho mặt mục tiêu, với vòng ngoài cùng chạm vào 4 điểm (trung tâm trên cùng, trung tâm dưới cùng, trung tâm bên phải, trung tâm bên trái). Mặt mục tiêu được đại diện sẽ luôn có cùng tỷ lệ, với tất cả các vòng có chiều rộng bằng 1/20 chiều rộng của hình ảnh mục tiêu đầu vào. Ví dụ: được cung cấp một hình ảnh đầu vào có kích thước đầu vào 400px x 400px, bạn có thể giả sử rằng mỗi vòng có chiều rộng bên trong là 20px, như minh họa bên dưới:

Ví dụ minh họa crappy

Làm rõ

  • Nếu chạm vào hai vòng riêng biệt, số vòng cao hơn sẽ được tính
  • Bạn không phải tự động tính đến các lỗi hoặc trường hợp 'x', trừ khi cố gắng nhận tiền thưởng
  • Bạn có thể cho rằng không có vòng tròn màu xanh lá cây nào đang chồng chéo
  • Bạn cũng có thể cho rằng không có pixel nào khác của màu xanh lục đó trong hình ảnh
  • Hình ảnh sẽ ở định dạng PNG, JPEG hoặc PPM (sự lựa chọn của bạn)
  • Thư viện xử lý hình ảnh bên ngoài được cho phép, nếu tác giả trước khi đăng câu hỏi này
  • Bạn có thể cho rằng tất cả các vòng tròn màu xanh lá cây trên một mục tiêu sẽ có cùng đường kính
  • Nếu chụp (hah) cho phần thưởng vòng tròn chồng chéo, bạn có thể cho rằng ít nhất một vòng tròn trong ảnh không có chồng chéo khác
  • Các sơ hở tiêu chuẩn không được phép

Các trường hợp thử nghiệm

Hai trường hợp sau đây mỗi điểm 52 (hoặc trong trường hợp tiền thưởng, 52 với 1 'x' và 1 lần bỏ lỡ):

Và trường hợp thử nghiệm cuối cùng này nên đạt 25 điểm :

Tặng kem

  • -25 byte nếu bạn cũng trả về số lần bỏ lỡ (bên ngoài bất kỳ vòng nào)
  • -30 byte nếu bạn cũng trả về số lượng X (giả sử rằng x trong cùng là 3/100 chiều rộng của hình ảnh và 10 sau đó là 2/100 chiều rộng của hình ảnh. Tỷ lệ 1-9 không thay đổi)
  • -35% số byte nếu bạn tính đến các vòng tròn chồng chéo

Đây là mã golf, vì vậy ít byte nhất sẽ thắng. Chúc vui vẻ!


"30 kết thúc tại 3 mũi tên một kết thúc, cho tổng số 30 mũi tên"? Không phải đó là 90 mũi tên sao?
DavidC

@DavidCarraher Tôi nhận ra điều đó ngay khi tôi đăng. Đã sửa
globalby

Chúng ta có thể sử dụng định dạng hình ảnh nào? PNG? PPM? Định dạng tùy chỉnh của chúng ta? (Tôi sẽ giả sử hai cái đầu tiên nhưng không phải cái thứ ba, nhưng chỉ để làm rõ.)
Doorknob

Hãy nói rằng chỉ JPEG hoặc PNG vì đơn giản @Doorknob冰
globby

1
Tôi nghĩ phần thưởng khó nhất là phần thưởng có ít nhất.
Justin

Câu trả lời:


4

Xử lý 2, 448-25 = 423 byte

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;}

Đọc trong tệp hình ảnh f vòng qua các pixel cho đến khi tìm thấy màu xanh lục sau đó lấp đầy vòng tròn xác định điểm gần trung tâm nhất. Sau đó thêm số điểm đó vào tổng số. nếu điểm số âm, nó sẽ được thêm vào một bộ đếm.

Chương trình sẽ xuất ra 2 số, số thứ nhất là số điểm và số thứ hai là số lần bỏ lỡ.

  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;
}

bạn có thể xử lý ở đây


4

Perl 5 + GD: 225 - 25 = 200

Chỉnh sửa: Tìm thấy lý do cho việc đọc pixel không chính xác trong các PNG được lập chỉ mục và áp dụng một cách giải quyết. Vì một số lý do với thư viện GD, các giá trị pixel màu xanh lá cây được đọc là (4.254,4). Tôi không chắc chắn nếu điều này là cụ thể cho các tệp PNG có trong câu hỏi. Ngắt dòng có thể được loại bỏ trong mã dưới đây.

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 $%"

Tạo một hình ảnh PNG trên đầu vào và in 2 giá trị: Số điểm và sai. Ví dụ:

perl arch.pl <arch52.png
52 1

Thay đổi phút cuối:

Trong chế độ màu thực mà dù sao tôi cũng cần các chỉ mục màu được sử dụng getPixelfillchỉ đơn giản là các giá trị RGB được mã hóa số nguyên, do đó không cần sử dụng rgbcolorAllocatechuyển đổi sang và từ các chỉ mục đó.

Giải trình:

  • Tạo danh sách tất cả các tọa độ pixel (dưới dạng các cặp số nguyên được phân tách bằng dấu cách).
  • Sắp xếp theo điểm số tiềm năng (sử dụng sub vtham số thông qua $_thay vì tham số tiêu chuẩn vì nó ngắn hơn).
  • Đối với mỗi pixel bắt đầu từ những điểm có điểm cao nhất nếu nó có màu xanh lá cây, hãy thêm vào kết quả và lấp đầy vị trí của nó màu đen.

Đó không phải là hình ảnh; Câu trả lời @ bubalou của đọc một cách chính xác các màu sắc như # 00FF00
globby

@globby Tôi biết màu sắc là chính xác trong hình ảnh (tôi đã kiểm tra bằng phần mềm chỉnh sửa hình ảnh), nhưng có lẽ cũng có thông tin meta tương tự để cắt không gian màu.
nutki

có khả năng. Mặc dù điều đó thật kỳ lạ
globalby

3

Haskell - 579-25 = 554 603-25-30 576-25-30 = 521 byte

Chiến lược:

  • Lập danh sách ba lần (d, x, y) cho tất cả các pixel (d là khoảng cách đến trung tâm)
  • sắp xếp danh sách theo khoảng cách
  • bắt đầu với khoảng cách lớn nhất: nếu pixel đó là pixel xanh lục duy nhất trong một vùng lân cận nhỏ, hãy giữ khoảng cách của nó trong danh sách L, nếu không thì làm đen nó
  • tính điểm từ danh sách khoảng cách L

Đầu ra là một bộ ba (điểm, bỏ lỡ, Xs), vd (52,1,1) cho hình ảnh thử nghiệm.

Chương trình có thể thất bại nếu pixel của một vòng tròn gần trung tâm nhất nằm trong 3 pixel của một vòng tròn khác.

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

Một mẹo: all idgiống như and.also, bạn có thể thực hiện jvới các mẫu bảo vệj n m|PixelRGBA8 0 255 0 _<-getColor n m v=0<1|0<1=0>1
tự hào

@proudhaskeller: Vâng, cảm ơn!
nimi

2

Toán học - 371 386 - 25 = 361

Một giải pháp tối ưu hơn. Tính toán câu trả lời nhanh hơn nhiều so với giải pháp Python của tôi.

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}&

Python với PIL - Một giải pháp tầm thường và không tối ưu, 961 byte

Điều này chỉ đơn giản là cố gắng thể hiện một cách tiếp cận ngớ ngẩn trong việc giải quyết vấn đề. Phải mất ~ 2 phút để chạy hai trường hợp thử nghiệm đầu tiên và ~ 20 phút để chạy lần thứ ba trên hệ thống của tôi vì nhanh chóng được tạo ra, sử dụng nhiều tài nguyên khủng khiếp và trình phát hiện vòng tròn phức tạp về mặt thuật toán. Mặc dù vậy, nó đáp ứng yêu cầu, mặc dù nó chắc chắn không được đánh gôn tối ưu. Càng có nhiều màu xanh trên hình ảnh, thời gian chạy càng lâu.

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

Lấy một đối tượng hình ảnh PIL và trả về điểm số.

Các bước cần thực hiện:

  1. Cô lập vòng tròn màu xanh lá cây (không hiệu quả)
    • Tìm tất cả hàng xóm của một số pixel n , nếu có pixel màu xanh lục thì thêm chúng vào vòng tròn
    • Xác định phác thảo thô bằng cách lọc ra các pixel có 8 lân cận
  2. Vẽ một đại diện mục tiêu
    • Tạo một khung vẽ trống
    • Vẽ một nền màu độc đáo (dễ thực hiện bỏ lỡ)
    • Vẽ các hình elip lồng nhau với màu sắc độc đáo
  3. Xác định vùng ghi điểm của mỗi vòng tròn bằng cách xác định (các) màu của mục tiêu nằm bên dưới vòng tròn
  4. Chọn mức cao hơn của các khu vực cho điểm (nếu nhiều) và thêm số điểm vào tổng số
  5. Trả lại tổng số

Hàm Python của bạn acó thể được viết là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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.