Odwróć planszę Saper


32

Saper to popularna gra komputerowa, w którą prawdopodobnie zmarnowałeś czas, grając, w której próbujesz odsłonić komórki, które są kopalniami w prostokątnej siatce na podstawie wskazówek o tym, ile sąsiednich min ma każda komórka niemina. A jeśli jeszcze tego nie grałeś, zrób to tutaj .

Sprytny matematyczny fakt o siatce Saperów (aka board) jest taki, że:

Plansza i jej uzupełnienie mają taką samą całkowitą liczbę kopalni . ( Dowód )

To znaczy, że jeśli masz całkowicie ujawnioną siatkę Saper, suma wszystkich liczb na tej siatce, tj. Suma kopalni , będzie równa sumie kopalni uzupełnienia siatki, która jest siatką, w której każda kopalnia została zastąpiona z nie-kopalnią, a każda nie-kopalnia zastąpiona kopalnią.

Na przykład dla siatki Saper

**1..
34321
*2**1

suma kopalni wynosi 1 + 3 + 4 + 3 + 2 + 1 + 2 + 1 = 17.

Uzupełnieniem siatki jest

24***
*****
3*44*

która ma moje kopie łącznie 2 + 4 + 3 + 4 + 4 = 17 ponownie.

Napisz program, który pobierze dowolną siatkę Saper w postaci tekstowej, gdzie *reprezentuje minę i 1poprzez 8reprezentuje liczbę min sąsiadujących z komórką inną niż kopalnia. Możesz użyć .lub 0lub (spacji) do reprezentowania komórek bez sąsiadów kopalni, twój wybór. Możesz założyć, że siatka wejściowa zostanie poprawnie oznaczona, tj. Każda komórka nie będąca kopalnią będzie dokładnie oznaczać całkowitą liczbę min bezpośrednio przylegających do niej prostopadle lub ukośnie.

Twój program musi wydrukować uzupełnienie sieci w tym samym formacie (przy użyciu tego samego ., 0lub , jak oczekiwano na wejściu).

Najkrótszy kod w bajtach wygrywa.

  • Zamiast programu możesz napisać funkcję, która pobiera siatkę wejściową jako ciąg i wypisuje lub zwraca siatkę dopełniacza.
  • Końcowy znak nowej linii na wejściu lub wyjściu jest w porządku, ale nie powinno być żadnych innych znaków poza tymi, które tworzą siatkę.
  • Możesz założyć, że siatka 1 × 1 będzie najmniejszym wejściem.

Przypadki testowe

Wszystkie dane wejściowe i wyjściowe można zamienić, ponieważ uzupełnieniem uzupełnienia jest pierwotna siatka. Siatki mogą być również obracane w dalszych przypadkach testowych.

Wkład:

111
1*1
111

Wydajność:

***
*8*
***

Wkład:

.

Wydajność:

*

Wkład:

*11*1.1**1...1***1.....1*****1..........

Wydajność:

1**2***11*****1.1*******1...1***********

Dane wejściowe: ( Wytnij przykład węzła )

**212*32
333*33**
1*22*333
222222*1
*33*2232
2**22*2*

Wydajność:

24***4**
***7**64
*8**7***
******8*
4**7****
*33**5*3

TI-BASIC nie może zaakceptować pustej linii danych wejściowych. Czy użycie ogranicznika końcowego (na przykład ?) w wierszu po ostatnim wierszu płyty jest dopuszczalne, czy też mogę przenieść liczbę wierszy wejściowych przez wiersz poleceń?
lirtosiast

@ThomasKwa Ogranicznik końca brzmi dobrze dla TI-BASIC i innych języków, które mają dziwne ograniczenia nowego wiersza.
Calvin's Hobbies

Odpowiedzi:


12

Pyth, 39 38 bajtów

j.es.eh-+K\*l-s:RtWYY+Y2:+K.zk+k3KZb.z

Wypróbuj online: demonstracja

Główny algorytm jest naprawdę prosty. Po prostu iteruję każdą komórkę, biorę otaczające pudełko 3x3 (lub mniejsze, gdy komórka znajduje się na granicy) i drukuję gwiazdę lub liczbę gwiazd niebędących gwiazdami w tym pudełku.

Wyjaśnienie:

j.es.eh-+K\*l-s:RtWYY+Y2:+K.zk+k3KZb.z  implicit: .z = list of input strings
 .e                                 .z  map each index k, line b of .z to:
    .e                             b      map each index Y, char Z of b to:
         K\*                                assign "*" to K
                         +K.z               insert K at the front of .z
                        :    k+k3           slice from k to k+3
               :RtWYY+Y2                    take the slice from Y-1 or 0 
                                            to Y+2 for each line
              s                             join, this gives the 3x3 rectangle
                                             (or smaller on the border)
             -                   K          remove all "*"s
            l                               take the length
        +K                                   "*" + ^
       -                          Z         remove Z from this string
      h                                     and take the first char
                                            (if cell=mine take the number, 
                                             otherwise take the number)
  s                                       join the chars of one line
j                                       join by newlines

Naprawdę fajnie, +1
MKII

22

CJam, 58 57 bajtów

0WX]2m*qN/{'*f+z}2*f{\~@m<fm<W<}:..+{W<{_'*#'*@'*-,?}/N}/

Dane wejściowe nie powinny kończyć się wierszem. Dane wyjściowe zawierają 0komórki bez pobliskich min.

Wypróbuj online w interpretatorze CJam .

Pomysł

Zaczynamy od wypełnienia macierzy wejściowej jednym wierszem i jedną kolumną gwiazdek.

Do wprowadzenia

*4*
**2

to skutkuje

*4**
**2*
****

Teraz generujemy wszystkie możliwe modyfikacje, które wynikają z obracania wierszy i kolumn o 0, -1 lub 1 jednostkę w górę / w lewo:

*4** **** **2* **4* **** ***2 4*** **** *2**
**2* *4** **** ***2 **4* **** *2** 4*** ****
**** **2* *4** **** ***2 **4* **** *2** 4***

Odrzucamy „miejsca wypełnienia” z każdego obrotu, tj.

*4* *** **2 **4 *** *** 4** *** *2*
**2 *4* *** *** **4 *** *2* 4** ***

i utwórz pojedynczą macierz, łącząc odpowiednie znaki każdego obrotu:

******4** 4*******2 **24*****
*******4* *4****2** 2***4****

Pierwszym znakiem każdej pozycji jest jej oryginalny charakter.

  • Jeśli jest to gwiazdka, należy ją zastąpić gwiazdką.

  • Jeśli jest to gwiazdka, liczba nie-gwiazdek w tym ciągu to liczba sąsiednich min.

Jak to działa

0WX]2m*   e# Push the array of all vectors of {0,-1,1}^2.
qN/       e# Read all input from STDIN and split at linefeeds.
{'*f+z}2* e# Append a '*' to each row and transpose rows with columns. Repeat.
f{        e# For each vector [A B], push the modified input Q; then:
  \~      e#   Swap Q with [A B] and dump A and B on the stack.
  @m<     e#   Rotate the rows of Q B units up.
  fm<     e#   Rotate each row of the result A units left.
  W<      e#   Discard the last row.
}         e# This pushes all nine rotations with Manhattan distance 1.
:..+      e# Concatenate the corresponding characters for each position.
{         e# For each row:
  W<      e#   Discard the character corresponding to the last column.
  {       e#   For each remaining string:
    _'*#  e#     Find the first index of '*' in a copy.
    '*    e#     Push '*'.
    @'*-, e#     Count the non-asterisks in the string.
    ?     e#     Select '*' if the index is non-zero, the count otherwise.
  }/      e#
  N       e#   Push a linefeed.
}/        e#

7
Boję się - to niesamowite.
Deusovi

Proszę pana, właśnie zepsułeś system. +1! Czy mogę zapytać, gdzie znalazłeś tę teorię?
GamrCorps

9
@IonLee To jest wszystko ja. To naprawdę bardzo prosty pomysł: zamiast sprawdzać komórki wokół danej komórki, przesuwamy całą siatkę i obserwujemy, co wpada do komórki.
Dennis

Brawo! Nigdy bym o tym nie pomyślał.
GamrCorps

7

Ruby, 119

->s{w=1+s.index('
')
s.size.times{|c|t=0;9.times{|i|(s+?**w*2)[c+i/3*w-w+i%3-1]<?0||t+=1}
print [t,?*,'
'][s[c]<=>?*]}}

Ungolfed w programie testowym:

f=->s{
  w=1+s.index("\n")                          #width of board
  s.size.times{|c|                           #iterate through input
    t=0;                                     #number of digits surrounding current cell
    9.times{|i|                              #iterate through 3x3 box (centre must be * if this ever gets printed.)
      (s+"*"*w*2)[c+i/3*w-w+i%3-1]<"0"||t+=1 #copy of s has plenty of * appended to avoid index errors
    }                                        #add 1 every time a number is found.
  print [t,"*","\n"][s[c]<=>"*"]             #if * print t. if after * in ACSII it's a number, print *. if before, it's \n, print \n
  }
}


f['**212*32
333*33**
1*22*333
222222*1
*33*2232
2**22*2*']

2

Oktawa, 76

m=@(s)char(conv2(b=(cell2mat(strsplit(s)'))~='*',ones(3),'same').*~b-6*b+48)

Wyjaśnienie

  • Konwertuj ciąg wejściowy na macierz ciągów, używając strspliti cell2mat.

  • Uzyskaj macierz logiczną zawierającą miejsce, w 1którym nie ma *oryginalnej macierzy.

  • Przekonaj się dzięki matrycy 3x3 z jedynkami.

  • Zamaskuj go odwrotną macierzą logiczną i umieść *w miejscu maski.

  • Uwaga: Komórki bez sąsiadów kopalni są reprezentowane jako 0.

Wykonanie

>> m(['**100' 10 '34321' 10 '*2**1'])   %// `10` is newline
ans =

24***
*****
3*44*

>> m(['24***' 10 '*****' 10 '3*44*'])
ans =

**100
34321
*2**1
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.