Как указываются размеры суммы массива во время выполнения?

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

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

Размер 0 (поперек)
_ _ _ _ _ _ _ _ _ _ _ _ _ _
| _ 0 _ | _ 0 _ | _ 0 _ | _ 2 _ | Размер 1
| _ 1 _ | _ 0 _ | _ 2 _ | _ 0 _ | (вниз)
| _ 0 _ | _ 3 _ | _ 0 _ | _ 6 _ |
| _ 0 _ | _ 0 _ | _ 0 _ | _ 0 _ |

Я «забочусь о» только измерении 0 и «не забочусь» об остальных (dim 1).
Суммирование этого массива с вышеуказанными спецификациями
"свернуть" стеки измерения 1 до одного массива 4 x 1:

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

Это можно затем суммировать или выполнить любую операцию.

Мне нужно сделать это с массивом «n» измерений, которые могут быть равны 20. Кроме того, я должен быть в состоянии сделать это, заботясь об определенных измерениях и сворачивая остальные. Мне особенно тяжело с этим, потому что я не могу представить 20 измерений: с. Если бы кто-нибудь мог помочь мне настроить некоторый код на c / c ++, чтобы свернуть / суммировать, я был бы очень очень благодарен.

Обновить:

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

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

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

22.08.2008 18:56:04
Эд, я просматриваю твою историю постов и задаюсь вопросом, не пытаешься ли ты продержаться в переполнении стека. Есть ли у вас какие-то вопросы?
Jeff Atwood 22.08.2008 19:23:59
10 ОТВЕТОВ
РЕШЕНИЕ

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

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

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

Это легче в питоне из-за утки, хотя ...

2
24.08.2008 12:52:03

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

0
22.08.2008 18:58:07

Я думаю, что лучшее, что можно сделать здесь, - это одно из двух:

  1. Переосмыслите дизайн, если он слишком сложный, найдите менее сложный способ.
  2. Перестаньте пытаться визуализировать это ..: P Просто сохраните данные измерения, которые нужно суммировать, а затем делайте их по одному. Если у вас есть базовый код, посмотрите на повышение эффективности вашего алгоритма.
0
22.08.2008 19:04:34

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

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

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

0
22.08.2008 19:13:10

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

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

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

0
3.07.2012 15:02:20

Вы делаете это в c / c ++ ... так что у вас есть массив массив массивов ... вам не нужно визуализировать 20 измерений, поскольку это не то, как данные размещаются в памяти, для 2 мерная:

[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.08.2008 19:29:03

@Джефф

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

@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
22.08.2008 20:32:24
x = number_of_dimensions;
while (x > 1)
{
  switch (x)
  {
    case 20:
      reduce20DimensionArray();
      x--;
    break;
    case 19:
      .....
  }
}

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

0
22.08.2008 20:13:51

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

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

0
22.08.2008 20:16:57

Такого рода вещи намного проще, если вы используете контейнеры 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";
    }
}
2
22.08.2008 21:19:16