Вот мое предложение в C ++
Я попытался наложить как минимальное ограничение на тип итератора, так как я мог так это решение предполагал просто итератор вперед, и он может быть const_iterator. Это должно работать с любым стандартным контейнером. В тех случаях, когда аргументы не имеют смысла, это вызывает std :: invalid_argumnent
#include <vector>
#include <stdexcept>
template <typename Fci> // Fci - forward const iterator
std::vector<std::vector<Fci> >
enumerate_combinations(Fci begin, Fci end, unsigned int combination_size)
{
if(begin == end && combination_size > 0u)
throw std::invalid_argument("empty set and positive combination size!");
std::vector<std::vector<Fci> > result; // empty set of combinations
if(combination_size == 0u) return result; // there is exactly one combination of
// size 0 - emty set
std::vector<Fci> current_combination;
current_combination.reserve(combination_size + 1u); // I reserve one aditional slot
// in my vector to store
// the end sentinel there.
// The code is cleaner thanks to that
for(unsigned int i = 0u; i < combination_size && begin != end; ++i, ++begin)
{
current_combination.push_back(begin); // Construction of the first combination
}
// Since I assume the itarators support only incrementing, I have to iterate over
// the set to get its size, which is expensive. Here I had to itrate anyway to
// produce the first cobination, so I use the loop to also check the size.
if(current_combination.size() < combination_size)
throw std::invalid_argument("combination size > set size!");
result.push_back(current_combination); // Store the first combination in the results set
current_combination.push_back(end); // Here I add mentioned earlier sentinel to
// simplyfy rest of the code. If I did it
// earlier, previous statement would get ugly.
while(true)
{
unsigned int i = combination_size;
Fci tmp; // Thanks to the sentinel I can find first
do // iterator to change, simply by scaning
{ // from right to left and looking for the
tmp = current_combination[--i]; // first "bubble". The fact, that it's
++tmp; // a forward iterator makes it ugly but I
} // can't help it.
while(i > 0u && tmp == current_combination[i + 1u]);
// Here is probably my most obfuscated expression.
// Loop above looks for a "bubble". If there is no "bubble", that means, that
// current_combination is the last combination, Expression in the if statement
// below evaluates to true and the function exits returning result.
// If the "bubble" is found however, the ststement below has a sideeffect of
// incrementing the first iterator to the left of the "bubble".
if(++current_combination[i] == current_combination[i + 1u])
return result;
// Rest of the code sets posiotons of the rest of the iterstors
// (if there are any), that are to the right of the incremented one,
// to form next combination
while(++i < combination_size)
{
current_combination[i] = current_combination[i - 1u];
++current_combination[i];
}
// Below is the ugly side of using the sentinel. Well it had to haave some
// disadvantage. Try without it.
result.push_back(std::vector<Fci>(current_combination.begin(),
current_combination.end() - 1));
}
}
Вам нужно поместить его в мини-страницу
, например:
\begin{tabular}{ ll }
sample &
\begin{minipage}{3in}
\begin{verbatim}
<how>
<to value="make" />
<this value="work" />
</how>
\end{verbatim}
\end{minipage}
\end{tabular}
К сожалению, это означает, что вам нужно заранее решить, какой ширины будет столбец (это то, что {3in}
часть делает). Обычно я начинаю с 3 дюймов, а затем увеличиваю или уменьшаю его до тех пор, пока страница не будет выглядеть хорошо, и я не перестану получать сообщения о переполнении hbox.
Попробуйте с
\begin{tabular}{lp{5in}}
Т.е. измените окружение verbatim
, чтобы оно было в колонке типа p
. Другие решения - использовать multicols
или minipage
для окружения verbatim
.