كيف يمكن تحديد مجموع أبعاد المصفوفة في وقت التشغيل؟

StackOverflow https://stackoverflow.com/questions/23190

سؤال

أنا أعمل على وظيفة لتحديد إنتروبيا التوزيع.ويستخدم كوبولا، إن وجد على دراية بذلك.أحتاج إلى تلخيص القيم الموجودة في المصفوفة بناءً على الأبعاد التي "يتم الاهتمام بها".

مثال:خذ بعين الاعتبار المثال التالي...

Dimension 0 (across)
_ _ _ _ _ _ _ _ _ _ _ _ _
|_ 0 _|_ 0 _|_ 0 _|_ 2 _|  Dimension 1
|_ 1 _|_ 0 _|_ 2 _|_ 0 _|   (down)
|_ 0 _|_ 3 _|_ 0 _|_ 6 _|
|_ 0 _|_ 0 _|_ 0 _|_ 0 _|

I "care about" dimension 0 only, and "don't care" about the rest (dim 1).
Summing this array with the above specifications will
"collapse" the "stacks" of dimension 1 down to a single 4 x 1 array:

_ _ _ _ _ _ _ _ _ _ _ _ _ 
|_ 1 _|_ 3 _|_ 2 _|_ 8 _|

This can then be summed, or have any operation performed.

أحتاج إلى القيام بذلك باستخدام مجموعة من الأبعاد 'n'، والتي يمكن أن تكون 20 عمليًا.وأيضًا، أحتاج إلى أن أكون قادرًا على القيام بذلك، مع الاهتمام بأبعاد معينة، وانهيار الباقي.أواجه وقتًا عصيبًا بشكل خاص مع هذا لأنني لا أستطيع تصور 20 بُعدًا :p.إذا كان بإمكان أي شخص مساعدتي في إعداد بعض أكواد c/c++ للانهيار/الجمع، سأكون ممتنًا جدًا.

تحديث:

لقد عدت الى المنزل للتو.إليك بعض المعلومات للإجابة على أسئلتك:

  1. آسف لاسترجاع التعديلات، كنت آمل أنه عندما قمت بالنقر على التراجع، ستظهر لي التغييرات حتى أتمكن من رؤية ما أفسدته، تمامًا مثل ويكيبيديا.ولم يكن هذا هو الحال، كما اكتشفت.
  2. @jeff - ما الذي لا معنى له؟أنا أستخدم هذه الخدمة الرائعة لسبب مشروع (على ما أعتقد).أريد أن أتحسن في هوايتي، وهذا كل ما في الأمر، لأنني في المدرسة الثانوية.تتعلق العديد من منشوراتي بتنفيذ الخوارزمية الجينية (هذا المنشور، مصفوفة متناثرة، ترتيب مصفوفة، معالجة المؤشر).
  3. أنا أستخدم تمثيل مصفوفة متفرقة، حيث أنه من الممكن تجاوز عدد الجزيئات الموجودة في الكون باستخدام مصفوفة تقليدية (كثيفة).في الوقت الحالي، لا يهم تنفيذ مصفوفة سبارسيراي نفسها كثيرًا، حيث إنني أعمل على جعلها تعمل مع مصفوفة قياسية قبل الانتقال إلى تمثيل متفرق.بالنسبة لأولئك الذين لم يروا أسئلتي السابقة، فأنا أستخدم شجرة بحث ثنائية كهيكل لاحتواء نقاط المصفوفة المتفرقة، ووظيفة "محرك" لاجتياز الشجرة حسب الضرورة، وإرجاع كل ما تم تصميم الوظيفة للقيام به.وهذا مرن، لذا يمكنني استيعاب الكثير من الطرق المختلفة للوصول إلى المصفوفة.
  4. البنية عبارة عن مكعب فائق، ويتم تحديد عدد الأبعاد في وقت التشغيل، بالإضافة إلى طول كل بُعد (وهي جميعها متماثلة، لأنها مكعب فائق).

شكرا للجميع على مساهمتك.

هل كانت مفيدة؟

المحلول

قد يكون لهذا تطبيقات.لنفترض أنك نفذت لعبة الحياة ثنائية الأبعاد لكونواي (والتي تحدد مستوى ثنائي الأبعاد، 1 لـ "حي"، 0 لـ "ميت") وقمت بتخزين سجل الألعاب لكل تكرار (والذي يحدد بعد ذلك مكعبًا ثلاثي الأبعاد).إذا أردت معرفة عدد البكتيريا التي كانت على قيد الحياة عبر التاريخ، فستستخدم الخوارزمية المذكورة أعلاه.يمكنك استخدام نفس الخوارزمية لإصدار ثلاثي الأبعاد (ورباعي الأبعاد وخماسي الأبعاد وما إلى ذلك) من شبكة Game of Life.

أود أن أقول إن هذا كان سؤالًا للتكرار، فأنا لست مبرمجًا بلغة C بعد ولكني أعلم أنه ممكن في لغة C.في بايثون،


def iter_arr(array):
  sum = 0
  for i in array:
    if type(i) == type(list()):
      sum = sum + iter_arr(i)
    else:
      sum = sum + i
  return sum 
  1. التكرار على كل عنصر في المصفوفة
  2. إذا كان العنصر عبارة عن مصفوفة أخرى، فاستدعاء الدالة مرة أخرى
  3. إذا لم يكن العنصر مصفوفة، فأضفه إلى المجموع
  4. مبلغ الإرجاع

يمكنك بعد ذلك تطبيق ذلك على كل عنصر في بُعد "الاهتمام".

هذا أسهل في لغة بايثون بسبب كتابة البط على الرغم من ...

نصائح أخرى

@جيف

أعتقد في الواقع أن هذا سؤال مثير للاهتمام.لست متأكدًا من مدى فائدته، لكنه سؤال وجيه.

@إد

هل يمكنك تقديم المزيد من المعلومات حول هذا السؤال؟لقد قلت أن أبعاد المصفوفة ديناميكية، ولكن هل عدد العناصر ديناميكي أيضًا؟

يحرر:سأحاول الإجابة على السؤال على أي حال.لا أستطيع أن أعطيك الكود الموجود في أعلى رأسي (سيستغرق الأمر بعض الوقت للحصول عليه بشكل صحيح بدون أي مترجم هنا على هذا الكمبيوتر)، ولكن يمكنني توجيهك في الاتجاه الصحيح ...

لنستخدم 8 أبعاد (0-7) مع الفهارس من 0 إلى 3 كمثال.أنت تهتم فقط بـ 1،2 و 6.هذا يعني أن لديك صفيفين.أولاً، array_care[4][4][4] ل 1،2 و 6.ال array_care[4][4][4] سوف تعقد النتيجة النهائية.

بعد ذلك، نريد التكرار بطريقة محددة جدًا.لدينا المصفوفة input[4][4][4][4][4][4][4][4] للتحليل، ونحن نهتم بالأبعاد 1 و2 و6.

نحتاج إلى تحديد بعض الفهارس المؤقتة:

int dim[8] = {0,0,0,0,0,0,0,0};

نحتاج أيضًا إلى تخزين الترتيب الذي نريد زيادة الفهارس به:

int increase_index_order[8] = {7,5,4,3,0,6,2,1};
int i = 0;

هذا الأمر مهم للقيام بما طلبته.

تحديد علامة الإنهاء:

bool terminate=false;

الآن يمكننا إنشاء حلقتنا:

while (terminate)
{
array_care[dim[1]][dim[2]][dim[6]] += input[dim[0]][dim[1]][dim[2]][dim[3]][dim[4]][dim[5]][dim[6]][dim[7]];

while ((dim[increase_index_order[i]] = 3) && (i < 8))
{
dim[increase_index_order[i]]=0;
i++;
}

if (i < 8) {
dim[increase_index_order[i]]++; i=0;
} else {
terminate=true;
}
}

يجب أن يعمل ذلك لمدة 8 أبعاد، مع الاهتمام بثلاثة أبعاد.سيستغرق الأمر المزيد من الوقت لجعله ديناميكيًا، وليس لدي الوقت.أتمنى أن يساعدك هذا.أعتذر، لكنني لم أتعلم ترميز التعليمات البرمجية بعد.:(

هذا النوع من الأشياء يكون أسهل بكثير إذا كنت تستخدم حاويات STL، أو ربما Boost.MultiArray.ولكن إذا كان يجب عليك استخدام مصفوفة:

#include <iostream>
#include <boost/foreach.hpp>
#include <vector>

int sum(int x) {
    return x;
}

template <class T, unsigned N>
int sum(const T (&x)[N]) {
    int r = 0;
    for(int i = 0; i < N; ++i) {
        r += sum(x[i]);
    }
    return r;
}

template <class T, unsigned N>
std::vector<int> reduce(const T (&x)[N]) {
    std::vector<int> result;
    for(int i = 0; i < N; ++i) {
        result.push_back(sum(x[i]));
    }
    return result;
}

int main() {
    int x[][2][2] = {
        { { 1, 2 }, { 3, 4 } },
        { { 5, 6 }, { 7, 8 } }
    };

    BOOST_FOREACH(int v, reduce(x)) {
        std::cout<<v<<"\n";
    }
}

في الواقع، من خلال طي الأعمدة، قمت بجمعها بالفعل، وبالتالي فإن البعد لا يهم على الإطلاق بالنسبة لمثالك.هل فاتني شيء أم فعلت؟

أعتقد أن أفضل ما يمكنك فعله هنا هو أحد الأمرين أو كليهما:

  1. أعد التفكير في التصميم، إذا كان معقدًا للغاية، فابحث عن طريقة أقل تعقيدًا.
  2. توقف عن محاولة تصور ذلك..:P ما عليك سوى تخزين الأبعاد المعنية التي تحتاج إلى جمعها، ثم القيام بها واحدًا تلو الآخر.بمجرد حصولك على الكود الأساسي، فكر في تحسين كفاءة الخوارزمية الخاصة بك.

أختلف معك، هناك دائما طريقة أخرى..

وإذا كنت حقا لا تستطيع refactor، فأنت بحاجة إلى تقسيم المشكلة إلى أجزاء أصغر..كما قلت، حدد الأبعاد التي تحتاج إلى جمعها، ثم اضربها واحدًا تلو الآخر.

توقف أيضًا عن تغيير التعديلات، فهي تصحح الأخطاء الإملائية، وتحاول مساعدتك ;)

أنت تفعل هذا في c/c++ ...بحيث يكون لديك مجموعة من مجموعة من مجموعة ...ليس عليك تصور 20 بُعدًا نظرًا لأن هذه ليست الطريقة التي يتم بها وضع البيانات في الذاكرة، فهي ثنائية الأبعاد:

[1] --> [1,2,3,4,5,6,...]
[2] --> [1,2,3,4,5,6,...]
[3] --> [1,2,3,4,5,6,...]
[4] --> [1,2,3,4,5,6,...]
[5] --> [1,2,3,4,5,6,...]
 .           .
 .           .
 .           .

فلماذا لا يمكنك التكرار عبر الأول مع تلخيص محتوياته؟إذا كنت تحاول العثور على الحجم، إذن sizeof(array)/sizeof(int) هو نهج محفوف بالمخاطر.يجب أن تعرف البعد لتتمكن من معالجة هذه البيانات، وإعداد الذاكرة، حتى تعرف عمق التكرار الذي يجب جمعه.إليك بعض التعليمات البرمجية الزائفة لما يبدو أنه يجب عليك فعله،

sum( n_matrix, depth )
  running_total = 0
  if depth = 0 then
    foreach element in the array
      running_total += elm
  else 
     foreach element in the array
       running_total += sum( elm , depth-1 )
  return running_total
x = number_of_dimensions;
while (x > 1)
{
  switch (x)
  {
    case 20:
      reduce20DimensionArray();
      x--;
    break;
    case 19:
      .....
  }
}

(آسف، لم أستطع المقاومة.)

إذا فهمت بشكل صحيح، فأنت تريد جمع كل القيم في المقطع العرضي المحدد في كل "سلة" بطول بُعد واحد.أقترح إنشاء مصفوفة أحادية الأبعاد لوجهتك، ثم تكرار كل عنصر في المصفوفة الخاصة بك وإضافة القيمة إلى الوجهة مع فهرس البعد محل الاهتمام.

إذا كنت تستخدم عددًا عشوائيًا من الأبعاد، فيجب أن يكون لديك طريقة لمعالجة العناصر (سأكون مهتمًا بكيفية تنفيذ ذلك).سيؤثر تنفيذك لهذا على كيفية تعيين فهرس الوجهة.ولكن هناك طريقة واضحة تتمثل في التحقق من البيانات في حلقات التكرار.

عندما تقول أنك لا تعرف عدد الأبعاد الموجودة، كيف تحدد هياكل البيانات بالضبط؟

في مرحلة ما، يحتاج شخص ما إلى إنشاء هذه المصفوفة، وللقيام بذلك، يجب عليه معرفة أبعاد المصفوفة.يمكنك إجبار المنشئ على تمرير هذه البيانات مع المصفوفة.

ما لم يكن السؤال هو تحديد بنية البيانات هذه ...

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top