길을 찾아라!


10

프로그램이나 함수를 작성해야합니다.

입력은 숫자의 '맵'입니다. 줄 바꾸기 문자 ( \n)가 포함 된 문자열 또는 2D 문자열 배열로 맵을 선택할 수 있습니다 .

모든 맵은 5 자 x 5 자이며 문자는 항상 0보다 큰 자릿수 또는 공백입니다.

다음은지도의 예입니다.

12 45
11233
  233
    1
2 899

당신의 작업은지도에서 연결된 구성 요소를 찾는 것입니다. 유효한 구성 요소는 공백이 아닌 수평 및 / 또는 수직 ( 대각선이 아닌 )으로 연결된 동일한 숫자 로 구성된 일련의 집합 입니다. 그런 다음 유효한 연결된 구성 요소의 문자를 s 로 바꾸고 그 결과를 인쇄하거나 반환해야합니다.x

따라서 위 예제의 출력은 다음과 같습니다.

x2 45
xx2xx
  2xx
    1
2 899

다음은 또 다른 테스트 사례입니다 (Martin Ender 덕분에).

Input:
2   3
    4
 1  5
111 6
11  7

Output:
2   3
    4
 x  5
xxx 6
xx  7

이것은 코드 골프이므로 바이트 단위의 가장 짧은 코드가 이깁니다!



내장이 허용됩니까?
안스

@Joannes, 응
Daniel

답변:


1

자바 스크립트 (ES6) 171 161 139 137 136 133 132 바이트

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>

이것은 내 파이썬 답변의 번역입니다. 문자형 배열로서의 I / O.

효율적인 방법이 없습니다 sum.


5

파이썬 3 238 237 200 199 192 181 바이트

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

함수를 정의 f(a)입력을 문자 배열로 가져오고 수정 된 동일한 배열을 반환 를 . ( 문자 배열은 기본적으로 문자열로 허용됩니다. )

설명이 담겨 있지 않은

수정 된 코드는 재귀 적이지만 동일하게 작동합니다.

# 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 바이트 오프 ...
FlipTack

1
@FlipTack 그래. 나는 그것이 오늘날 일어나고 있다고 생각하지 않지만 이것을 이것을 JS로 번역하고 있으며 유망한 것으로 보입니다.
PurkkaKoodari

3

루비, 304 바이트

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

사용법 예 :

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

코드는 'blot'메소드를 재사용하여 경로 길이를 계산합니다.

변수 / 방법 :

  • f (s) : 맵 문자열을 변환하고 'x'로 새 맵을 반환하는 함수
  • ps (i) : 맵 인덱스 i의 경로 크기 (x = i % 6, y = i / 6)
  • s : 입력 문자열, "\ n"으로 구분 된 맵 라인
  • z : 입력 문자열의 사본
  • b (s, i) : 'blot'함수 : 경로를 통해 맵 인덱스 i에서 'x'를 씁니다.
  • @v : '방문한'배열

더 자세한 설명을 시도하십시오.

입력 문자열의 복사본을 만들어지도의 특정 지점에서 경로의 길이를 찾는 데 사용합니다.

z = s.dup

맵 인덱스 i를 인수로 사용하는 'ps'(경로 길이) 익명 함수 (lambda)를 정의합니다. 해당 지점부터 경로의 길이를 반환합니다. 'b'(점) 메소드를 호출하여 원래 맵의 사본에 x를 삽입 한 다음 리턴 된 문자열에서 x의 수를 세면됩니다.

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

다음 부분은 맵의 각 문자를 반복합니다 (인덱스 i, 문자 s [i]). 위치 i의 경로 길이가 2보다 길고 공백이나 개행 문자가 아닌 경우 맵 위치 i에서 'b'(점) 함수를 호출합니다.

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

b (블롯) 함수는 맵 문자열과 인덱스를 인수로 사용합니다. @v (방문 된 배열)를 초기화하고 b2 도우미 함수를 호출합니다.

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

b2 함수는 맵 문자열, 맵 위치 (i) 및 현재 경로의 문자 (c)를 사용합니다. 연결된 자릿수 섹션을 'x'문자로 대체하기 위해 재귀 적으로 호출됩니다. 입력 문자열을 반환합니다 (ps 함수가 반환 값에서 scan ()을 호출 할 수 있도록 함).

이 if 문은 주어진 맵 위치 (i)가 문자열 범위 (0 ... s.size) 내에 있고 s [i]의 문자가 시작 문자와 같은지 점검합니다. 또한 @v [i]는 무한 재귀를 피하기 위해 검사됩니다.

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

인덱스 (i)의 문자를 'x'문자로 바꾸는 비트입니다. 또한 해당 인덱스를 방문한 것으로 표시합니다.

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

여기서 b2는 경로를 재귀 적으로 검색합니다. i + 1은 오른쪽에 한 문자, i-1은 왼쪽에 한 문자, i + 6은 한 행 아래 (5 자리 + 1 줄 바꿈 = 6 자), i-6은 한 행입니다.

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

1

C (ANSI) 243 233 179 188 바이트

골프 :

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

주석으로 :

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

}

입력:

문자열의 시작과 끝에 줄 바꿈이 필요합니다.

입력 예 :

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

출력 예 :

x2 45
xx2xx
  2xx
    1
2 899

최신 정보

그리드를 고정하면 거의 60 바이트를 줄일 수있었습니다.


수정 맵 크기로 변경하면 22 자 정도 저장할 수있을 것 같습니다. 다른 것을 찾으면 변경하고 싶습니다.
dj0wns

1

Mathematica, 180 바이트

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

설명:

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

5x5배열 을 받아들이는 순수한 함수 . 접미사 전치 연산자를 나타내는 3 바이트 개인용 문자 입니다.U+F3C7\[Transpose]

(f=Flatten@#;p=Partition): 입력 목록을 평평하게하여에 저장합니다 f. 설정 p = Partition하고 돌려줍니다.

g=p[r,5]: 배열입니다 {{1,2,3,4,5}, ..., {21,22,23,24,25}}(이것이로 r설정 되었기 때문입니다 Range@25).

Join[g=p[r,5],g]:의 행과 열 목록 g.

p[#,2,1]&: 겹치는 #길이의 하위 목록 으로 목록을 분할하는 순수한 기능 ; 즉,에서 인접한 쌍의 목록입니다 .21#

##&@@p[#,2,1]&:를 반환한다는 점을 제외하면 위와 동일합니다 Sequence.

##&@@p[#,2,1]&/@Join[g=p[r,5],g]:의 행과 열의 이전 기능을 매핑 g하여에 인접한 모든 항목의 목록을 얻습니다 g. 내 직감은 더 짧은 방법이 있다고 말합니다.

r~Graph~Cases[...]: 정점이 정수 1, ..., 25이고 g입력 배열에서 동일한 대응하는 항목이있는 인접한 항목 사이의 가장자리 인 그래프 (이외의 " ")

{a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ": 패턴과 일치 {a,b}하도록 f[[a]] == f[[b]](동일 입력 배열의 값)는 어느 동일하지 " ". 바이트 A = f[[a]]를 저장하도록 설정하십시오 1.

...:>a<->b: 모든 경기를 a에서 b까지의 방향이없는 가장자리로 바꿉니다.

VertexComponent: 첫 번째 인수 (그래프)에서 두 번째 인수 (정점)의 연결된 컴포넌트를 반환합니다.

Tr[1^VertexComponent[...]]: 연결된 구성 요소의 크기입니다. 1에서 바이트를 저장합니다 Length@VertexComponent[...].

If[Tr[...]<3,f[[#]],"x"]&: 항목 소요 순수 기능 #의를 g. 연결된 컴포넌트의 크기가보다 작 으면 3입력의 해당 항목으로 교체하십시오. 그렇지 않으면로 교체하십시오 "x".

(f=Flatten@#;p=Partition)[...,5]: 마지막으로 결과를 5x5배열로 바꿉니다.


0

클로저, 188 바이트

이것은 매우 압도적입니다 : 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))%))

다음과 같이 호출됩니다 (1D 벡터 문자가 필요함).

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

ungolf하기에는 너무 게으르지 만 기본적으로 for[m(range 30)]각 인덱스를 방문하고 각 인덱스에 대해 내부 let[n(for[p[-1 -6 1 6]...(+ m p))]는 중간 위치와 동일한 값 (1-9)을 가진 위치를 나열하는 0 ~ 4 개의 요소 목록을 만듭니다. 둘 이상의 이웃이 중간 부분과 일치하면이 모든 항목이 클러스터를 형성하므로 해당 위치가에 사용 된 세트에 추가됩니다 (if((set(flatten(...)))i). i집합에서 인덱스 를 찾으면 \x방출되고 원래 값은 그렇지 않습니다. 그것은 :when( ... )매우 재미있다 ...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.