Поиск всех возможных комбинаций 4 векторов с C++

Я хочу найти все возможные комбинации четырех базисных векторов (размерность = 4) в зависимости от пользовательского ввода. Следует разрешить повторение.

т.е. назовем векторы a, b, c и d.

Если Пользователь вводит N=3, комбинации могут быть:

ааа ааб аак . . . ддд

Я старался изо всех сил, но я еще не знаком с C++.

Приложение также должно вычислить произведение базисных векторов (т. е. a*a*a) и сохранить результат.

Я, конечно, заглянул на форум раньше, но нашел статьи только о комбинировании целых чисел или элементов векторов.

Спасибо за вашу помощь.


person Kepler    schedule 16.07.2011    source источник
comment
Давайте посмотрим ваш существующий код. Дайте нам знать, где вы застряли   -  person Merlyn Morgan-Graham    schedule 16.07.2011
comment
Кодирование без пользовательского ввода было легким, ровно столько циклов for, сколько я хотел бы иметь. Но если я заранее не знаю, сколько циклов for потребуется, я не знаю, с чего начать.   -  person Kepler    schedule 16.07.2011
comment
это домашнее задание, да?   -  person Karoly Horvath    schedule 16.07.2011
comment
@Kepler: рекурсия звонит в колокол?   -  person Karoly Horvath    schedule 16.07.2011
comment
Я должен сделать это для учебы. Я знаю, что такое рекурсия, но пока не могу найти рекурсию самостоятельно. Итерация - это ключ :-) Но если у вас есть рекурсивный способ, все в порядке.   -  person Kepler    schedule 16.07.2011
comment
рекурсия является ключевым. вы можете поддерживать состояние в стеке, но это только усложнит код.   -  person Karoly Horvath    schedule 16.07.2011


Ответы (4)


Если ваша программа основана на Linux (например, у вас есть доступ к оболочке типа bash), то вы можете получить все комбинации, скажем, a,b,c,d с N=3, введя команду: "echo {a ,b,c,d}{a,b,c,d}{a,b,c,d}" - выведет все приведенные выше комбинации: aaa, aab... и т.д.

Затем вы можете поймать этот вывод и проанализировать его побуквенно и умножить базовый вектор (скажем, (1,1,1,1) для dim = 4) на каждый из векторов, соответствующих букве. Но опять же, что вы подразумеваете под умножением векторов? Вы имеете в виду найти величину а*а*а? Потому что вы не можете умножать (1x4) векторы вместе - вы можете взять только их скалярное произведение. (поэтому единственно возможной интерпретацией a*a*a может быть |a|^3.)

Пример вызова эхо-команды:

#include <stdio.h>
#include <string>
#include <vector>

int n; //user given - n>1
Vector4D* vectors[n]; // Or some other name for the class
// Have the user input the vectors
std::string base = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
std::string list = "{"+base.substr(0,2*n+1)+"}";
std::string query = "echo ";
for(int i = 0; i<4; i++){
    query += list;
}
File *file;
file=popen(query.c_string(), "r");
char combo[4];
std::vector<Vector4D> results;
while(fscanf(file,"%s", combo)){
    Vector4D result(1,1,1,1); //our default (identity) vector
    for(int i = 0; i<4; i++){
        result = Vector4D.multiply(result, Vectors[combo[i]-'a']);
    }
    results.push_back(result);
} 
fclose(file);

что-то вроде этого, хотя а) непроверенный б) неполный в) работает только для размеров выборки до 26 векторов (хорошо 52, если вы включаете заглавные буквы)

person strelok    schedule 16.07.2011
comment
перекрестное произведение звонит в колокол? - person Karoly Horvath; 16.07.2011
comment
Я никогда не слышал, чтобы люди называли перекрестное произведение умножением. Бьет меня, почему кто-то бы. Кроме того, в примере крестик даст 0, так что это кажется немного ненужным. И крестик 0 даже не имеет смысла. Численно это тоже ноль, но визуально это не имеет смысла. - person strelok; 16.07.2011
comment
@strelok: Потому что продукт — это синоним умножения. В математике произведение — это результат умножения... - person Merlyn Morgan-Graham; 16.07.2011
comment
что мне действительно нужно сделать, так это вычислить тензорное произведение, но когда у меня есть комбинации, это не должно быть проблемой - person Kepler; 16.07.2011
comment
@strelok: перекрестное произведение коллинеарных векторов имеет смысл. возьмем пример из физики, где вы вычисляете силу, действующую на движущийся заряд в магнитном поле. если векторы выровнены, силы нет. также обратите внимание, что aaa.. — это всего лишь одна из всех комбинаций. - person Karoly Horvath; 16.07.2011
comment
Я никогда не говорил, что пересечение A не имеет смысла — я сказал, что пересечение A с вектором 0 не имеет смысла/не будет полезным. А насчет OpenSUSE... он должен работать - на нем должна быть форма команды echo... - person strelok; 16.07.2011
comment
Да, вы можете построить запрос из C++, а затем получить результат с помощью команды popen(). ="nofollow noreferrer">linux.about.com/library/cmd/blcmdl3_popen.htm - person strelok; 16.07.2011
comment
Пересечение вектора с 0, опять же, имеет смысл. взять тот же пример. - person Karoly Horvath; 16.07.2011

Я бы рассмотрел использование многомерного массива (в данном случае двумерного массива).

Мой уровень программирования тоже не так хорош, поэтому мои программы, как правило, немного неуклюжи, но, надеюсь, вы сможете понять, о чем я говорю, в приведенном ниже примере псевдокода!

основывать количество гнезд на числе, введенном пользователем:

user enters 4

array{ar1{a,b,c,d},ar2{a,b,c,d},ar3{a,b,c,d}ar4{a,b,c,d}}
create counter var for each array (c1, c2, c3, c4)

loop increment counters c1-4 for each letter (a-b)
print value from array table.

Я знаю, что это довольно небрежно, но это лучшее, что я могу придумать с головы (не программировал почти 3 года! LOL), но определенно изучите многомерные массивы:

http://www.tenouk.com/clabworksheet/labworksheet10.html

удачи!

person Jason    schedule 16.07.2011
comment
Что вы имеете в виду под: счетчики приращения цикла c1-4 для каждой буквы (ab)? - person Kepler; 16.07.2011
comment
@Kepler - вы создаете счетчик для каждого массива (также известного как C1-C4) и используете каждый счетчик для перехода к каждому подэлементу массива. (используйте счетчик для увеличения/сброса от A до D). взгляните на ссылку, которую я предоставил для получения дополнительной информации по этому вопросу. - person Jason; 19.07.2011

Поскольку это домашнее задание, я не буду писать вам полное решение. Проверьте этот псевдокод:

all(&srcvectors, depth, temp, &resultvectors)
    if (depth == 0)
        resultvectors.push(temp);
    else
        for (int i=0; i < 4; i++)
            all(srcvectors, depth-1, crossproduct(temp, srcvectors[i]), resultvectors);

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

Надеюсь это поможет.

person Karoly Horvath    schedule 16.07.2011

наденьте два цикла for размером 4 на 4. Это будет выполняться через каждую возможную комбинацию.

vector<char> temp;


temp.push_back('a');
temp.push_back('b');
temp.push_back('c');
temp.push_back('d');



for(int i = 0; i < 4; i++)
{
    for(int k = 0; k < 4; k++)
        cout << temp[i] << temp[k] << endl;
}

Добавьте больше петель для большей длины. Прямо сейчас он делает только 2 выходные комбинации одновременно.

Например:

vector<char> temp;


temp.push_back('a');
temp.push_back('b');
temp.push_back('c');
temp.push_back('d');


for(int j = 0; j < 4; j++)
{
    for(int i = 0; i < 4; i++)
    {
        for(int k = 0; k < 4; k++)
        {
            cout << temp[j] << temp[i] << temp[k] << endl;
            Sleep(25);
        }
    }
}

system("PAUSE");

это выведет все возможные комбинации длиной до 3. Что-нибудь еще, и вам понадобится рекурсивная функция.

person Drake    schedule 16.07.2011
comment
Примечание модератора Комментарии под этим сообщением были удалены, поскольку разговор превратился в гораздо больше шума, чем сигнала. Пожалуйста, оставляйте комментарии вежливыми, конструктивными и по теме. - person Tim Post♦; 16.07.2011