Çok boyutlu bir dizinin indeksi


28

C ve C ++ gibi daha düşük seviyeli diller aslında çok boyutlu diziler kavramına sahip değildir. (Vektörler ve dinamik diziler dışında) ile çok boyutlu bir dizi oluşturduğunuzda

int foo[5][10];

Bu aslında sadece sözdizimsel şeker . C'nin yaptığı şey, 5 * 10 elementli tek bir bitişik dizi oluşturmaktır . Bu

foo[4][2]

aynı zamanda sözdizimsel şekerdir. Bu gerçekten de öğeyi ifade eder

4 * 10 + 2

veya, 42. element. Genel olarak, elemanın göstergesi [a][b]dizide foo[x][y]olan

a * y + b

Aynı kavram 3d diziler için de geçerlidir. Eğer elimizde foo[x][y][z]ve elemana erişirsek, [a][b][c]elimizde gerçekten varız:

a * y * z + b * z + c

Bu kavram n boyutlu diziler için geçerlidir . Boyutları olan bir dizimiz varsa D1, D2, D3 ... Dnve elemana erişirsek S1, S2, S3 ... Snformül

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

Meydan okuma

Yukarıdaki formüle göre çok boyutlu bir dizinin indeksini hesaplayan bir program veya işlev yazmalısınız. Giriş iki dizi olacak. İlk dizi boyutlar, ikinci dizi ise dizinlerdir. Bu iki dizinin uzunluğu her zaman eşit ve en az 1 olacaktır.

Dizilerdeki her sayının negatif olmayan bir tamsayı olacağını güvenle kabul edebilirsiniz. Ayrıca , endekslerde yer 0alsa 0 da , boyut dizisinde yer alamayacağınızı varsayabilirsiniz . Ayrıca endekslerin boyutlardan daha büyük olmayacağını da varsayabilirsiniz.

Test 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
Yani bu 0 tabanlı indeksleme, doğru mu? Tercih ettiğimiz dil için daha doğalsa 1 tabanlı endekslemeyi kullanabilir miyiz?
Alex A.

@AlexA. Evet, bu kabul edilebilir.
DJMcMayhem

11
Aslında, C'nin gerçekte yaptığı şey, türün beş öğesinden oluşan tek bir bitişik dizi oluşturmaktır int[10].


1
@Hurkyl Evet, ancak bu dizideki tamsayıların tümü hala bitişik. Sadece anlambilim.
DJMcMayhem

Yanıtlar:


60

APL, 1 bayt

TryAPL'de test edin .


21
İşte bu. Bir kazananımız var. Artık herkes eve gidebilir.
DJMcMayhem

3
Neden ... bu neden çalışıyor? o_O
Alex A.

10
@AlexA. Çok boyutlu bir dizinin indekslenmesi esasen karışık temel dönüşümdür.
Dennis,

21
Oh, bak, golf oynarken bir delik!
Fon Monica'nın Davası

8
Çoğu zaman buraya eğlence için gelirim. O zaman, yanlışlıkla derin içgörüler
edindiğim


11

JavaScript (ES6), 34 bayt

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

Kesinlikle reducedaha iyi olmalı map.


7

Python, 43 bayt

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

İdeone üzerinde test et .


15
Dennis sadece hepimizi sağlam bir şekilde sarsmaz, ama her
DJMcMayhem

7

Jöle , 7 6 bayt

Ṇ;żḅ@/

Çevrimiçi deneyin! veya tüm test durumlarını doğrulayın .

Nasıl çalışır

Ṇ;żḅ@/  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 bayt

PiPZ}N$X]

Bu, MATL'deki doğal tercih olan 1 tabanlı endekslemeyi (şimdi zorluğun izin verdiği) kullanır.

Mücadeledeki test durumlarıyla karşılaştırmak 1için, giriş indeksi vektöründeki her girişe ekleyin 1ve çıkıştan çıkarın .

Çevrimiçi deneyin!

açıklama

Kod, X]çok boyutlu endeksleri tek, doğrusal bir endekse (Matlab veya Octave'in sub2indfonksiyonu gibi) dönüştüren yerleşik fonksiyona dayanmaktadır .

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 bayt

4L)1hPYpP*s

Bu, orijinal mücadelede olduğu gibi 0 tabanlı endeksleme kullanır.

Çevrimiçi deneyin!

açıklama

Kod açıkça gerekli çarpımları ve eklemeleri yapar.

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

Python, 85 bayt

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

Muhtemelen dışarıdaki daha iyi piton golfçüleri tarafından popomu tekmeleyeceğim.



4

Haskell, 34 bayt

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

Kullanım örneği: [10,10,4,62,7] # [1,2,3,4,5]-> 22167.

Nasıl çalışır:

      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 bayt

Hızlı bir makro:

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

Gibi kullanın:

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

Bu kuralların kötüye kullanılması biraz olabilir. Belirtilen indekslerin işaretçiyi ne kadar uzak tuttuğunu görmek için kontrollerden çok verilen boyutta bir dizi oluşturur. STDOUT çıkışları.

Bu çok kirli hissettiriyor ... Ama ben bunun geçerli olduğu gerçeğini seviyorum.


3

Mathematica, 27 bayt

#~FromDigits~MixedRadix@#2&

İlk argüman olarak dizinlerin listesini ve ikinci boyutların listesini alan adsız bir işlev. Dennis'in APL cevabıyla aynı gözlemi temel alarak endeksin hesaplanmasının gerçekten karışık temel bir dönüşüm olduğu söylenebilir.


3

Octave, 58 54 bayt

@AlexA'ya teşekkürler. 4 bayt kaldıran öneri için

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

Giriş ve çıkış 1 tabanlıdır. Test durumlarıyla karşılaştırmak 1için girişteki her girişi ekleyin 1ve çıktıdan çıkarın .

Bu anonim bir işlevdir. Aramak için değişkene atayın.

Burada dene .

açıklama

Bu aslında çok boyutlu dizi (kurarak çalışır reshape(...)değerlerle dolu), 1, 2, ... lineer sırayla ( 1:prod(d)) ve ardından çok boyutlu indeksi ile indeksleme corrresponding değeri elde etmek.

İndeksleme, giriş çok boyutlu indeksini ibir hücre dizisine ( num2cell(...)) ve ardından virgülle ayrılmış bir listeye ( {:}) dönüştürerek yapılır.

flipC'den Octave'ye kadar boyutların sırasını uyarlamak için iki işlem gerekir.


Neden yeniden şekillendirme ikinci bir parantez çiftine sahiptir ki bu sözdizimsel değildir?
Abr001,

@ Agawa001 İkinci bir çift sonra reshape mı demek istiyorsun ? Bu Matlab’da sözdizimsel değil, ancak Octave’de kabul edildi. Bir indeks olarak çalışır
Luis Mendo

Ah Octave !! bu, aydınlanma için matlab, tha, ks'den daha iyi ve daha ergonomik olmalıdır.
Abr001,

Agawa001 @ Ayrıca yol açabilir bazı karışıklık olsa
Luis Mendo

Örnek koddaki anonim işlevler için bir ipucu: Kodumun @(...) ...ilk satırında, ardından f = ans;ikinci sırada kullanıyorum. Bu, ilk satırın uzunluğunu rapor edilecek bayt sayısına eşittir.
BERS

3

CJam, 7 bayt

0q~z+:b

Çevrimiçi deneyin!

Nasıl çalışır

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.

Bize bir şans ver Dennis! : D
HyperNeutrino

2

Haskell, 47 bayt

İki eşit uzunluktaki çözüm:

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

Gibi Aranan: ((sum.).s)[4,2][5,10].

İşte bir infix sürümü:

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

2

Octave, 47 / 43 /31 baytlık

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

Burada test et .

Bir de istendi olarak, söyledikten yorumun , 1 tabanlı dizin dil kullanılıyor bu doğal olduğunda OK olduğu söyleniyordu. Bu durumda, 4 bayt kaydedebiliriz:

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

Analojide, kodun amacı bu dilde bir diziyi doğrusal olarak indekslemekse , MATLAB / Octave sütununun ana düzenini çevreleyen ve hesaba katmanın da gerekmemesi gerektiğini savunuyorum. Bu durumda, çözümüm olur

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

Onu burada test et .


Merhaba, PPCG'ye hoş geldiniz! Mükemmel cevap!
NoOneIsHere

1

Mathematica, 47 bayt

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

(Unicode U +, F3C7, ya da \[Transpose].) Bunun için, olarak ifade yazdım D N ( D , n -1 (⋯ ( D 3 ( D 2 S 1 + S 2 ) + S 3 ) ⋯) + S , n -1 ) + S n . Sadece Foldher iki listenin de işlevi.


1

Aslında, 13 bayt

;pX╗lr`╜tπ`M*

Çevrimiçi deneyin!

Bu program, ilk giriş olarak endeks listesini ve ikinci giriş olarak ölçü listesini alır.

Açıklama:

;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

Raket 76 bayt

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

Ungolfed:

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

Test yapmak:

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

Çıktı:

42
22167
37

0

C #, 73 bayt

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

Test vakaları ile tam program:

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

Perl 6, 39 bayt

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

Burada oldukça saf bir golf var, sadece isimsiz bir denizaltısı ezdi.

Perl 6, bir $döngüde bir sayaç oluşturmak için yararlı olan isimsiz bir durum değişkenine sahiptir (örneğin, artım sonrası $++veya artım öncesi kullanarak ++$). Bir boyut içindeki boyut dizisi diliminin başlangıç ​​dizinini artırmak için bu durum değişkenini önceden arttırıyorum.

İşte alt listelerini oluşturan asaletli bir işlev

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

O zaman bu, multiplication ( ×) operatörüyle alt listeleri azaltma ve sonuçları verme meselesidir 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

Perl, 71 bayt

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

Ungolfed:

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 115 bayt

-18 bayt kullanmak için 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...);}};

Ungolfed:

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

Kullanımı:

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

Alternatif, sadece fonksiyonlar, 116 bayt

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

Ungolfed:

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

Kullanımı:

f(5,10)(4,2)
f(10,10,10)(4,3,2)
f(10,10,4,62,7)(1,2,3,4,5)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.