Как Суммировать размеры массива, указанного во время выполнения?

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 ++ для свертывания / sum, я был бы очень, очень благодарен.

Обновить:

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

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

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

Это было полезно?

Решение

У этого могут быть приложения.Допустим, вы реализовали 2D Conway's Game of Life (которая определяет 2D плоскость, 1 для "живой", 0 для "мертвой"), и вы сохранили историю игр для каждой итерации (которая затем определяет 3D куб).Если бы вы хотели знать, сколько бактерий было живым за всю историю, вы бы использовали приведенный выше алгоритм.Вы могли бы использовать тот же алгоритм для 3D-(и 4D, 5D и т.д.) версий Game of Life grid.

Я бы сказал, что это был вопрос для рекурсии, я еще не программист на 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 это проще из-за утиного набора текста...

Другие советы

@Джефф

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

@Эд

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

Редактировать:Я все равно попытаюсь ответить на этот вопрос.Я не могу дать вам код сразу (потребовалось бы некоторое время, чтобы разобраться в нем без какого-либо компилятора здесь, на этом компьютере), но я могу указать вам правильное направление ...

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

Такого рода вещи намного проще, если вы используете контейнеры STL, или, может быть Повышение.Многомассивный.Но если вы должны использовать массив:

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

Позволю себе не согласиться, всегда есть другой способ..

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

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

Вы делаете это на c / c ++...итак, у вас есть массив array of array...вам не нужно визуализировать 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:
      .....
  }
}

(Извините, не смог удержаться.)

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top