Как указываются размеры суммы массива во время выполнения? - PullRequest
4 голосов
/ 22 августа 2008

Я работаю над функцией, чтобы установить энтропию распределения. Он использует связку, если кто-либо знаком с этим. Мне нужно суммировать значения в массиве, основываясь на том, какие измерения "заботятся".

Пример: рассмотрим следующий пример ...

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 измерений: с. Если бы кто-нибудь мог помочь мне настроить некоторый код на c / c ++, чтобы свернуть / суммировать, я был бы очень очень благодарен.

Обновление:

Только что вернулся домой. Вот некоторая информация, чтобы ответить на ваши вопросы:

  1. Извините за откат изменений, я надеялся, что когда я нажму на откат, он покажет мне изменения, чтобы я мог видеть, что я испортил, немного похоже на Википедию. Как я выяснил, это был не тот случай.
  2. @ jeff - Что не имеет смысла? Я пользуюсь этим замечательным сервисом по (как мне кажется, законной) причине. Я хочу стать лучше в своем хобби, и это все, чем я занимаюсь в старшей школе. Многие из моих постов касаются реализации генетического алгоритма (этот пост, sparsearray, ранжирование массива, манипулирование указателями).
  3. Я использую представление разреженного массива, поскольку можно превысить число молекул во вселенной, используя традиционный (плотный) массив. На данный момент реализация самого sparsearray не имеет большого значения, так как я работаю над тем, чтобы он работал со стандартным массивом, прежде чем переходить к разреженному представлению. Для тех, кто не видел мои предыдущие вопросы, я использую бинарное дерево поиска в качестве структуры, которая содержит разреженные точки массива, и функцию «драйвера» для обхода дерева по мере необходимости, возвращая то, для чего предназначена функция. Это гибкий инструмент, поэтому я могу использовать множество различных методов доступа к массиву.
  4. Структура представляет собой гиперкуб, и число измерений указывается во время выполнения, а также длина каждого измерения (которые все одинаковы, поскольку это гиперкуб).

Спасибо всем за ваш вклад.

Ответы [ 10 ]

2 голосов
/ 24 августа 2008

Это может иметь приложения. Допустим, вы реализовали 2D игру жизни Конвея (которая определяет 2D-плоскость, 1 для «живого», 0 для «мертвого») и сохранили историю игр для каждой итерации (которая затем определяет 3D-куб). Если вы хотите узнать, сколько бактерий было в живых за всю историю, вы должны использовать приведенный выше алгоритм. Вы можете использовать тот же алгоритм для 3D, (и 4D, 5D и т. Д.) Версии сетки Жизни.

Я бы сказал, что это был вопрос для рекурсии, я еще не программист на C, но я знаю, что это возможно на C. В python,


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. Возвращаемая сумма

Затем вы примените это к каждому элементу в измерении «заботятся о».

Это проще в python из-за утки, хотя ...

2 голосов
/ 22 августа 2008

@ Jeff

Я действительно думаю, что это интересный вопрос. Я не уверен, насколько это полезно, но это правильный вопрос.

@ Ed

Можете ли вы предоставить немного больше информации по этому вопросу? Вы сказали, что размерность массива динамическая, но динамично ли количество элементов?

РЕДАКТИРОВАТЬ: Я собираюсь попытаться ответить на вопрос в любом случае. Я не могу дать вам код с ног на голову (потребуется некоторое время, чтобы сделать это правильно без компилятора здесь на этом ПК), но я могу указать вам правильное направление ...

Давайте использовать 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 измерений, заботясь о 3 измерениях. Потребовалось бы немного больше времени, чтобы сделать его динамичным, а у меня нет времени. Надеюсь это поможет. Я прошу прощения, но я еще не выучил разметки кода. (

2 голосов
/ 23 августа 2008

Такого рода вещи намного проще, если вы используете контейнеры 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";
    }
}
0 голосов
/ 23 августа 2008

Если я правильно понимаю, вы хотите суммировать все значения в поперечном сечении, определенные в каждом «бункере» по 1 измерению. Я предлагаю создать одномерный массив для вашего места назначения, а затем перебрать каждый элемент в вашем массиве, добавив значение к месту назначения с индексом интересующего измерения.

Если вы используете произвольное количество измерений, у вас должен быть способ адресации элементов (мне было бы любопытно, как вы реализуете это). Ваша реализация этого повлияет на то, как вы установите целевой индекс. Но очевидный способ был бы, если бы операторы проверялись в циклах итерации.

0 голосов
/ 22 августа 2008
x = number_of_dimensions;
while (x > 1)
{
  switch (x)
  {
    case 20:
      reduce20DimensionArray();
      x--;
    break;
    case 19:
      .....
  }
}

(Извините, не удержался.)

0 голосов
/ 22 августа 2008

Вы делаете это в 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
0 голосов
/ 22 августа 2008

Когда вы говорите, что не знаете, сколько существует измерений, как именно вы определяете структуры данных?

В какой-то момент кому-то нужно создать этот массив, и для этого ему нужно знать размеры массива. Вы можете заставить создателя передать эти данные вместе с массивом.

Если вопрос не в том, чтобы определить такую ​​структуру данных ...

0 голосов
/ 22 августа 2008

Прошу отличаться, ВСЕГДА есть другой путь ..

И если вы действительно не можете выполнить рефакторинг, тогда вам нужно разбить проблему на более мелкие части ... Как я уже сказал, определите, какие измерения нужно суммировать, а затем нажмите их по одному за раз ...

Кроме того, прекратите изменять правки, они исправляют ваши орфографические ошибки, они пытаются вам помочь;)

0 голосов
/ 22 августа 2008

Я думаю, что лучше всего сделать одну / обе вещи:

  1. Переосмыслите дизайн, если он слишком сложный, найдите менее сложный способ.
  2. Хватит пытаться визуализировать это ..: P Просто сохраните данные измерения, которые вам нужно сложить, а затем делайте их по одному. Получив базовый код, посмотрите на повышение эффективности вашего алгоритма.
0 голосов
/ 22 августа 2008

На самом деле, сжимая столбцы, вы уже суммировали их, поэтому размерность для вашего примера не имеет значения. Я что-то пропустил или ты?

...