Znajdź ścieżki!


10

Musisz napisać program lub funkcję.

Dane wejściowe to „mapa” liczb. Możesz wybrać mapę jako ciąg znaków z nowymi znakami linii ( \n) lub tablicę ciągów 2D.

Wszystkie mapy mają od 5 znaków do 5 znaków, a znaki są zawsze cyframi większymi niż 0 lub spacjami.

Oto przykład mapy:

12 45
11233
  233
    1
2 899

Twoim zadaniem jest znalezienie połączonych komponentów na mapie. Poprawnym składnikiem jest seria co najmniej trzech identycznych cyfr w poziomie i / lub w pionie ( nie po przekątnej ) ( nie spacje ). Następnie należy zastąpić znaki prawidłowych połączonych komponentów literą xs i wydrukować lub zwrócić ten wynik.

Zatem wynik dla powyższego przykładu byłby następujący:

x2 45
xx2xx
  2xx
    1
2 899

Oto kolejny przypadek testowy (dzięki Martinowi Enderowi):

Input:
2   3
    4
 1  5
111 6
11  7

Output:
2   3
    4
 x  5
xxx 6
xx  7

To jest kod golfowy, więc wygrywa najkrótszy kod w bajtach!



Czy wbudowane są dozwolone?
Ioannes,

@Joannes, tak.
Daniel

Odpowiedzi:


1

JavaScript (ES6), 171 161 139 137 136 133 132 132 bajtów

f=(a,i=0)=>(F=i=>" "<c&&a[i]===c&&(a[i]=n,1+F(i-1)+F(i+1)+F(i-6)+F(i+6)),n=1,c=a[i],n=F(i)>2?"x":c,c=1,F(i),i>28?a:f(a,++i+(i%6>4)))
<!-- this HTML included just for testing --><textarea rows=5 cols=6 oninput="document.querySelector`pre`.innerHTML=this.value.length==29?f([...this.value]).join``:'invalid input'">12 45&#10;11233&#10;  233&#10;    1&#10;2 899</textarea><br/><pre></pre>

To jest tłumaczenie mojej odpowiedzi w języku Python. I / O jako tablice znaków.

Szkoda, że ​​nie ma skutecznego sposobu na zrobienie sum...


5

Python 3, 238 237 200 199 192 181 bajtów

def f(a,i=0):F=lambda i,n,c:29>i>=0!=" "!=a[i]==c!=n and(a.__setitem__(i,n)or-~sum(F(i+j,n,c)for j in[-1,1,-6,6]));j=i+i//5;F(j,[a[j],"x"][2<F(j,1,a[j])],1);i>23or f(a,i+1);return a

Definiuje funkcję, f(a)która pobiera dane wejściowe jako tablicę znaków i zwraca tę samą zmodyfikowaną tablicę. ( Tablice znaków są domyślnie akceptowane jako ciągi znaków ).

Nie obeznany z wyjaśnieniem

Zmodyfikowany kod jest rekurencyjny, ale działa tak samo.

# The main function; fills all continuous nonempty areas of size >= 3 in array
# with x's. Both modifies and returns array.
def findpaths(array):
    # Fills a continuous area of curr_char in array with new_char, starting
    # from index. Returns the number of cells affected.
    def floodfill(index, new_char, curr_char):
        if (0 <= index < 29                   # Check that the position is in bounds
                and (index + 1) % 6 != 0      # Don't fill newlines
                and array[index] != " "       # Don't fill empty cells
                and array[index] == curr_char # Don't fill over other characters
                and curr_char != new_char):   # Don't fill already filled-in cells
            array[index] = new_char # Fill current position
            return (1 # Add neighboring cells' results, plus 1 for this cell
                    + floodfill(index + 1, new_char, curr_char)  # Next char
                    + floodfill(index - 1, new_char, curr_char)  # Previous char
                    + floodfill(index + 6, new_char, curr_char)  # Next line
                    + floodfill(index - 6, new_char, curr_char)) # Previous line
        return 0 # Nothing was filled. The golfed solution returns False here,
                 # but that's coerced to 0 when adding.

    for i in range(25): # Loop through the 25 cells
        i += i // 5 # Accommodate for newlines in input
        curr_char = array[i] # Get the cell's contents
        # Fill the area from the cell with dummies
        area_size = floodfill(i, 1, curr_char)
        # Convert dummies to "x" if area was large enough, back to original otherwise
        fill_char = "x" if 2 < area_size else curr_char
        floodfill(i, fill_char, 1)
    return array

2 bajty na pokonanie rozwiązania matematycznego ...
FlipTack

1
@FlipTack Tak. Nie sądzę, że to się dzisiaj dzieje, ale tłumaczę to na JS i wygląda obiecująco.
PurkkaKoodari

3

Rubinowy, 304 bajty

def b(s,i)
  @v=[]
  b2(s,i,s[i])
end
def b2(s,i,c)
  if(0...s.size)===i&&s[i]==c&&!@v[i]
    @v[i]=s[i]='x'
    [1,-1,6,-6].each{|j|b2(s,i+j,c)}
  end
  s
end
def f(s)
  z = s.dup
  ps = ->(i){b(z.dup,i).scan('x').size}
  (0...s.size).each{|i|b(s, i)if ![' ',"\n"].include?(s[i])&&ps.call(i)>2}
  s
end

przykładowe użycie:

puts f(File.read("map.txt"))

kod ponownie wykorzystuje metodę „blot” do obliczenia długości ścieżki.

zmienne / metody:

  • f (s): funkcja do konwersji ciągu mapy, zwraca nową mapę z 'x'
  • ps (i): rozmiar ścieżki z indeksu mapy i (gdzie x = i% 6, y = i / 6)
  • s: ciąg wejściowy, linie mapy oddzielone „\ n”
  • z: kopia ciągu wejściowego
  • b (s, i): funkcja „blot”: zapisuje „x” z indeksu mapy i nad ścieżkami
  • @v: tablica „odwiedzona”

Spróbuj uzyskać bardziej szczegółowe wyjaśnienie:

zrób kopię ciągu wejściowego, którego używamy do znalezienia długości ścieżki z dowolnego punktu na mapie.

z = s.dup

zdefiniuj funkcję anonimową „ps” (długość ścieżki) (lambda), która przyjmuje indeks mapy i jako argument. zwraca długość ścieżki od tego punktu. robi to poprzez wywołanie metody „b” (blot) w celu wstawienia x na kopii oryginalnej mapy, a następnie zliczając liczbę x w zwracanym ciągu.

  ps = ->(i){b(z.dup,i).scan('x').size}

następna część iteruje każdy znak na mapie (indeks i, znak s [i]). wywołuje funkcję „b” (blot) na pozycji mapy i, jeśli długość ścieżki od pozycji i jest większa niż 2 i jeśli nie jest to spacja lub znak nowej linii.

  (0...s.size).each { |i|
     b(s, i) if ![' ',"\n"].include?(s[i]) && ps.call(i) > 2
  }

funkcja b (blot) przyjmuje jako argument ciąg mapy i indeks. inicjuje @v (odwiedzana tablica) i wywołuje funkcję pomocniczą b2.

def b(s,i)
  @v=[]
  b2(s,i,s[i])
end

funkcja b2 przyjmuje ciąg mapy, pozycję mapy (i) oraz znak w bieżącej ścieżce (c). wywołuje się rekurencyjnie, aby zastąpić połączone sekcje cyfr znakiem „x”. zwraca ciąg wejściowy (jest to po to, aby funkcja ps mogła wywołać scan () na zwracanej wartości).

ta instrukcja if sprawdza, czy podana pozycja mapy (i) mieści się w granicach ciągu (0 ... s.size) i czy znak w s [i] jest taki sam jak znak początkowy. sprawdzane jest również @v [i], aby uniknąć nieskończonej rekurencji.

if(0...s.size) === i && s[i] == c && !@v[i]

jest to bit, który zastępuje znak w indeksie (i) znakiem „x”. oznacza również ten indeks jako odwiedzony.

@v[i] = s[i] = 'x'

w tym miejscu b2 nazywa się rekurencyjnie szukając ścieżki. i + 1 to jeden znak po prawej, i-1 to jeden znak po lewej, i + 6 to jeden wiersz w dół (5 cyfr + 1 nowa linia = 6 znaków), i-6 to jeden rząd w górę.

[1,-1,6,-6].each { |j| b2(s, i+j, c) }

1

C (Ansi), 243 233 179 188 bajtów

Gra w golfa:

#define O o[1][l]
x,n,l,L;r(o,l)char**o;{if(!(l>L|l<0|O<47|O!=x))n++,O++,r(o,l-1),r(o,l+6),r(o,l-6),r(o,l+1),n>2?O='x':O--;}main(g,o)char**o;{for(;(L=30)>l;l++)n=0,x=O,r(o,l);puts(o[1]);}

Z adnotacjami:

#define O o[1][l]
x,n,l,L;      /*-------------------------- Globals*/
r(o,l)char**o;{ /*------------------------ Recursive Function*/
    if(!(l>L|l<0|O<47|O!=x)) /*----------- if this cell is valid(in
                                              range, is a number, is the 
                                              same as the parent number*/
    n++,     /*--------------------------- Increment count*/
    O++,     /*--------------------------- Increment character to mark*/
    r(o,l-1),  /*------------------------- Recurse left*/
    r(o,l+6),  /*------------------------- Recurse down*/
    r(o,l-6),  /*------------------------- Recurse down*/
    r(o,l+1),  /*------------------------- Recurse right*/
    n>2?O='x':O--;  /*---------------------If greater than 3, replace with x, else decrement character*/ 
}          /*----------------------------- Return*/

main(g,o)char**o;{ /*--------------------- Main*/
    for(;l<(L=30);l++){ /*---------------- For entire string and set L*/
        n=0;
        x=O;        /*-------------------- set counter to 0*/
        r(o,l); /*------------------------ Recurse*/
    } /*---------------------------------- End While*/
    puts(o[1]); /*------------------------ Print*/

}

Wejście:

Oczekuje nowej linii na początku i na końcu łańcucha.

Przykładowe dane wejściowe:

./findPaths "
12 45
11233
  233
    1
2 899
"

Przykładowe dane wyjściowe:

x2 45
xx2xx
  2xx
    1
2 899

Aktualizacja

Naprawienie siatki pozwoliło mi zgolić prawie 60 bajtów.


Myślę, że mogę zapisać 22 znaki, jeśli zmienię to na naprawiony rozmiar mapy - zmienię to, jeśli znajdę coś innego, co chcę zmienić
dj0wns

1

Mathematica, 180 bajtów

(f=Flatten@#;p=Partition)[If[Tr[1^VertexComponent[r~Graph~Cases[##&@@p[#,2,1]&/@Join[g=p[r,5],g],{a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ":>a<->b],#]]<3,f[[#]],"x"]&/@(r=Range@25),5]&

Wyjaśnienie:

(f=Flatten@#;p=Partition)[
  If[
    Tr[1^VertexComponent[
        r~Graph~Cases[
          ##&@@p[#,2,1]&/@Join[g=p[r,5],g],
          {a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ":>a<->b
        ],
        #
      ]]<3,
    f[[#]],
    "x"
  ]&/@(r=Range@25),
  5
]&

Czysta funkcja, która akceptuje 5x5tablicę. to 3-bajtowy prywatny znak U+F3C7reprezentujący operator transpozycji Postfiksa \[Transpose].

(f=Flatten@#;p=Partition): Spłaszcza listę wejściową i zapisuje ją f. Ustawia p = Partitioni zwraca.

g=p[r,5]: Tablica {{1,2,3,4,5}, ..., {21,22,23,24,25}}( dzieje się tak, ponieważ rzostaje ustawiona na Range@25).

Join[g=p[r,5],g]: lista wierszy i kolumn g.

p[#,2,1]&: Czysta funkcja #dzieląca listę na podlisty o długości 2z nakładaniem się 1; tj. lista sąsiednich par w #.

##&@@p[#,2,1]&: Tak samo jak powyżej, z tym że zwraca a Sequence.

##&@@p[#,2,1]&/@Join[g=p[r,5],g]: Odwzorowuje poprzednią funkcję wierszy i kolumn w gcelu uzyskania listy wszystkich sąsiednich pozycji w g. Mój żołądek mówi, że jest na to krótszy sposób.

r~Graph~Cases[...]: Wykres, którego wierzchołki są liczbami całkowitymi, 1, ..., 25a których krawędzie są krawędziami między sąsiednimi wpisami, w gktórych te same odpowiadające wpisy w tablicy wejściowej (inne niż " ")

{a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ": Wzorzec, który pasuje do {a,b}tego f[[a]] == f[[b]](ta sama wartość w tablicy wejściowej) i który nie jest równy " ". Ustaw, A = f[[a]]aby zapisać 1bajt.

...:>a<->b: Zamień każde dopasowanie na nieukierunkowaną krawędź od a do b.

VertexComponent: Zwraca połączony składnik drugiego argumentu (wierzchołek) w pierwszym argumencie (wykres).

Tr[1^VertexComponent[...]]: Rozmiar podłączonego komponentu. Zapisuje 1bajt z Length@VertexComponent[...].

If[Tr[...]<3,f[[#]],"x"]&Pure funkcja, która zajmuje pozycję #w g. Jeśli rozmiar podłączonego komponentu jest mniejszy niż 3, zastąp go odpowiednim wpisem na wejściu. W przeciwnym razie zastąp go "x".

(f=Flatten@#;p=Partition)[...,5]: I w końcu przekształć wynik w 5x5tablicę.


0

Clojure, 188 bajtów

To jest przytłaczające: D

#(apply str(map-indexed(fn[i v](if((set(flatten(for[m(range 30)](let[n(for[p[-1 -6 1 6]:when(=(get %(+ m p)0)((set"123456789")(% m)))](+ m p))](if(< 1(count n))(conj n m)[])))))i)\x v))%))

Nazywany tak (wymaga 1D wektora znaków):

(def f #(apply str(...))

(print (str "\n" (f (vec (str "12 45\n"
                              "11233\n"
                              "  233\n"
                              "    1\n"
                              "2 899\n")))))

(print (str "\n" (f (vec (str "2   3\n"
                              "    4\n"
                              " 1  5\n"
                              "111 6\n"
                              "11  7\n")))))

Zbyt leniwy, aby go odholfować, ale w zasadzie for[m(range 30)]odwiedza każdy indeks, a dla każdego indeksu wewnętrzna let[n(for[p[-1 -6 1 6]...(+ m p))]tworzy listę od 0 do 4 elementów, która wymienia lokalizacje, które miały tę samą wartość (1 - 9) co lokalizacja środkowa. Jeśli więcej niż 1 sąsiad pasuje do środkowej części, oznacza to, że wszystkie one tworzą klaster, więc te lokalizacje są dodawane do zestawu używanego w (if((set(flatten(...)))i). Jeśli indeks izostanie znaleziony z zestawu, wówczas \xzostanie wyemitowany, a wartość oryginalna inaczej. To :when( ... )całkiem interesujące ...

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.