Заповніть підказки міномета


54

Сапер - популярна гра-головоломка, де ви повинні виявити, які плитки є "мінами", не клацаючи на них. Кожна плитка є або міною (представленою *), або підказкою, тобто число від 0 до 8, що представляє, скільки з 8 сусідніх плиток є мінами. Ваше завдання сьогодні - взяти дошку, що містить міни, і заповнити всі підказки. Наприклад, подивіться наступну дошку 5х4 з 5 мінами:

 *  
*  * 
  *  
    *

Після заповнення ключів рада буде виглядати приблизно так:

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
FYI, я зробив увесь зразок IO вручну, тому можливо, там є деякі незначні помилки. Повідомте мене, якщо щось відхилиться, і я спробую це якнайшвидше виправити.
DJMcMayhem


1
Чи може сітка бути неквадратичною?
Тон Євангелія

Чи можуть міни представлені іншим персонажем?
Акангка

@ChristianIrwan Ні, міни завжди будуть зірочкою.
DJMcMayhem

Відповіді:


21

MATL , 18 17 байт

Завдяки @ mbomb007 за виправлення вхідних даних тестового випадку 6

32>t3Y6Z+-6b(48+c

Вхід - це двовимірний масив символів у форматі

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

Спробуйте в Інтернеті!

Тестові приклади: 1 , 2 , 3 , 4 , 5 , 6 .

Пояснення

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, би розізлило мене, граючи фактичну гру.
Magic Octopus Urn

Чому? Тестовий випадок 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))

Редагувати: Збережено 18 байт завдяки ідеї від @ETHproductions.


Я думаю, ви можете зберегти купу, визначивши функцію, щоб перевірити, чи не є пробіл індексу: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 за покращення.

Помітні бали:

Матриці є векторами у Р. Для отримання елементів не потрібно 2-D індексування.

seq(M)поверне послідовність тієї ж "довжини" (рядки x стовпці), що і M.

Ви не можете змішувати позитивні та негативні індекси вилучення в Р. 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. Мені вдалося зісковзнути кілька брекетів з однієї з функцій if: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}
sebastian-c

1
Ви визначаєте, b=ncol(M)а потім не використовуєте його, щоб ви могли позбутися цього.
gtwebb

Я можу збрити чотири символи (і vectorise): 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 / функціонал / лямбда
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, які в більшості випадків повинні бути коротшими. Ви також можете поєднати деклараціїx,y,i,j
Frozn

Я вже це робив c[i][j]==32і так далі, і просто змінив їх у частині "Негольфінований"
Роман

І я коротший за Фітон. Принаймні!
Роман Греф

Ви впевнені, що ваш код, який не має волі, правильний? Для першого тесту він виводить: 0000*1\n*10011\n110000\n000000\n00**10\n0*22*1. Не могли б ви додати тестове посилання на ideone.com? EDIT: Крім того, якщо я сам щось не роблю, ваш вихідний код ssss0s\n0sssss\nssssss\nssssss\nss00ss\ns0ss0sдля гольфу: для першого тестового випадку (він замінив усе *нулями ..): S
Кевін Круїссен

Відредаговано. Я додаю тестове посилання, як тільки мій pior internet дозволить мені це.
Роман Ґраф

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є undefinedі c+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 + 2з iі i - 1з i - 3. Це обтрусить пару байтів.
Роберто Бонвальлет

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
@Arnauld. Насправді, читання властивості буквального числа не призведе до помилки, тому його також можна покращити як (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 байти

-3 байти завдяки міді, -10 байт, якщо дозволена зміна вхідної сітки, ще -11 байт шляхом позбавлення continueта ще -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 + пробіл
  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
Кілька другорядних гольфів: ви можете розмістити свої перші три призначення змінних в одному рядку, розділених крапками з комою та втратити відступ. Також використовуйте if'*'==L[y][x]:для збереження байта.
Мідь

Якщо ви призначаєте r=range;на тому самому рядку n,S,s, ви можете зберегти п'ять символів, замінивши виклики 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 Я насправді не знаю, гадаю, це може бути частиною декларації. Можна також виключити master .. якщо на початку сценарію є майстер 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]заощадити один байт
Йорг Гюльсерманн

@ JörgHülsermann Це знищило б лінії.
Тіт

@ JörgHülsermann ... але фокус працює для порівняння зірочок (у новій версії)
Тіт

2

Turtlèd , 99 байт

(віє, я забуваю посилання: |)

Бере введення з дужками навколо кожного рядка

Turtlèd не може приймати багаторядковий вхід, тому після останнього рядка запишіть |на сигнал закінчення введення

Зверніть увагу на невідповідні дужки, оскільки відкриті дужки розбирають наступний знак як частину команди дужок

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

Спробуйте в Інтернеті!

Як це працює (загальний опис):

Поки він |не введений, він записує вхід у кожному рядку з дужками, щоб допомогти йому розпізнати кінець кожного рядка. Після того, як це сталося, воно повертається до верхньої частини введення. Він проходить через кожен символ вхідних даних. Якщо це простір, він оглядає простір, додаючи по одній до лічильника кожну знахідку, яку знайшов. після кожного рядка він видаляє дужки. Коли він потрапить до останнього рядка, з | у ньому він зупиняється та видаляє |. сітка друкується неявно.


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

Введення здійснюється у вигляді двовимірного масиву символів, за яким слідують числа рядків і стовпців. Результат буде повернуто на місце.

(Здебільшого) Безголівки:

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

Підхід прямий - переведіть петлю на кожну позицію, переведіть петлю над сусідами та додайте всі зірочки. Є два фокуси на рівні біт:

  • Коли ми вирішуємо, чи є комірка зірочкою чи ні, ми можемо просто перевірити, чи встановлено біт вісімки, оскільки число в комірці повинно бути менше 8 (максимальне значення комірки).

  • Ми можемо перетворити пробільний символ у нульовий символ, OR-ing 16.

Редагувати: Поле байта два байти, використовуючи /замість >=.

Редагувати: Ще п’ять байтів, змінивши напрямок петель.


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]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.