将元素插入列表的任务 - 有点困难

Task with inserting elements to list - tough a little

这只是过去几个问题的延续。

我的函数应该returnstd::vector<std::set<std::string>>

一组名字应该被分类到一个游戏的团队中。团队的规模应该相同,但这并不总是可能的,除非 n 可以被 k 整除。因此,他们决定第一种模式(n,k)队有n/k+1人,其余队有n/k人。

函数接受的字符串向量必须转换为字符串列表。

我需要遍历列表元素并将它们添加到集合中。但是,在列表 中移动时,我需要跳过列表 中已经添加到集合中的元素。在遍历列表之前将列表的第一个元素添加到集合中。

移动是根据最后插入的成员的长度计算的。例如,如果插入 Damir,则 move (shift) 将为 5.

解释:

更新[根据@stefaanv 的建议]:

#include <iostream>
#include <list>
#include <set>
#include <string>
#include <vector>
typedef std::vector<std::set<std::string>> vek;
vek Distribution(const std::vector<std::string>&names, int k) {
  vek teams(k);
  int num = names.size();
  int number_of_first = num % k;
  int number_of_members_first = num / k + 1;
  int number_of_members_remaining = num / k;
  std::list<std::string> lista;
  for (int i = 0; i < num; i++)
    lista.push_back(names[i]);
  auto it = lista.begin();
  auto temp = it;
  int n = num, new_member = 0, index_list = 0;
  for (int i = 0; i < k; i++) {
    if (i <= number_of_first) {
      int number_of_members_in_team = 0;
      while (number_of_members_in_team < number_of_members_first) {
        for (int i = 0; i < new_member; i++)
          index_list++;
        if (index_list > n - 1)
          index_list = index_list - n;
        while (it != lista.begin())
          it--;
        for (int i = 0; i < index_list; i++)
          it++;
        teams[i].insert(*it);
        number_of_members_in_team++;
        new_member = it->length();
        it = lista.erase(it);
        n--;
      }
    } else {
      int number_of_members_in_team = 0;
      while (number_of_members_in_team < number_of_members_remaining) {
        for (int i = 0; i < new_member; i++)
          index_list++;
        if (index_list > n - 1)
          index_list = index_list - n;
        while (it != lista.begin())
          it--;
        for (int i = 0; i < index_list; i++)
          it++;
        teams[i].insert(*it);
        number_of_members_in_team++;
        new_member = it->length();
        it = lista.erase(it);
        n--;
      }
    }
  }
  return teams;
}
int main() {
  for (auto i :
       Distribution({"Damir", "Ana", "Muhamed", "Marko", "Ivan", "Mirsad",
                     "Nikolina", "Alen", "Jasmina", "Merima"},
                    3)) {
    for (auto j : i)
      std::cout << j << " ";
    std::cout << std::endl;
  }
  return 0;
}

正确的输出是:

Ana Damir Mirsad Muhammed

Ivan Merima Nikolina

Alen Jasmina Marko

我在输出中什么也没得到!

我只需要对算法进行简单的修复。我没有任何输出的原因是:

it = lista.erase(it);
n--;

如果我不使用这些代码行,我会得到分别有 4、3 和 3 个名称的 3 个团队,只是名称有误。所以现在我得到了正确数量的团队和正确数量的团队成员。这里唯一的问题仍然是为团队添加正确的名称...

你能给我更好的方法吗?

检查功能中的一个错误:您只检查当前团队中的名称以跳过它,但您应该跳过任何已经放入团队中的名称。

我已经给了你另一个问题的替代方案,所以不需要检查功能(从列表中删除)。

此外,在遍历列表时,您应该考虑到当您到达结尾时,您必须从开头继续。将名称添加 100 次不是一个好的选择。

提示:

  • 尝试在注释中添加您的代码应该执行的操作,这样您就可以了解为什么代码无法按预期工作。
  • 如果可能,使用 const 引用将 data-structures 传递给函数
  • 接下来的轮班数:it->length() 也可以,不用找名字了。
  • 您可以轻松避免代码重复,唯一的区别是一个数字。
  • i 和 l 具有相同的含义,当你从 0 到 < k 迭代 i 时,它们变得相同。

根据我的评论更改问题中的代码后进行编辑

根据您编辑的代码编写我将如何做的代码(有两个名称与预期输出交换),make_team()Distribution() 正在一起处理数据,因此它们可能是加入了 class:

#include <iostream>
#include <list>
#include <set>
#include <string>
#include <vector>

// data structure for result
typedef std::vector<std::set<std::string>> ResultType;

// put players in one team according to shift algorithm (shifts is length of name of last player) to make more random
// list_players and it_players are references and are being changed in this function
std::set<std::string> make_team(std::list<std::string>& list_players, std::list<std::string>::iterator& it_players,int size)
{
  std::set<std::string> team;
  int number_shifts = 0;
  int number_of_members_in_team = 0;
  while (number_of_members_in_team < size) 
  {
    // shift to new selection (rotate: end becomes begin)
    for (int i = 0; i < number_shifts - 1; i++)
    {
      it_players++;
      if (it_players == list_players.end()) it_players = list_players.begin();
    }
    // move to team by inserting and deleting from list
    team.insert(*it_players);
    number_of_members_in_team++;
    number_shifts = it_players->length(); // distribute algorithm: shift number of times as length of name of last chosen player
    it_players = list_players.erase(it_players);
    if (list_players.empty()) // just in case
      return team;
  }
  return team;
}

// distribute players to given number of teams
ResultType Distribution(const std::vector<std::string>&names, int number_teams) {
  // init
  ResultType teams(number_teams);
  int number_players = names.size();
  int number_of_first = number_players % number_teams;
  int number_of_members = number_players / number_teams + 1; // adjusted after number_of_first
  std::list<std::string> list_players(names.begin(), names.end());
  auto it_players = list_players.begin();
  
  // do for all teams
  for (int tm = 0; tm < number_teams; ++tm) 
  {
    if (tm == number_of_first) // adjust because not all teams can have the same size, so first teams can be larger by 1
      number_of_members--;

    teams[tm] = make_team(list_players, it_players, number_of_members);
    if (list_players.empty())
      return teams;
  }
  return teams;
}

// test harnass
int main() {
  for (auto i :
       Distribution({"Damir", "Ana", "Muhamed", "Marko", "Ivan", "Mirsad",
                     "Nikolina", "Alen", "Jasmina", "Merima"},
                    3)) {
    for (auto j : i)
      std::cout << j << " ";
    std::cout << std::endl;
  }
  return 0;
}