Desafio de Dijkstra

23

Apresentado em homenagem à APL como uma ferramenta interativa que completa 50 anos este ano

fundo

Ken [Iverson] apresentou seu artigo Formalismo em linguagens de programação em agosto de 1963, em uma Conferência de Trabalho sobre Estruturas Mecânicas de Linguagem, Princeton, NJ. (Backus, Caril, Dijkstra, Floyd, Iverson, Newell, Perlis, Wilkes). O artigo também registra a discussão que ocorreu após a apresentação, terminando com uma troca entre Ken e [Edsger] Dijkstra , na qual a resposta de Ken à pergunta de Dijkstra foi uma frase.

Desafio

Como você representaria uma operação mais complexa, por exemplo, a soma de todos os elementos de uma matriz M que são iguais à soma dos índices de linha e coluna correspondentes?

Escreva um trecho ou expressão (sem necessidade de um programa ou função completo) para calcular a soma de cada elemento em uma matriz inteira que é igual à soma de seus índices. Ou, como FryAmTheEggman coloca: dada uma matriz M com elementos a ij retorna a soma de cada a ij onde a ij = i + j.

Você pode assumir que a matriz já está em um local de variável ou memória, ou pode ser aceita como argumento ou entrada. Você pode usar índices baseados em 0 ou 1.

Casos de teste

 

0 para matriz vazia

2

0para índices baseados em 0 ou 2para índices baseados em 1

1 5 2
9 4 2
5 9 6

2para 0 com base ou 10para 1 com base

 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 com base ou 3para 1 com base

Anedota

A resposta de Iverson foi ++ / ( M = ¹ ⨢ ) // M , que não é válida na Notação Iverson conforme definida em A Programming Language , nem no que acabou se tornando APL. Em notação Iverson, que teria sido + / ( M = ¹ ( μ ( M )) ⨢ ¹ ( ν ( M ))) / M . Nas primeiras versões do APL era +/(,M=(⍳1↑⍴M)∘.+⍳1↓⍴M)/,M.

Adão
fonte
em que a resposta de Ken à pergunta de Dijkstra foi unilateral. Mas então aquele verso estava errado?
Luis Mendo
Preciso produzi-lo ou imprimi-lo, ou posso simplesmente escrever a expressão como um trecho?
Freira vazando
2
@LuisMendo Não, Iverson estava projetando ativamente o idioma e, nessa iteração, seu one-liner estava correto. "APL" tornou-se famoso com a publicação do livro A P ROGRAMAÇÃO L anguage , mas no momento da publicação, foi necessária a segunda expressão. Nenhuma dessas notações foi implementada para ser executável em máquina.
Adám 19/07/2016
@LeakyNun Escrever um trecho ou expressão para calcular
Adám
@ Adám Obrigado. Agora faz mais sentido
Luis Mendo

Respostas:

9

APL, 13 12 bytes

1 byte graças a @ jimmy23013.

1 indexado.

A matriz é armazenada na variável m.

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

Experimente online!

Com base na resposta em J , que é uma linguagem baseada no APL.

No TryAPL, para digitar: +/m`em`c`1+/`1`i`rm

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

Explicação

+/∊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
Freira Furada
fonte
Finalmente, eu estava esperando por este.
Adám 19/07/2016
Não tenho certeza de que "Para digitar:" é uma boa idéia. Aplica-se apenas ao TryAPL e RIDE, mas não ao produto principal. Pelo menos você pode explicar que `significa "chave APL".
Adám 19/07/2016
11
+/∊m∩¨+/¨⍳⍴m.
jimmy23013
@ jimmy23013 Isso é muito bom!
Adám 19/07/2016
9

MATL , 15 14 10 bytes

3#fbb+y=*s

A entrada possui linhas separadas por ;. Por exemplo: [1 5 2; 9 4 2; 5 9 6]. A indexação baseada em 1 é usada.

Experimente online! Ou verifique todos os casos de teste .

Explicação

Vou usar o exemplo com entrada [3 -1 3 3; 3 -1 3 1]na explicação.

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
fonte
6

JavaScript, 49 46 bytes

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

Editar: salvou 3 bytes graças a @MartinEnder, indicando que os snippets são permitidos.

Neil
fonte
5

Retina , 46 bytes

A contagem de bytes assume a codificação ISO 8859-1.

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

A entrada usa separadores de espaço e avanço de linha para representar a matriz. Os índices são baseados em 0.

Experimente online!

Explicação

Não é exatamente o tipo de desafio para o qual a Retina foi criada, mas está surpreendentemente bem ... :)

Etapa 1: Substituição

\d+
$*

Isso simplesmente expande todos os números inteiros na string como números unários usando 1como dígito unário. Números negativos como -3simplesmente se tornarão coisas assim -111.

Etapa 2: partida

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

Devido à !opção, isso imprime todas as correspondências do regex especificado. O referido regex usa grupos de balanceamento para verificar se o número atual é igual à soma de seus índices.

Para fazer isso, primeiro determinamos a soma dos índices com o lookbehind (?<=(\S* |.*¶)*). Isso adiciona uma captura para cada número na frente do atual na mesma linha (via \S* ), bem como uma captura para cada linha na frente do atual (via .*¶) para agrupar 1. Portanto, obtemos a soma dos índices com base em zero como resultado.

Em seguida, tentamos corresponder o próximo número inteiro enquanto removemos capturas dessa pilha com (?<-1>1)+\b. E, então, fazer o jogo falhar se quaisquer capturas são deixados em grupo 1com (?(1)1)para assegurar a igualdade.

Observe que os números negativos nunca são correspondidos, porque o lookbehind não pode passar da -frente da lista de 1s e (?<-1>1)+também não pode corresponder.

Isso nos fornece uma lista de todos os números unários que são iguais à soma de seus índices.

Etapa 3: partida

1

Terminamos com outro estágio de correspondência, mas sem a !opção, isso apenas conta o número de correspondências, que soma todos os números unários do resultado anterior e também converte essa soma em decimal.

Martin Ender
fonte
Você pode usar unário como entrada?
Freira vazando
@LeakyNun Não sei, eu meio que tentei evitá-lo. Parece muito hacky, especialmente porque o Retina não tem mais problemas com a conversão.
Martin Ender
4

Geléia, 15 14 10 bytes

4 bytes graças a Adnan.

1 indexado.

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

Experimente online!

Verifique todos os casos de teste de uma só vez. (Ligeiramente modificado.)

Freira Furada
fonte
Não tenho certeza se funciona, mas você pode fazer em J€vez de L€R€?
21416 Adnan
11
Oh meu Deus, você é um gênio.
Leaky Nun
4

Python 2 - 60 57 bytes

É um trecho de código, portanto, seriam mais alguns bytes se eu realmente retornasse o valor, eu acho. e=enumerate;sum(i*(x+y==i)for x,r in e(a)for y,i in e(r))

Obrigado pela ajuda Leaky Num :-)

Explicação rápida. aé uma matriz contendo números. Basta percorrer os índices e somar todos os valores em que o valor é igual à soma do índice.

Jeremy
fonte
ah não deu certo. então seus 57 bytes agora: (Adicionei uma explicação rápida
Jeremy
Você pode querer incluir o link que acabei de fornecer.
Freira vazando
4

R, 24 bytes

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

Baseado em 1.
Casos de teste:

> 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
fonte
3

J, 15 bytes

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

Usos indexação baseado em zero e assume a matriz já está armazenado na variável M .

Explicação

+/,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
milhas
fonte
3
Não é apenas o mais curto até agora; +1 por fazê-lo no idioma Iverson.
Adám 19/07/2016
3

CJam, 23 21 20 bytes

Agradecemos a Peter Taylor por salvar 3 bytes.

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

Espera que a matriz esteja na pilha e deixa a soma. Os índices são baseados em zero em ambos os casos.

Teste aqui.

Martin Ender
fonte
Você pode salvar um casal com, em _,,vez do interior eee. para o loop interno:ee{~_,,@f+1$.=.*~}%1b
Peter Taylor
@ PeterTaylor Ah legal, obrigado. :)
Martin Ender
Na verdade, há mais um, fazendo uma espécie de meet-in-the-middle:ee{~_@f-_,,.=.*~}%1b
Peter Taylor
3

k4, 24 bytes

Assume que a matriz está armazenada m.

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

Esse é um daqueles quebra-cabeças em que as simplificações envolvidas no projeto de k de APL (e J) realmente doem - k's !é equivalente a APLs, mas só funciona em vetores, então eu mesmo tenho que montar a matriz de índices; produto interno é um caractere em APL, mas cinco em k; e perco três caracteres ao manipular adequadamente a matriz vazia porque k não possui matrizes fortemente tipadas.

Aaron Davies
fonte
2
Por outro lado, você tem uma linguagem poderosa, muito mais consistente e com muito menos primitivos para aprender.
Adám
2

PowerShell v2 +, 43 bytes

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

Como um trecho. O uso é canalizar explicitamente a matriz para isso (veja exemplos abaixo). Assume que$i e $oé nulo ou zero no início (eu os configurei explicitamente como tal nos exemplos abaixo) e utiliza o índice 0.

Faz um loop foreach em cada linha da matriz. Definimos $jcomo 0e depois percorremos cada elemento da linha em outro loop $_|%{...}. Cada loop interno, incrementamos $opelo elemento atual multiplicado por um booleano ($_-eq$i+$j++), ou seja, se esse booleano for $TRUE, será o 1contrário 0. Então saímos do loop interno, incrementamos$i e iniciamos a próxima linha. Finalmente, partimos $ono oleoduto no final.

Exemplos

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
fonte
2

Ruby, 63 bytes

Com z como uma 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}}

Não é nada empolgante.

Se z é uma matriz achatada com x e y com os tamanhos das matrizes, como:

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

Então temos essa monstruosidade - talvez mais rubi-ish com seus produtos sofisticados e zíperes, mas na verdade maiores:

(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
fonte
Talvez exista um método mais sofisticado de matriz ou enumerador que o encurte, ainda não o encontrei, mas adoraria vê-lo.
David Ljung Madison Stellar
2

Na verdade, 21 bytes

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

Experimente online!

Agradeço ao Leaky Nun por me fazer parar de ser preguiçoso e finalmente escrever isso.

Isso usa matrizes indexadas a 0 e recebe a entrada como uma lista aninhada.

Explicação:

ñ`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
fonte
2

Matlab / Octave, 48 bytes

1 indexado.

Não manipulará o primeiro caso de teste porque [1:0], por algum motivo, tem tamanho 1x0

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

Testado na oitava 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
fonte
Bem-vindo ao PPCG! No Octave você pode fazer sum((M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0))(:)). Além disso, acho que você pode alterar ==0e inicial ~para reduzir ainda mais a contagem de bytes. Finalmente, note que você precisa para lidar com todos os casos de teste ou então a questão deve ser excluída
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

Bônus: funciona para matrizes irregulares!

Entrada armazenada a, saída armazenada em 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}})
Freira Furada
fonte
1

PHP, 59 bytes

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

espera matriz $ a definida; deve estar vazio ou bidimensional, com indexação 0.
calcula a soma para
inserção de $ s (anteriormente 0 ou indefinido - 0 é igual a NULL) +2antes da final )para o comportamento indexado a 1

Feliz aniversário APL!

funções e suíte de testes

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));
}
Titus
fonte
1

Braquilog , 15 bytes

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

Experimente online!

              +    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.
String não relacionada
fonte
1

Wolfram Language (Mathematica) , 42 bytes

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

Experimente online!

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
fonte