迪克斯特拉的挑战


23

为纪念APL成为今年50岁的互动工具而颁发

背景

肯·艾弗森(Ken [Iverson])在1963年8月于新泽西州普林斯顿举行的机械语言结构工作会议上发表了他的论文《程序语言形式化》。(巴克斯,库里,迪克斯特拉,弗洛伊德,艾弗森,纽厄尔,玻璃市,威尔克斯)。该文件还记录了演讲后的讨论,最后在Ken和[Edsger] Dijkstra之间进行了交流,其中Ken对Dijkstra问题的答复是单线的。

挑战

您将如何表示一个更复杂的操作,例如,矩阵M中所有元素的总和等于相应的行索引和列索引的总和?

编写一个代码段或表达式(不需要完整的程序或函数)以计算给定整数矩阵中每个元素的总和,该整数等于其索引的总和。或者,如FryAmTheEggman所说:给定一个矩阵中号的元素一个 IJ返回每个的总和一个 IJ其中一个 IJ = I + J。

您可以假定矩阵已经在变量或存储位置中,或者可以将其用作参数或输入。您可以使用基于0或1的索引。

测试用例

 

0 用于空矩阵

2

0基于0的索引或2基于1的索引

1 5 2
9 4 2
5 9 6

2基于0或10基于1

 0 3  0  4
 0 4  1  4
 4 3  1  2
-2 4 -2 -1

11

3 -1 3 3
3 -1 3 1

6基于0或3基于1

轶事

艾弗森的答案++ /(中号 = ¹⨢ ¹)// 中号,既不是有效的艾弗森表示法中定义的编程语言,也不是在什么最终成为APL。在艾弗森表示法中,它会一直+ /(中号 = ¹(μ中号))⨢ ¹(ν中号)))/ 中号。在APL的第一个版本中是+/(,M=(⍳1↑⍴M)∘.+⍳1↓⍴M)/,M


肯(Ken)对迪克斯特拉(Dijkstra)问题的答复是单线的。但是那一线是错误的吗?
路易斯·门多

我需要输出它还是将其打印出来,还是可以将表达式作为代码段写下来?
Leaky Nun

2
@LuisMendo不,艾弗森正在积极地设计语言,在那一次迭代中,他的一句话是正确的。“APL”一举成名的书的出版一个P AGC软件大号 anguage,但在发布的时候,需要第二个表达式。这些表示法都没有实现为机器可执行的。
阿达姆(Adám)2016年

@LeakyNun 写片段或表达来计算
ADAM

@Adám谢谢。现在更有意义
Luis Mendo

Answers:


9

APL,13 12字节

1个字节,感谢@ jimmy23013。

1个索引。

数组存储在变量中m

+ /,m×m = + /¨⍳⍴m
+ / ∊m∩¨ + /¨⍳⍴m

在线尝试!

基于J的答案,这是一种基于APL的语言。

在TryAPL中,键入: +/m`em`c`1+/`1`i`rm

与数组: +/m`em`c`1+/`1`i`rm `[ 2 4 `r 3 `21 3 3 3 `21 3 1

说明

+/∊m∩¨+/¨⍳⍴m
           m    temp ← variable
          ⍴     temp ← shape of temp
         ⍳      temp ← a 2D array where each element is
                       the corresponding index. for the
                       example, this gives:
                       ┌───┬───┬───┬───┐
                       │1 1│1 2│1 3│1 4│
                       ├───┼───┼───┼───┤
                       │2 1│2 2│2 3│2 4│
                       └───┴───┴───┴───┘
      +/¨       each element in temp ← its sum
   m∩¨          temp ← intersect each element in temp with the variable
+/              temp ← sum of temp

终于,我在等这个。
阿达姆(Adám)2016年

我不确定“输入:”是个好主意。它仅适用于TryAPL和RIDE,不适用于主要产品。至少您可以解释这`意味着“ APL密钥”。
阿达姆,2013年

1
+/∊m∩¨+/¨⍳⍴m
jimmy23013 '16

@ jimmy23013真的很好!
2013年

9

MATL15 14 10字节

3#fbb+y=*s

输入的行以分隔;。例如:[1 5 2; 9 4 2; 5 9 6]。使用基于1的索引。

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

说明

我将[3 -1 3 3; 3 -1 3 1]在解释中将示例与输入一起使用。

3#f    % Three-output find: for all nonzero values of implicit input matrix, pushes
       % three column vectors with row indices, column indices, and values
       %   Stack contains: [1;2;1;2;1;2;1;2], [1;1;2;2;3;3;4;4], [3;3;-1;-1;3;3;3;1]
bb     % Bubble up twice: move vectors of row and column indices to top
       %   Stack contains: [3;3;-1;-1;3;3;3;1], [1;2;1;2;1;2;1;2], [1;1;2;2;3;3;4;4]
+      % Element-wise sum of top two arrays
       %   Stack contains: [3;3;-1;-1;3;3;3;1], [2;3;3;4;4;5;5;6]
y      % Duplicate the vector of nonzero values onto the top of the stack
       %   Stack contains: [3;3;-1;-1;3;3;3;1], [2;3;3;4;4;5;5;6], [3;3;-1;-1;3;3;3;1] 
=      % Element-wise equality test of top two arrays
       %   Stack contains: [3;3;-1;-1;3;3;3;1], [0;1;0;0;0;0;0;0]
*      % Element-wise multiply of top two arrays
       %   Stack contains: [0;3;0;0;0;0;0;0]
s      % Sum of array
       %   Stack contains: 3

6

JavaScript,49 46字节

a.map((b,i)=>b.map((c,j)=>r+=c==i+j&&c),r=0)|r

编辑:由于@MartinEnder指出允许摘要,因此节省了3个字节。


5

视网膜,46字节

字节数假定为ISO 8859-1编码。

\d+
$*
M!`(?<=(\S* |.*¶)*)(?<-1>1)+\b(?(1)1)
1

输入使用空格和换行符来表示矩阵。索引从0开始。

在线尝试!

说明

虽然Retina并不是为了挑战而做出的,但是它做得非常好……:)

阶段1:替代

\d+
$*

这只是使用一进制数字将字符串中的所有整数扩展为一1进制数字。负数之类的-3东西只会变成-111

阶段2:比赛

M!`(?<=(\S* |.*¶)*)(?<-1>1)+\b(?(1)1)

由于该!选项,这将打印给定正则表达式的所有匹配项。所述正则表达式使用平衡组来检查当前数量是否与其索引总和相同。

为此,我们首先使用lookbehind确定索引的总和(?<=(\S* |.*¶)*)。这将为同一行中的当前行前面的每个数字添加一个捕获(通过\S* ),并为当前.*¶组中的当前行前面的每个行添加一个捕获(通过)1。因此,我们得到的结果是从零开始的索引总和。

然后,我们尝试匹配整个下一个数字,同时使用来从此堆栈中删除捕获(?<-1>1)+\b。然后,如果将任何捕获保留在分组1(?(1)1)以确保相等,则使匹配失败。

请注意,负数永远不会匹配,因为-后面的查找不能超过1s 列表前面的,并且(?<-1>1)+也不能匹配它。

这为我们提供了所有等于其索引之和的一元数的列表。

第三阶段:比赛

1

我们以另一个匹配阶段结束,但是没有!选项,它只是计算匹配的数目,既将之前结果中的所有一元数相加,又将其总和转换回十进制。


你能用一元作为输入吗?
Leaky Nun

@LeakyNun不知道,我一直在努力避免它。似乎太过分了,尤其是因为Retina不再遇到转换问题。
Martin Ender


4

Python 2- 60 57个字节

这是一个代码段,所以我猜如果我实际返回该值,它将再多几个字节。 e=enumerate;sum(i*(x+y==i)for x,r in e(a)for y,i in e(r))

感谢您的帮助泄漏Num :-)

快速说明。a是一个保存数字的数组。只需遍历索引并求和所有等于值之和的所有值。



哦,它没有用。所以它现在是57个字节:(我添加了一个简短的解释
杰里米

您可能要包括我刚刚给您的链接。
Leaky Nun

4

R,24个字节

sum(M[M==row(M)+col(M)])

基于1。
测试用例:

> M<-matrix(nrow=0,ncol=0)
> M
<0 x 0 matrix>
> sum(M[M==row(M)+col(M)])
[1] 0
> M<-matrix(2,nrow=1,ncol=1)
> M
     [,1]
[1,]    2
> sum(M[M==row(M)+col(M)])
[1] 2
> M<-matrix(c(1,9,5,5,4,9,2,2,6),nrow=3)
> M
     [,1] [,2] [,3]
[1,]    1    5    2
[2,]    9    4    2
[3,]    5    9    6
> sum(M[M==row(M)+col(M)])
[1] 10
> M<-matrix(c(0,0,4,-2,3,4,3,4,0,1,1,-2,4,4,2,-1),nrow=4)
> M
     [,1] [,2] [,3] [,4]
[1,]    0    3    0    4
[2,]    0    4    1    4
[3,]    4    3    1    2
[4,]   -2    4   -2   -1
> sum(M[M==row(M)+col(M)])
[1] 11
> M<-matrix(c(3,3,-1,-1,3,3,3,1),nrow=2)
> M
     [,1] [,2] [,3] [,4]
[1,]    3   -1    3    3
[2,]    3   -1    3    1
> sum(M[M==row(M)+col(M)])
[1] 3

3

J,15个字节

+/,M*M=+/&i./$M

使用基于零的索引,并假定矩阵已存储在变量M中

说明

+/,M*M=+/&i./$M
             $a  Get the shape of M
            /    Insert between the shape
         &i.     Create a range from 0 to each end exclusive
       +/        Forms a table which is the sum of each row and column index
     M=          1 if the element is equal to its index sum else 0
   M*            Multiply by their values
  ,              Flatten
+/               Reduce using addition to get the sum

3
不仅最短,直到现在;+1以艾弗森(Iverson)语言进行。
阿达姆,2013年

3

CJam,23 21 20字节

感谢Peter Taylor节省了3个字节。

ee{~_@f-_,,.=.*~}%1b

期望矩阵在堆栈上,并留下总和。在两种情况下,索引都是从零开始的。

在这里测试。


您可以保存一对,以_,,代替内部循环ee.内部循环:ee{~_,,@f+1$.=.*~}%1b
Peter Taylor

@PeterTaylor啊,整洁,谢谢。:)
Martin Ender

实际上,还有一种通过在中间相遇实现的方式:ee{~_@f-_,,.=.*~}%1b
彼得·泰勒

3

k4,24个字节

假设矩阵存储在中m

+//7h$m*m=(!#m)+/:\:!#*m

这是从APL(和J)设计k涉及的简化工作确实令人感到困惑的难题之一– k !与APL的等效,但仅适用于向量,因此我必须自己组装索引矩阵。内部积在APL中是一个字符,但在k中是五个字符;而且我损失了三个字符来正确处理空矩阵,因为k没有强类型矩阵。


2
另一方面,您拥有一门功能强大的语言,它更加一致,学习的原语也少得多。
2013年


2

PowerShell v2 +,43个字节

%{$j=0;$_|%{$o+=$_*($_-eq$i+$j++)};$i++};$o

作为摘要。用法是将矩阵显式地传递给它(请参见下面的示例)。假设$i,和$o在开始时为null或零(我在下面的示例中已经明确地将它们设置为),并使用0-index。

在矩阵的每一行上进行foreach循环。我们设置$j0,然后在另一个循环中遍历该行的每个元素$_|%{...}。在每个内部循环中,我们$o将当前元素乘以一个布尔值($_-eq$i+$j++),即如果该布尔值为$TRUE,则为1,否则为0。然后,我们退出内部循环,递增$i,并开始下一行。最后,我们离开$o在管道的最后。

例子

PS C:\Tools\Scripts\golfing> $o=0;$i=0;$j=0;@(@(3,-1,3,3),@(3,-1,3,1))|%{$j=0;$_|%{$o+=$_*($_-eq$i+$j++)};$i++};$o
6

PS C:\Tools\Scripts\golfing> $o=0;$i=0;$j=0;@(@(0,3,0,4),@(0,4,1,4),@(4,3,1,2),@(-2,4,-2,-1))|%{$j=0;$_|%{$o+=$_*($_-eq$i+$j++)};$i++};$o
11

2

Ruby,63个字节

将z作为数字的二维数组:

s=0;z.each_index{|i|z[i].each_index{|j|s+=i+j if z[i][j]==i+j}}

一点也不令人兴奋。

如果z是具有x和y且具有数组大小的扁平数组,例如:

x=z.size
y=z[0].size
z=z.flatten

然后,我们就有了这种怪异的东西-也许花哨的产品和拉链看起来更像红宝石,但实际上更大:

(1..x).to_a.product((1..y).to_a).zip(z).inject(0){|s,n|s+(n[0][0]+n[0][1]==n[1]+2?n[1]:0)}

也许有一个更简单的数组或枚举器方法可以缩短它,我还没有找到它,但是我很乐意看到它。
David Ljung Madison Stellar

2

其实是21个位元组

ñ`i╗ñ"i╜+@;(=*"£Mi`MΣ

在线尝试!

感谢Leaky Nun使我不再懒惰,最后写了这篇。

这使用索引为0的矩阵,并将输入作为嵌套列表。

说明:

ñ`i╗ñ"i╜+@;(=*"£Mi`MΣ
ñ                      enumerate input
 `i╗ñ"i╜+@;(=*"£Mi`M   for each (i, row) pair:
  i╗                     flatten, store i in register 0
    ñ                    enumerate the row
     "i╜+@;(=*"£M        for each (j, val) pair:
      i╜+                  flatten, add i to j
         @;(               make an extra copy of val, bring i+j back to top
            =              compare equality of i+j and val
             *             multiply (0 if not equal, val if they are)
                 i       flatten the resulting list
                    Σ  sum the values


2

Matlab /八度,48字节

1个索引。

由于[1:0]某种原因大小为1x0,因此无法处理第一个测试用例

sum(sum(M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0)))

经过Octave 3测试。

完整程序:

M = [2]
sum(sum(M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0)))
M = [1 5 2; 9 4 2; 5 9 6]
sum(sum(M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0)))
M = [ 0 3  0  4; 0 4  1  4; 4 3  1  2;-2 4 -2 -1]
sum(sum(M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0)))
M = [ 3 -1 3 3; 3 -1 3 1]
sum(sum(M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0)))

欢迎来到PPCG!在Octave中,您可以做sum((M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0))(:))。另外,我认为您可以==0通过更改和初始更改~来进一步减少字节数。最后,请注意,您需要处理所有测试用例,否则应删除
Luis Mendo

1

Lua,70个字节

1个索引。

s=0 for i=1,#a do for j=1,#a[i]do s=i+j==a[i][j]and s+i+j or s end end

奖励:它适用于破烂的数组!

输入存储在中a,输出存储在中s

完整程序:

function Dijkstras_Challenge(a)
    s=0 for i=1,#a do for j=1,#a[i]do s=i+j==a[i][j]and s+i+j or s end end
    print(s)
end

Dijkstras_Challenge({})
Dijkstras_Challenge({{2}})
Dijkstras_Challenge({{1,5,2},{9,4,2},{5,9,6}})
Dijkstras_Challenge({{0,3,0,4},{0,4,1,4},{4,3,1,2},{-2,4,-2,-1}})
Dijkstras_Challenge({{3,-1,3,3},{3,-1,3,1}})

1

PHP,59字节

foreach($a as$y=>$r)foreach($r as$x=>$v)$s+=($v==$x+$y)*$v;

期望定义数组$ a; 必须为空或二维,0索引。
计算总和为$ s(以前为0或未定义-0等于NULL)
插入+2)1索引行为的final之前

APL生日快乐!

功能和测试套件

function f0($a) { foreach($a as$y=>$r)foreach($r as$x=>$v)$s+=($v==$x+$y)*$v;return $s|0; }
function f1($a) { foreach($a as$y=>$r)foreach($r as$x=>$v)$s+=($v==$x+$y+2)*$v;return $s|0;}
$samples = [
    [], 0, 0,
    [[2]], 0, 2,
    [[1,5,2],[9,4,2],[5,9,6]], 2, 10,
    [[0,3,0,4],[0,4,1,4],[4,3,1,2],[-2,4,-2,-1]],11,11,
    [[3,-1,3,3],[3,-1,3,1]],6,3
];
function test($x,$e,$y){static $h='<table border=1><tr><th>input</th><th>output</th><th>expected</th><th>ok?</th></tr>';echo"$h<tr><td>",out($x),'</td><td>',out($y),'</td><td>',out($e),'</td><td>',cmp($e,$y)?'N':'Y',"</td></tr>";$h='';}
while($samples)
{
    $a=array_shift($samples);
    test($a,'B0:'.array_shift($samples),'B0:'.f0($a));
    test($a,'B1:'.array_shift($samples),'B1:'.f1($a));
}

1

Brachylog,15个字节

{iiʰI-ʰ=∧Ihh}ᶠ+

在线尝试!

              +    The output is the sum of
{           }ᶠ     all possible results of
 i                 taking a row from the input with its index,
  i                taking an element with its index
   ʰ               from that row,
    I    Ihh       and outputting the element
       =∧          so long as the index of the row is equal to
     -ʰ            the value of the element minus its index within the row.

1

Wolfram语言(Mathematica),42个字节

ArrayRules/*Cases[p_~_~v_/;Tr@p==v:>v]/*Tr

在线尝试!

1个索引。

ArrayRules                                  (*Convert into a list of (position->value) Rules*)
          /*Cases[p_~_~v_/;Tr@p==v          (*select those where sum(position)==value*)
                                  :>v]/*Tr  (*and find the sum of those values*)
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.