掃海艇の手がかりを記入する


54

マインスイーパは人気のパズルゲームで、どのタイルが「地雷」であるかを、それらのタイルをクリックせずに発見する必要があります。各タイルは地雷(で表される*)または手掛かり、つまり8つの隣接するタイルのうちどれだけが地雷であるかを表す0から8までの数字です。今日のあなたの仕事は、鉱山を含むボードを取り、すべての手がかりを埋めることです。たとえば、5つの地雷がある次の5x4ボードを見てください。

 *  
*  * 
  *  
    *

手がかりを入力すると、ボードは次のようになります。

2*211
*33*1
12*32
0112*

詳細

完全なプログラム、またはスペースとアスタリスクのみを含む文字のグリッドを取り込み、各スペースが隣接する鉱山(アスタリスク)の数で置き換えられる別のグリッドを出力する関数を作成する必要があります。これらはいずれも、グリッドに受け入れられる形式です。

  • 改行を含む文字列

  • 文字/単一文字列の2Dリスト

  • 文字列のリスト

グリッドは少なくとも 1x1であると仮定できますが、グリッドはすべて地雷またはすべてのスペースである可能性があります。

入力グリッドには常に適切な数のスペースが埋め込まれます。いつものように、これはなので、標準の抜け穴が適用され、バイト単位の最短回答が勝ちます!

サンプルIO

空白を確認できるように、すべてのサンプルIOを角括弧で囲んで示します。

Input:
[    * ]
[*     ]
[      ]
[      ]
[  **  ]
[ *  * ]

Output:
[1101*1]
[*10111]
[110000]
[012210]
[12**21]
[1*33*1]

Input:
[****]
[****]

Output:
[****]
[****]

Input:
[   ]
[   ]
[   ]
[   ]

Output:
[000]
[000]
[000]
[000]

Input:
[*   ]
[**  ]
[    ]
[   *]

Ouput:
[*310]
[**10]
[2221]
[001*]

Input:
[**    ]
[*    *]
[  *   ]
[      ]
[*     ]
[****  ]

Output:
[**1011]
[*4211*]
[12*111]
[121100]
[*43210]
[****10]

Input:
[     *    ]
[        * ]
[     *    ]
[**   ***  ]
[      *** ]
[          ]
[       ** ]
[  * *     ]
[*      ** ]
[       ** ]

Output:
[00001*1111]
[00002221*1]
[22102*4321]
[**102***31]
[221013***1]
[0000013542]
[0112111**1]
[12*2*12442]
[*212112**2]
[1100002**2]

2
参考までに、私はすべてのサンプルIOを手作業で作成したので、そこにいくつかの小さなエラーがある可能性があります。何か問題があると思われる場合はお知らせください。できるだけ早く修正を試みます。
DJMcMayhem


1
グリッドを非正方形にすることはできますか?
トンホスペル

地雷は別のキャラクターで表現できますか?
-Akangka

@ChristianIrwanいいえ、鉱山は常にアスタリスクになります。
DJMcMayhem

回答:


21

MATL18 17バイト

テストケース6の入力を修正してくれた@ mbomb007に感謝

32>t3Y6Z+-6b(48+c

入力は次の形式の2D char配列です。

[' *   '; '*  * '; '  *  '; '    *']

オンラインでお試しください!

テストケース:123456

説明

32>      % Input 2D char array implicitly. Transform it into a 2D logical
         % array with asterisk replaced by true and space by false
t        % Duplicate
3Y6      % Push [1 1 1; 1 0 1; 1 1 1]. This defines the neighbourhood
Z+       % 2D convolution, keeping size. Gives the number of neighbouring
         % mines for each position
-6       % Push -6
b        % Bubble up in stack
(        % Assign -6 to the entries indicated by the logical array, i.e.
         % to the positions that originally contained asterisks 
48+      % Add 48. This transforms each number of neighbouring mines
         % into its ASCII code, and -6 into 42 (ASCII code of asterisk)
c        % Convert to char. Display implicitly

1
ワオ。それは印象的です。
BladorthinTheGrey

2
テストケース6を取得すると、実際のゲームをプレイするのに腹が立ちます。
魔法のタコUr

どうして?テストケース6が最も現実的です。
WBT

@carusocomputingテストケース2を取得すると、さらに腹が立つでしょう。:P
DJMcMayhem

10

JavaScript(ES6)、114 96バイト

a=>a.map((s,i)=>s.replace(/ /g,(_,j)=>g(k=>(s=a[i+k])?g(k=>s[j+k]>' '):0)),g=f=>f(-1)+f(0)+f(1))

編集:@ETHproductionsのアイデアのおかげで18バイトを節約しました。


インデックスが非スペースであるかどうかをチェックする関数を定義することで、束を節約できると思いますa=>a.map((s,i)=>s.replace(/ /g,(_,j)=>a.slice(i-!!i,i+2).reduce((t,s)=>t+(q=i=>s[i+j]>' ')(-1)+q(0)+q(1),0)))
。– ETHproductions

@ETHproductions私はあなたのアイデアを極端に取りました...私は通常、関数パラメーターを書くことができません!
ニール

7

R、127 112バイト

function(M){a=nrow(M);for(i in seq(M))if(M[i]!="*")M[i]=sum(M[pmax(i+c(-1,1,-a+-1:1,a+-1:1),0)]=="*",na.rm=T);M}

@gtwebbと@ sebastian-cの改善に感謝します。

注目すべき点:

行列はRのベクトルです。要素を取得するために2次元のインデックスを作成する必要はありません。

seq(M)と同じ「長さ」(行x列)のシーケンスを返しますM

Rで正と負の抽出インデックスを混在させることはできません。M[-3]正当なRコードですが、望ましいものではありません。

入力はR行列の形式です。いくつかの例:

> M <- matrix("",5,5)
> M[3,3] <- "*"
> f(M)
     [,1] [,2] [,3] [,4] [,5]
[1,] "0"  "0"  "0"  "0"  "0" 
[2,] "0"  "1"  "1"  "1"  "0" 
[3,] "0"  "1"  "*"  "1"  "0" 
[4,] "0"  "1"  "1"  "1"  "0" 
[5,] "0"  "0"  "0"  "0"  "0" 
> M[2,2] <- "*"
> f(M)
     [,1] [,2] [,3] [,4] [,5]
[1,] "1"  "1"  "1"  "0"  "0" 
[2,] "1"  "*"  "2"  "1"  "0" 
[3,] "1"  "2"  "*"  "1"  "0" 
[4,] "0"  "1"  "1"  "1"  "0" 
[5,] "0"  "0"  "0"  "0"  "0" 
> M[3,2] <- "*"
> f(M)
     [,1] [,2] [,3] [,4] [,5]
[1,] "1"  "1"  "1"  "0"  "0" 
[2,] "2"  "*"  "3"  "1"  "0" 
[3,] "2"  "*"  "*"  "1"  "0" 
[4,] "1"  "2"  "2"  "1"  "0" 
[5,] "0"  "0"  "0"  "0"  "0" 
> 

1
T代わりにを使用して、いくつかの文字を切り取ることができTRUEます。私もあれば機能の一つオフいくつかのブレースをスライドすることで管理:f=function(M){a=nrow(M);b=ncol(M);for(i in seq(M))if(M[i]!="*")M[i]=sum(M[pmax(i+c(-1,1,-a+-1:1,a+-1:1),0)]=="*",na.rm=T);M}
セバスチャン-C

1
定義してb=ncol(M)から使用しないでください。
gtwebb

4つの文字を削る(およびベクトル化する)ことができます。— M->{a=nrow(M);p=M=='*';M[]=ifelse(p,'*',sapply(seq(M),i->sum(p[pmax(i+c(-1,1,-a+-1:1,a+-1:1),0)],na.rm=T)))}しかし、これは再定義された<-ラムダを必要とするため、少し不正です。klmr/ functional / lambdaを
Konrad Rudolph

@Konradの面白いアイデアですが、ベースRに感謝します!
JDL

6

Java、190バイト

編集:

  • -6バイトオフ。@Froznに感謝
  • -1バイトオフ。私のおかげで:)
  • -1バイトオフ。また、いくつかの間違いを見つけました。@Kevin Cruijssenに感謝

スニペット

c->{for(int x,y,j,i=-1;++i<c.length;)for(j=-1;++j<c[0].length;){if(c[i][j]<33){c[i][j]=48;for(x=i-2;++x<i+2;)for(y=j-2;++y<j+2;)try{if(c[x][y]==43)c[i][j]++;}catch(Exception e){}}}return c;}

ゴルフをしていない:

public class Main{
  public static char[][] minesweeper(char[][] woclues){
    for(int i = 0; i < woclues.length ; i++){
      for(int j = 0; j < woclues[0].length ; j++){
        if( woclues[i][j] == ' '){
          woclues[i][j] = '0';
          for(int x = i - 1; x < i + 2 ; x++){
            for(int y = j - 1; y < j + 2 ; y++){
              try{
                if(woclues[x][y] == '*'){
                  woclues[i][j]++;
                }
              }catch( ArrayIndexOutOfBoundsException e){}
            }
          }
        }
      }
    }
    return woclues;
  }
  public static void main(String[]args){
    char[][] in = new char[args.length][args[0].length()];
    for(int i = 0; i < args.length;i++){
      in[i]=args[i].toCharArray();
    }
    for(char[] c:minesweeper(in)){
      System.out.println(new String(c));
    }
  }
}

できた。


char値をASCII値と比較できます。ASCII値はほとんどの場合短くする必要があります。また、次の宣言を組み合わせることができますx,y,i,j
Frozn

私はすでにやったc[i][j]==32というように、ちょうどUngolfed部分でそれらを変更
ローマGRAFを

そして、私はPhytonより背が低いです。少なくとも!
ローマングラフ

改変されていないコードは正しいですか?最初のテストケースでは、次を出力します0000*1\n*10011\n110000\n000000\n00**10\n0*22*1。ideone.comテストリンクを追加できますか?編集:また、しない限り、私は何か間違ったことをやっている自分は、あなたのgolfedコード出力:ssss0s\n0sssss\nssssss\nssssss\nss00ss\ns0ss0s最初のテストケースのために(それがすべて置き換えられた*ゼロで...):S
ケビンCruijssen

編集済み。私の貧弱なインターネットがそれを許すとすぐに、私はテストリンクを追加します。
ローマングラフ

5

JavaScript(ES6)、107

文字列の配列としての入出力

f=l=>l.map((r,i)=>r.replace(/ /g,(c,j)=>(s=r=>(c+r).substr(j,3).split`*`.length,s(l[i-1])+s(l[i+1])+s(r)-3)))

注意関数sが範囲外リストLの要素で呼び出される場合、パラメータがaあるundefinedc+aもたらす" undefined"のJavaScriptの風変わりな変換規則のおかげ

より読みやすい

l=>
  l.map(
    (r,i) =>
      r.replace(/ /g, (c,j) =>
        (
          s = a => (c+a).substr(j,3).split`*`.length,
          s(l[i-1])+s(l[i+1])+s(r)-3
        )
      )
  )

5

Python 2、138バイト

def f(s):w=s.find('\n')+1;print''.join([c,`(s[i-(i>0):i+2]+(w*' '+s)[i-1:i+2]+s[i-1+w:i+2+w]).count('*')`][c==' ']for i,c in enumerate(s))

次のfような入力文字列を受け入れる関数を定義します

"  *\n** \n*  \n"

文字列をSTDOUTに出力します:

23*
**2
*31

1
列挙を2(enumerate(s,2))から開始し、すべての出現をi + 2with iおよびi - 1with で置き換えますi - 3。これにより、数バイトが削減されます。
ロベルトボンバレット16年

5

JavaScriptの(ES6)186の 182 177 161 152バイト

f=a=>{for(s='',y=a[0].length;y--;)for(s=`
`+s,x=a.length;x--;)(k=>{for(t=0,i=9;i--;)t+=(a[x+i%3-1]||[])[y+i/3-1|0]==k;s=(a[x][y]<k?t:k)+s})`*`;return s}

更新

以下のための上記のコード" *"戻ります"2*"。これは、次のスクリプトで修正されています。

168 167バイト

f=a=>{for(s='',y=a[0].length;y--;)for(s=`
`+s,x=a.length;x--;)a[x][y]=='*'?s='*'+s:(k=>{for(t=0,j=3;j--;)for(i=3;i--;)t+=(a[x+i-1]||1)[y+j-1]=='*';s=t+s})`*`;return s}

ここで試してみてください。


1
t+=(a[x+i%3-1]||[])[y+i/3-1|0]==k同様の方法で動作し、try/ catch部分を保存する必要があると思います。
アーナルド

1
@アーナウルド。実際、リテラル数のプロパティを読み取ってもエラーはスローされないため、として改善することもできます(a[x+i%3-1]||1)[y+i/3-1|0]
sbisit

4

Haskell、115バイト

z=zip[1..]
x%i=[a|(j,a)<-z x,abs(i-j)<2]
f x=[[head$[c|c>' ']++show(sum[1|'*'<-(%j)=<<x%i])|(j,c)<-z r]|(i,r)<-z x]

f文字列のリストに関数を定義します


3

Python 2、192バイト

Copperのおかげで-3バイト、入力グリッドの変更が許可されている場合は-10 continueバイト、削除してさらに-11バイト、カウンター変数を削除するために-12バイト

def f(L):
 n,S,s=len(L[0]),[0,1,2],[' '];P=[s*(n+2)];K=P+[s+x+s for x in L]+P
 for y in range(len(L)):
    for x in range(n):
     if'*'!=L[y][x]:L[y][x]=`sum(K[y+d][x+e]=='*'for d in S for e in S)`

文字のリストのリストを使用してL、埋め込みバージョンを作成するKため、境界で問題はありません。インデントは

  1. スペース
  2. タブ
  3. Tab + Space
  4. Tab + Tab

使用法:

s=""" *   
*  * 
  *  
    *"""
print s
s=[[c for c in x] for x in s.split('\n')]
f(s)
s='\n'.join([ ''.join(x) for x in s])
print s

1
いくつかのマイナーなゴルフ:セミコロンで区切られた同じ行に最初の3つの変数の割り当てを配置し、インデントを失うことができます。また、を使用if'*'==L[y][x]:してバイトを保存します。

あなたが割り当てた場合r=range;と同じ行にn,S,s、あなたはへの呼び出しを置き換えることにより、5つの文字を保存することができrange(...)r(...)
alexwlchan

やって@alexwlchanこれは2つの*節約できますangeので、8バイトを、しかし、私は追加する必要があります,rし、,range何も得ていないようにも8バイトです。
カールナップ

@KarlNapf Gah、あなたは正しい-私は忘れていたrange
alexwlchan

3

ルビー、112

文字列を受け取って返します。文字列は改行で区切られ、改行で終了する必要があります。

->s{w=1+s=~/\n/
s.size.times{|i|s[i]==' '&&(n=0;9.times{|j|(s+$/*w)[i+j%3-1+j/3*w-w]==?*&&n+=1};s[i])=n.to_s}
s}

テストプログラムで

f=->s{
  w=(s=~/\n/)+1                              #Calculate width.
  s.size.times{|i|                           #For each char in s
    s[i]==' '&&(                             #If it is a space
      n=0                                    #set counter n to 0 and visit
      9.times{|j|                            #a 3x3 square of chars.
        (s+$/*w)[i+j%3-1+j/3*w-w]==?*&&n+=1  #If *, increment n.
      }                                      #(Pad s with w newlines to avoid *'s detected by wraparound.)
      s[i]=n.to_s                            #Write n back to s in string format
    )
  }
s}                                           #Return s.

puts f[
" *   
*  * 
  *  
    *
"]

3

TSQL 292 291バイト

ゴルフ:

DECLARE @ varchar(max)=
' *   
*  * 
  *  
    *';
WITH C as(SELECT x+1i,substring(@,x+1,1)v,x/z r,x%z c FROM master..spt_values CROSS APPLY(SELECT number x,charindex(char(10),@)z)z WHERE type='P'and x<len(@))SELECT @=stuff(@,i,1,z)FROM(SELECT i,(SELECT count(*)FROM C WHERE abs(D.c-c)<2and abs(D.r-r)<2and'*'=v)z FROM C D WHERE''=v)h PRINT @

ゴルフをしていない:

DECLARE @ varchar(max)=
' *   
*  * 
  *  
    *';
WITH C as
(
  SELECT x+1i,substring(@,x+1,1)v,x/z r,x%z c
  FROM master..spt_values
  CROSS APPLY(SELECT number x,charindex(char(10),@)z)z
  WHERE type='P'and x<len(@)
)
SELECT @=stuff(@,i,1,z)
FROM
(
  SELECT
    i,
    (
      SELECT count(*)
      FROM C
      WHERE 
       abs(D.c-c)<2and abs(D.r-r)<2and'*'=v
    )z
  FROM C D
  WHERE''=v
)h
PRINT @

フィドル


;あなたのコードの前には数えますか?数えたようです。
エリックアウトゴルファー

@EriktheGolferはい、WITHの前にスクリプトがあります。コンパイラは、削除されるとエラーを出します。フィドルでアイデアをテストすることが可能です
t-clausen.dk

つまり、一般的なソースのバイトカウントに含めるべきでしょうか。代わりに「Initial STDIN」ステートメントの一部であるように思われるためです。
エリックアウトゴルファー

@EriktheGolfer私は本当に知りません、私はそれが宣言の一部であることができると思います。マスターを除外することもでき ます。スクリプトの先頭にUSEマスターがある場合。しかし、それはフィドルで迷惑なメッセージを与えます。
t-clausen.dk

前の行にセミコロンを入れてみましたが、うまくいきました。最後の行が重要だと思います。
エリックアウトゴルファー

2

ラケット415バイト

(let*((l(string->list s))(g (λ(r c)(if(or(>= r n)(>= c n)(< r 0)(< c 0))#f(list-ref l(+ c(* n r))))))(ng (λ(r c)(let*((h'(-1 0 1))(k(filter(λ(x)x)
(for*/list((i h)(j h)#:unless(= 0 i j))(g(+ r i)(+ c j))))))(count(λ(x)(equal? x #\*))k))))(k(for*/list((i n)(j n))(ng i j)))
(ol(map(λ(x y)(if(equal? x #\*)"*"(number->string y)))l k)))(for((i(* n n))(j ol))(display j)(when(= 0(modulo(add1 i)n))(displayln ""))))

ゴルフをしていない:

(define (f s n)
  (let* ((l (string->list s))
         (get                            ; fn to get value at a (row, col)
          (lambda(r c)                   ; #f if invalid row or col
            (if (or (>= r n)
                    (>= c n)
                    (< r 0)
                    (< c 0))
                #f (list-ref l (+ c (* n r))))))

         (neighbors                      ; fn to count neighboring "*"
          (lambda(r c)
            (let* ((h '(-1 0 1))
                   (u (filter
                       (lambda(x) x)
                       (for*/list ((i h)(j h)
                                   #:unless (= 0 i j))
                         (get (+ r i) (+ c j))))))
              (count (lambda(x)(equal? x #\*)) u))))

         (k (for*/list ((i n) (j n))    ; for each row,col count neighboring "*"
              (neighbors i j)))
         (ol(map (lambda(x y)           ; get outlist- replace blanks with neighboring star count
                   (if(equal? x #\*) 
                      "*"
                      (number->string y)))
                 l k)))

    (for ((i (* n n))(j ol))            ; display outlist
      (display j)
      (when (= 0 (modulo (add1 i) n))
        (displayln "")))))

テスト(列番号が指定された単一の文字列としてリストされます。スペースでも機能します):

(f "----*-*-------------------**---*--*-" 6) 

出力:

1101*1
*10111
110000
012210
12**21
1*33*1

2

PHP、145の 133 132 127バイト

for($s=$argv[1];$s[$p];print$c)if(" "==$c=$s[$p++])for($y=-2;$y++<1;)for($x=$p-3;$x++<$p;)$c+="!"<$s[$x+$y*strpos($s,"\n")+$y];

改行で区切られた単一の文字列として入力を受け取ります。で実行し-rます。

壊す

for($s=$argv[1];$s[$p]; // loop through all characters (including newlines)
    print$c                     // 3. print result
)
    if(" "==$c=$s[$p++])        // 1. if character is space
        for($y=-2;$y++<1;)      // 2. count surrounding asterisk characters
            for($x=$p-3;$x++<$p;)
                $c+="!"<$s[$x+$y*strpos($s,"\n")+$y];

"!">$n=$s[$p]" "==$n=$s[$p]1バイトを保存する代わりに
ヨルグヒュルサーマン

@JörgHülsermannそれは改行を破壊するでしょう。
タイタス

@JörgHülsermann...しかし、トリックはアスタリスクの比較に有効です(新しいバージョン)
Titus

2

タートルード、99バイト

(リンクを忘れてしまいました:|)

各行を角かっこで囲んで入力します

Turtlèdは複数行の入力を受け付けることができないため、最後の行の後に、|入力の終了をシグナルに書き込みます

ブラケットの不一致は、オープンブラケットがブラケットコマンドの一部として次の文字を解析するためです。

[|!.([[]r+.][[l]d)][ u]d[|[]r( #012345678#l(*+)u(*+)r(*+)r(*+)d(*+)d(*+)l(*+)l(*+)ur.)]' [[l]' d]' 

オンラインでお試しください!

仕組み(一般的な説明):

までは|入力されて、それが各行の終わりを認識しやすくするためのブラケットで、各行の入力を書き出します。それが起こった後、入力の最上部に戻ります。入力の各文字を通過します。それがスペースである場合、それはスペースの周りを見て、見つけた各爆弾のカウンターに1を追加します。各行の後に、括弧を削除します。最後の行に到達すると、|で その中で、停止し、|を削除します。グリッドは暗黙的に印刷されます。


0

C、152の 150 147 145バイト

i,j,r,c;f(B,R,C)char**B;{for(i=R*C;i--;)for(j=9;j--;){char*b=B[i/C]+i%C;r=i/C+j/3-1;c=i%C+j%3-1;r<0|c<0|r/R|c/C|*b&8||(*b=16|*b+(B[r][c]==42));}}

入力は文字の2次元配列の形式で、その後に行と列の数が続きます。結果はインプレースで返されます。

(ほとんど)ゴルフをしていない:

i, j, r, c;
f(B, R, C) char **B; {
    for (i = R*C; i--;)
        for (j = 9; j--;) {
            char *b = B[i/C] + i%C;
            r = i/C + j/3 - 1;
            c = i%C + j%3 - 1;
            r < 0 | c < 0 | r / R | c / C | *b & 8 ||
                (*b = 16 | *b + (B[r][c] == 42));
        }
}

アプローチは簡単です。各位置をループし、その隣をループし、すべてのアスタリスクを加算します。2つのビットレベルのトリックがあります。

  • セルがアスタリスクかどうかを判断するときは、8桁のビットが設定されているかどうかを確認できます。これは、セル内の数が8(最大セル値)未満でなければならないためです。

  • 16をORすることで、スペース文字をゼロ文字に変換できます。

編集:の代わりにを使用/して、2バイトをオフにゴルフ>=

編集:ループの方向を逆にしてさらに5バイト。


0

C#、341バイト

間違いなく短縮できるナイーブな実装。

s=>s=="*"?1:0;s=>{for(int i=0,j,n,l=s.Length,c=s[i].Length;i<l;++i)for(j=0;j<c;++j)if(s[i][j]!="*"){n=0;if(i>0){n+=a(s[i-1][j]);n+=j>0?a(s[i-1][j-1]):0;n+=j+1<c?a(s[i-1][j+1]):0;}n+=a(s[i][j]);n+=j>0?a(s[i][j-1]):0;n+=j+1<c?a(s[i][j+1]):0;if(i+1<l){n+=a(s[i+1][j]);n+=j>0?a(s[i+1][j-1]):0;n+=j+1<c?a(s[i+1][j+1]):0;}s[i][j]=n+"";}return s;};

0

Python 2、183バイト

def s(m):
 j=m.find('\n')+1;q='q'*j*2;m=list(q+m+q)
 for i in range(len(m)):
  if m[i]==' ':m[i]=`sum([m[k+i]=='*'for k in [-j-1,-j,-j+1,-1,1,j-1,j,j+1]])`
 return''.join(m)[j*2:-j*2]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.