Wyzwanie Dijkstry


23

Prezentowane na cześć APL jako interaktywne narzędzie, które w tym roku skończy 50 lat

tło

Ken [Iverson] przedstawił swój artykuł Formalizm w programowaniu języków w sierpniu 1963 r. Na konferencji roboczej w sprawie mechanicznych struktur językowych, Princeton, NJ. Lista uczestników jest pełna sławnych i niedługo sławnych nazwisk oraz kilku przyszłych zwycięzców nagrody Turinga (Backus, Curry, Dijkstra, Floyd, Iverson, Newell, Perlis, Wilkes). W artykule zapisano również dyskusję, która miała miejsce po prezentacji, kończącą się wymianą między Kenem a [Edsgerem] Dijkstrą , w której odpowiedź Kena na pytanie Dijkstry była jednokierunkowa.

Wyzwanie

Jak przedstawiłbyś bardziej złożoną operację, na przykład sumę wszystkich elementów macierzy M, które są równe sumie odpowiednich indeksów wierszy i kolumn?

Napisz fragment kodu lub wyrażenie (nie potrzeba pełnego programu lub funkcji), aby obliczyć sumę każdego elementu w danej macierzy liczb całkowitych, która jest równa sumie jego indeksów. Lub, FryAmTheEggman mówi: podane macierz M elementy ij powrotu sumy każdego ij gdzie ij = i + J.

Możesz założyć, że macierz jest już w miejscu zmiennej lub pamięci, lub możesz potraktować ją jako argument lub dane wejściowe. Możesz użyć indeksów opartych na 0 lub 1.

Przypadki testowe

 

0 dla pustej matrycy

2

0dla indeksów opartych na 0 lub 2dla bazujących na 1

1 5 2
9 4 2
5 9 6

2dla 0 lub 101 dla

 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

6dla 0 lub 31 dla

Anegdota

Odpowiedź Iversona brzmiała ++ / ( M = ¹ ⨢ ¹) // M , co nie jest ani poprawne w notacji Iverson, jak zdefiniowano w A Programming Language , ani w tym, co ostatecznie stało się APL. W notacji Iverson, byłoby + / ( M = đ ( μ ( M )) ⨢ đ ( ν ( M ))) / M . Tak było w pierwszych wersjach APL +/(,M=(⍳1↑⍴M)∘.+⍳1↓⍴M)/,M.


w której odpowiedź Kena na pytanie Dijkstry była jednokierunkowa. Ale w takim razie ten jednowarstwowy produkt był błędny?
Luis Mendo,

Czy muszę go wydrukować lub wydrukować, czy też mogę zapisać wyrażenie jako fragment?
Leaky Nun

2
@LuisMendo Nie, Iverson aktywnie projektował język i przy tej iteracji jego linijka była poprawna. „APL” zasłynął z publikacją książki P ROGRAMOWANIE L anguage , ale w momencie publikacji, drugie wyrażenie było potrzebne. Żadna z tych notacji nigdy nie została zaimplementowana, aby była wykonywalna na komputerze.
Adám,

@LeakyNun Napisz fragment lub wyrażenie do obliczenia
Adám

@ Adám Thanks. Teraz ma to większy sens
Luis Mendo,

Odpowiedzi:


9

APL, 13 12 bajtów

1 bajt dzięki @ jimmy23013.

1-indeksowany.

Tablica jest przechowywana w zmiennej m.

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

Wypróbuj online!

Na podstawie odpowiedzi w J , która jest językiem opartym na APL.

W TryAPL, aby wprowadzić: +/m`em`c`1+/`1`i`rm

Z tablicą: +/m`em`c`1+/`1`i`rm `[ 2 4 `r 3 `21 3 3 3 `21 3 1

Wyjaśnienie

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

W końcu czekałem na to.
Adám,

Nie jestem pewien, czy „Aby wprowadzić:” jest dobrym pomysłem. Dotyczy to tylko TryAPL i RIDE, ale nie dotyczy głównego produktu. Przynajmniej możesz wyjaśnić, że `to znaczy „klucz APL”.
Adám,

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

@ jimmy23013 To naprawdę dobrze!
Adám

9

MATL , 15 14 10 bajtów

3#fbb+y=*s

Dane wejściowe mają wiersze oddzielone ;. Na przykład: [1 5 2; 9 4 2; 5 9 6]. Stosowane jest indeksowanie 1.

Wypróbuj online! Lub sprawdź wszystkie przypadki testowe .

Wyjaśnienie

Użyję tego przykładu z [3 -1 3 3; 3 -1 3 1]danymi wejściowymi w wyjaśnieniu.

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 bajtów

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

Edycja: Zapisano 3 bajty dzięki @MartinEnder wskazując, że fragmenty są dozwolone.


5

Siatkówka , 46 bajtów

Liczba bajtów zakłada kodowanie ISO 8859-1.

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

Dane wejściowe używają separatorów przestrzeni i kanału liniowego do reprezentowania macierzy. Indeksy są oparte na 0.

Wypróbuj online!

Wyjaśnienie

Nie do końca takie wyzwanie, dla którego stworzono Retinę, ale robi się zaskakująco dobrze ... :)

Etap 1: Zmiana

\d+
$*

To po prostu rozszerza wszystkie liczby całkowite w ciągu jako liczby jednoargumentowe, używając 1jako cyfry jednoargumentowej. Liczby ujemne -3po prostu staną się takimi jak -111.

Etap 2: Mecz

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

Z powodu tej !opcji powoduje to wydrukowanie wszystkich dopasowań podanego wyrażenia regularnego. Wspomniany regex używa grup bilansujących do sprawdzenia, czy bieżąca liczba jest taka sama jak suma jego wskaźników.

Aby to zrobić, najpierw określamy sumę wskaźników za pomocą lookbehind (?<=(\S* |.*¶)*). Dodaje to jedno przechwytywanie dla każdego numeru przed bieżącym na tej samej linii (przez \S* ), a także jedno przechwytywanie dla każdej linii przed bieżącym (przez .*¶) do grupy 1. W rezultacie otrzymujemy zerową sumę wskaźników.

Następnie próbujemy dopasować cały następny numer, usuwając przechwytywanie z tego stosu (?<-1>1)+\b. A następnie wykonujemy nie mecz, czy nie przechwytuje są pozostawione na grupy 1z (?(1)1)celu zapewnienia równości.

Zauważ, że liczby ujemne nigdy nie są dopasowywane, ponieważ wygląd nie może przekroczyć -pierwszej listy 1i (?<-1>1)+nie może się z nią równać.

To daje nam listę wszystkich liczb jednostkowych, które są równe sumie ich wskaźników.

Etap 3: Mecz

1

Kończymy kolejnym etapem dopasowania, ale bez tej !opcji liczy się tylko liczba dopasowań, która zarówno sumuje wszystkie liczby jednostkowe z poprzedniego wyniku, jak i konwertuje tę sumę z powrotem na dziesiętne.


Czy możesz użyć unary jako danych wejściowych?
Leaky Nun

@LeakyNun Nie wiem, próbowałem tego uniknąć. Wydaje się to po prostu zbyt hackujące, zwłaszcza że Retina nie ma już problemów z konwersją.
Martin Ender


4

Python 2 - 60 57 bajtów

Jest to fragment kodu, więc chyba zwróciłbym wartość, jak sądzę. e=enumerate;sum(i*(x+y==i)for x,r in e(a)for y,i in e(r))

Dzięki za pomoc Leaky Num :-)

Szybkie wyjaśnienie. ajest tablicą zawierającą liczby. Po prostu iteruj przez indeksy i zsumuj wszystkie wartości, których wartość jest równa sumie indeksu.



och, to nie zadziałało. więc teraz ma 57 bajtów: (Dodałem szybkie wyjaśnienie
Jeremy,

Możesz dołączyć link, który ci właśnie podałem.
Leaky Nun

4

R, 24 bajty

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

Na podstawie 1.
Przypadki testowe:

> 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 bajtów

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

Używa się od zera indeksowania i przyjmuje matrycy jest już przechowywany w zmiennej M .

Wyjaśnienie

+/,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
Nie tylko najkrótszy do tej pory; +1 za zrobienie tego w języku Iverson.
Adám,

3

CJam, 23 21 20 bajtów

Podziękowania dla Petera Taylora za oszczędność 3 bajtów.

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

Oczekuje, że macierz będzie na stosie i zamiast tego pozostawi sumę. Wskaźniki są zerowane w obu przypadkach.

Sprawdź to tutaj.


Możesz uratować parę z _,,zamiast wewnętrznej eei .wewnętrznej pętli:ee{~_,,@f+1$.=.*~}%1b
Peter Taylor

@PeterTaylor Ah schludnie, dziękuję. :)
Martin Ender

W rzeczywistości istnieje jeszcze jeden rodzaj spotkania w środku:ee{~_@f-_,,.=.*~}%1b
Peter Taylor

3

k4, 24 bajty

Zakłada, że ​​macierz jest przechowywana w m.

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

Jest to jedna z tych zagadek, w których uproszczenia związane z projektowaniem k z APL (i J) naprawdę boli - k's !jest odpowiednikiem APL, ale działa tylko na wektorach, więc sam muszę zestawić macierz indeksów; iloczyn wewnętrzny to jedna postać w APL, ale pięć w k; i tracę trzy znaki, aby poprawnie obsługiwać pustą macierz, ponieważ k nie ma silnie typowanych macierzy.


2
Z drugiej strony masz potężny język, który jest o wiele bardziej spójny i z mniejszą liczbą prymitywów do nauki.
Adám,


2

PowerShell v2 +, 43 bajty

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

Jako fragment. Zastosowanie polega na jawnym potokowaniu macierzy do tego (patrz przykłady poniżej). Zakłada się, że $ii $osą albo wartość null lub zero na początku (mam jawnie ustawić je jako takie w poniższych przykładach) i wykorzystuje 0-index.

Wykonuje pętlę foreach w każdym rzędzie macierzy. Ustawiamy $jsię 0, a następnie przejść przez każdy element w rzędzie w innej pętli $_|%{...}. Każdą wewnętrzną pętlę zwiększamy $oprzez bieżący element pomnożony przez wartość logiczną ($_-eq$i+$j++), co oznacza, że ​​jeśli ta wartość logiczna jest $TRUE, to w 1przeciwnym razie będzie 0. Następnie wychodzimy z wewnętrznej pętli, zwiększamy $ii rozpoczynamy następny rząd. Na koniec wychodzimy $oz rurociągu na końcu.

Przykłady

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

Rubinowy, 63 bajty

Z z jako dwuwymiarowa tablica liczb:

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

Wcale nie strasznie ekscytujące.

Jeśli z jest spłaszczoną tablicą z xiy mającymi rozmiary tablic, takie jak:

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

Następnie mamy tę potworność - być może bardziej rubinową z jej fantazyjnymi produktami i zamkami, ale w rzeczywistości większą:

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

Być może istnieje bardziej wyszukana tablica lub metoda wyliczająca, która by ją skróciła, jeszcze jej nie znalazłem, ale chciałbym to zobaczyć.
David Ljung Madison Stellar

2

Właściwie 21 bajtów

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

Wypróbuj online!

Dzięki Leaky Nun za to, że przestałem być leniwy i wreszcie to napisałem.

Wykorzystuje macierze 0-indeksowane i przyjmuje dane wejściowe jako listę zagnieżdżoną.

Wyjaśnienie:

ñ`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 / Octave, 48 bajtów

1-indeksowany.

Nie obsłuży pierwszego przypadku testowego, ponieważ [1:0]z jakiegoś powodu ma rozmiar 1x0

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

Testowane w Octave 3.

Pełny program:

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

Witamy w PPCG! W Octave możesz to zrobić sum((M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0))(:)). Ponadto myślę, że możesz zmienić ==0i początkowo, ~aby dodatkowo zmniejszyć liczbę bajtów. Wreszcie należy pamiętać, że trzeba obsłużyć wszystkich przypadków testowych, albo pytanie powinno zostać usunięte
Luis Mendo

1

Lua, 70 bajtów

1-indeksowany.

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: działa dla tablic obdartych!

Wejście zapisane w a, wyjście zapisane w s.

Pełny program:

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 bajtów

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

oczekuje, że tablica $ jest zdefiniowana; musi być pusty lub dwuwymiarowy, z indeksowaniem 0.
oblicza sumę do $ s (poprzednio 0 lub niezdefiniowany - 0 równa się NULL)
wstawić +2przed końcem) dla zachowania 1-indeksowanego

Wszystkiego najlepszego APL!

funkcje i pakiet testowy

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 bajtów

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

Wypróbuj 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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.