首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >划分水流图

划分水流图
EN

Code Golf用户
提问于 2014-01-23 06:44:40
回答 3查看 3.2K关注 0票数 17

我是Palantir技术公司在接受采访时在互联网上提出的挑战

一群农民有一些海拔数据,我们将帮助他们了解降雨如何流过农田。我们将土地表示为一个二维的高度阵列,并使用以下模型,基于水下坡的想法:如果一个细胞的四个相邻细胞都有较高的高度,我们称这个细胞为水槽;水聚集在水槽中。否则,水会流向海拔最低的邻近细胞。如果一个单元不是接收器,您可以假设它有一个唯一的最低邻居,并且这个邻居将低于单元格。直接或间接流入同一水槽的细胞据说是同一盆地的一部分。你的挑战是把地图划分成盆地。特别是,给定一个海拔图,您的代码应该将地图划分为盆地,并按降序输出盆地的大小。假设高程图是正方形的。输入将以一个整数开始,S,地图的高度(和宽度)。下一条S线将分别包含一排地图,每一行都带有S整数--这一行中的加高单元格。有些农民有小块地,如下面的例子,而有些人则有较大的地块。然而,在任何情况下,农民都不会拥有超过S= 5000的一块土地。您的代码应该输出一个按降序排列的盆地大小的空格分隔列表。(忽略尾随空格。)下面是几个例子。输入:

代码语言:javascript
复制
3
1 5 2
2 4 7
3 6 9 

输出:7 2用A和B标记的盆地是:

代码语言:javascript
复制
A A B
A A B
A A A 

输入:

代码语言:javascript
复制
1
10

输出:1这里只有一个盆地。输入:

代码语言:javascript
复制
5
1 0 2 5 8
2 3 4 7 9
3 5 7 8 9
1 2 5 4 2
3 3 5 2 1 

输出:11 7 7标有A、B和C‘s的盆地是:

代码语言:javascript
复制
A A A A A
A A A A A
B B A C C
B B B C C
B B C C C 

输入:

代码语言:javascript
复制
4
0 2 1 3
2 1 0 4
3 3 3 3
5 5 2 1 

输出:7 5 4标有A、B和C‘s的盆地是:

代码语言:javascript
复制
A A B B
A B B B
A B B C
A C C C
EN

回答 3

Code Golf用户

发布于 2014-05-07 03:18:13

Ruby,216

代码语言:javascript
复制
r=[]
M=gets('').split.map &:to_i
N=M.shift
g=M.map{1}
M.sort.reverse.map{|w|t=[c=M.index(w),c%N<0?c:c-1,c%N<N-1?c+1:c,c+N,c-N].min_by{|y|M[y]&&y>=0?M[y]:M.max}
M[c]+=1
t!=c ?g[t]+=g[c]:r<<g[c]}
A2gt;<<r.sort.reverse*' '

这是一种稍微不同的方法,只在每个平方上调用"flow“一次(性能取决于Array::index的性能)。它从最高的海拔到最低的高度,一次把一个细胞排空到它的最低邻居,并在它完成时标记完成的单元格(增加1到海拔)。

评论和间隔:

代码语言:javascript
复制
results=[]
ELEVATIONS = gets('').split.map &:to_i  # ELEVATIONS is the input map
MAP_SIZE = ELEVATIONS.shift             # MAP_SIZE is the first line of input
watershed_size = ELEVATIONS.map{1}      # watershed_size is the size of the watershed of each cell

ELEVATIONS.sort.reverse.map { |water_level| 
    # target_index is where the water flows to.  It's the minimum elevation of the (up to) 5 cells:
    target_index = [
        current_index = ELEVATIONS.index(water_level),                              # this cell
        (current_index % MAP_SIZE) < 0           ? current_index : current_index-1, # left if possible
        (current_index % MAP_SIZE) >= MAP_SIZE-1 ? current_index : current_index+1, # right if possible
        current_index + MAP_SIZE,                                                   # below
        current_index - MAP_SIZE                                                    # above
    ].min_by{ |y|
        # if y is out of range, use max. Else, use ELEVATIONS[y]
        (ELEVATIONS[y] && y>=0) ? ELEVATIONS[y] : ELEVATIONS.max
    }
# done with this cell.
# increment the elevation to mark done since it no longer matters
ELEVATIONS[current_index] += 1

# if this is not a sink
(target_index != current_index) ? 
    # add my watershed size to the target's
    watershed_size[target_index] += watershed_size[current_index] 
    # else, push my watershed size onto results
    : results << watershed_size[current_index]}

Changelog:

216 -取消选择场外指数的更好方法

221 -原来"11“在”2“之前.恢复到to_i,但在getses上节省一些空间。

224号-为什么要声明s?和each => map

229-大型高尔夫--首先将高地排序为s (从而删除while子句),使用min_by而不是sort_by{...}[0],不要在海拔上费心to_i,使用flat_map和收缩select{}块。

271 -将分水岭大小移动到新的数组中并使用sort_by。

315 -将结果移动到数组中,这提供了各种好处,并缩短了相邻索引列表。在指数lambda中也增加了一个煤焦。

355 -第一次承诺

票数 1
EN

Code Golf用户

发布于 2014-05-08 23:42:16

JavaScript (ECMAScript 6) -226个字符

代码语言:javascript
复制
s=S.split(/\s/);n=s.shift(k=[]);u=k.a;t=s.map((v,i)=>[v,i,1]);t.slice().sort(X=(a,b)=>a[0]-b[0]).reverse().map(v=>{i=v[1];p=[v,i%n?t[i-1]:u,t[i-n],(i+1)%n?t[i+1]:u,t[+n+i]].sort(X)[0];p==v?k.push(v[2]):p[2]+=v[2]});k.join(' ')

解释

代码语言:javascript
复制
s=S.split(/\s/);                  // split S into an array using whitespace as the boundary.
n=s.shift();                      // remove the grid size from s and put it into n.
k=[];                             // an empty array to hold the position of the sinks.
u=k.a;                            // An undefined variable
t=s.map((v,i)=>[v,i,1]);          // map s to an array of:
                                  // - the elevation
                                  // - the position of this grid square
                                  // - the number of grid squares which have flowed into
                                  //      this grid square (initially 1).
X=(a,b)=>a[0]-b[0];               // A comparator function for sorting.
t.slice()                         // Take a copy of t
 .sort(X)                         // Then sort it by ascending elevation
 .reverse()                       // Reverse it to be sorted in descending order
 .map(v=>{                        // For each grid square (starting with highest elevation)
   i=v[1];                        // Get the position within the grid
   p=[v,i%n?t[i-1]:u,t[i-n],(i+1)%n?t[i+1]:u,t[+n+i]]
                                  // Create an array of the grid square and 4 adjacent
                                  //   squares (or undefined if off the edge of the grid)
     .sort(X)                     // Then sort by ascending elevation
     [0];                         // Then get the square with the lowest elevation.
   p==v                           // If the current grid square has the lowest elevation
     ?k.push(v[2])                // Then add the number of grid square which have
                                  //   flowed into it to k
     :p[2]+=v[2]});               // Else flow the current grid square into its lowest
                                  //   neighbour.
k.join(' ')                       // Output the sizes of the block with  space separation.

早期版本-286个字符

代码语言:javascript
复制
s=S.split(/\s/);n=s.shift()*1;k=[];u=k[1];t=s.map((v,i)=>({v:v,p:i,o:[]}));for(i in t){t[p=[t[i],i%n?t[i-1]:u,t[i-n],(+i+1)%n?t[+i+1]:u,t[+i+n]].sort((a,b)=>(a.v-b.v))[0].p].o.push([i]);p==i&&k.push([i])}k.map(x=>{while(x[L="length"]<(x=[].concat(...x.map(y=>t[y].o)))[L]);return x[L]})

假设输入在变量S中;

解释

代码语言:javascript
复制
s=S.split(/\s/);                  // split S into an array using whitespace as the boundary.
n=s.shift()*1;                    // remove the grid size from s and put it into n.
k=[];                             // an empty array to hold the position of the sinks.
u=k[1];                           // Undefined
t=s.map((v,i)=>({v:v,p:i,o:[]})); // map s to an Object with attributes:
                                  // - v: the elevation
                                  // - p: the position of this grid square
                                  // - o: an array of positions of neighbours which
                                  //      flow into this grid square.
for(i in t){                      // for each grid square
  p=[t[i],i%n?t[i-1]:u,t[i-n],(+i+1)%n?t[+i+1]:u,t[+i+n]]
                                  // start with an array containing the objects 
                                  //   representing that grid square and its 4 neighbours
                                  //   (or undefined for those neighbours which are
                                  //   outside the grid)
      .sort((a,b)=>(a.v-b.v))     // then sort that array in ascending order of elevation
      [0].p                       // then get the first array element (with lowest
                                  //   elevation) and get the position of that grid square.
  t[p].o.push([i]);               // Add the position of the current grid square to the
                                  //   array of neighbours which flow into the grid square
                                  //   we've just found.
  p==i&&k.push([i])               // Finally, if the two positions are identical then
                                  //   we've found a sink so add it to the array of sinks (k)
}
k.map(x=>{                        // For each sink start with an array, x, containing the
                                  //   position of the sink.
  while(x.length<(x=[].concat(...x.map(y=>t[y].o))).length);
                                  // Compare x to the concatenation of x with all the
                                  //   positions of grid squares which flow into squares
                                  //   in x and loop until it stops growing.
  return x.length                 // Then return the number of grid squares.
})

测试

代码语言:javascript
复制
S="3\n1 5 2\n2 4 7\n3 6 9";
s=S.split(/\s/);n=s.shift()*1;k=[];u=k[1];t=s.map((v,i)=>({v:v,p:i,o:[]}));for(i in t){t[p=[t[i],i%n?t[i-1]:u,t[i-n],(+i+1)%n?t[+i+1]:u,t[+i+n]].sort((a,b)=>(a.v-b.v))[0].p].o.push([i]);p==i&&k.push([i])}k.map(x=>{while(x[L="length"]<(x=[].concat(...x.map(y=>t[y].o)))[L]);return x[L]})

产出:[7, 2]

代码语言:javascript
复制
S="5\n1 0 2 5 8\n2 3 4 7 9\n3 5 7 8 9\n1 2 5 4 2\n3 3 5 2 1"
s=S.split(/\s/);n=s.shift()*1;k=[];u=k[1];t=s.map((v,i)=>({v:v,p:i,o:[]}));for(i in t){t[p=[t[i],i%n?t[i-1]:u,t[i-n],(+i+1)%n?t[+i+1]:u,t[+i+n]].sort((a,b)=>(a.v-b.v))[0].p].o.push([i]);p==i&&k.push([i])}k.map(x=>{while(x[L="length"]<(x=[].concat(...x.map(y=>t[y].o)))[L]);return x[L]})

产出:[11, 7, 7]

代码语言:javascript
复制
S="4\n0 2 1 3\n2 1 0 4\n3 3 3 3\n5 5 2 1"
s=S.split(/\s/);n=s.shift()*1;k=[];u=k[1];t=s.map((v,i)=>({v:v,p:i,o:[]}));for(i in t){t[p=[t[i],i%n?t[i-1]:u,t[i-n],(+i+1)%n?t[+i+1]:u,t[+i+n]].sort((a,b)=>(a.v-b.v))[0].p].o.push([i]);p==i&&k.push([i])}k.map(x=>{while(x[L="length"]<(x=[].concat(...x.map(y=>t[y].o)))[L]);return x[L]})

产出:[5, 7, 4]

票数 1
EN

Code Golf用户

发布于 2014-05-14 00:17:46

Julia,315

代码语言:javascript
复制
function f(a,i,j)
    z=size(a,1)
    n=filter((x)->0<x[1]<=z&&0<x[2]<=z,[(i+1,j),(i-1,j),(i,j-1),(i,j+1)])
    v=[a[b...] for b in n]
    all(v.>a[i,j]) && (return i,j)
    f(a,n[indmin(v)]...)
end
p(a)=prod(["$n " for n=(b=[f(a,i,j) for i=1:size(a,1),j=1:size(a,2)];sort([sum(b.==s) for s=unique(b)],rev=true))])

只是一个递归函数,它要么确定当前单元格是接收器,要么找到漏池,然后在每组索引上调用它。我不想做输入部分,因为无论如何我都不会赢,而且那部分也不好玩。

票数 1
EN
页面原文内容由Code Golf提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codegolf.stackexchange.com/questions/19188

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档