다차원 배열의 인덱스


28

C 및 C ++와 같은 저급 언어에는 실제로 다차원 배열 개념이 없습니다. (벡터 및 동적 배열 이외) 다차원 배열을 사용하여

int foo[5][10];

이것은 실제로 구문 설탕 입니다. C가 실제로하는 일은 5 * 10 요소 의 단일 연속 배열을 만드는 것 입니다. 이

foo[4][2]

또한 구문 설탕입니다. 이것은 실제로 요소를 나타냅니다

4 * 10 + 2

또는 42 번째 요소입니다. 일반적으로, 요소의 인덱스 [a][b]어레이가 foo[x][y]있어요

a * y + b

3D 배열에도 동일한 개념이 적용됩니다. 우리가 가지고 foo[x][y][z]있고 요소에 [a][b][c]액세스하면 실제로 요소에 액세스합니다.

a * y * z + b * z + c

이 개념은 n 차원 배열에 적용됩니다 . 차원이있는 배열이 D1, D2, D3 ... Dn있고 요소 S1, S2, S3 ... Sn에 액세스 하면 수식은

(S1 * D2 * D3 ... * Dn) + (S2 * D3 * D4 ... * Dn) + (S3 * D4 ... * Dn) ... + (Sn-1 * Dn) + Sn

도전

위의 공식에 따라 다차원 배열의 인덱스를 계산하는 프로그램이나 함수를 작성해야합니다. 입력은 두 개의 배열입니다. 첫 번째 배열은 차원이고 두 번째 배열은 인덱스입니다. 이 두 배열의 길이는 항상 같고 1 이상입니다.

배열의 모든 숫자가 음이 아닌 정수라고 가정 할 수 있습니다. 0비록 차원 배열에서 차원 배열을 얻지 못한다고 가정 할 수도 0 있습니다. 인덱스에 수 있습니다. 인덱스가 치수보다 크지 않다고 가정 할 수도 있습니다.

IO 테스트

Dimensions: [5, 10]
Indices: [4, 2]
Output: 42

Dimensions: [10, 10, 4, 62, 7]
Indices: [1, 2, 3, 4, 5]
Output: 22167

Dimensions: [5, 1, 10]
Indices: [3, 0, 7]
Output: 37

Dimensions: [6, 6, 6, 6, 6, 6, 6, 6, 6, 6]
Indices: [3, 1, 5, 5, 3, 0, 5, 2, 5, 4]
Output: 33570178

4
따라서 이것은 0 기반 색인입니다. 맞습니까? 우리가 선택한 언어에 더 자연스러운 1 기반 색인을 사용할 수 있습니까?
Alex A.

@AlexA. 예, 괜찮습니다.
DJMcMayhem

11
실제로 C가 '실제로'하는 것은 type의 다섯 가지 요소로 구성된 단일 연속 배열을 만드는 것 int[10]입니다.


1
@Hurkyl 네, 그러나 해당 배열의 모든 정수는 여전히 연속적입니다. 그것은 의미론 일뿐입니다.
DJMcMayhem

답변:


60

APL, 1 바이트

TryAPL에서 테스트하십시오 .


21
그게 다야 우리는 승자가 있습니다. 다른 사람들은 이제 집에 갈 수 있습니다.
DJMcMayhem

3
왜 ... 왜 작동합니까? o_O
Alex A.

10
@AlexA. 다차원 배열 인덱싱은 기본적으로 혼합 된 기본 변환입니다.
Dennis

21
아, 골프를 타면서 구멍을 뚫어보세요!
Fund Monica의 소송

8
나는 대부분 재미를 위해 여기에옵니다. 그때 우연히 심오한 통찰을받는
때가 있습니다


11

자바 스크립트 (ES6), 34 바이트

(d,a)=>a.reduce((r,i,j)=>r*d[j]+i)

반드시 reduce보다 낫습니다 map.


7

파이썬, 43 바이트

f=lambda x,y:x>[]and y.pop()+x.pop()*f(x,y)

Ideone에서 테스트하십시오 .


15
데니스는 우리 모두를 단호하게 때릴뿐만 아니라 모든 사람에게 해를 끼칩니다 . 단일. 언어.
DJMcMayhem

7

젤리 , 7 6 바이트

Ṇ;żḅ@/

온라인으로 사용해보십시오! 또는 모든 테스트 사례를 확인하십시오 .

작동 원리

Ṇ;żḅ@/  Main link. Arguments: D (list of dimensions), I (list of indices)

Ṇ       Yield 0, the logical NOT of D.
  ż     Zip D with I.
        If D = [10, 10, 4, 62, 7] and I = [1, 2, 3, 4, 5], this yields
        [[10, 1], [10, 2], [4, 3], [62, 4], [7, 5]].
 ;      Concatenate, yielding [0, [10, 1], [10, 2], [4, 3], [62, 4], [7, 5]].
   ḅ@/  Reduce by swapped base conversion to integer.
        [10, 1] in base    0 is    0 × 10 + 1 = 1.
        [10, 2] in base    1 is    1 × 10 + 2 = 12.
        [ 4, 3] in base   12 is   12 ×  4 + 3 = 51.
        [62, 4] in base   51 is   51 × 62 + 4 = 3166.
        [ 7, 5] in base 3166 is 3166 ×  7 + 5 = 22167.


5

MATL , 9 바이트

PiPZ}N$X]

이것은 MATL에서 자연스럽게 선택되는 1 기반 인덱싱 (이제 챌린지에서 허용)을 사용합니다.

챌린지의 테스트 사례와 비교하려면 1입력 인덱스 벡터의 각 항목을 추가 1하고 출력에서 뺍니다 .

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

설명

이 코드는 내장 X]함수를 기반으로하며 다차원 인덱스를 Matlab 또는 Octave의 sub2ind함수 와 같은 단일 선형 인덱스로 변환 합니다.

P      % Take dimension vector implicitly. Reverse
iP     % Take vector of indices. Reverse
Z}     % Split vector into its elements
N$X]   % Convert indices to linear index (`sub2ind` function). Implicitly display


5

MATL , 11 바이트

4L)1hPYpP*s

이것은 원래의 도전과 같이 0 기반 인덱싱을 사용합니다.

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

설명

코드는 필요한 곱셈과 덧셈을 명시 적으로 수행합니다.

4L)    % Take first input array implicitly. Remove its first entry
1h     % Append a 1
PYpP   % Cumulative product from right to left
*      % Take second input array implicitly. Multiply the two arrays element-wise
s      % Sum of resulting array. Implicitly display

4

파이썬, 85 바이트

lambda a,b:sum(b[i]*eval('*'.join(str(n)for n in a[i+1:])or'1')for i in range(len(a)))

아마 더 나은 파이썬 골퍼들이 내 엉덩이를 걷어차 게 할 것입니다.



4

하스켈, 34 바이트

a#b=sum$zipWith(*)(0:b)$scanr(*)1a

사용 예 : [10,10,4,62,7] # [1,2,3,4,5] -> 22167.

작동 방식 :

      scanr(*)1a  -- build partial products of the first parameter from the right,
                  -- starting with 1, e.g. [173600,17360,1736,434,7,1]
    (0:b)         -- prepend 0 to second parameter, e.g. [0,1,2,3,4,5]
  zipWith(*)      -- multiply both lists elementwise, e.g. [0,17360,3472,1302,28,5]
sum               -- calculate sum

4

C ++, 66 바이트

빠른 매크로 :

#include<stdio.h>
#define F(d,i) int x d;printf("%d",&x i-(int*)x)

다음과 같이 사용하십시오.

int main(){
    F([5][1][10], [3][0][7]);
}

이것은 약간의 규칙 남용 일 수 있습니다. 주어진 인덱스가 포인터를 얼마나 멀리 오프셋하는지 확인하는 것보다 지정된 크기의 배열을 만듭니다. STDOUT으로 출력합니다.

이것은 더럽게 느껴집니다 ... 그러나 나는 이것이 유효하다는 사실을 좋아합니다.


3

Mathematica, 27 바이트

#~FromDigits~MixedRadix@#2&

인덱스 목록을 첫 번째 인수로, 차원 목록을 두 번째로 사용하는 명명되지 않은 함수입니다. Dennis의 APL 답변과 동일한 관찰 결과에 따르면 인덱스 계산은 실제로 혼합 기준 변환이라는 것입니다.


3

옥타브, 58 54 바이트

@AlexA에게 감사합니다. 그의 제안으로 4 바이트를 제거했습니다.

@(d,i)reshape(1:prod(d),flip(d))(num2cell(flip(i)){:})

입력 및 출력은 1 기반입니다. 테스트 사례와 비교하려면1 입력에 각 항목을1 하고 출력에서 빼 십시오.

이것은 익명의 기능입니다. 호출하려면 변수에 지정하십시오.

여기 사용해보십시오 .

설명

실제로 다차원 배열 (구축하여이 작업 reshape(...)값을 작성) 1, 2선형 순서 (1:prod(d) )하고 다차원 색인은 색인화 corrresponding 값을 취득한다.

인덱싱은 입력 다차원 인덱스 i를 셀형 배열 ( num2cell(...)) 로 변환 한 다음 쉼표로 구분 된 목록 ({:} ) .

flip동작은 C로부터 옥타브 측정 순서를 적용 할 필요가있다.


왜 형태를 바꾸는 것이 비구 문적 괄호 쌍을 가지고 있지 않습니까?
Abr001am

Agawa001 마 @ 당신은 두 번째 쌍을 의미 reshape ? Matlab에서는 구문이 아니지만 Octave에서는 허용됩니다. 그것은 색인으로 작동합니다
Luis Mendo

오 옥타브 !! 그것은 깨달음을 위해 matlab, tha, ks보다 더 좋고 인체 공학적이어야합니다.
Abr001am

@ Agawa001 또한 혼란을 일으킬 수 있습니다 하지만,
루이스 Mendo

예제 코드에서 익명 함수에 대한 팁 : 코드 @(...) ...의 첫 번째 줄에서 사용 하고 두 번째 줄 f = ans;에서 사용합니다. 이렇게하면 첫 번째 줄의 길이가보고 할 바이트 수와 같습니다.
bers

3

CJam, 7 바이트

0q~z+:b

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

작동 원리

0        e# Push 0 on the stack.
 q       e# Read and push all input, e.g., "[[10 10 4 62 7] [1 2 3 4 5]]".
  ~      e# Eval, pushing [[10 10 4 62 7] [1 2 3 4 5]].
   z     e# Zip, pushing [[10 1] [10 2] [4 3] [62 4] [7 5]].
    +    e# Concatenate, pushing [0 [10 1] [10 2] [4 3] [62 4] [7 5]]
     :b  e# Reduce by base conversion.
         e# [10 1] in base    0 is    0 * 10 + 1 = 1.
         e# [10 2] in base    1 is    1 * 10 + 2 = 12.
         e# [ 4 3] in base   12 is   12 *  4 + 3 = 51.
         e# [62 4] in base   51 is   51 * 62 + 4 = 3166.
         e# [ 7 5] in base 3166 is 3166 *  7 + 5 = 22167.

기회를 줘, 데니스! : D
HyperNeutrino

2

하스켈, 47 바이트

두 개의 동일한 길이 솔루션 :

s(a:b)(x:y)=a*product y:s b y
s _ _=[]
(sum.).s

다음과 같이 호출 ((sum.).s)[4,2][5,10]됩니다..

다음은 접미사 버전입니다.

(a:b)&(x:y)=a*product y:b&y
_ & _=[]
(sum.).(&)

2

옥타브 (47) / 43 / 31 바이트

@(d,i)sub2ind(flip(d),num2cell(flip(i+1)){:})-1

여기에서 테스트 .

코멘트 에서 요청 했듯이 1 기반 색인 생성은 사용되는 언어에 자연 스럽다면 괜찮다고 말했습니다. 이 경우 4 바이트를 절약 할 수 있습니다.

@(d,i)sub2ind(flip(d),num2cell(flip(i)){:})

유사하게, 코드의 목적이 해당 언어 내 에서 배열을 선형으로 색인화하는 것이라면 MATLAB / Octave의 열 주요 순서를 뒤집고 설명하는 전체가 필요하지 않아야한다고 주장합니다. 이 경우 내 솔루션은

@(d,i)sub2ind(d,num2cell(i){:})

여기서 테스트 해보십시오 .


안녕하세요, PPCG에 오신 것을 환영합니다! 좋은 답변입니다!
NoOneIsHere 여기

1

수학, 47 바이트

Fold[Last@#2#+First@#2&,First@#,Rest/@{##}]&

(유니 코드는 U + F3C7 또는) \[Transpose]입니다.이를 위해 D n ( D n -1 (⋯ ( D 3 ( D 2 S 1 + S 2 ) + S 3 ) ⋯) + S n -1 로 표현을 다시 썼습니다. ) + S n . 그냥 Fold두 목록을 통해 기능이야.


1

실제로 13 바이트

;pX╗lr`╜tπ`M*

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

이 프로그램은 인덱스 목록을 첫 번째 입력으로, 차원 목록을 두 번째 입력으로 사용합니다.

설명:

;pX╗lr`╜tπ`M*
;pX╗            push dims[1:] to reg0
    lr`   `M    map: for n in range(len(dims)):
       ╜tπ        push product of last n values in reg0
            *   dot product of indices and map result

1

라켓 76 바이트

(λ(l i(s 0))(if(null? i)s(f(cdr l)(cdr i)(+ s(*(car i)(apply *(cdr l)))))))

언 골프 드 :

(define f
  (λ (ll il (sum 0))
    (if (null? il)
        sum
        (f (rest ll)
           (rest il)
           (+ sum
              (* (first il)
                 (apply * (rest ll))))))))

테스트 :

(f '(5 10) '(4 2))
(f '(10 10 4 62 7) '(1 2 3 4 5))
(f '(5 1 10) '(3 0 7))

산출:

42
22167
37

0

C #, 73 바이트

d=>i=>{int n=d.Length,x=0,y=1;for(;n>0;){x+=y*i[--n];y*=d[n];}return x;};

테스트 케이스가 포함 된 전체 프로그램 :

using System;

namespace IndexOfAMultidimensionalArray
{
    class Program
    {
        static void Main(string[] args)
        {
            Func<int[],Func<int[],int>>f= d=>i=>{int n=d.Length,x=0,y=1;for(;n>0;){x+=y*i[--n];y*=d[n];}return x;};

            int[] dimensions, indices;
            dimensions =new int[]{5, 10};
            indices=new int[]{4,2};
            Console.WriteLine(f(dimensions)(indices));      //42

            dimensions=new int[]{10, 10, 4, 62, 7};
            indices=new int[]{1, 2, 3, 4, 5};
            Console.WriteLine(f(dimensions)(indices));      //22167

            dimensions=new int[]{5, 1, 10};
            indices=new int[]{3, 0, 7};
            Console.WriteLine(f(dimensions)(indices));      //37

            dimensions=new int[]{6, 6, 6, 6, 6, 6, 6, 6, 6, 6};
            indices=new int[]{3, 1, 5, 5, 3, 0, 5, 2, 5, 4};
            Console.WriteLine(f(dimensions)(indices));      //33570178
        }
    }
}

0

펄 6, 39 바이트

->\d,\i{sum i.map:{[×] $_,|d[++$ ..*]}}

여기서 순진한 골프는 익명의 잠수함을 just습니다.

Perl 6에는 $루프에서 카운터를 생성하는 데 유용한 익명 상태 변수 가 있습니다 (예 : 증가 후 $++또는 증가 후 사용)++$ ). 이 상태 변수를 미리 증분하여 맵 내에서 차원 배열 슬라이스의 시작 색인을 증가시킵니다.

하위 목록을 만드는 ungolfed 함수는 다음과 같습니다.

sub md-index(@dim, @idx) {
    @idx.map(-> $i { $i, |@dim[++$ .. *] })
}
say md-index([10, 10, 4, 62, 7], [1, 2, 3, 4, 5]);
# OUTPUT: ((1 10 4 62 7) (2 4 62 7) (3 62 7) (4 7) (5))

그런 다음 곱셈 ( ×) 연산자로 하위 목록을 줄이고 sum결과를 조정하는 것입니다.

sub md-index(@dim, @idx) {
    @idx.map(-> $i { [×] $i, |@dim[++$ .. *] }).sum
}
say md-index([10, 10, 4, 62, 7], [1, 2, 3, 4, 5]);
# OUTPUT: 22167

0

펄, 71 바이트

sub{$s+=$_[1][-$_]*($p*=$_[0][1-$_])for($p=$_[0][$s=0]=1)..@{$_[0]};$s}

언 골프 드 :

sub {
    my $s = 0;
    my $p = 1;

    $_[0]->[0] = 1;
    for (1 .. @{$_[1]}) {
        $p *= $_[0]->[1 - $_];
        $s += $_[1]->[-$_] * $p;
    }

    return $s;
}

0

C ++ 17, 133 바이트

사용을위한 -18 바이트 auto...

template<int d,int ...D>struct M{int f(int s){return s;}int f(int s,auto...S){return(s*...*D)+M<D...>().f(S...);}};

언 골프 드 :

template <int d,int ...D> //extract first dimension
struct M{
 int f(int s){return s;} //base case for Sn
 int f(int s, auto... S) { //extract first index 
  return (s*...*D)+M<D...>().f(S...); 
  //S_i * D_(i+1) * D(i+2) * ... + recursive without first dimension and first index
 }
};

용법:

M<5,10>().f(4,2)
M<10,10,4,62,7>().f(1,2,3,4,5)

대체 기능 만 116 바이트

#define R return
#define A auto
A f(A d){R[](A s){R s;};}A f(A d,A...D){R[=](A s,A...S){R(s*...*D)+f(D...)(S...);};}

언 골프 드 :

auto f(auto d){
  return [](auto s){
   return s;
  };
}
auto f(auto d, auto...D){
  return [=](auto s, auto...S){
    return (s*...*D)+f(D...)(S...);
  };
}

용법:

f(5,10)(4,2)
f(10,10,10)(4,3,2)
f(10,10,4,62,7)(1,2,3,4,5)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.