10、10、10…いいですか?


15

序文

私が今日アーチェリー900ラウンドを撮影していたとき(10が6矢印で終わり、10が3矢印で終わり、合計90の矢印と最大スコア900)、この挑戦​​を考えました。

アーチェリー(FITAが提供するターゲットフェース [あなたが撃つ紙)で射撃していると仮定すると、]矢印ごとに最大スコア10を獲得できます。ターゲットフェースには直径が10から11のリングが含まれ、互いに入れ子になっています。内側のリングから外側に向かって、10ポイントから1ポイントまでカウントされます(11リングの場合、「X」としてカウントされる2番目の最も内側のリングがあります。より高い値)。観察する:

FITAターゲットスコアリング

もちろん、上の図に見られるように、FITAメトリックスコアリングを参照しています。よく見ると、最も内側のリングが見えます。これは色あせた点線で、スコアはマークされていません。それが私が言っていた「X」ですが、ボーナスを競わない限り、それに注意を払う必要はありません。

チャレンジ

入力として完全に正方形の画像(または必要に応じて画像ファイル名)を受け取る関数(または言語が関数をサポートしない場合は完全なプログラム)を作成し、いくつかの緑(HEX#00FF00、RGB(0、 255、0))いくつかのサイズのドット、およびスコアを返します。画像には緑の点以外のデータが含まれている場合がありますが、緑は常にまったく同じ色合いになります。

正方形の画像がターゲットの顔を表しており、最も外側のリングが4つのポイント(上中央、下中央、右中央、左中央)に接触していると想像できます。表現されたターゲット面は常に同じ比率で、すべてのリングの幅は入力ターゲット画像の幅のちょうど1/20になります。例として、入力寸法が400px x 400pxの入力画像が与えられた場合、以下に示すように、各リングの内側の幅は20pxであると想定できます。

安っぽい例図

明確化

  • 2つの別々のリングに触れると、2つのリングのうち高い方がカウントされます
  • ボーナスを試す場合を除き、ミスや「x」ケースを自動的に考慮する必要はありません。
  • あなたは緑の円が重なっていないと仮定することができます
  • また、その緑の色合いの他のピクセルが画像にないことを仮定することができます
  • 画像はPNG、JPEG、またはPPM形式のいずれかです(選択)
  • この質問の投稿前に作成された場合、外部画像処理ライブラリが許可されます
  • 1つのターゲット上のすべての緑色の円の直径が同じであると仮定できます
  • 重複する円のボーナスを撮影する場合(hah)、画像内の少なくとも1つの円に別の重複する円がないと仮定できます。
  • 標準的な抜け穴は許可されていません

テストケース

次の2つのケースでは、それぞれ52を獲得する必要があります(または、ボーナスの場合は、1 'x'と1ミスの52)。

そして、この最後のテストケースは25を記録する必要があります。

ボーナス

  • ミスの数(リングの外)も返す場合は-25バイト
  • Xの量も返す場合は-30バイト(最も内側のxが画像の幅の3/100であり、10が画像の幅の2/100であると仮定します。1-9の比率は変更されません)
  • 重複する円を考慮した場合、-35%バイトカウント

これはコードゴルフであるため、最小バイトが勝ちます。楽しんで!


「30は3つの矢印で終わり、合計で30の矢印」それは90本の矢ではありませんか?
DavidC 14

@DavidCarraher投稿したとおりだと気付いた。修正済み
グロビー14

どの画像形式を使用できますか?PNG?PPM?独自のカスタムフォーマット?(最初の2つを仮定しますが、3番目は仮定しませんが、説明のためだけです。)
ドアノブ

簡単にするために、JPEGまたはPNGだけを例に考えてみましょう@Doorknob冰
globby 14

1
最も難しいボーナスは報酬が最も少ないものだと思います。
ジャスティン14

回答:


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

画像ファイルを読み込むと、緑色が見つかるまでピクセルをループし、次に中心に最も近いポイントを決定する塗りつぶしが円を塗りつぶします。次に、そのスコアを合計に追加します。スコアが負の場合、ミスカウンターに追加されます。

プログラムは2つの数値を出力します。最初の数値はスコアで、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

Perl 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

直前の変更:

とにかく必要なトゥルーカラーモードでは、getPixelとによって使用されるカラーインデックスfill必要は使用しないようにするために、単純に整数RGB値を符号化されrgb、およびcolorAllocateすると、これらのインデックスへ変換します。

説明:

  • すべてのピクセル座標のリストを生成します(スペースで区切られた整数のペアとして)。
  • 潜在的なスコアで並べ替え(使用しsub vてパラメータをとります$_、標準パラメーターの代わりに)。
  • 最も高いスコアのピクセルから開始する各ピクセルが緑の場合、結果に追加され、その場所が黒で塗りつぶされます。

それは画像ではありません。@bubalouの答えは、色を#00FF00として正しく読みました
グロビー14

@globby画像の色が正しいことは知っています(画像編集ソフトウェアで確認しました)が、色空間をトリミングするためのメタ情報も同じかもしれません。
nutki

おそらく。それは奇妙なことです
グロビー14

3

Haskell- 579-25 = 554 603-25-30 576-25-30 = 521バイト

戦略:

  • すべてのピクセルの(d、x、y)トリプルのリストを作成します(dは中心までの距離)
  • 距離でリストを並べ替える
  • 最大距離から開始:ピクセルが小さな近傍で唯一の緑のピクセルである場合、リストLで距離を維持し、そうでない場合は黒くします
  • 距離リストLからスコアを計算する

出力(52,1,1)は、テストイメージなどのトリプル(スコア、ミス、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

ヒント:.also all idと同じで、パターンガードandを使用して実装できますjj n m|PixelRGBA8 0 255 0 _<-getColor n m v=0<1|0<1=0>1
誇りに思っているhaskeller

@proudhaskeller:はい、ありがとう!
nimi

2

Mathematica- 371 386-25 = 361

より最適なソリューション。私のPythonソリューションよりもはるかに高速に答えを計算します。

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 with PIL-些細で最適でないソリューション、961バイト

これは単に、問題を解決する愚かなアプローチを示すことを試みることです。 最初の2つのテストケースを実行するのに2分、システムで3番目のテストケースを実行するのに約2分かかります。それにもかかわらず、それは要件を満たしますが、最適なゴルフではありません。画像上に緑が多いほど、実行に時間がかかります。

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. 合計を返す

Python関数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.