La sfida di Dijkstra


23

Presentato in onore di APL come strumento interattivo che compie 50 anni quest'anno

sfondo

Ken [Iverson] presentò il suo documento Formalismo nei linguaggi di programmazione nell'agosto del 1963 ad una conferenza di lavoro sulle strutture del linguaggio meccanico, Princeton, NJ L'elenco dei confidenti è pieno di nomi famosi e che presto saranno noti, e alcuni futuri vincitori del Turing Award (Backus, Curry, Dijkstra, Floyd, Iverson, Newell, Perlis, Wilkes). Il documento registra anche la discussione che si è verificata dopo la presentazione, terminando con uno scambio tra Ken e [Edsger] Dijkstra , in cui la risposta di Ken alla domanda di Dijkstra è stata univoca.

Sfida

Come rappresenteresti un'operazione più complessa, ad esempio la somma di tutti gli elementi di una matrice M che sono uguali alla somma degli indici di riga e colonna corrispondenti?

Scrivi uno snippet o un'espressione (non è necessario un programma o una funzione completi) per calcolare la somma di ciascun elemento in una data matrice intera che è uguale alla somma dei suoi indici. Oppure, come dice FryAmTheEggman: data una matrice M con elementi a ij restituisce la somma di ciascuno a ij dove a ij = i + j.

È possibile supporre che la matrice si trovi già in una posizione di memoria o variabile, oppure è possibile prenderla come argomento o input. È possibile utilizzare indici basati su 0 o 1.

Casi test

 

0 per matrice vuota

2

0per 0 indici basati o 2per 1 base

1 5 2
9 4 2
5 9 6

2per 0 in base o 10per 1 in 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

6per 0 in base o 3per 1 in base

aneddoto

La risposta di Iverson fu ++ / ( M = ¹ ⨢ ¹) // M , che non è né valido nella Notazione Iverson come definita in Un linguaggio di programmazione , né in quello che alla fine divenne APL. Nella notazione di Iverson, sarebbe stato + / ( M = ¹ ( μ ( M )) ⨢ ¹ ( ν ( M ))) / M . Era nelle primissime versioni di APL +/(,M=(⍳1↑⍴M)∘.+⍳1↓⍴M)/,M.


in cui la risposta di Ken alla domanda di Dijkstra era una linea. Ma allora quel one-liner era sbagliato?
Luis Mendo,

Devo stamparlo o stamparlo o posso semplicemente scrivere l'espressione come frammento?
Leaky Nun,

2
@LuisMendo No, Iverson stava progettando attivamente il linguaggio e, a quell'iterazione, il suo one-liner era corretto. "APL" è diventato famoso con la pubblicazione del libro A P rogramming L anguage , ma al momento della pubblicazione era necessaria la seconda espressione. Nessuna di queste notazioni è mai stata implementata per essere eseguibile in macchina.
Adám,

@LeakyNun Scrivi uno snippet o un'espressione da calcolare
Adám,

@Adám Grazie. Adesso ha più senso
Luis Mendo,

Risposte:


9

APL, 13 12 byte

1 byte grazie a @ jimmy23013.

1-indicizzati.

L'array è archiviato nella variabile m.

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

Provalo online!

Basato sulla risposta in J , che è una lingua basata su APL.

In TryAPL, per digitare: +/m`em`c`1+/`1`i`rm

Con l'array: +/m`em`c`1+/`1`i`rm `[ 2 4 `r 3 `21 3 3 3 `21 3 1

Spiegazione

+/∊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

Finalmente stavo aspettando questo.
Adám,

Non sono sicuro che "Digitare:" sia una buona idea. Si applica solo a TryAPL e RIDE, ma non al prodotto principale. Almeno puoi spiegare che `significa "chiave APL".
Adám,

1
+/∊m∩¨+/¨⍳⍴m.
jimmy23013,

@ jimmy23013 È davvero bello!
Adám,

9

MATL , 15 14 10 byte

3#fbb+y=*s

L'input ha righe separate da ;. Ad esempio: [1 5 2; 9 4 2; 5 9 6]. Viene utilizzata l'indicizzazione basata su 1.

Provalo online! Oppure verifica tutti i casi di test .

Spiegazione

Userò l'esempio con input [3 -1 3 3; 3 -1 3 1]nella spiegazione.

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 byte

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

Modifica: salvato 3 byte grazie a @MartinEnder sottolineando che i frammenti sono consentiti.


5

Retina , 46 byte

Il conteggio dei byte presuppone la codifica ISO 8859-1.

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

L'input utilizza separatori di spazio e avanzamento riga per rappresentare la matrice. Gli indici sono basati su 0.

Provalo online!

Spiegazione

Non proprio il tipo di sfida per cui Retina è stata fatta, ma sta sorprendentemente bene ... :)

Fase 1: sostituzione

\d+
$*

Questo semplicemente espande tutti i numeri interi nella stringa come numeri unari usando 1come cifra unaria. Numeri negativi come -3diventeranno semplicemente cose come -111.

Fase 2: incontro

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

Grazie !all'opzione, questo stampa tutte le corrispondenze della regex data. Detto regex utilizza gruppi di bilanciamento per verificare se il numero corrente è uguale alla somma dei suoi indici.

Per fare ciò, determiniamo innanzitutto la somma degli indici con il lookbehind (?<=(\S* |.*¶)*). Ciò aggiunge una cattura per ogni numero davanti a quello corrente sulla stessa linea (via \S* ), nonché una cattura per ogni linea davanti a quella corrente (via .*¶) al gruppo1 . Quindi, otteniamo la somma di indici a base zero come risultato.

Quindi proviamo a far corrispondere l'intero numero successivo mentre rimuoviamo le acquisizioni da questo stack con (?<-1>1)+\b. E allora facciamo la partita fallire se eventuali catture vengono lasciati sul gruppo 1con (?(1)1)a garantire la parità.

Si noti che i numeri negativi non sono mai abbinati, perché il lookbehind non può andare oltre la -davanti lista di 1s ed il (?<-1>1)+non può corrispondere neanche.

Questo ci dà un elenco di tutti i numeri unari che equivalgono alla somma dei loro indici.

Fase 3: partita

1

Concludiamo con un altro stadio di match, ma senza l' !opzione, questo conta solo il numero di match, che somma sia tutti i numeri unari del risultato precedente sia converte anche la somma in decimale.


Puoi usare unario come input?
Leaky Nun,

@LeakyNun Non lo so, ho cercato di evitarlo. Sembra troppo confuso, soprattutto perché Retina non ha più problemi con la conversione.
Martin Ender,


4

Python 2 - 60 57 byte

È uno snippet di codice, quindi sarebbe qualche byte in più se effettivamente restituissi il valore, immagino. e=enumerate;sum(i*(x+y==i)for x,r in e(a)for y,i in e(r))

Grazie per l'aiuto Leaky Num :-)

Spiegazione veloce. aè un array che contiene numeri. Basta scorrere gli indici e sommare tutti i valori in cui il valore è uguale alla somma dell'indice.



oh non ha funzionato. quindi i suoi 57 byte ora: (ho aggiunto una breve spiegazione
Jeremy,

Potresti voler includere il link che ti ho appena dato.
Leaky Nun,

4

R, 24 byte

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

1-based.
Casi 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

3

J, 15 byte

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

Usi indicizzazione base zero e assume la matrice è già memorizzato nella variabile M .

Spiegazione

+/,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
Non solo il più breve finora; +1 per averlo fatto in una lingua Iverson.
Adám,

3

CJam, 23 21 20 byte

Grazie a Peter Taylor per aver salvato 3 byte.

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

Si aspetta che la matrice sia in pila e lascia invece la somma. Gli indici sono a base zero in entrambi i casi.

Provalo qui.


Puoi salvare una coppia con _,,invece di quella interna eee .per il circuito interno:ee{~_,,@f+1$.=.*~}%1b
Peter Taylor,

@PeterTaylor Ah pulito, grazie. :)
Martin Ender,

In effetti, ce n'è un altro, facendo una sorta di raduno al centro:ee{~_@f-_,,.=.*~}%1b
Peter Taylor,

3

k4, 24 byte

Presuppone che la matrice sia memorizzata m.

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

Questo è uno di quei rompicapo in cui le semplificazioni implicate nella progettazione di k da APL (e J) fanno davvero male: k !è l'equivalente di APL ma funziona solo su vettori, quindi devo assemblare io stesso la matrice di indici; il prodotto interno è un personaggio in APL ma cinque in k; e perdo tre caratteri nel maneggiare correttamente la matrice vuota perché k non ha matrici fortemente tipizzate.


2
D'altra parte, hai un linguaggio potente che è molto più coerente e con molte meno primitive da imparare.
Adám,


2

PowerShell v2 +, 43 byte

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

Come frammento. L'utilizzo consiste nel reindirizzare esplicitamente la matrice a questo (vedere gli esempi seguenti). Suppone che $i, e$o sono nulli o nulli all'inizio (li ho esplicitamente impostati come tali negli esempi seguenti) e utilizza 0-index.

Esegue un ciclo foreach su ogni riga della matrice. Abbiamo impostato $jsu 0, quindi esaminiamo ogni elemento della riga in un altro ciclo $_|%{...}. Ogni ciclo interno, incrementiamo $oper l'elemento corrente moltiplicato per un booleano ($_-eq$i+$j++), il che significa che se quel booleano è $TRUE, lo sarà 1, altrimenti 0. Quindi usciamo dal ciclo interno, incrementiamo $ie iniziamo la riga successiva. Alla fine, partiamo$o in cantiere alla fine.

Esempi

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

Rubino, 63 byte

Con z come matrice bidimensionale di numeri:

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

Per niente terribilmente eccitante.

Se z è un array appiattito con xey che ha le dimensioni degli array, come:

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

Quindi abbiamo questa mostruosità - forse più rubino con i suoi fantasiosi prodotti e cerniere, ma in realtà più 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)}

Forse esiste un array o un metodo enumeratore più elaborato che lo accorcerebbe, non l'ho ancora trovato, ma mi piacerebbe vederlo.
David Ljung Madison Stellar il

2

In realtà, 21 byte

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

Provalo online!

Grazie a Leaky Nun per avermi fatto smettere di essere pigro e finalmente scrivere questo.

Questo utilizza matrici con indice 0 e accetta input come elenco nidificato.

Spiegazione:

ñ`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 / Ottava, 48 byte

1-indicizzati.

Non gestirà il primo caso di test perché [1:0]ha dimensioni 1x0 per qualche motivo

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

Testato in Octave 3.

Programma 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)))

Benvenuti in PPCG! In Octave puoi farlo sum((M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0))(:)). Inoltre, penso che tu possa cambiare ==0da e iniziale ~per ridurre ulteriormente il conteggio dei byte. Infine, tieni presente che devi gestire tutti i casi di test, altrimenti la domanda dovrebbe essere eliminata
Luis Mendo,

1

Lua, 70 byte

1-indicizzati.

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: funziona con array irregolari!

Ingresso memorizzato in a, output archiviato in s.

Programma 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}})

1

PHP, 59 byte

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

si aspetta l'array $ a definito; deve essere vuoto o bidimensionale, indicizzato 0.
calcola la somma in $ s (precedentemente 0 o non definito - 0 uguale a NULL)
inserisce +2prima del finale )per il comportamento con 1 indice

Buon compleanno APL!

funzioni e suite di test

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 byte

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

Provalo 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.

1

Wolfram Language (Mathematica) , 42 byte

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

Provalo online!

1-indicizzati.

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*)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.