Tìm những con đường!


10

Bạn phải viết một chương trình hoặc chức năng.

Đầu vào là một "bản đồ" các con số. Bạn có thể chọn lấy bản đồ dưới dạng một chuỗi với các ký tự dòng mới ( \n) hoặc một chuỗi các chuỗi 2D.

Tất cả các bản đồ có 5 ký tự cho 5 ký tự và các ký tự luôn là các chữ số lớn hơn 0 hoặc dấu cách.

Dưới đây là một ví dụ về bản đồ:

12 45
11233
  233
    1
2 899

Nhiệm vụ của bạn là tìm các thành phần được kết nối trong bản đồ. Một thành phần hợp lệ là một chuỗi gồm ít nhất ba chữ số giống hệt nhau theo chiều ngang và / hoặc chiều dọc ( không theo đường chéo ) ( không phải dấu cách ). Sau đó, bạn sẽ cần thay thế các ký tự của các thành phần được kết nối hợp lệ bằng xs và in hoặc trả về kết quả đó.

Vì vậy, đầu ra cho ví dụ trên sẽ là:

x2 45
xx2xx
  2xx
    1
2 899

Đây là một trường hợp thử nghiệm khác (nhờ Martin Ender):

Input:
2   3
    4
 1  5
111 6
11  7

Output:
2   3
    4
 x  5
xxx 6
xx  7

Đây là mã golf để mã ngắn nhất trong byte thắng!



Được xây dựng cho phép?
Ioannes

@Jannannes, vâng.
Daniel

Câu trả lời:


1

JavaScript (ES6), 171 161 139 137 136 133 132 byte

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>

Đây là bản dịch câu trả lời Python của tôi. I / O là mảng ký tự.

Quá tệ, không có cách nào hiệu quả để làm sum...


5

Python 3, 238 237 200 199 192 181 byte

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

Xác định một hàm f(a)lấy đầu vào là một mảng các ký tự và trả về cùng một mảng được sửa đổi. ( Mảng ký tự được chấp nhận dưới dạng chuỗi theo mặc định. )

Ung dung với lời giải thích

Mã sửa đổi là đệ quy, nhưng hoạt động như nhau.

# 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

Tắt 2 byte để đánh bại giải pháp toán học ...
FlipTack

1
@FlipTack Vâng. Tôi không nghĩ rằng nó đang xảy ra ngày hôm nay, nhưng tôi đang dịch nó sang JS và nó có vẻ đầy hứa hẹn.
PurkkaKoodari

3

Ruby, 304 byte

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

sử dụng ví dụ:

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

mã sử dụng lại phương thức 'blot' để tính toán độ dài đường dẫn.

biến / phương thức:

  • f (s): chức năng chuyển đổi chuỗi bản đồ, trả về bản đồ mới với 'x'
  • ps (i): kích thước đường dẫn từ chỉ mục bản đồ i (trong đó x = i% 6, y = i / 6)
  • s: chuỗi đầu vào, các dòng bản đồ được phân tách bằng "\ n"
  • z: bản sao của chuỗi đầu vào
  • b (s, i): Hàm 'blot': ghi 'x' từ chỉ mục bản đồ i qua các đường dẫn
  • @v: mảng 'đã truy cập'

Cố gắng giải thích chi tiết hơn:

tạo một bản sao của chuỗi đầu vào mà chúng ta sử dụng để tìm độ dài của đường dẫn từ bất kỳ điểm đã cho nào trên bản đồ.

z = s.dup

xác định hàm ẩn danh 'ps' (độ dài đường dẫn) (lambda), lấy chỉ số bản đồ i làm đối số. nó trả về độ dài của đường dẫn từ điểm đó. nó thực hiện điều này bằng cách gọi phương thức 'b' (blot) để chèn x 'vào một bản sao của bản đồ gốc và sau đó đếm số x trong chuỗi trả về.

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

phần sau lặp lại qua từng ký tự trong bản đồ (chỉ mục i, ký tự s [i]). nó gọi hàm 'b' (blot) trên vị trí bản đồ i nếu độ dài đường dẫn từ vị trí i lớn hơn 2 và nếu đó không phải là ký tự khoảng trắng hoặc dòng mới.

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

hàm b (blot) lấy chuỗi bản đồ và một chỉ mục làm đối số. nó khởi tạo @v (mảng đã truy cập) và gọi hàm trợ giúp b2.

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

hàm b2 lấy chuỗi bản đồ, vị trí bản đồ (i) và một ký tự trong đường dẫn hiện tại (c). nó tự gọi đệ quy để thay thế các phần chữ số được kết nối bằng ký tự 'x'. nó trả về chuỗi đầu vào (đây là hàm ps có thể gọi scan () trên giá trị trả về).

điều này nếu câu lệnh đang kiểm tra xem vị trí bản đồ (i) đã cho nằm trong giới hạn của chuỗi (0 ... s.size) và ký tự tại s [i] giống với ký tự bắt đầu. cũng @v [i] được kiểm tra để tránh đệ quy vô hạn.

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

đây là bit thay thế ký tự ở chỉ mục (i) bằng ký tự 'x'. nó cũng đánh dấu chỉ số đó khi truy cập.

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

đây là nơi b2 tự gọi nó theo cách đệ quy tìm kiếm đường dẫn. i + 1 là một ký tự bên phải, i-1 là một ký tự bên trái, i + 6 là một hàng xuống (5 chữ số + 1 dòng mới = 6 ký tự), i-6 là một hàng lên.

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

1

C (Ansi), 243 233 179 188 byte

Chơi gôn

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

Với chú thích:

#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*/

}

Đầu vào:

Mong đợi một dòng mới ở đầu và cuối chuỗi.

Ví dụ đầu vào:

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

Kết quả ví dụ:

x2 45
xx2xx
  2xx
    1
2 899

Cập nhật

Làm cho lưới cố định cho phép tôi cạo gần 60 byte.


Tôi đoán tôi có thể lưu như 22 ký tự nếu tôi thay đổi kích thước bản đồ này - tôi sẽ thay đổi nếu tôi tìm thấy bất cứ điều gì khác mà tôi muốn thay đổi
dj0wns

1

Toán học, 180 byte

(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]&

Giải trình:

(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
]&

Hàm thuần túy chấp nhận một 5x5mảng. là ký tự sử dụng riêng 3 byte U+F3C7đại diện cho toán tử chuyển đổi hậu tố \[Transpose].

(f=Flatten@#;p=Partition): Làm phẳng danh sách đầu vào và lưu nó vào f. Đặt p = Partitionvà trả lại nó.

g=p[r,5]: Mảng {{1,2,3,4,5}, ..., {21,22,23,24,25}}(điều này là do rđược đặt thành Range@25).

Join[g=p[r,5],g]: danh sách các hàng và cột của g.

p[#,2,1]&: Hàm thuần túy phân vùng danh sách #thành các danh sách con có độ dài 2chồng chéo 1; tức là danh sách các cặp liền kề trong #.

##&@@p[#,2,1]&: Tương tự như trên trừ nó trả về a Sequence.

##&@@p[#,2,1]&/@Join[g=p[r,5],g]: Bản đồ chức năng trước đó của các hàng và cột của gđể có được danh sách tất cả các mục liền kề trong g. Ruột của tôi nói rằng có một cách ngắn hơn để làm điều này.

r~Graph~Cases[...]: Đồ thị có các đỉnh là các số nguyên 1, ..., 25và các cạnh của nó là các cạnh giữa các mục liền kề gcó cùng các mục tương ứng trong mảng đầu vào (trừ " ")

{a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ": Mẫu phù hợp với {a,b}sao cho f[[a]] == f[[b]](cùng giá trị trong mảng đầu vào) và mẫu không bằng " ". Đặt A = f[[a]]để lưu 1byte.

...:>a<->b: Thay thế mọi trận đấu bằng một cạnh không xác định từ a đến b.

VertexComponent: Trả về thành phần được kết nối của đối số thứ hai (một đỉnh) trong đối số thứ nhất (biểu đồ).

Tr[1^VertexComponent[...]]: Kích thước của thành phần được kết nối. Lưu 1byte từ Length@VertexComponent[...].

If[Tr[...]<3,f[[#]],"x"]&: Hàm thuần túy có một mục #trong g. Nếu kích thước của thành phần được kết nối của nó nhỏ hơn 3, thay thế nó bằng mục tương ứng trong đầu vào. Nếu không, thay thế nó bằng "x".

(f=Flatten@#;p=Partition)[...,5]: Và cuối cùng định hình lại kết quả thành một 5x5mảng.


0

Clojure, 188 byte

Điều này là khá áp đảo: 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))%))

Được gọi như thế này (cần một vectơ 1D ký tự):

(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")))))

Quá lười biếng để đánh lừa nó nhưng về cơ bản for[m(range 30)]truy cập từng chỉ mục và đối với mỗi chỉ mục, bên trong sẽ let[n(for[p[-1 -6 1 6]...(+ m p))]tạo một danh sách từ 0 đến 4 phần tử liệt kê các vị trí có cùng giá trị (1-9) làm vị trí ở giữa. Nếu có nhiều hơn 1 hàng xóm khớp với phần giữa thì có nghĩa là tất cả những thứ này tạo thành một cụm, vì vậy những vị trí đó được thêm vào tập hợp được sử dụng tại (if((set(flatten(...)))i). Nếu chỉ mục iđược tìm thấy từ tập hợp thì \xđược phát ra và giá trị ban đầu khác. Điều đó :when( ... )khá thú vị ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.