El desafío de Dijkstra

23

Presentado en honor a APL como una herramienta interactiva que cumple 50 este año

Fondo

Ken [Iverson] presentó su artículo Formalismo en lenguajes de programación en agosto de 1963 en una Conferencia de trabajo sobre estructuras de lenguaje mecánico, Princeton, NJ La lista de congresistas está llena de nombres famosos y que pronto serán famosos, y algunos ganadores futuros del Premio Turing (Backus, Curry, Dijkstra, Floyd, Iverson, Newell, Perlis, Wilkes). El documento también registra la discusión que tuvo lugar después de la presentación, que terminó con un intercambio entre Ken y [Edsger] Dijkstra , en el que la respuesta de Ken a la pregunta de Dijkstra fue de una sola línea.

Reto

¿Cómo representaría una operación más compleja, por ejemplo, la suma de todos los elementos de una matriz M que son iguales a la suma de los índices de fila y columna correspondientes?

Escriba un fragmento o expresión (sin necesidad de un programa o función completa) para calcular la suma de cada elemento en una matriz entera dada que sea igual a la suma de sus índices. O, como dice FryAmTheEggman: dada una matriz M con elementos a ij devuelve la suma de cada a ij donde a ij = i + j.

Puede suponer que la matriz ya está en una ubicación variable o de memoria, o puede tomarla como argumento o entrada. Puede usar 0 o 1 índices basados.

Casos de prueba

 

0 para matriz vacía

2

0para índices basados ​​en 0 o 2para índices basados en 1

1 5 2
9 4 2
5 9 6

2para 0 basado o 10para 1 basado

 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

6para 0 basado o 3para 1 basado

Anécdota

La respuesta de Iverson fue ++ / ( M = ¹ ⨢ ¹) // M , que no es válida en la notación de Iverson como se define en un lenguaje de programación , ni en lo que finalmente se convirtió en APL. En la notación Iverson, que habría sido + / ( M = ¹ ( μ ( M )) ⨢ ¹ ( ν ( M ))) / M . En las primeras versiones de APL lo era +/(,M=(⍳1↑⍴M)∘.+⍳1↓⍴M)/,M.

Adán
fuente
en el que la respuesta de Ken a la pregunta de Dijkstra fue de una sola línea. ¿Pero entonces esa frase estaba equivocada?
Luis Mendo
¿Necesito imprimirlo o imprimirlo, o puedo simplemente escribir la expresión como un fragmento?
Leaky Nun
2
@LuisMendo No, Iverson estaba diseñando activamente el lenguaje, y en esa iteración, su respuesta era correcta. "APL" se hizo famoso con la publicación del libro A P rogramming L anguage , pero en el momento de la publicación, se necesitaba la segunda expresión. Ninguna de estas notaciones se implementó para ser ejecutable por máquina.
Adám
@LeakyNun Escribe un fragmento o expresión para calcular
Adám
@ Adám Gracias. Tiene más sentido ahora
Luis Mendo

Respuestas:

9

APL, 13 12 bytes

1 byte gracias a @ jimmy23013.

1 indexado.

La matriz se almacena en la variable m.

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

Pruébalo en línea!

Basado en la respuesta en J , que es un lenguaje basado en APL.

En TryAPL, para ingresar: +/m`em`c`1+/`1`i`rm

Con la matriz: +/m`em`c`1+/`1`i`rm `[ 2 4 `r 3 `21 3 3 3 `21 3 1

Explicación

+/∊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
Monja permeable
fuente
Finalmente, estaba esperando este.
Adám
No estoy seguro de que "To key in:" sea una buena idea. Solo se aplica a TryAPL y RIDE, pero no al producto principal. Al menos puedes explicar que `significa "clave APL".
Adám
1
+/∊m∩¨+/¨⍳⍴m.
jimmy23013
@ jimmy23013 ¡Eso es realmente bueno!
Adám
9

MATL , 15 14 10 bytes

3#fbb+y=*s

La entrada tiene filas separadas por ;. Por ejemplo: [1 5 2; 9 4 2; 5 9 6]. Se utiliza la indexación basada en 1.

Pruébalo en línea! O verificar todos los casos de prueba .

Explicación

Usaré el ejemplo con entrada [3 -1 3 3; 3 -1 3 1]en la explicación.

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
Luis Mendo
fuente
6

JavaScript, 49 46 bytes

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

Editar: Guardado 3 bytes gracias a @MartinEnder que señala que los fragmentos están permitidos.

Neil
fuente
5

Retina , 46 bytes

El recuento de bytes asume la codificación ISO 8859-1.

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

La entrada usa separadores de espacio y salto de línea para representar la matriz. Los índices están basados ​​en 0.

Pruébalo en línea!

Explicación

No es exactamente el tipo de desafío para el que se hizo Retina, pero lo está haciendo sorprendentemente bien ... :)

Etapa 1: sustitución

\d+
$*

Esto simplemente expande todos los enteros en la cadena como números unarios utilizando 1como dígito unario. Los números negativos como -3simplemente se convertirán en cosas como -111.

Etapa 2: partido

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

Debido a la !opción, esto imprime todas las coincidencias de la expresión regular dada. Dicha expresión regular utiliza grupos de equilibrio para verificar si el número actual es el mismo que la suma de sus índices.

Para hacer eso, primero determinamos la suma de los índices con el lookbehind (?<=(\S* |.*¶)*). Esto agrega una captura para cada número frente a la actual en la misma línea (vía \S* ), así como una captura para cada línea frente a la actual (vía .*¶) para agrupar 1. Por lo tanto, obtenemos la suma de índices basada en cero como resultado.

Luego intentamos hacer coincidir el siguiente número completo mientras eliminamos las capturas de esta pila (?<-1>1)+\b. Y luego hacemos el partido fallar si cualquier captura se dejan en grupo 1con el (?(1)1)de garantizar la igualdad.

Tenga en cuenta que los números negativos nunca coinciden, porque el mirar hacia atrás no puede pasar -por delante de la lista de 1sy (?<-1>1)+tampoco puede coincidir.

Esto nos da una lista de todos los números unarios que equivalen a la suma de sus índices.

Etapa 3: partido

1

Terminamos con otra etapa de coincidencia, pero sin la !opción, esto solo cuenta el número de coincidencias, que suma todos los números unarios del resultado anterior y también convierte esa suma de nuevo a decimal.

Martin Ender
fuente
¿Se puede usar unario como entrada?
Monja goteante
@LeakyNun No sé, he estado tratando de evitarlo. Simplemente parece demasiado hacky, especialmente porque Retina ya no tiene problemas con la conversión.
Martin Ender
4

Jalea, 15 14 10 bytes

4 bytes gracias a Adnan.

1 indexado.

L € R € + "LR $ = ³ × ³FS 
L € R € +" LR $ = × ³FS
J € + "J = × ⁸FS

Pruébalo en línea!

Verifique todas las cajas de prueba a la vez. (Ligeramente modificado.)

Monja permeable
fuente
No estoy seguro de si funciona, pero ¿puedes hacerlo en J€lugar de hacerlo L€R€?
Adnan
1
Dios mío, eres un genio.
Leaky Nun
4

Python 2 - 60 60 57 bytes

Es un fragmento de código, por lo que supondría unos pocos bytes más si realmente devuelvo el valor. e=enumerate;sum(i*(x+y==i)for x,r in e(a)for y,i in e(r))

Gracias por la ayuda Leaky Num :-)

Explicación rápida aes una matriz que contiene números. Simplemente recorra los índices y sume todos los valores donde el valor sea igual a la suma del índice.

Jeremy
fuente
oh no funcionó ahora son 57 bytes: (agregué una explicación rápida
Jeremy
Es posible que desee incluir el enlace que acabo de darle.
Leaky Nun
4

R, 24 bytes

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

Basado en 1.
Casos de prueba:

> 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
plannapus
fuente
3

J, 15 bytes

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

Utiliza indexación basada en cero y supone que la matriz ya está almacenada en la variable M .

Explicación

+/,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
millas
fuente
3
No solo el más corto hasta ahora; +1 por hacerlo en un idioma Iverson.
Adám
3

CJam, 23 21 20 bytes

Gracias a Peter Taylor por guardar 3 bytes.

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

Espera que la matriz esté en la pila y deja la suma en su lugar. Los índices están basados ​​en cero en cualquier caso.

Pruébalo aquí.

Martin Ender
fuente
Puede guardar una pareja en _,,lugar del interno eey .para el bucle interno:ee{~_,,@f+1$.=.*~}%1b
Peter Taylor
@PeterTaylor Ah ordenado, gracias. :)
Martin Ender
De hecho, hay uno más, haciendo una especie de encuentro en el medio:ee{~_@f-_,,.=.*~}%1b
Peter Taylor
3

k4, 24 bytes

Asume que la matriz está almacenada m.

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

Este es uno de esos acertijos donde las simplificaciones involucradas en el diseño de k a partir de APL (y J) realmente duelen: k !es el equivalente de APL pero solo funciona en vectores, así que tengo que armar la matriz de índices yo mismo; El producto interno es un carácter en APL pero cinco en k; y pierdo tres caracteres por manejar la matriz vacía correctamente porque k no tiene matrices fuertemente tipadas.

Aaron Davies
fuente
2
Por otro lado, tienes un lenguaje poderoso que es mucho más consistente y con muchos menos primitivos para aprender.
Adám
2

PowerShell v2 +, 43 bytes

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

Como un fragmento El uso es canalizar explícitamente la matriz a esto (ver ejemplos a continuación). Asume eso $i, y $oson nulos o cero al comienzo (los configuré explícitamente como tales en los ejemplos a continuación), y utiliza 0-index.

Hace un bucle foreach en cada fila de la matriz. Nosotros fijamos$j a 0, y luego ir a través de cada elemento de la fila en otro bucle $_|%{...}. Cada bucle interno, incrementamos $opor el elemento actual multiplicado por un booleano ($_-eq$i+$j++), lo que significa que si ese booleano es $TRUE, lo será 1, de lo contrario 0. Luego salimos del bucle interno, incrementamos $iy comenzamos la siguiente fila. Finalmente nos vamos$o en la tubería al final.

Ejemplos

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
AdmBorkBork
fuente
2

Ruby, 63 bytes

Con z como una matriz bidimensional de números:

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

No es terriblemente emocionante en absoluto.

Si z es una matriz aplanada con xey teniendo los tamaños de las matrices, como por ejemplo:

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

Luego tenemos esta monstruosidad, quizás más rubí con sus lujosos productos y cremalleras, pero en realidad más grande:

(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
fuente
Quizás haya un método más elegante de matriz o enumerador que lo acortaría, aún no lo he encontrado, pero me encantaría verlo.
David Ljung Madison Stellar
2

En realidad, 21 bytes

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

Pruébalo en línea!

Gracias a Leaky Nun por hacerme dejar de ser flojo y finalmente escribir esto.

Esto utiliza matrices indexadas a 0 y toma la entrada como una lista anidada.

Explicación:

ñ`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
Mego
fuente
2

Matlab / Octave, 48 bytes

1 indexado.

No manejará el primer caso de prueba porque [1:0]tiene un tamaño de 1x0 por alguna razón

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

Probado en Octave 3.

Programa completo:

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)))
SpamBot
fuente
Bienvenido a PPCG! En Octave puedes hacer sum((M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0))(:)). Además, creo que puede cambiar ==0por e inicial ~para reducir aún más el recuento de bytes. Finalmente, tenga en cuenta que debe manejar todos los casos de prueba o, de lo contrario, la pregunta debe eliminarse
Luis Mendo
1

Lua, 70 bytes

1 indexado.

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

Bonificación: ¡funciona para matrices irregulares!

Entrada almacenada en a, salida almacenada en s.

Programa completo:

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}})
Monja permeable
fuente
1

PHP, 59 bytes

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

espera la matriz $ a definida; debe estar vacío o bidimensional, indexado a 0.
calcula la suma a $ s (anteriormente 0 o indefinido - 0 es igual a NULL)
inserte +2antes del final )para un comportamiento indexado 1

Feliz cumpleaños APL!

funciones y conjunto de pruebas

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));
}
Tito
fuente
1

Brachylog , 15 bytes

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

Pruébalo en línea!

              +    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.
Cadena no relacionada
fuente
1

Wolfram Language (Mathematica) , 42 bytes

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

Pruébalo en línea!

1 indexado.

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*)
attinat
fuente