En C ++, comment diviser une chaîne en une chaîne plus petite de taille égale?
Par exemple, j’ai une chaîne “012345678” et je souhaite la scinder en 5 chaînes plus petites. Cela devrait me renvoyer quelque chose comme “01”, “23”, “45”, “67”, “8”.
J’ai du mal à déterminer la longueur des petites chaînes. Dans l’exemple précédent, la chaîne d’origine a une taille de 9 et je souhaite la scinder en 5 chaînes plus petites. Chaque chaîne, à l’exception de la dernière, doit donc avoir une longueur de 9/5 = 1, mais la dernière sera de longueur 9 – 1 * 4 = 5, ce qui est inacceptable.
Donc, la définition formelle de ce problème : la chaîne originale est divisée EXACTEMENT en n chaînes, et aucune des deux chaînes ne devrait différer de plus de 1 en longueur.
Je ne me concentre pas sur la syntaxe ou la bibliothèque C ++. C’est comment concevoir un algorithme pour que la chaîne renvoyée puisse avoir une taille presque égale.
Pour diviser N éléments en M parties , avec des longueurs inférieures à une unité, vous pouvez utiliser la formule (N*i+N)/M - (N*i)/M
tant que longueur de la i
ème partie, comme illustré ci-dessous.
#include #include using namespace std; int main() { ssortingng text = "abcdefghijklmnopqrstuvwxyz"; int N = text.length(); for (int M=3; M<14; ++M) { cout <<" length:"<< N <<" parts:"<< M << "\n"; int at, pre=0, i; for (pre = i = 0; i < M; ++i) { at = (N+N*i)/M; cout << "part " << i << "\t" << pre << "\t" << at; cout << "\t" << text.substr(pre, at-pre) << "\n"; pre = at; } } return 0; }
Par exemple, lorsque M
vaut 4 ou 5, le code ci-dessus produit:
length:26 parts:4 part 0 0 6 abcdef part 1 6 13 ghijklm part 2 13 19 nopqrs part 3 19 26 tuvwxyz length:26 parts:5 part 0 0 5 abcde part 1 5 10 fghij part 2 10 15 klmno part 3 15 20 pqrst part 4 20 26 uvwxyz
Ma solution:
std::vector split(std::ssortingng const & s, size_t count) { size_t minsize = s.size()/count; int extra = s.size() - minsize * count; std::vector tokens; for(size_t i = 0, offset=0 ; i < count ; ++i, --extra) { size_t size = minsize + (extra>0?1:0); if ( (offset + size) < s.size()) tokens.push_back(s.substr(offset,size)); else tokens.push_back(s.substr(offset, s.size() - offset)); offset += size; } return tokens; }
Code de test:
int main() { std::ssortingng s; while (std::cin >> s) { std::vector tokens = split(s, 5); //output std::copy(tokens.begin(), tokens.end(), std::ostream_iterator (std::cout, ", ")); std::cout << std::endl; } }
Consortingbution:
012345 0123456 01234567 012345678 0123456789 01234567890
Sortie:
01, 2, 3, 4, 5, 01, 23, 4, 5, 6, 01, 23, 45, 6, 7, 01, 23, 45, 67, 8, 01, 23, 45, 67, 89, 012, 34, 56, 78, 90,
Démo en ligne: http://ideone.com/gINtK
Cette solution a tendance à rendre les jetons égaux, c'est-à-dire que tous les jetons peuvent ne pas avoir la même taille.
Il suffit de connaître la longueur des sous-chaînes;
Supposons que m est la size()
de votre chaîne:
int k = (m%n == 0)? n : nm%n;
Alors, k
des sous-chaînes doivent être de longueur m/n
et nk
de longueur m/n+1
.
Vous obtenez des iterators où vous voulez le scinder, puis vous les utilisez pour construire de nouvelles chaînes. Par exemple:
std::ssortingng s1 = "ssortingng to split"; std::ssortingng::iterator halfway = s1.begin() + s1.size() / 2; std::ssortingng s2(s1.begin(), halfway); std::ssortingng s3(halfway, s1.end());
Disons que la longueur de la chaîne est L
et qu’elle doit être divisée en n
sous-chaînes.
# Find the next multiple of `n` greater than or equal to `L` L = 9 n = 5 LL = n * (L / n) if LL < L: LL += n # Split a string of length LL into n equal sizes. The string is at # most (n-1) longer than L. lengths = [(LL / n) for x in range (n)] # Remove one from the first (or any) (LL-L) elements. for i in range (LL-L): lengths [i] = lengths [i] - 1 # Get indices from lengths. s = 0 idx = [] for i in lengths: idx.append (s) s = s + i idx.append (L) print idx
EDIT: OK, OK, j'ai oublié que cela devrait être C ++.
EDIT: Ici ça va ...
#include #include unsigned int L = 13; unsigned int n = 5; int main () { int i; unsigned int LL; std::vector lengths, idx; /* Find the next multiple of `n` greater than or equal to `L` */ LL = n * (L / n); if (LL < L) LL += n; /* Split a string of length LL into n equal sizes. The string is at most (n-1) longer than L. */ for (i = 0; i < n; ++i) lengths.push_back (LL/n); /* Remove one from the first (or any) (LL-L) elements. */ for (i = 0; i < LL - L; ++i) --lengths [i]; /* Get indices from lengths. */ int s = 0; for (auto &ii: lengths) { idx.push_back (s); s += ii; } idx.push_back (L); for (auto &i : idx) std::cout << i << " "; std::cout << std::endl; return 0; }
Essayez substr
.