Dijkstra's Challenge


23

Представлено в честь APL как интерактивного инструмента, которому в этом году исполняется 50 лет

Задний план

Кен [Айверсон] представил свою работу « Формализм в языках программирования» в августе 1963 года на рабочей конференции по механическим языковым структурам, Принстон, штат Нью-Джерси. Список участников конференции полон известных и скоро известных имен, а также нескольких будущих лауреатов премии Тьюринга. (Бэкус, Карри, Дейкстра, Флойд, Айверсон, Ньюэлл, Перлис, Уилкс). В документе также записано обсуждение, которое состоялось после презентации, завершившейся обменом между Кеном и [Эдсгером] Дейкстрой , в котором ответ Кена на вопрос Дейкстры был однорядным.

Вызов

Как бы вы представили более сложную операцию, например, сумму всех элементов матрицы M , равных сумме соответствующих индексов строк и столбцов?

Напишите фрагмент или выражение (нет необходимости в полной программе или функции), чтобы вычислить сумму каждого элемента в данной целочисленной матрице, которая равна сумме его индексов. Или, как говорит FryAmTheEggman: для данной матрицы M с элементами a ij возвращают сумму каждого a ij, где a ij = i + j.

Вы можете предположить, что матрица уже находится в переменной или ячейке памяти, или вы можете принять ее в качестве аргумента или ввода. Вы можете использовать 0 или 1 на основе индексов.

Контрольные примеры

 

0 для пустой матрицы

2

0для 0 на основе индексов или 2для 1 на основе

1 5 2
9 4 2
5 9 6

2для 0 на основе или 10для 1 на основе

 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

6для 0 на основе или 3для 1 на основе

Анекдот

Ответ Айверсона был ++ / ( M = ¹ ⨢ ¹) // M , что недопустимо ни в обозначении Айверсона, как определено в языке программирования , ни в том, что в итоге стало APL. В обозначениях Айверсон, было бы + / ( М = ¹ ( μ ( М )) ⨢ ¹ ( ν ( М ))) / М . В самых первых версиях APL это было +/(,M=(⍳1↑⍴M)∘.+⍳1↓⍴M)/,M.


в котором ответ Кена на вопрос Дейкстры был однострочным. Но тогда эта однострочная была не права?
Луис Мендо

Нужно ли выводить его или распечатывать, или я могу просто записать выражение как фрагмент?
Утренняя монахиня

2
@ LuisMendo Нет, Айверсон активно разрабатывал язык, и на этой итерации его однострочный текст был верным. «АПЗ» стал известен с изданием книги P rogramming L anguage , но в то время публикации, было необходимо второе выражение. Ни одна из этих нотаций не была реализована для машинного исполнения.
Адам

@LeakyNun Напишите фрагмент или выражение для вычисления
Adám

@ Adám Спасибо. Это имеет больше смысла сейчас
Луис Мендо

Ответы:


9

APL, 13 12 байт

1 байт благодаря @ jimmy23013.

1-индексироваться.

Массив хранится в переменной m.

+ /, М × м = + / ¨⍳⍴m
+ / + Εm∩¨ / ¨⍳⍴m

Попробуйте онлайн!

На основании ответа в J , который является языком на основе APL.

В TryAPL введите: +/m`em`c`1+/`1`i`rm

С массивом: +/m`em`c`1+/`1`i`rm `[ 2 4 `r 3 `21 3 3 3 `21 3 1

объяснение

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

Наконец-то я ждал этого.
Адам

Я не уверен, что "Чтобы ввести:" это хорошая идея. Это относится только к TryAPL и RIDE, но не к основному продукту. По крайней мере, вы можете объяснить, что `означает «ключ APL».
Адам

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

@ jimmy23013 Это действительно хорошо!
Адам

9

MATL , 15 14 10 байт

3#fbb+y=*s

У входа есть строки, разделенные ;. Например: [1 5 2; 9 4 2; 5 9 6]. Используется индексирование на основе 1.

Попробуйте онлайн! Или проверьте все тестовые случаи .

объяснение

Я буду использовать пример с вводом [3 -1 3 3; 3 -1 3 1]в объяснении.

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 байт

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

Редактировать: 3 байта сохранены благодаря @MartinEnder, указывающему, что фрагменты разрешены.


5

Сетчатка , 46 байт

Число байтов предполагает кодировку ISO 8859-1.

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

Ввод использует разделители пробела и перевода строки для представления матрицы. Индексы начинаются с 0.

Попробуйте онлайн!

объяснение

Не совсем то испытание, для которого была создана Retina, но на удивление хорошо ... :)

Этап 1: Замена

\d+
$*

Это просто расширяет все целые числа в строке как унарные числа, используя 1в качестве унарной цифры. Отрицательные числа как -3просто станут вещами как -111.

Этап 2: Матч

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

Из-за !опции, это печатает все совпадения данного регулярного выражения. Упомянутое регулярное выражение использует балансирующие группы, чтобы проверить, совпадает ли текущее число с суммой его индексов.

Чтобы сделать это, мы сначала определяем сумму индексов с обратной стороны (?<=(\S* |.*¶)*). Это добавляет один захват для каждого номера перед текущим на той же строке (через \S* ), а также один захват для каждой строки перед текущей (через .*¶) для группировки 1. Следовательно, в результате мы получаем сумму индексов, начинающуюся с нуля.

Затем мы пытаемся сопоставить все следующее число, удаляя захваты из этого стека с (?<-1>1)+\b. И тогда мы делаем матч потерпеть неудачу , если какие - либо захваты оставлены на группы 1с (?(1)1)целью обеспечения равенства.

Обратите внимание, что отрицательные числа никогда не совпадают, потому что lookbehind не может пройти -перед списком 1s и (?<-1>1)+не может соответствовать ему.

Это дает нам список всех унарных чисел, которые равны сумме их индексов.

Этап 3: Матч

1

Мы заканчиваем другим этапом совпадения, но без !опции, это просто подсчитывает количество совпадений, которое одновременно суммирует все унарные числа из предыдущего результата, а также преобразует эту сумму обратно в десятичную.


Можете ли вы использовать унарный в качестве ввода?
Дрянная Монахиня

@ LeakyNun Не знаю, я пытался избежать этого. Это кажется слишком хакерским, тем более что у Retina больше нет проблем с конверсией.
Мартин Эндер

4

Желе, 15 14 10 байт

4 байта благодаря Аднану.

1-индексироваться.

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

Попробуйте онлайн!

Проверьте все тестовые случаи одновременно. (Слегка изменено.)


Я не уверен, что это работает, но вы можете сделать J€вместо L€R€?
Аднан

1
Боже мой, ты гений.
Утренняя монахиня

4

Python 2 - 60 57 байт

Это фрагмент кода, так что, я думаю, было бы еще несколько байтов, если бы я на самом деле вернул значение. e=enumerate;sum(i*(x+y==i)for x,r in e(a)for y,i in e(r))

Спасибо за помощь Leaky Num :-)

Быстрое объяснение. aмассив, содержащий числа Просто перебирайте индексы и суммируйте все значения, где значение равно сумме индекса.



о, это не сработало. поэтому его 57 байтов сейчас :( Я добавил быстрое объяснение
Джереми

Вы можете включить ссылку, которую я только что дал вам.
Дрянная Монахиня

4

R, 24 байта

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

1 на основе.
Тестовые случаи:

> 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 байт

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

Использование нуля на основе индексации и принимает матрицу уже хранящиеся в переменной M .

объяснение

+/,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
Не только самый короткий до сих пор; +1 за то, что делал это на языке Айверсона.
Адам

3

CJam, 23 21 20 байт

Спасибо Питеру Тейлору за сохранение 3 байта.

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

Ожидает, что матрица будет в стеке, и вместо этого оставляет сумму. Индексы начинаются с нуля в любом случае.

Проверьте это здесь.


Вы можете сохранить пару _,,вместо внутреннего eeи .для внутреннего цикла:ee{~_,,@f+1$.=.*~}%1b
Питер Тейлор

@PeterTaylor Ах, аккуратно, спасибо. :)
Мартин Эндер

На самом деле, есть еще один, выполняя своего рода встречу в середине:ee{~_@f-_,,.=.*~}%1b
Питер Тейлор

3

k4, 24 байта

Предполагается, что матрица хранится в m.

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

Это одна из тех загадок, где упрощения, связанные с конструированием k из APL (и J), действительно вредят - k !- это эквивалент APL, но работает только над векторами, поэтому я должен собрать матрицу индексов самостоятельно; внутренний продукт - один символ в APL, но пять в k; и я теряю три символа для правильной обработки пустой матрицы, потому что k не имеет строго типизированных матриц.


2
С другой стороны, у вас есть мощный язык, который гораздо более последовательный и с гораздо меньшим количеством примитивов для изучения.
Адам


2

PowerShell v2 +, 43 байта

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

Как фрагмент Использование состоит в том, чтобы явно направить матрицу к этому (см. Примеры ниже). Подразумевается , что $i, и $oявляются либо нулевой или нуль в начале (я явно установить их в качестве таковых в примерах ниже), и использует 0-индекс.

Делает цикл по каждому элементу в каждой строке матрицы. Мы установили , $jчтобы 0, а затем пройти через каждый элемент строки в другом цикле $_|%{...}. Каждый внутренний цикл мы увеличиваем $oна текущий элемент, умноженный на логическое ($_-eq$i+$j++)значение, что означает, что если логическое значение есть $TRUE, оно будет 1иначе 0. Затем мы выходим из внутреннего цикла, увеличиваем $iи начинаем следующий ряд. Наконец, мы выходим $oна конвейер в конце.

Примеры

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

Рубин, 63 байта

С z в качестве двумерного массива чисел:

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

Не очень интересно вообще.

Если z - плоский массив с x и y, имеющими размеры массивов, такие как:

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

Тогда у нас есть это чудовище - возможно, более рубиновое с его модными продуктами и почтовыми индексами, но на самом деле больше:

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

Возможно, есть более интересный метод массива или перечислителя, который сократил бы его, я еще не нашел его, но я бы хотел его увидеть.
Дэвид Люнг Мэдисон Стеллар

2

На самом деле, 21 байт

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

Попробуйте онлайн!

Спасибо Leaky Nun за то, что заставил меня перестать лениться и наконец написал это.

Это использует 0-индексированные матрицы и принимает входные данные как вложенный список.

Объяснение:

ñ`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 байтов

1-индексироваться.

Не будет обрабатывать первый контрольный пример, потому [1:0]что по какой-то причине имеет размер 1x0

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

Проверено в Октаве 3.

Полная программа:

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

Добро пожаловать в PPCG! В Октаве вы можете сделать sum((M.*(M-[1:size(M,1)]'-[1:size(M,2)]==0))(:)). Кроме того, я думаю, что вы можете изменить ==0начальное значение ~для дальнейшего уменьшения количества байтов. Наконец, обратите внимание, что вам нужно обработать все контрольные примеры, иначе вопрос должен быть удален
Луис Мендо

1

Луа, 70 байт

1-индексироваться.

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

Бонус: это работает для рваных массивов!

Вход хранится в a, выход хранится в s.

Полная программа:

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 байт

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

ожидает массив $ a; должен быть пустым или двумерным, с 0 индексами.
вычисляет сумму до $ s (ранее 0 или неопределенно - 0 равно NULL),
вставляет +2перед финалом )для 1-индексированного поведения

С Днем Рождения APL!

функции и набор тестов

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


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.