自然派#2-河


12

目标

给定一个带有一列哈希的字符串,计算其总长度并除以从开始到结束的距离。

模拟

我们在模拟什么?根据本文,河流的长度与起点和终点之间的距离之比约为Pi!(这可能在经验上得到了证明,但是我可以找到数据,对于这一挑战,我们认为它是正确的)。

我们如何模拟这一点?

  • 接受空格和哈希的字符串输入
  • 每个哈希将与其他两个相邻
    • 除了第一个和最后一个散列,该散列只有1个
  • 每个字符都位于格点上 (x, y)
  • x 是字符在其行中的索引
    • 例如c,第四个字符是0123c567
  • y 是字符的行号
    • 例如c在第三行:
      0line
      1line
      2line
      3c...
  • 求和相邻散列之间的距离,将其称为 S
  • 取第一个和最后一个哈希之间的距离,称为 D
  • 返回 S/D

在此处输入图片说明

规格

  • 输入值
    • 灵活,可以采用任何标准方式(例如,函数参数,STDIN)和任何标准格式(例如,字符串,二进制)进行输入
  • 输出量
    • 灵活,以任何标准方式(例如退货,打印)提供输出
    • 可以使用空格,尾随空格和前导空格
    • 精度,请提供至少4位小数位数(即3.1416
  • 计分
    • 最短的代码胜出!

测试用例

这些是我对河流的近似值。我的估算值可能很差,或者我对河流人口的估算值很差。另外,我是手动进行计算的。我本来想念的。

黄河

        ### ####           
       #   #    #          
       #       #          #
       #       #         # 
       #       #        #  
      #         #      #   
##   #          # #####    
  ##  #          #         
    ##                     
1.6519

尼罗河

         #     
         #     
          #    
           #   
           #   
          #    
         #     
        #      
        #  #   
        # # #  
         #  #  
            #  
          ##   
         #     
         #     
        #      
        #      
       #       
       #       
       #       
       #       
   #  #        
  # ##         
  #            
  #            
   #           
    #          
     #         
     #         
      #        
     #         
    #          
     #         
      #        
1.5498

密西西比河

 ###            
#   #           
     #          
     #          
    #           
   #            
  #             
  #             
  #             
   #            
    #           
     #          
      #         
       #        
        #       
        #       
        #       
         #      
          #     
           #    
          #     
       ###      
      #         
       #        
      #         
     #          
    #           
    #           
    #           
    #           
     #          
      ##        
        #       
        #       
         ##     
           ##   
             ## 
               #
              # 
             #  
            #   
           #    
          #     
         #      
        #       
        #       
        #       
        #       
        #       
       #        
      #         
     #          
      #         
       #        
        ####    
            #   
             #  
1.5257

TL; DR

这些挑战是仅需要自然和大脑(可能还有一些可重用资源)才能逼近Pi的算法仿真。如果您在僵尸启示录期间确实需要Pi,那么这些方法不会浪费弹药!总共有九个挑战


3
它们本身称为哈希。“ Hashtag”只是内联标签的术语,表示为#<tag>
FlipTack

1
我假设应该使用勾股定理来计算距离。它是否正确?
Loovjo,2013年

另外,我们可以将输入作为行列表吗?
Loovjo

@Loovjo ^^可以,它是欧几里得几何,所以您要计算就可以了。^是的,输入很灵活。
NonlinearFruit

1
@NonlinearFruit谢谢。则可能是ASCII版本不够弯曲:)
Luis Mendo,2016年

Answers:


6

MATL48 44 42 37 33字节

由于rahnema1将两个卷积合为一个的想法(八度答案),节省了不少字节

t5BQ4B&vX^Z+*ssGt3Y6Z+1=*&fdwdYy/

这将输入作为二进制矩阵,并;作为行分隔符。1对应于哈希和0空间。

在线尝试!验证所有测试用例

这是一个格式转换器,将输入作为2D char数组(同样使用;分隔符),并生成相应二进制矩阵的字符串表示形式。

说明

真有趣!该代码使用三个两个2D卷积,每个卷积具有不同的用途:

  1. 为了检测垂直邻域和水平邻域,它们的距离为1,所需的遮罩为

    0 1 0
    1 0 1
    0 1 0
    

    但是我们只希望每邻居被检测一次。因此,我们取了一半的掩码(可以删除最后一行零):

    0 1 0
    1 0 0
    

    同样,要检测对角邻点(距离为)sqrt(2),则掩码为

    1 0 1
    0 0 0
    1 0 1
    

    但是通过与上述相同的理由,它变成

    1 0 1
    0 0 0
    

    如果将此蒙版乘以sqrt(2)第一个并加上,则两个卷积可以用合并的蒙版替换为一个卷积

    sqrt(2) 1  sqrt(2)
    1       0        0
    
  2. 根据定义,起点和终点是只有一个邻居的点。为了检测它们,我们与

    1 1 1
    1 0 1
    1 1 1
    

    并查看给出1的结果。

要生成第1项的组合蒙版,可以缩短生成其平方然后取平方根的时间。项目2中的掩码是预定义的文字。

t     % Take input matrix implicitly. Duplicate
5B    % 5 in binary: [1 0 1]
Q     % Add 1; [2 1 2]
4B    % 4 in binary: [1 0 0]
&v    % Concatenate vertically
X^    % Square root of each entry
Z+    % 2D convolution, maintaining size
*     % Multiply, to only keep results corresponding to 1 in the input
ss    % Sum of all matrix entries. This gives total distance
Gt    % Push input again. Duplicate
3Y6   % Predefined literal. This gives third mask
Z+    % 2D convolution, maintaining size
1=    % Values different than 1 are set to 0
*     % Multiply, to only keep results corresponding to 1 in the input
&f    % Push array of row indices and array of column indices of nonzeros
d     % Difference. This is the horizontal difference between start and end
wd    % Swap, difference. This is the vertical difference between start and end 
Yy    % Hypothenuse. This gives total distance in straight line
/     % Divide. Display implicitly

2
有人曾经说过,卷积是成功的关键
瑕疵

4

八度,99字节

@(a)sum((c=conv2(a,[s=[q=2^.5 1 q];1 0 1;s],'same').*a)(:))/2/{[x y]=find(c<2&c>0),pdist([x y])}{2}

MATL答案几乎相同的方法,但是这里的卷积核是

1.41 ,  1  , 1.41
1    ,  0  , 1 
1.41 ,  1  , 1.41

sqrt(2) =1.41是对角邻居和1 直接邻居的,所以当我们对河上的结果求和时,我们得到的是真实距离的两倍。
非高尔夫版本

a=logical([...
0 0 0 0 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 
1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 0 0 0 0 
0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]);
sq = sqrt(2);
kernel = [...
    sq ,  1  , sq
    1  ,  0  , 1 
    sq ,  1  , sq];
%2D convolution
c=conv2(a,kernel,'same').*a;
#river length
river_length = sum(c (:))/2;
#find start and end points
[x y]=find(c<2&c>0);
# distance between start and end points
dis = pdist([x y]);
result = river_length/ dis 

试穿(粘贴) Octave Online


您将前两个卷积合并为一个的想法为我节省了几个字节:)
Luis Mendo

{[x y]=find(c<2&c>0),pdist([x y])}{2}真是太聪明了!!!
瑕疵的2016年

一个好消息是我们没有MATLAB的限制!
rahnema16年

2
@flawr同意。那应该去八度高尔夫技巧
路易斯·门多

@LuisMendo提示中包含了一些条目
rahnema1 '16

2

JavaScript(ES6),178

输入带有矩形形式的换行符的字符串:每行用空格填充相同的长度(如示例中所示)

r=>r.replace(/#/g,(c,i)=>([d=r.search`
`,-d,++d,-d,++d,-d,1,-1].map((d,j)=>r[i+d]==c&&(--n,s+=j&2?1:Math.SQRT2),n=1),n||(v=w,w=i)),w=s=0)&&s/2/Math.hypot(v%--d-w%d,~(v/d)-~(w/d))

少打高尔夫球

r=>(
  r.replace(/#/g, // exec the following for each '#' in the string
    (c,i) => // c: current char (=#), i: current position
    ( // check in 8 directions
      // note: d starts as the offset to next row, prev x position
      // and is incremented up to offset to next row, succ x position
      // note 2: there are 2 diagonal offsets, then 2 orthogonal offsets
      //         then other 2 diagonal, then 2 more orthogonal
      [d=r.search`\n`,-d, ++d,-d, ++d,-d, 1,-1].map( // for each offset
        (d,j) => // d: current offset, j: array position (0 to 7)
        r[i+d] == c && // if find a '#' at current offset ...
          ( 
            --n, // decrement n to check for 2 neighbors or just 1
            s += j & 2 ? 1 : Math.SQRT2 // add the right distance to s
          ),
      n = 1), // n starts at 1, will be -1 if 2 neighbors found, else 0
      // if n==0 we have found a start or end position, record it in v and w
      n || (v=w, w=i)
   ),
  w=s=0), // init s and w, no need to init v
  // at the end 
  // d is the length of a line + 1
  // s is twice the total length of the river
  // v and w can be used to find the x,y position of start and end
  s/2/Math.hypot(v%--d-w%d,~(v/d)-~(w/d))
)

测试

F=
r=>r.replace(/#/g,(c,i)=>([d=r.search`\n`,-d,++d,-d,++d,-d,1,-1].map((d,j)=>r[i+d]==c&&(--n,s+=j&2?1:Math.SQRT2),n=1),n||(v=w,w=i)),w=s=0)&&s/2/Math.hypot(v%--d-w%d,~(v/d)-~(w/d))

Yellow=`        ### ####           
       #   #    #          
       #       #          #
       #       #         # 
       #       #        #  
      #         #      #   
##   #          # #####    
  ##  #          #         
    ##                     `

Nile=`         #     
         #     
          #    
           #   
           #   
          #    
         #     
        #      
        #  #   
        # # #  
         #  #  
            #  
          ##   
         #     
         #     
        #      
        #      
       #       
       #       
       #       
       #       
   #  #        
  # ##         
  #            
  #            
   #           
    #          
     #         
     #         
      #        
     #         
    #          
     #         
      #        `

Missi=` ###            
#   #           
     #          
     #          
    #           
   #            
  #             
  #             
  #             
   #            
    #           
     #          
      #         
       #        
        #       
        #       
        #       
         #      
          #     
           #    
          #     
       ###      
      #         
       #        
      #         
     #          
    #           
    #           
    #           
    #           
     #          
      ##        
        #       
        #       
         ##     
           ##   
             ## 
               #
              # 
             #  
            #   
           #    
          #     
         #      
        #       
        #       
        #       
        #       
        #       
       #        
      #         
     #          
      #         
       #        
        ####    
            #   
             #  `
console.log('Yellow River',F(Yellow))
console.log('Nile River',F(Nile))
console.log('Mississippi River',F(Missi))

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.