ดัชนีของอาร์เรย์หลายมิติ


28

ภาษาระดับต่ำกว่าเช่น C และ C ++ จริง ๆ แล้วไม่มีแนวคิดของอาร์เรย์หลายมิติ (นอกเหนือจากเวกเตอร์และอาร์เรย์แบบไดนามิก) เมื่อคุณสร้างอาร์เรย์หลายมิติด้วย

int foo[5][10];

นี้เป็นจริงเพียงแค่น้ำตาลประโยค สิ่งที่ C ทำจริงๆคือสร้างอาเรย์เดี่ยวที่ต่อเนื่องกันขององค์ประกอบ5 * 10 นี้

foo[4][2]

ยังเป็นน้ำตาล syntactic นี่หมายถึงองค์ประกอบที่

4 * 10 + 2

หรือองค์ประกอบที่ 42 โดยทั่วไปดัชนีขององค์ประกอบ[a][b]ในอาร์เรย์foo[x][y]อยู่ที่

a * y + b

แนวคิดเดียวกันนี้ใช้กับอาร์เรย์ 3 มิติ ถ้าเรามีfoo[x][y][z]และเราเข้าถึงองค์ประกอบ[a][b][c]เราเข้าถึงองค์ประกอบจริงๆ:

a * y * z + b * z + c

แนวคิดนี้ใช้กับอาร์เรย์n -dimensional ถ้าเรามีอาร์เรย์ที่มีมิติ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 'จริงๆไม่' int[10]คือการสร้างอาร์เรย์ที่ต่อเนื่องกันเดียวของห้าองค์ประกอบประเภท


1
@Hurkyl ใช่ แต่จำนวนเต็มทั้งหมดในอาร์เรย์นั้นยังคงอยู่ติดกัน มันเป็นแค่ความหมาย
DJMcMayhem

คำตอบ:


60

APL, 1 ไบต์

ทดสอบบนTryAPL


21
ก็แค่นั้นแหละ เรามีผู้ชนะ ทุกคนสามารถกลับบ้านได้แล้ว
DJMcMayhem

3
ทำไม ... ทำไมจึงใช้งานได้ o_O
Alex A.

10
@AlexA การทำดัชนีอาร์เรย์หลายมิติเป็นการแปลงฐานแบบผสมเป็นหลัก
Dennis

21
โอ้ดูสิหลุมหนึ่งในขณะที่เล่นกอล์ฟ!
คดีฟ้องร้องกองทุนโมนิก้า

8
ส่วนใหญ่ฉันมาที่นี่เพื่อความสนุก มีหลายครั้งที่ฉันได้รับข้อมูลเชิงลึกอย่างลึกซึ้งโดยไม่ตั้งใจ
slebetman



7

Python ขนาด 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]

สิ่งนี้ใช้การจัดทำดัชนีแบบ 1 (ตอนนี้ได้รับอนุญาตจากความท้าทาย) ซึ่งเป็นตัวเลือกที่เป็นธรรมชาติใน MATL

หากต้องการเปรียบเทียบกับกรณีทดสอบในการท้าทายให้เพิ่ม1แต่ละรายการในเวกเตอร์ดัชนีอินพุตและลบออก1จากผลลัพธ์

ลองออนไลน์!

คำอธิบาย

รหัสจะขึ้นอยู่กับX]ฟังก์ชั่นbuiltin ซึ่งจะแปลงดัชนีหลายมิติเป็นดัชนีเชิงเส้นเดี่ยว (เช่นsub2indฟังก์ชันMatlab หรือฟังก์ชันของ Octave )

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

Python ขนาด 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

Haskell, 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&

ฟังก์ชั่นที่ไม่มีชื่อซึ่งใช้รายการของดัชนีเป็นอาร์กิวเมนต์แรกและรายการของมิติที่สอง จากการสังเกตเช่นเดียวกับคำตอบ APL ของ Dennis ที่คำนวณดัชนีนั้นเป็นเพียงการแปลงแบบผสม


3

อ็อกเทฟ58 58ไบต์

ขอบคุณ @AlexA สำหรับคำแนะนำของเขาซึ่งลบ 4 ไบต์

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

อินพุตและเอาต์พุตเป็นพื้นฐาน 1 หากต้องการเปรียบเทียบกับกรณีทดสอบให้เพิ่ม1ot แต่ละรายการในอินพุตและลบออก1จากเอาต์พุต

นี่คือฟังก์ชั่นที่ไม่ระบุชื่อ หากต้องการเรียกใช้กำหนดค่าให้กับตัวแปร

ลองได้ที่นี่

คำอธิบาย

สิ่งนี้ทำงานโดยการสร้างอาร์เรย์หลายมิติ ( reshape(...)) เต็มไปด้วยค่า1, 2... ในลำดับเชิงเส้น ( 1:prod(d)) และจากนั้นทำดัชนีด้วยดัชนีหลายมิติเพื่อรับค่าที่สอดคล้องกัน

การจัดทำดัชนีจะกระทำโดยการแปลงดัชนีหลายมิติอินพุตiเป็นเซลล์อาร์เรย์ ( num2cell(...)) จากนั้นเป็นรายการที่คั่นด้วยเครื่องหมายจุลภาค ( {:})

การflipดำเนินการทั้งสองจำเป็นต้องปรับลำดับของมิติจาก C ไปเป็นระดับแปดเสียง


ทำไมการก่อร่างใหม่จึงมีวงเล็บคู่ที่สองนั้นไม่ใช่ syntactic
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

Haskell, 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

Mathematica, 47 ไบต์

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

(Unicode เป็น 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)))))))

Ungolfed:

(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

Perl 6, 39 ไบต์

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

สนามกอล์ฟค่อนข้างไร้เดียงสาที่นี่

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

Perl, 71 ไบต์

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 ไบต์

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

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

การใช้งาน:

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

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

การใช้งาน:

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.