10, 10, 10… Umarım?


15

önsöz

Bugün okçulukta 900 tur okurken (toplamda 6 okda 10 uç ve 3 okda 10 uç, toplam 90 ok ve maksimum 900 puan için) bu zorluğu düşündüm.

Okçulukta (FITA tarafından sağlanan bir hedef yüze [ateş ettiğiniz kağıt parçası] çekim yaptığınızı varsayarsak ), her ok için maksimum 10 puan alabilirsiniz. Hedef yüz 10 veya 11 halka azalan çapa sahiptir, iç içe geçmiş. İç halkadan dışarıya doğru, bunlar 10 noktadan bir noktaya kadar sayılır (ve 11 halka durumunda, 10 puan alan ancak kravat kırma vakalarında kullanılan 'X' olarak sayılan en içteki en iç halka vardır. daha yüksek değer). Gözlemek:

FITA Hedef Puanlama

Tabii ki, yukarıdaki resimde görüldüğü gibi FITA Metrik puanlamasına atıfta bulunuyorum. Yakından bakarsanız, puanı işaretlenmemiş soluk noktalı bir çizgi olan en içteki halkayı gözlemleyebilirsiniz. Bahsettiğim 'X', ancak bonus için rekabet etmedikçe buna dikkat etmek zorunda kalmayacaksınız.

Meydan okuma

Bir miktar yeşil içeren (HEX # 00FF00, RGB (0, 255, 0)) bazı büyüklükteki noktalar ve puanı döndürür. Görüntü yeşil noktalardan başka veriler içerebilir , ancak yeşil her zaman aynı renk olacaktır.

Kare görüntünün, en dıştaki halka 4 noktaya (üst orta, alt orta, sağ orta, sol orta) değecek şekilde hedef yüzü temsil ettiğini düşünebilirsiniz. Temsili hedef yüzü her zaman aynı oranda olacaktır, tüm halkalar giriş hedefi görüntüsünün genişliğinin tam olarak 1 / 20'sine sahiptir. Örnek olarak, giriş boyutları 400 piksel x 400 piksel olan bir giriş görüntüsü verildiğinde, her halkanın aşağıda gösterildiği gibi 20 piksel iç genişliğe sahip olduğunu varsayabilirsiniz:

Boktan örnek illüstrasyon

Açıklamalar

  • İki ayrı halkaya dokunursanız, iki halkanın üst kısmı sayılır
  • Bonusu denemedikçe otomatik olarak cevapları veya 'x' durumunu hesaba katmanıza gerek yoktur
  • Hiçbir yeşil dairenin çakışmadığını varsayabilirsiniz.
  • Ayrıca, görüntüde bu yeşil gölgenin başka piksellerinin olmadığını varsayabilirsiniz.
  • Görüntü PNG, JPEG veya PPM biçiminde olacaktır (seçiminiz)
  • Bu sorunun gönderilmesinden önce yazılmışsa harici görüntü işleme kütüphanelerine izin verilir
  • Bir hedefteki tüm yeşil dairelerin aynı çapa sahip olacağını varsayabilirsiniz.
  • Üst üste gelen daireler bonusu için çekim (hah) yapıyorsanız, görüntüdeki en az bir dairenin başka bir üst üste binmediğini varsayabilirsiniz.
  • Standart boşluklara izin verilmiyor

Test senaryoları

Aşağıdaki iki durumun her biri 52 puan almalıdır (veya bonus durumunda, 1 'x' ve 1 özledim ile 52):

Ve bu son test durumu 25 puan almalıdır :

Bonus

  • Eğer cevap sayısını (halkaların dışında) da döndürürseniz -25 bayt
  • Xs miktarını da döndürürseniz -30 bayt (en içteki x'in görüntünün genişliğinin 3 / 100'ü olduğunu ve 10'un da görüntünün genişliğinin 2 / 100'ü olduğunu varsayalım. 1-9 oranlarında değişmeden kalır)
  • Çakışan çevreleri hesaba katarsanız% -35 bayt sayısı

Bu kod golf, yani en az bayt kazanır. İyi eğlenceler!


"Toplam 30 ok için 3 uçta 30 uç"? 90 ok olmamalı mı?
DavidC

@DavidCarraher Ben bunu yayınlarken farkettim. Düzeltildi
globby

Hangi görüntü formatlarını kullanabiliriz? PNG? PPM? Kendi özel biçimimiz? (Ben ilk ikisini varsayar, ancak üçüncü değil, ama sadece açıklama için.)
Kapı tokmağı

Diyelim ki basitlik için JPEG veya PNG @Doorknob 冰
globby

1
Bence en zor bonus en az ödül olan bonus.
Justin

Yanıtlar:


4

İşleme 2, 448-25 = 423 bayt

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

Bir görüntü dosyasındaki okur f yeşil bulana kadar pikseller arasında dolaşır ve ardından sel, merkeze en yakın noktayı belirleyen daireyi doldurur. Sonra bu puanı bir toplam ekler. eğer puan negatifse, bir cevapsız sayıcıya eklenir.

Program 2 sayı çıkaracak, birincisi skor, ikincisi de kaçış sayısı.

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

Eğer işleme alabilirsiniz burada


4

Perl 5 + GD: 225-25 = 200

Düzenleme: Dizine alınmış PNG'lerde yanlış piksel okuma nedenini buldu ve bir geçici çözüm uyguladı. Bazı nedenlerden dolayı GD kütüphanesinde yeşil piksel değerleri (4,254,4) olarak okunur. Bunun soruya dahil olan PNG dosyalarına özgü olup olmadığından emin değilim. Satır kesmeleri aşağıdaki koddan kaldırılabilir.

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

Girişe bir PNG görüntüsü alır ve 2 değer yazdırır: Nokta ve özlüyor sayısı. Örneğin:

perl arch.pl <arch52.png
52 1

Son dakika değişikliği:

Zaten gerekli renk dizinleri tarafından kullanılan getPixelve fillsadece tamsayı kodlanmış RGB değerleri olan gerçek renk modunda , bu nedenle bu dizinler ve dönüştürmek için kullanmak rgbve colorAllocatebu dizinlere gerek yok.

Açıklama:

  • Tüm piksel koordinatlarının listesini oluşturun (boşlukla ayrılmış tamsayı çiftleri olarak).
  • Potansiyel puana göre sırala ( daha kısa olduğu için standart parametreler yerine sub vparametreyi alır $_).
  • Yeşilse en yüksek puan alanlardan başlayarak her piksel için sonuca ekleyin ve sel konumunu siyahla doldurun.

Görüntüler değil; @ bubalou'nun cevabı renkleri doğru şekilde # 00FF00
globby

@globby Görüntüdeki renklerin doğru olduğunu biliyorum (görüntü düzenleme yazılımı ile kontrol ettim), ancak belki de renk alanını kırpmak için aynı meta bilgi var.
nutki

muhtemelen. Bu garip
globi

3

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

Strateji:

  • Tüm pikseller için (d, x, y) üçlülerinin bir listesini yapın (d merkezden uzaklıktır)
  • listeyi mesafeye göre sırala
  • en büyük mesafeden başlayarak: piksel küçük bir mahalledeki tek yeşil piksel ise, L listesindeki mesafesini koruyun, aksi takdirde kararın
  • mesafe listesinden skoru hesapla L

Çıktı bir üçlü (skor, özlüyor, X'ler), örneğin (52,1,1)test görüntüsü için.

Merkeze en yakın dairenin pikseli başka bir dairenin 3 pikseli içindeyse program başarısız olabilir.

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

Bir ipucu: all idandjj n m|PixelRGBA8 0 255 0 _<-getColor n m v=0<1|0<1=0>1
.also

@proudhaskeller: Evet, teşekkürler!
nimi

2

Mathematica'da - 371 386-25 = 361

Daha optimal bir çözüm. Cevabı Python çözümümden çok daha hızlı hesaplar.

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 ile Python - Önemsiz ve optimal olmayan bir çözüm, 961 bayt

Bu sadece problemin çözümünde aptalca bir yaklaşım sergilemeye çalışmaktır. İlk iki test vakasını çalıştırmak ~ 2 dakika ve hızlı bir şekilde, çok kaynak yoğun ve itici bir şekilde algoritmik olarak karmaşık daire dedektörü nedeniyle sistemimde üçüncüsünü çalıştırmak ~ 20 dakika sürer. Buna rağmen, kesinlikle en uygun şekilde golf edilmemiş olsa da, gereksinimleri karşılar. Görüntüde ne kadar yeşil olursa, o kadar uzun sürer.

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

Bir PIL resim nesnesi alır ve skoru döndürür.

Gerekli adımlar:

  1. Yeşil daireleri izole edin (verimsiz)
    • Bazı piksellerin tüm komşularını bulun n, varsa yeşil pikseller varsa onları daireye ekleyin
    • 8 komşusu olan pikselleri filtreleyerek kaba taslak belirleme
  2. Hedef gösterimi çizme
    • Boş bir tuval oluşturma
    • Benzersiz bir renkli arka plan çizin (uygulaması kolay özlüyor)
    • Eşsiz renklerle iç içe elips çizme
  3. Dairenin altında olacak hedefin rengini / renklerini belirleyerek, her dairenin hangi puanlama bölgelerinde olduğunu belirleyin
  4. Puanlama bölgelerinden daha yüksek olanı seçin (çoklu) ve puanı toplama ekleyin
  5. Toplamı döndür

Python işleviniz aşu şekilde yazılabilira=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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.