Le défi de Dijkstra

23

Présenté en l'honneur d' APL comme un outil interactif qui aura 50 ans cette année

Contexte

Ken [Iverson] a présenté son article Formalisme dans les langages de programmation en août 1963 lors d'une conférence de travail sur les structures de langage mécanique, à Princeton, NJ. (Backus, Curry, Dijkstra, Floyd, Iverson, Newell, Perlis, Wilkes). Le document enregistre également la discussion qui a eu lieu après la présentation, se terminant par un échange entre Ken et [Edsger] Dijkstra , dans lequel la réponse de Ken à la question de Dijkstra était unilatérale.

Défi

Comment représenteriez-vous une opération plus complexe, par exemple, la somme de tous les éléments d'une matrice M qui sont égaux à la somme des indices de ligne et de colonne correspondants?

Écrivez un extrait ou une expression (pas besoin d'un programme ou d'une fonction complète) pour calculer la somme de chaque élément dans une matrice entière donnée qui est égale à la somme de ses indices. Ou, comme le dit FryAmTheEggman: étant donné une matrice M avec des éléments a ij renvoie la somme de chacun a ija ij = i + j.

Vous pouvez supposer que la matrice se trouve déjà dans un emplacement de variable ou de mémoire, ou vous pouvez la prendre comme argument ou entrée. Vous pouvez utiliser des indices basés sur 0 ou 1.

Cas de test

 

0 pour matrice vide

2

0pour les indices basés sur 0 ou 2pour les indices basés sur 1

1 5 2
9 4 2
5 9 6

2pour 0 basé ou 10pour 1 basé

 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

6pour 0 basé ou 3pour 1 basé

Anecdote

La réponse d'Iverson était ++ / ( M = ¹ ⨢ ¹) // M , qui n'est ni valide dans la notation Iverson telle que définie dans A Programming Language , ni dans ce qui est finalement devenu APL. Dans la notation Iverson, il aurait été de + / ( M = ¹ ( μ ( M )) ⨢ ¹ ( ν ( M ))) / M . C'était dans les toutes premières versions d'APL +/(,M=(⍳1↑⍴M)∘.+⍳1↓⍴M)/,M.

Adam
la source
dans lequel la réponse de Ken à la question de Dijkstra était une ligne simple. Mais alors ce one-liner était faux?
Luis Mendo
Dois-je le sortir ou l'imprimer, ou puis-je simplement écrire l'expression sous forme d'extrait?
Leaky Nun
2
@LuisMendo Non, Iverson concevait activement la langue, et à cette itération, son one-liner était correct. "APL" est devenu célèbre avec la publication du livre A P rogramming L anguage , mais au moment de la publication, la deuxième expression était nécessaire. Aucune de ces notations n'a jamais été implémentée pour être exécutable par une machine.
Adám
@LeakyNun Écrivez un extrait ou une expression à calculer
Adam
@ Adám Merci. Cela a plus de sens maintenant
Luis Mendo

Réponses:

9

APL, 13 12 octets

1 octet grâce à @ jimmy23013.

1 indexé.

Le tableau est stocké dans la variable m.

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

Essayez-le en ligne!

Basé sur la réponse de J , qui est un langage basé sur APL.

Dans TryAPL, pour saisir: +/m`em`c`1+/`1`i`rm

Avec le tableau: +/m`em`c`1+/`1`i`rm `[ 2 4 `r 3 `21 3 3 3 `21 3 1

Explication

+/∊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
Leaky Nun
la source
Enfin, j'attendais celui-ci.
Adám
Je ne suis pas sûr que le "To key in:" soit une bonne idée. Elle ne s'applique qu'à TryAPL et RIDE, mais pas au produit principal. Au moins, vous pouvez expliquer que cela `signifie "clé APL".
Adám
1
+/∊m∩¨+/¨⍳⍴m.
jimmy23013
@ jimmy23013 C'est vraiment bien!
Adám
9

MATL , 15 14 10 octets

3#fbb+y=*s

L'entrée a des lignes séparées par ;. Par exemple: [1 5 2; 9 4 2; 5 9 6]. L'indexation basée sur 1 est utilisée.

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Explication

Je vais utiliser l'exemple avec entrée [3 -1 3 3; 3 -1 3 1]dans l'explication.

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
la source
6

JavaScript, 49 46 octets

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

Edit: enregistré 3 octets grâce à @MartinEnder soulignant que les extraits sont autorisés.

Neil
la source
5

Rétine , 46 octets

Le nombre d'octets suppose un codage ISO 8859-1.

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

L'entrée utilise des séparateurs d'espace et de saut de ligne pour représenter la matrice. Les indices sont basés sur 0.

Essayez-le en ligne!

Explication

Pas tout à fait le genre de défi pour Retina, mais il se débrouille étonnamment bien ... :)

Étape 1: substitution

\d+
$*

Cela développe simplement tous les entiers de la chaîne sous forme de nombres unaires en utilisant 1comme chiffre unaire. Les nombres négatifs comme -3deviendront simplement des choses comme -111.

Étape 2: Match

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

En raison de l' !option, cela imprime toutes les correspondances de l'expression régulière donnée. Ladite expression régulière utilise des groupes d'équilibrage pour vérifier si le nombre actuel est le même que la somme de ses indices.

Pour ce faire, nous déterminons d'abord la somme des indices avec le lookbehind (?<=(\S* |.*¶)*). Cela ajoute une capture pour chaque numéro devant celui en cours sur la même ligne (via \S* ) ainsi qu'une capture pour chaque ligne devant celui en cours (via .*¶) au groupe 1. Par conséquent, nous obtenons la somme des indices basée sur zéro.

Ensuite, nous essayons de faire correspondre le nombre entier suivant tout en supprimant les captures de cette pile avec (?<-1>1)+\b. Et puis nous faisons échouer la correspondance s'il reste des captures sur le groupe 1avec (?(1)1)pour assurer l'égalité.

Notez que les nombres négatifs ne sont jamais appariés, car le lookbehind ne peut pas dépasser l' -avant de la liste des 1s et (?<-1>1)+ne peut pas non plus correspondre.

Cela nous donne une liste de tous les nombres unaires qui égalent la somme de leurs indices.

Étape 3: Match

1

Nous terminons avec une autre étape de correspondance, mais sans l' !option, cela compte simplement le nombre de correspondances, qui à la fois additionne tous les nombres unaires du résultat précédent et convertit également cette somme en décimale.

Martin Ender
la source
Pouvez-vous utiliser unaire comme entrée?
Leaky Nun
@LeakyNun Je ne sais pas, j'ai essayé de l'éviter. Cela semble trop hacky, d'autant plus que Retina n'a plus aucun problème avec la conversion.
Martin Ender
4

Gelée, 15 14 10 octets

4 octets grâce à Adnan.

1 indexé.

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

Essayez-le en ligne!

Vérifiez tous les tests en même temps. (Légèrement modifié.)

Leaky Nun
la source
Je ne sais pas si cela fonctionne, mais pouvez-vous faire à la J€place de L€R€?
Adnan
1
Oh mon Dieu, tu es un génie.
Leaky Nun
4

Python 2 - 60 57 octets

C'est un extrait de code, donc ce serait quelques octets de plus si je retournais la valeur, je suppose. e=enumerate;sum(i*(x+y==i)for x,r in e(a)for y,i in e(r))

Merci pour l'aide Leaky Num :-)

Explication rapide. aest un tableau contenant des nombres. Parcourez simplement les index et additionnez toutes les valeurs où la valeur est égale à la somme de l'index.

Jeremy
la source
oh ça n'a pas marché. donc ses 57 octets maintenant: (j'ai ajouté une explication rapide
Jeremy
Vous voudrez peut-être inclure le lien que je viens de vous donner.
Leaky Nun
4

R, 24 octets

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

1 basé.
Cas de test:

> 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
la source
3

J, 15 octets

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

Les utilisations indexation de base zéro et assume la matrice est déjà stockée dans la variable M .

Explication

+/,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
miles
la source
3
Pas seulement le plus court jusqu'à présent; +1 pour l'avoir fait dans une langue Iverson.
Adám
3

CJam, 23 21 20 octets

Merci à Peter Taylor d'avoir économisé 3 octets.

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

Attend que la matrice soit sur la pile et laisse la somme à la place. Les indices sont basés sur zéro dans les deux cas.

Testez-le ici.

Martin Ender
la source
Vous pouvez enregistrer un couple avec _,,au lieu de l'intérieur eeet .pour la boucle intérieure:ee{~_,,@f+1$.=.*~}%1b
Peter Taylor
@PeterTaylor Ah bien, merci. :)
Martin Ender
En fait, il y en a un de plus, en faisant une sorte de rencontre au milieu:ee{~_@f-_,,.=.*~}%1b
Peter Taylor
3

k4, 24 octets

Suppose que la matrice est stockée dans m.

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

C'est l'une de ces énigmes où les simplifications impliquées dans la conception de k à partir d'APL (et J) font vraiment mal - les k !sont l'équivalent des APL mais ne fonctionnent que sur les vecteurs, donc je dois assembler moi-même la matrice des indices; le produit intérieur est un caractère en APL mais cinq en k; et je perds trois caractères pour gérer correctement la matrice vide parce que k n'a pas de matrices fortement typées.

Aaron Davies
la source
2
D'un autre côté, vous avez un langage puissant qui est beaucoup plus cohérent et avec beaucoup moins de primitives à apprendre.
Adám
2

PowerShell v2 +, 43 octets

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

Comme extrait. L'usage est de diriger explicitement la matrice vers cela (voir les exemples ci-dessous). Suppose que $i, et $osont soit nuls soit nuls au début (je les ai explicitement définis comme tels dans les exemples ci-dessous), et utilise 0-index.

Effectue une boucle foreach sur chaque ligne de la matrice. Nous nous mettons $jà 0, puis parcourons chaque élément de la ligne dans une autre boucle $_|%{...}. Chaque boucle interne, nous incrémentons $opar l'élément courant multiplié par un booléen ($_-eq$i+$j++), ce qui signifie que si ce booléen est $TRUE, ce sera le cas 1, sinon 0. Ensuite, nous quittons la boucle intérieure, incrémentons $iet commençons la ligne suivante. Enfin, nous partons $osur le pipeline à la fin.

Exemples

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
la source
2

Rubis, 63 octets

Avec z comme tableau bidimensionnel de nombres:

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

Pas terriblement excitant du tout.

Si z est un tableau aplati avec x et y ayant les tailles des tableaux, telles que:

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

Ensuite, nous avons cette monstruosité - peut-être plus rubis avec ses produits fantaisie et ses fermetures éclair, mais en fait plus gros:

(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
la source
Peut-être existe-t-il un tableau plus sophistiqué ou une méthode d'énumérateur qui le raccourcirait, je ne l'ai pas encore trouvé, mais j'aimerais le voir.
David Ljung Madison Stellar
2

En fait, 21 octets

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

Essayez-le en ligne!

Merci à Leaky Nun de m'avoir fait cesser d'être paresseux et enfin d'écrire ceci.

Cela utilise des matrices indexées 0 et prend l'entrée comme une liste imbriquée.

Explication:

ñ`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
la source
2

Matlab / Octave, 48 octets

1 indexé.

Ne gérera pas le premier cas de test car [1:0]a une taille 1x0 pour une raison quelconque

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

Testé en Octave 3.

Programme complet:

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
la source
Bienvenue chez PPCG! Dans Octave, vous pouvez le faire sum((M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0))(:)). En outre, je pense que vous pouvez modifier ==0par et initialiser ~pour réduire davantage le nombre d'octets. Enfin, notez que vous devez gérer tous les cas de test, sinon la question devrait être supprimée
Luis Mendo
1

Lua, 70 octets

1 indexé.

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

Bonus: cela fonctionne pour les tableaux en lambeaux!

Entrée stockée dans a, sortie stockée dans s.

Programme complet:

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}})
Leaky Nun
la source
1

PHP, 59 octets

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

attend le tableau $ a défini; doit être vide ou bidimensionnel, indexé 0.
calcule la somme à $ s (auparavant 0 ou non défini - 0 est égal à NULL)
insérer +2avant la finale )pour un comportement indexé 1

Joyeux anniversaire APL!

fonctions et suite de tests

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
la source
1

Brachylog , 15 octets

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

Essayez-le en ligne!

              +    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.
Chaîne indépendante
la source
1

Wolfram Language (Mathematica) , 42 octets

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

Essayez-le en ligne!

1 indexé.

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
la source