找到路径!


10

您必须编写一个程序或函数。

输入是数字的“映射”。您可以选择将地图作为带换行符(\n)的字符串或二维字符串数组。

所有地图都是5个字符乘5个字符,并且这些字符始终是大于0的数字或空格。

这是地图的示例:

12 45
11233
  233
    1
2 899

您的任务是在地图中找到连接的组件。有效成分是至少三个水平和/或垂直(非对角线)相连的相同数字(不是空格)的序列。然后,您需要用xs 替换有效连接的组件的字符,然后打印或返回该结果。

因此,以上示例的输出为:

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

这是代码高尔夫球,因此以字节为单位的最短代码获胜!



是否允许内置?
Ioannes

@Joannes,是的。
丹尼尔(Daniel)

Answers:


1

的JavaScript(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>

这是我的Python答案的翻译。I / O作为字符数组。

太糟糕了,没有有效的方法sum...


5

Python 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个字节以击败mathematica解决方案...
FlipTack

1
@FlipTack是的。我认为今天不会发生这种情况,但是我正在将其翻译成JS,它看起来很有希望。
PurkkaKoodari

3

Ruby,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"))

该代码重用了“印迹”方法来计算路径长度。

变量/方法:

  • f(s):转换地图字符串的函数,返回带有“ x”的新地图
  • ps(i):地图索引i的路径大小(其中x = i%6,y = i / 6)
  • s:输入字符串,用“ \ n”分隔的地图线
  • z:输入字符串的副本
  • b(s,i):“印迹”功能:在路径上从地图索引i写入“ x”
  • @v:'访问'数组

尝试进行更详细的说明:

复制输入字符串,以用于查找地图中任何给定点的路径长度。

z = s.dup

定义一个“ ps”(路径长度)匿名函数(lambda),该函数将地图索引i作为参数。它从该点返回路径的长度。它通过调用'b'(blot)方法在原始地图的副本上插入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 helper函数。

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]

这是用“ x”字符替换索引(i)处的字符的位。它还将该索引标记为已访问。

@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个字节。


我想如果将其更改为
Fixs

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]&:将列表#分成长度2重叠的子列表的纯函数1; 即,中的相邻对的列表#

##&@@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

Clojure,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))%))

这样称呼(需要一维矢量字符):

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

懒得取消它,但基本上for[m(range 30)]访问每个索引,并且内部为每个索引let[n(for[p[-1 -6 1 6]...(+ m p))]创建一个0到4个元素的列表,该列表列出的值与中间位置的值相同(1-9)。如果超过1个邻居与中间片段匹配,则意味着所有这些片段都组成一个簇,因此会将这些位置添加到处使用的集合中(if((set(flatten(...)))i)。如果i从集合中找到索引,则\x发出该索引,否则返回原始值。那:when( ... )很有趣...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.