Dynamiczne+zagniezdzone wywolanie tablic w petlach

0

Witam Panowie i zwracam sie z uprzejma prosba o wsparcie :)

Mam zestaw tablic roznych typow:

	ArrInt3D arrInt3D;
	ArrDouble3D arrDouble3D;
	VecInt vecInt;
	ArrInt2D arrInt2D;

Oraz odpowiadajace im tablice/wartosci nizszgo rzedu reprezentujace ich wiersze:

	ArrInt2D arrInt2D;
	ArrDouble2D arrDouble2D;
	int valueInt;
	VecInt vecInt;

Powyzsze tablice (pierwszy zestaw) w zaleznosci od warunkow maja byc wywolywane wg okreslonego porzadku opisanego przez dodatkowa tablice:

VecInt vecIntOrder;

w takim oto ukladzie zagniezdzonych petli:

	for (auto &subArr1 : arr1){
		for (auto &subArr2 : arr2) {
			for (auto &subArr3 : arr3) {
				for (auto &subArr4 : arr4) {

				}
			}
		}
	}

Pytania mam nastepujace:

  1. W jaki sposob w C++ dynamicznie przyporzadkowac tablice zadeklarowane w sposob jawny tablicom w zagniezdzonych petlach Arr1, Arr2, Arr3, Arr4 wg okreslonego wczesniej porzadku ?
  2. W jaki sposob w C++ sub tablice: subArr1, subArr2, subArr3, subArr4 przyporzadkowac odpowiednim tablicom nizszego rzedu ?

Z gory bardzo dziekuje za pomoc :D

0

Ja też niewiele zrozumiałem, ale spróbuję... :)

Nie chciałeś napisać czegoś takiego:

	for (auto &subArr1 : arr1){
		for (auto &subArr2 : subArr1) {
			for (auto &subArr3 : subArr2) {
				for (auto &elem : subArr3) {

				}
			}
		}
	}

Czy to nie jest odpowiedź (lub jej część) na Twoje zagmatwane pytanie...?

Jeśli zdefiniujesz sobie coś takiego:

vector<vector<vector<vector<int>>>> arr1;

to powyższe pętle powinny działać...

0

Chcialem napisac dokladnie to co napisalem :).

Zatem bardziej obrazowo:

	for (auto &arrInt2D : arrInt3D){
		for (auto &arrDouble2D : arrDouble3D) {
			for (auto &valInt : vecInt) {
				for (auto &vecInt : arrInt2D) {

				}
			}
		}
	}

Jak widac tablice umieszczone sa w zagniezdzonych petlach w pewnym porzadku: arrInt3D, arrDouble3D, vecInt, arrInt2D.
Problem polega na tym ze ten porzadek jest dynamiczny i w zaleznosci od sytuacji moze byc np taki: arrDouble3D, vecInt, arrInt3D, arrInt2D.

1

Jedyne rozwiązanie jakie widzę, to umieszczenie tych tablic w innej tablicy, a następnie wywoływanie zależnie od indeksu, który będzie się zmieniał.

edit: Typy tablic nie będą problemem, jeśli opakujesz je w jedną klasę, po której będą dziedziczyć. Natomiast sam vector możesz nastawić na przechowywanie ich typu bazowego.

edit2: Jeśli chodzi o sub-tablice, to rozwiązaniem także może być opakowanie tablic w klasie, której polem publicznym będzie sama tablica, a jej polem prywatnym sub-tablica.

edit3: Przykładowo może to wyglądać tak:

class BasicArray
{
}

class ArrInt3DC : public BasicArray
{
public:
    ArrInt3D arrInt3D;
private:
    ArrInt2D arrInt2D;
}

// Wykorzystanie:
std::vector<std::unique_ptr<BasicArray>> arrays;

edit4: Tak jak @YooSy pisał poniżej - wskaźnik jako typ szablonowy.

2

Żeby

std::vector<BasicArray> arrays;

działało poprawnie dla dowolnego typu po klasie bazowej, typem szablonowym vectora powinien być wskaźnik.

np.

std::vector<std::unique_ptr<BasicArray>> arrays;
1

A szablon coś pomoże?

template <typename T1, typename T2, typename T3, typename T4>
void petle(T1 & a1, T2 & a2, T3 & a3, T4 & a4) {
	for (auto &sa1 : a1) {
		for (auto &sa2 : a2) {
			for (auto &sa3 : a3) {
				for (auto &sa4 : a4) {
...
				}
			}
		}
	}
}
0

Panowie bardzo Wam dziekuje za reakcje - sprobuje to jakos rozkminic w sposob jaki sugerujecie :/ .

1

Dla mnie to problem XY.
Radzę zadać pytanie inaczej: napisz jaki problem ma rozwiązywać twój kod!
W tej chwili pytasz jak naprawić jakiś dziwny pomysł, którego nie jesteśmy w stanie zrozumieć, a problem zapewne jest bardzo prosty (podejrzewam problem, w którym potrzebna jest struktura drzewa).
http://xyproblem.info/

0
MarekR22 napisał(a):

Dla mnie to problem XY.
Radzę zadać pytanie inaczej: napisz jaki problem ma rozwiązywać twój kod!

Gwoli zaspokojenia ciekawosci. Problem dotyczy partii kodu odpowiedzialnej za wielokrotne uruchomienie algorytmu w oparciu o przewidziana przez uzytkownika zmiane poszczegolnych elementow konfiguracji. Kazda tablica zatem odpowiada pewnemu zakresowi konfiguracji, natomiast wiersze tej tablicy to po prostu rozne warianty konkretnego elementu konfiguracji.

MarekR22 napisał(a):

W tej chwili pytasz jak naprawić jakiś dziwny pomysł, którego nie jesteśmy w stanie zrozumieć, a problem zapewne jest bardzo prosty (podejrzewam problem, w którym potrzebna jest struktura drzewa).
http://xyproblem.info/

Pomysl nie jest dziwny i wbrew temu co piszesz niektorzy jednak dali sobie rade ze zrozumieniem.
Co do prostoty, to owszem jego realizacja jest banalnie prosta w php i nawet w java, jednak nastrecza pewne trudnosci w C++ ze wzgledu na jego specyfike. Co jednak najwazniejsze - wiem o czym mowie poniewaz mam za soba implementacje w obu tych jezykach. Stwierdzenie dotyczace potrzeby struktury drzewa oparte o fakt istnienia zagniezdzonych petli absolutnie nic nie wnosi z oczywistego powodu: wszystko oparte o zagniezdzone petle ma taka strukture. Zatem nie o strukture tu chodzi ale o mozliwosc jej dynamicznej modyfikacji.

0

@MarekR22 akurat ma nosa do XY (o czym przekonałem się na własnej skórze:P). Nie chodzi o ciekawość a o rozwiązanie problemu.
Nie wiem czy to dobry pomysł, bo wciąż nie wiadomo dokładnie o co chodzi, ale te różne warianty różnych konfiguracji podsunęły mi pewną myśl: wzorzec Strategia

0

@Constantic: A może byś pokazał te swoje implementacje w PHP i Javie? Są gdzieś na githubie, żeby obejrzeć? Bo może jednak łatwo się da przenieść do C++...

0

Mi także pachnie XY. Jeśli jednak dobrze zrozumiałem problem, wystarczą Ci typy std::variant które przechowują kombinacje typów konfiguracji lub std::tuple które przechowują w kolejności typy tychże. Następnie ew. strategia wyboru odpowiedniej konfiguracji. IMHO próbujesz dopasować dynamizm z innego języka bez refleksji że C++ jest ściśle typowany.

0
koszalek-opalek napisał(a):

@Constantic: A może byś pokazał te swoje implementacje w PHP i Javie? Są gdzieś na githubie, żeby obejrzeć? Bo może jednak łatwo się da przenieść do C++...

Niestety nie moge to byly komercyjne SN, a wlasciwie cos w rodzaju oscylatora.

0
Mokrowski napisał(a):

Mi także pachnie XY.

Z pewnoscia masz racje. W sposob naturalny najpierw proboje opierac sie na znanych mi juz wczesniej rozwiazaniach.

Mokrowski napisał(a):

Jeśli jednak dobrze zrozumiałem problem, wystarczą Ci typy std::variant które przechowują kombinacje typów konfiguracji lub std::tuple które przechowują w kolejności typy tychże.

Mozliwe, ze masz racje. Musze o tym jednak poczytac.

Mokrowski napisał(a):

... bez refleksji że C++ jest ściśle typowany.

Podobnie jak JAVA, ktora umozliwia implementacje wprost rozwiazania, ktore proboje uzyskac w C++. Jesli jednak chodzi o reflekscje to drugiej strony w C++ pojawily sie szablony...

0
Constantic napisał(a):
koszalek-opalek napisał(a):

@Constantic: A może byś pokazał te swoje implementacje w PHP i Javie? Są gdzieś na githubie, żeby obejrzeć? Bo może jednak łatwo się da przenieść do C++...

Niestety nie moge to byly komercyjne SN, a wlasciwie cos w rodzaju oscylatora.

Nawet tylko kawałka -- istotnego dla sprawy? Bo z Javy już do C++ niedaleko, a byśmy pomogli wiedząc, o co rzeczywiście chodzi...

0
koszalek-opalek napisał(a):
Constantic napisał(a):
koszalek-opalek napisał(a):

@Constantic: A może byś pokazał te swoje implementacje w PHP i Javie? Są gdzieś na githubie, żeby obejrzeć? Bo może jednak łatwo się da przenieść do C++...

Niestety nie moge to byly komercyjne SN, a wlasciwie cos w rodzaju oscylatora.

Nawet tylko kawałka -- istotnego dla sprawy? Bo z Javy już do C++ niedaleko, a byśmy pomogli wiedząc, o co rzeczywiście chodzi...

Bardzo Ci dziekuje za zangazowanie, ale musialbym wlamac sie na serwer klienta :), a poniewaz jest to wlasciciel platformy gier losowych/hazardowych nie byloby to latwe :). Uprzedzajac Twoje ewentualne pytanie - nie, nie mam nawet skrawka kodu na swoim prywatnym komputerze. Tajemnica handlowa/kontrakt itp itd :).
Probuje odtworzyc kod w C++ ze wzgledu na predkosc na potrzeby swojego prywatnego projektu bo w javie (nie wspominajac o php) kod byl mimo wszystko mulasty a ja bede potrzebowal czegos szybkiego dla sporej ilosci danych.

0

Ogólnie to opisałeś to i szkic masz ogólny. Instynktownie czuję że bez pełnej znajomości problemu, wyjdzie z tego potwór... No ale jak chcesz, możesz np. robić tak:

#include <iostream>
#include <tuple>
#include <variant> // lub experimental/variant jeśli kompilator nieco starszy... 
#include <vector>
#include <array>

// Definicje jakiś kontenerów
using VecInt = std::vector<int>;
using ArrInt = std::array<int, 5>;
using ArrVecInt2D = std::array<std::vector<int>, 5>;
using ArrArrInt2D = std::array<ArrInt, 5>;
using VecArrVecInt3D = std::vector<ArrVecInt2D>;
using ArrArrArrInt3D = std::array<ArrArrInt2D, 5>;

// Możliwe konfiguracje jednostkowe...
using Config1 = std::tuple<ArrVecInt2D, VecInt>;
using Config2 = std::tuple<ArrArrInt2D, ArrInt>;
using Config3 = std::tuple<VecArrVecInt3D, ArrVecInt2D>;
using Config4 = std::tuple<ArrArrArrInt3D, ArrArrInt2D>;

// Możliwe konbinacje konfiguracji... 
using CombineConfig1 = std::tuple<Config1, Config3>;
using CombineConfig2 = std::tuple<Config2, Config4>;

// Kontener konfiguracji...
using ConfigType = std::variant<CombineConfig1, CombineConfig2>;

int main() {
    // Jakieś przykładowe dane by mieć co wyświetlać...
    VecInt vec{1, 2, 3, 4};
    ArrInt arr{{1, 2, 3, 4, 5}};
    ArrVecInt2D arrVecInt2D{ { { 0, 0, 3}, { 1, 3, 5 }, { 0, 0, 3}, { 1, 3, 5 }, { 1, 3, 5 } } };
    ArrArrInt2D arrArrInt2D{ { { 1, 3, 4, 5, 6}, { 3, 5, 3, 3, 4}, arr, arr, arr } };
    VecArrVecInt3D vecArrVecInt3D{ arrVecInt2D, arrVecInt2D };
    ArrArrArrInt3D arrArrArrInt3D{ {arrArrInt2D, arrArrInt2D, arrArrInt2D, arrArrInt2D, arrArrInt2D}};

    std::vector<ConfigType> configs{
        std::make_tuple( // CombineConfig1
                std::make_tuple(arrVecInt2D, vec),
                std::make_tuple(vecArrVecInt3D, arrVecInt2D)
        ),
        std::make_tuple( // CombineConfig2
                std::make_tuple(arrArrInt2D, arr),
                std::make_tuple(arrArrArrInt3D, arrArrInt2D)
        )
    };

    std::size_t confIndex;
    std::cout << "Podaj wybór konfiguracji [0, 1]: ";
    std::cin >> confIndex; // TODO: Kontrola poprawności
    ConfigType& choicedConfig = configs[confIndex];
    std::cout << "Wybrano konfigurację: " << choicedConfig.index() << '\n';
    // Tu w zależności od .index(), implementacje konfiguracji. 
    // Zrobił bym szablonem z wymuszeniem instancjonowania kombinacji dla typów szablonu.
    // Pobranie danych z std::tuple, zwykłym std::get<X>

}

Dalej już proste implementacje. Początek jest przerażający :)

0

A tak wyglada completna implementacja w php dla porownania;

Zatem dla przykladowej tablicy porzadku wywolan konfigow:

$arrOrderLooperConfig = [
    [
        'structureLooper',
        'nodeLooper',
        'sequenceLooper',
    ],
    [
        'nodeLooper',
        'sequenceLooper',
        'structureLooper',
    ],
];

Ponizsza klasa zalatwia wszystko dynamicznie bedac skonczona implementacja oczekiwanego rozwiazania (nothing hardcoded :D ) :

class Optimizer
{
    private $orderLooper;
    private $structureLooper;
    private $nodeLooper;
    private $sequenceLooper;
    private $algorithm;

    public function __construct(
        OrderLooper $orderLooper,
        StructureLooper $structureLooper,
        NodeLooper $nodeLooper,
        SequenceLooper $sequenceLooper,
        Algorithm $algorithm
    ) {
        $this->orderLooper = $orderLooper;
        $this->structureLooper = $structureLooper;
        $this->nodeLooper = $nodeLooper;
        $this->sequenceLooper = $sequenceLooper;
        $this->algorithm = $algorithm;
    }

    public function init()
    {
        $this->orderLooper->init();

        $this->structureLooper->init();
        $this->nodeLooper->init();
        $this->sequenceLooper->init();
    }

    public function run()
    {
        $arrOrderLooperConfig = $this->orderLooper->getConfig();

        foreach($arrOrderLooperConfig as $rowOrderLooperConfig) {
            $arrConfig0 = $this->{$rowOrderLooperConfig[0]}->getArrConfig();

            foreach($arrConfig0 as $rowConfig0) {
                $this->{$looper0Name}->setRowConfig($rowConfig0);

                $arrConfig1 = $this->{$rowOrderLooperConfig[1]}->getArrConfig();

                foreach($arrConfig1 as $rowConfig1) {
                    $this->{$looper1Name}->setRowConfig($rowConfig1);

                    $arrConfig2 = $this->{$rowOrderLooperConfig[2]}->getArrConfig();

                    foreach($arrConfig2 as $rowConfig2) {
                        $this->{$looper2Name}->setRowConfig($rowConfig2);

                        $this->algorithm->run(
                            $this->structureLooper->getRowConfig(),
                            $this->nodeLooper->getRowConfig(),
                            $this->sequenceLooper->getRowConfig()
                        );
                    }
                }
            }
        }
    }
}

Oczywiscie w jave jest to "odrobine" bardziej zlozone, ale z grubsza da sie uzyskac podobny efekt - dla mnie jest juz jednak za pozno zeby klepac przyklad z palca.

1 użytkowników online, w tym zalogowanych: 0, gości: 1