Dijkstra의 도전


23

올해 50 세가되는 대화식 도구로 APL 을 기리기 위해 발표

배경

Ken [Iverson] 은 1963 년 8 월 뉴저지 프린스턴의 기계 언어 구조에 관한 실무 회의 에서 프로그래밍 언어의 형식론을 발표했습니다 . (Backus, Curry, Dijkstra, Floyd, Iverson, Newell, Perlis, Wilkes). 이 논문은 또한 발표 후 발생한 토론과 Ken과 [Edsger] Dijkstra 의 교류로 끝나며 Dijkstra의 질문에 대한 Ken의 답변은 하나의 라이너였습니다.

도전

예를 들어 대응하는 행과 열 인덱스의 합과 같은 행렬 M 의 모든 요소의 합과 같은 더 복잡한 연산을 어떻게 표현할 수 있습니까?

스 니펫 또는 표현식 (전체 프로그램이나 함수가 필요하지 않음)을 작성하여 주어진 정수 매트릭스에서 각 요소의 합계를 계산하십시오. FryAmTheEggman 둔다은 또는로서, 주어진 행렬 M을 요소 A는 IJ 각각의 합을 반환 IJ 여기서 IJ = I + J.

행렬이 이미 변수 또는 메모리 위치에 있다고 가정하거나 인수 또는 입력으로 사용할 수 있습니다. 0 또는 1 기반 인덱스를 사용할 수 있습니다.

테스트 사례

 

0 빈 행렬

2

00 기반 인덱스 또는 21 기반

1 5 2
9 4 2
5 9 6

20 기반 또는 101 기반

 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

60 기반 또는 31 기반

일화

Iverson의 대답은 ++ / ( M = ¹ ⨢ ¹) // M 인데, 이는 A Programming Language에 정의 된 Iverson 표기법 이나 APL이 된 것은 아닙니다. Iverson 표기법에서 + / ( M = ¹ ( μ ( M )) ⨢ ¹ ( ν ( M ))) / M 이었습니다. APL의 첫 번째 버전에서는이었습니다 .+/(,M=(⍳1↑⍴M)∘.+⍳1↓⍴M)/,M


Dijkstra의 질문에 대한 Ken의 대답은 하나의 라이너였습니다. 그러나 그 한 줄짜리가 잘못 되었습니까?
Luis Mendo

출력하거나 인쇄해야합니까, 아니면 그냥 스 니펫으로 표현을 적어도됩니까?
Leaky Nun

2
@LuisMendo 아니오, Iverson은 적극적으로 언어를 디자인하고 있었고, 반복시 그의 한 줄짜리가 정확했습니다. "APL"이 책의 출판으로 유명 해졌다 P rogramming L의 anguage을 하지만, 출판시, 두 번째 표현이 필요했다. 이러한 표기법 중 어느 것도 기계 실행 가능하도록 구현되지 않았습니다.
Adám

@LeakyNun 계산할 스 니펫 또는 표현식 작성
Adám

@ Adám 감사합니다. 이제 더 의미가 있습니다
Luis Mendo

답변:


9

APL, 13 12 바이트

@ jimmy23013 덕분에 1 바이트.

1- 색인.

배열은 변수에 저장됩니다 m.

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

온라인으로 사용해보십시오!

APL을 기반으로하는 언어 인 J의 답변을 기반으로 합니다 .

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

마침내 나는 이것을 기다리고 있었다.
Adám

"키 입력 :"이 좋은 생각인지 잘 모르겠습니다. TryAPL 및 RIDE에만 적용되며 기본 제품에는 적용되지 않습니다. 최소한 `"APL 키" 를 의미 한다고 설명 할 수 있습니다 .
Adám

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

정말 맛있어요!
Adám

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

자바 스크립트, 49 46 바이트

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

편집 : 스 니펫이 허용됨을 지적하는 @MartinEnder 덕분에 3 바이트가 절약되었습니다.


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)

!옵션 으로 인해 주어진 정규 표현식의 모든 일치 항목을 인쇄합니다. 상기 정규 표현식은 밸런싱 그룹 을 사용 하여 현재 숫자가 해당 인덱스의 합과 같은지 여부를 확인합니다.

이를 위해 먼저 lookbehind와 인덱스의 합을 결정합니다 (?<=(\S* |.*¶)*). 이것은 현재 라인 앞에있는 각 번호에 대해 하나의 캡처를 추가하고 (via \S* ) 현재 라인 앞에있는 각 라인에 대해 하나의 캡처 (via .*¶)를 그룹화 1합니다. 따라서 결과적으로 0부터 시작하는 인덱스의 합계를 얻습니다.

그런 다음이 스택에서 캡처를 제거하면서 전체 다음 숫자를 일치 시키려고합니다 (?<-1>1)+\b. 그리고 우리는 어떤 캡처가 그룹에 남아있는 경우 경기가 실패하게 1(?(1)1)평등을 보장하기 위해.

lookbehind -1s 목록 앞을 지나갈 수없고 일치 할 수 없기 때문에 음수는 절대로 일치 (?<-1>1)+하지 않습니다.

이것은 우리에게 그들의 인덱스의 합과 동일한 모든 단항 수의 목록을 제공합니다.

3 단계 : 경기

1

다른 일치 단계로 끝나지 만 !옵션이 없으면 일치 수만 계산합니다.이 숫자는 이전 결과의 모든 단항 수를 합산하고 해당 합계를 다시 십진수로 변환합니다.


단항을 입력으로 사용할 수 있습니까?
Leaky Nun

@LeakyNun 모르겠다, 나는 그것을 피하려고 노력했다. Retina가 더 이상 변환에 아무런 문제가 없기 때문에 너무 해키처럼 보입니다.
마틴 엔더


4

파이썬 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 바이트 지금 : (나는 빠른 설명을 추가
Jeremy

내가 준 링크를 포함하고 싶을 수도 있습니다.
Leaky Nun

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

0부터 시작하는 인덱싱을 사용하고 행렬이 변수 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했습니다.
Adám

3

CJam, 23 21 20 바이트

3 바이트를 절약 한 Peter Taylor에게 감사합니다.

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

행렬이 스택에있을 것으로 예상하고 대신 합계를 남겨 둡니다. 두 경우 모두 인덱스는 0부터 시작합니다.

여기에서 테스트하십시오.


_,,내부 ee.내부 루프 대신에 부부를 구할 수 있습니다 .ee{~_,,@f+1$.=.*~}%1b
Peter Taylor

@PeterTaylor 아, 깔끔합니다. 감사합니다. :)
Martin Ender

실제로, 일종의 중간자 회의를 통해 한 가지 더 있습니다.ee{~_@f-_,,.=.*~}%1b
Peter Taylor

3

k4, 24 바이트

행렬이에 있다고 가정합니다 m.

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

이것은 APL (및 J)에서 k를 설계하는 데 관련된 단순화가 실제로 해로운 퍼즐 중 하나입니다. k는 APL과 !동일 하지만 벡터에서만 작동하므로 인덱스 매트릭스를 직접 조립해야합니다. 내부 제품은 APL에서 1 자이지만 k에서 5 자입니다. k에는 강력한 형식의 행렬이 없기 때문에 빈 행렬을 올바르게 처리하기 위해 3자를 잃습니다.


2
반면에, 당신은 훨씬 더 일관성 있고 배우는 기본 요소가 훨씬 적은 강력한 언어를 가지고 있습니다.
Adám


2

PowerShell v2 +, 43 바이트

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

스 니펫으로. 사용법은 매트릭스를 명시 적으로 파이프로 파이프하는 것입니다 (아래 예 참조). 그렇게 가정 $i하고 $o시작 (I 명시 적으로 아래의 예에서와 같은을 설정 한)에서 중 null 또는 제로이며, 0 색인을 사용합니다.

행렬의 각 행에서 foreach 루프를 수행합니다. 우리는 설정 $j0다음 다른 루프에서 행의 각 요소를 통해 이동합니다 $_|%{...}. 각 내부 루프 $o는 현재 요소에 Boolean을 곱한 값으로 증가 하며, ($_-eq$i+$j++)Boolean이 $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를 2 차원 숫자 배열로 사용 :

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

아마도 그것을 단축시킬 더 멋진 배열 또는 열거 자 방법이있을 것입니다. 아직 찾지 못했지만 그것을보고 싶습니다.
David Ljung Madison 스텔라

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초기 및 초기 ~에 변경할 수 있다고 생각합니다 . 마지막으로 모든 테스트 사례를 처리해야합니다. 그렇지 않으면 질문을 삭제
Luis Mendo

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가 정의되어 있어야합니다. 비어 있거나 2 차원, 0 색인이어야합니다. 1- 인덱싱 된 동작의 마지막 에
합을 $ s (이전 0 또는 정의되지 않은-0은 NULL)
삽입으로 계산+2)

생일 축하해 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));
}

1

Brachylog , 15 바이트

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

온라인으로 사용해보십시오!

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.