На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Преобразование массива
    Всем привет!

    Пришла моя очередь просить помощи :) Нужен компактный алгоритм на C++20 не выше, с максимальным задействованием стандартной библиотеки.
    Пока просто приведу пример, что есть и что должно получиться:

    ExpandedWrap disabled
      #include <vector>
      #include <string>
       
      using Vint = std::vector<int>;
      using Bolt = std::vector<Vint>;
      using Wood = std::vector<std::string>;
       
      int main() {
          
        Bolt raw = { {4,6}, {5,2}, {4,7,1}, {3,2,1}, {2,2} };
       
        // тут ваше супер-преобразование-1 и нужный результат
        // Bolt wet = { {3,2,1}, {4,7,1}, {2,2}, {3,2}, {4,6}, {4,7}, {5,2}, {2}, {3}, {4}, {5} };
          
        Wood dirty = { "4.6", "5.2", "4.7.1", "3.2.1", "2.2" };
          
        // тут ваше супер-преобразование-2 и нужный результат
        // Wood pure = { "3.2.1", "4.7.1", "2.2", "3.2", "4.6", "4.7", "5.2", "2", "3", "4", "5" };
          
       return 0;
      }


    Если логика преобразований не совсем очевидна - дайте занть, я распишу.
      Лучше всё-таки помучиться © тов. Сухов

      Можно предположить, что выдаются сортированные префиксы подмассивов, при этом длина - первый ключ сортировки по убыванию, но лучше всё-таки объяснить, что имелось в виду.
        Цитата MBo @
        но лучше всё-таки объяснить, что имелось в виду

        Хорошо, сделаю вам многобукв :rolleyes: ...
        Имеется некий многоуровневый рубрикатор.

        Пример:

        1 Топчик
        1.1 Ниже
        1.1.1 Еще ниже
        ...
        3.2 Что-то там
        ...
        3.4 Что-то там еще

        Есть плоская таблица связи элементов с этим рубрикатором.

        Простой вариант - в таблице найдена одна связь 1.1.1. Значит нам нужно из нее (из связи) получить дополнительные связи 1.1 и 1. При этом будем считать самую "глубокую" связь 1.1.1 главной, остальные полученные - дополнительными. Что делать, если изначально имеем привязку не к одному элементу рубрикатора, а к нескольким? Тут придется привязывать как и в первом случае, но находить главную связь уже по своим правилам. А они будут такие:

        1) Все низ лежащие рубрики разворачиваем и дополняем в вектор
        2) Если появляются дубли - оставляем только один из элементов
        3) Производим сортировку по правилам - сперва по "длине" в порядке убывания, среди рубрик равной "длины" в порядке возрастания.

        Первую рубрику в полученном векторе считаем - главной. Остальные ... ну неглавными :lol:

        Ну вот как-то так.

        И да ... в самом начале вектор привязок от дублей изначально очищен. А в рубрикаторе в каждой ветке может быть своя глубина. А в таблице связей с рубрикатором могут быть связи только к самым низ лежащим рубрикам. В примере этого поста - связи к 1.1 или 1 быть не может, только 1.1.1.
          ОК, значит, я верно понял.

          Тогда можно создать std::priority_queue, содержащую vector<int>, и написать для очереди функцию сравнения, в которой первичный ключ - длина вектора, а вторичный при равенстве - набор значений.

          Закладываем все полные вектора в очередь.
          На каждом шаге извлекаем вектор с верхушки очереди, на вывод его, удаляем последний элемент вектора, и если он не пуст - кладём обратно в кучу.
          Сообщение отредактировано: MBo -
            Цитата MBo @
            Тогда можно создать std::priority_queue

            Пасип! Никогда это не приходилось использовать - буду почитать :)
              Впрочем, может, это и лишнее. Все префиксы всё равно генерировать надо - так сгенерировать их, сложить в одно место, и отсортировать с тем же компаратором.
                Цитата MBo @
                Впрочем, может, это и лишнее. Все префиксы всё равно генерировать надо - так сгенерировать их, сложить в одно место, и отсортировать с тем же компаратором.

                Именно. Я, пока ехал домой, тоже об этом подумал. Сначала разворачиваем все префиксы и складываем в кучу. Потом удаляем дубли. Потом сортируем. Да, так будет проще.
                  В общем, чтобы вопрос закрыть, опубликую свои реализации только для точечной нотации рубрикатора.

                  Сперва на Perl 5 :rolleyes: (https://ideone.com/M9UEve)

                  ExpandedWrap disabled
                    #!/usr/bin/perl
                     
                    use strict;
                    use warnings;
                    use v5.24;
                     
                    my @Arr = ('1.1', '2.4.5', '1.1.1', '3.4');
                    my %Tmp = ();
                     
                    foreach my $i (@Arr) {
                      $Tmp{$i} = '*';
                      my $j = $i;
                      while ($j =~ /^(.+).\d/) {
                        $j = $1;
                        $Tmp{$j} = '*';
                      }
                    }
                     
                    my @Res = sort {return (length($a) == length($b)) ? $a cmp $b : length($b) <=> length($a)} keys %Tmp;
                    map {say $_ } @Res;

                  Потом это же на C++ (https://ideone.com/96ifZV)

                  ExpandedWrap disabled
                    #include <iostream>
                    #include <vector>
                    #include <map>
                    #include <regex>
                    #include <algorithm>
                     
                    int main() {
                        std::vector<std::string> Arr = {"1.1", "2.4.5", "1.1.1", "3.4"};
                        std::map<std::string, std::string> Tmp;
                     
                        std::regex re(R"((.+?)\.\d)");
                        std::smatch match;
                     
                        for (const auto& i : Arr) {
                            Tmp[i] = "*";
                            std::string j = i;
                            while (std::regex_search(j, match, re)) {
                                j = match.str(1);
                                Tmp[j] = "*";
                            }
                        }
                     
                        std::vector<std::string> Res;
                        for (const auto& pair : Tmp) {
                            Res.push_back(pair.first);
                        }
                     
                        std::sort(Res.begin(), Res.end(), [](const std::string& a, const std::string& b) {
                            return (a.length() == b.length()) ? a < b : a.length() > b.length();
                        });
                     
                        for (const auto& item : Res) {
                            std::cout << item << std::endl;
                        }
                     
                        return 0;
                    }

                  Вывод будет одинаков:

                  ExpandedWrap disabled
                    1.1.1
                    2.4.5
                    1.1
                    2.4
                    3.4
                    1
                    2
                    3

                  Собственно , что и требовалось. За сим вопрос считаю для себя закрытым. Но если кому будет интересно реализовать компактнее - вэлком. Равно как и реализовать алгоритм чисто на векторах, без точечной нотации.
                    Сортировка по длинам строк опасна, для двузначных номеров (под)разделов будет сбоить.
                      Цитата Qraizer @
                      Сортировка по длинам строк опасна, для двузначных номеров (под)разделов будет сбоить.

                      Я тебя понял. У меня таких нет - но предусмотреть нужно!
                        Описание не осилил, но если подгонять под пример и использовать одни векторы, то как-то так:
                        ExpandedWrap disabled
                          #include <iostream>
                          #include <vector>
                          #include <algorithm>
                          #include <string>
                          #include <unordered_set>
                           
                          int main()
                          {
                              const std::vector<std::string> arr = {"1.1", "2.4.5", "1.1.1", "3.4"};
                              std::vector<std::vector<int>> int_arr;
                              std::vector<std::vector<int>> int_out_arr;
                              std::vector<std::string> out_arr;
                              for (const std::string& s : arr)
                              {
                                  std::vector<int> x;
                                  size_t i = 0;
                                  for ( ; ; )
                                  {
                                      const size_t j = s.find('.', i);
                                      x.emplace_back(std::stoi(s.substr(i, j != std::string::npos ? (j - i) : j)));
                                      if (j == std::string::npos)
                                          break;
                                      i = j + 1;
                                  }
                                  int_arr.emplace_back(std::move(x));
                              }
                              std::sort(int_arr.begin(), int_arr.end());
                              for (size_t i = 0; i < int_arr.size(); ++i)
                              {
                                  size_t len = int_arr[i].size();
                                  if (i != 0 && std::equal(int_arr[i - 1].begin(), int_arr[i - 1].end(), int_arr[i].begin()))
                                      len -= int_arr[i - 1].size();
                                  while (len-- > 1)
                                      int_out_arr.emplace_back(std::vector<int>(int_arr[i].begin(), int_arr[i].begin() + len));
                                  int_out_arr.emplace_back(int_arr[i]);
                              }
                              std::sort(int_out_arr.begin(), int_out_arr.end(), [](const std::vector<int>&a, const std::vector<int>&b){
                                  if (a.size() == b.size())
                                      return a < b;
                                  return a.size() > b.size();
                              });
                              for (const std::vector<int>& line : int_out_arr)
                              {
                                  std::string s;
                                  for (int value : line)
                                  {
                                      if (!s.empty())
                                          s += '.';
                                      s += std::to_string(value);
                                  }
                                  out_arr.emplace_back(std::move(s));
                              }
                              for (const std::string& s : out_arr)
                                  std::cout << s << std::endl;
                              return 0;
                          }
                          Я залетел в больничку, чисто на телефоне некузяво смотреть код. Вернусь - заценю.
                            Выписался с больнички с диагнозом "небольшой диабетик II" (неинсулиновый) :(

                            А по существу вопроса, shm, твой код немного косячит на следующем сетапе:

                            ExpandedWrap disabled
                              const std::vector<std::string> arr = {"1.12.1", "2.4.15", "1.11.1", "33.4"};

                            Выдает:

                            ExpandedWrap disabled
                              1.11.1
                              1.12.1
                              2.4.15
                              1.11
                              1.12
                              2.4
                              33.4
                              1
                              1
                              2
                              33

                            Дубль цифры "1". Ну а так, да - норм.
                              Цитата Qraizer @
                              От счас ещё пару постов и ей-богу захочется самому пописа́ть. А некогда, дидлаим.

                              Ну я вроде порешал этот вопрос :-?

                              Perl

                              ExpandedWrap disabled
                                #!/usr/bin/perl
                                 
                                use strict;
                                use warnings;
                                use v5.24;
                                 
                                my @Arr = ('1.12', '2.4.15', '111.1.1', '3.4', '1.1');
                                my @Res = ();
                                 
                                # если задан массив в "точечной нотации" преобразуем в массив массивов
                                 
                                my @Tmp = map {[split /\./]} @Arr;
                                 
                                # обработка
                                 
                                ExpandSubsections(\@Tmp, \@Res);
                                 
                                # печать результата
                                 
                                map {say join('.', @{$_})} @Res;
                                 
                                # ------------------------------------------
                                 
                                sub ExpandSubsections {
                                  my ($Tmp, $Res) = @_;
                                  my %Seen;
                                  foreach my $i (@{$Tmp}) {
                                    do {
                                      my @Items = @{$i};
                                      my $Key = join(".", @Items);
                                      unless (exists $Seen{$Key}) {
                                        $Seen{$Key} = "*";
                                        push @{$Res}, [@Items];
                                      }
                                      pop @{$i};
                                    } while (scalar(@{$i}));
                                  }
                                  @{$Res} = sort {
                                    return 1  if (@$b > @$a);
                                    return -1 if (@$b < @$a);
                                    for my $i (0 .. @$a - 1) {
                                      return -1 if ($a->[$i] < $b->[$i]);
                                      return 1  if ($a->[$i] > $b->[$i]);
                                    }
                                    return 0;
                                  } @{$Res};
                                }

                              C++

                              ExpandedWrap disabled
                                #include <iostream>
                                #include <algorithm>
                                #include <vector>
                                #include <sstream>
                                #include <iterator>
                                #include <unordered_map>
                                 
                                 
                                void ExpandSubsections(std::vector<std::vector<unsigned>>& tmp, std::vector<std::vector<unsigned>>& res) {
                                    std::unordered_map<std::string, bool> seen;
                                    for (const auto& i : tmp) {
                                        std::vector<unsigned> items = i;
                                        do {
                                            std::stringstream key;
                                            std::copy(items.begin(), items.end(), std::ostream_iterator<unsigned>(key, "."));
                                            std::string val = key.str();
                                            if (seen.find(val) == seen.end()) {
                                                res.push_back(items);
                                                seen[val] = true;
                                            }
                                            items.pop_back();
                                        } while (!items.empty());
                                    }
                                    std::sort(res.begin(), res.end(), [](const std::vector<unsigned>& a, const std::vector<unsigned>& b) {
                                        if (a.size() != b.size())
                                            return a.size() > b.size();
                                        for (size_t i = 0; i < a.size(); ++i) {
                                            if (a[i] != b[i])
                                                return a[i] < b[i];
                                        }
                                        return false;
                                    });
                                }
                                 
                                int main() {
                                    std::vector<std::string> arr = {"1.12", "2.4.15", "111.1.1", "3.4", "1.1"};
                                    std::vector<std::vector<unsigned>> res;
                                    
                                    // если задан массив в "точечной нотации" преобразуем в массив массивов
                                    
                                    std::vector<std::vector<unsigned>> tmp;
                                    for (const auto& str : arr) {
                                        std::vector<unsigned> subsection;
                                        std::stringstream ss(str);
                                        std::string el;
                                        while (std::getline(ss, el, '.')) subsection.push_back(std::stoul(el));
                                        tmp.push_back(subsection);
                                    }
                                    
                                    // обработка
                                    
                                    ExpandSubsections(tmp, res);
                                    
                                    // печать результата
                                    
                                    for (const auto& subsection : res) {
                                        for (size_t i = 0; i < subsection.size(); ++i) {
                                            std::cout << subsection[i];
                                            if (i != subsection.size() - 1)
                                                std::cout << ".";
                                        }
                                        std::cout << std::endl;
                                    }
                                    std::cout << std::endl;
                                    return 0;
                                }

                              Оба вывода идентичны, и так как мне надо ;)

                              ExpandedWrap disabled
                                2.4.15
                                111.1.1
                                1.1    
                                1.12  
                                2.4    
                                3.4    
                                111.1  
                                1      
                                2      
                                3      
                                111

                              Perl красивше! :lol:
                                Цитата Majestio @
                                Perl красивше!
                                Красивше русский. Особенно нелитературный. А Плюсы круче:
                                ExpandedWrap disabled
                                  #include <iostream>
                                  #include <vector>
                                  #include <string>
                                  #include <algorithm>
                                  #include <tuple>
                                  #include <set>
                                   
                                  // стратегия для векторов
                                  struct VectorAccessor
                                  {
                                    using value_type = std::vector<int>;
                                   
                                    static size_t getSize(const value_type& cont)             { return cont.size();  }
                                    static int    getItem(const value_type& cont, size_t idx) { return cont.at(idx); }
                                    static void   addItem(      value_type& cont, int    val) { cont.push_back(val); }
                                  };
                                   
                                  // стратегия для строк
                                  struct StringAccessor
                                  {
                                    using value_type = std::string;
                                   
                                    static size_t getSize(const value_type& cont)
                                    {
                                      return std::count(cont.begin(), cont.end(), '.') + 1;       // количество определяется точками
                                    }
                                    static int getItem(const value_type& cont, size_t idx)
                                    {
                                      auto getPosPoint =[&](size_t idx) -> std::string::size_type // ищем точку с номером idx
                                                           {                                      // условно номер 0 - это начало строки
                                                             std::string::size_type pos = 0;
                                   
                                                             for (size_t i = 0; i < idx; ++i)
                                                               pos = cont.find('.', pos + 1);
                                   
                                                             return pos;
                                                           };
                                      auto getPos = [&](size_t idx)                               // ищем границы целого с номером idx
                                                       {
                                                         std::string::size_type posL = getPosPoint(idx);
                                                         std::string::size_type posR = cont.find('.', posL + 1);
                                   
                                                         return std::make_tuple(posL, posR);
                                                       };
                                      auto [pos1, pos2] = getPos(idx);                            // получаем границы целого
                                   
                                      return std::stoul(cont.substr(pos1 == 0 ? 0 : pos1 + 1, pos2 - pos1)); // получаем целое
                                    }
                                    static void addItem(value_type& cont, int val)
                                    {
                                      cont += (cont.empty() ? "" : ".") + std::to_string(val);    // точка впереди не нужна
                                    }
                                  };
                                   
                                  // селектор политик
                                  template <typename T> struct Selector;
                                  template <>           struct Selector<std::vector<int>> { using ValueType = VectorAccessor; };
                                  template <>           struct Selector<std::string>      { using ValueType = StringAccessor; };
                                   
                                  // это не моё
                                  using Vint = std::vector<int>;
                                  using Bolt = std::vector<Vint>;
                                  using Wood = std::vector<std::string>;
                                   
                                  Bolt raw   = { {4,6}, {5,2}, {4,7,1}, {3,2,1}, {2,2} };
                                  Wood dirty = { "4.6", "5.2", "4.7.1", "3.2.1", "2.2" };
                                   
                                  // а это опять моё
                                   
                                  // Сравняльщик. Шаблонной лямбдой больно муторно
                                  template <typename T> struct Sorter
                                  {
                                    using selector = typename Selector<typename T::value_type>::ValueType;        // политика
                                   
                                    // если длины разные, то меньше тот, кто длинее;
                                    // иначе меньше тот, чей int с наименьшим номером меньше, пока предыдущие int равны
                                    bool operator()(const typename selector::value_type& left,
                                                    const typename selector::value_type& right) const
                                    {
                                      bool res = selector::getSize(left) != selector::getSize(right);     // сравнить длины
                                   
                                      if (res) return selector::getSize(left) > selector::getSize(right); // не равны.
                                      for (size_t i = 0; i < selector::getSize(left); ++i)                // иначе сравниваем int
                                        if (selector::getItem(left, i) != selector::getItem(right, i))    // по порядку, пока равны.
                                          return selector::getItem(left, i) < selector::getItem(right, i);// меньший int меньше
                                      return false;
                                    }
                                  };
                                   
                                  // получить результат из source
                                  template <typename T>
                                  auto doTest(const T& source)
                                  {
                                    std::multiset<typename T::value_type, Sorter<T>> heap(source.begin(), source.end());  // сортируем
                                    std::set     <typename T::value_type, Sorter<T>> product;
                                   
                                    using selector_type = decltype(heap)::key_compare::selector;          // селектор
                                   
                                    // просто копируем source в результат поэлементно, попутно добавляем все подэлементы элемента
                                    // с меньшими длинами
                                    for (const auto& i : heap)
                                    {
                                      size_t j = selector_type::getSize(i);                               // длина текущего элемента
                                   
                                      product.insert(i);                                                  // добавить элемент
                                      while (--j != 0)                                                    // перебрать подэлементы
                                      {                                                   // конечно выгоднее удалять последний,
                                        decltype(product)::value_type newItem;            // чем добавлять все, кроме последнего
                                                                                          // но лень переписывать политики
                                        for (size_t k = 0; k < j; ++k)                    // добавить все, кроме последнего
                                          selector_type::addItem(newItem, selector_type::getItem(i, k));
                                        product.insert(newItem);                          // добавить в результат
                                      }
                                    }
                                    return product;
                                  }
                                   
                                  // протестировать вектор векторов
                                  void testBold()
                                  {
                                    const auto& product = doTest(raw);
                                   
                                    // вывод
                                    for (const auto& i : product)
                                    {
                                      std::cout << '{';
                                      for (const auto& j : i)
                                        std::cout << ' ' << j << ' ';
                                      std::cout << "};";
                                    }
                                    std::cout << std::endl;
                                  }
                                   
                                  // протестировать вектор строк
                                  void testWood()
                                  {
                                    const auto& product = doTest(dirty);
                                   
                                    // вывод
                                    std::cout << '{';
                                    for (const auto& i : product)
                                      std::cout << ' ' << i << ' ';
                                    std::cout << "};";
                                    std::cout << std::endl;
                                  }
                                   
                                  int main()
                                  {
                                    testBold();
                                    testWood();
                                    dirty = {"1.12.1", "2.4.15", "1.11.1", "33.4"};               // и это тоже не моё
                                    testWood();
                                    dirty = {"1.12", "2.4.15", "111.1.1", "3.4", "1.1"};          // ну вы поняли
                                    testWood();
                                  }
                                Совершенно неоптимизировано. Собрано на коленке. Доводить до ума некогда, сорри.

                                Добавлено
                                Огромный простор для оптимизации. Особенно в Sorter<>::operator(), где можно закешировать всё, превратив Sorter<> в полноценный прокси. Зато сейчас все вспомогательные сущности иммутабельные, кому-то так больше нравится.

                                Добавлено
                                Кстати, Majestio, где тест с мульёном вложений подразделов? А то 3 как-то несерьёзно.
                                Сообщение отредактировано: Qraizer -
                                  Цитата Majestio @
                                  Нужен компактный алгоритм на C++20 не выше
                                  :lol:

                                  Цитата Qraizer @
                                  Собрано на коленке.

                                  :facepalm: ты спецом так раздул код?

                                  Добавлено
                                  Цитата Qraizer @
                                  Кстати, Majestio, где тест с мульёном вложений подразделов? А то 3 как-то несерьёзно.

                                  Не не не ... я не пишу универсальную хрень - чисто разовый утиль. Написал-использовал-забыл.
                                    P.S. Выглядит громоздко. Зато тут полноценное обобщённое решение. Для любого другого представления просто доопределяем политику struct blah_blah_blah_Accessor и однострочно специализируем Selector<>. М-м-м... doTest() должен справиться и без настройки, ему лишь бы контейнер какой-нить с begin()/end() дали. Наверное...

                                    Добавлено
                                    Собственно решение на ~100 строк, и оно, поверь, даже в таком виде быстрее за счёт отсутствия тяжёлых в ран-тайме сущностей. При этом это два решения сразу. Остальные строки только запускают этот код на разных примерах
                                    Сообщение отредактировано: Qraizer -
                                      Цитата Qraizer @
                                      Зато тут полноценное обобщённое решение.

                                      Ну если только для академических целей ... :whistle:
                                        Цитата Majestio @
                                        Не не не ... я не пишу универсальную хрень - чисто разовый утиль. Написал-использовал-забыл.
                                        Ну и зря. Тут вся сложность в алгоритме компаратора. Sorter<>::operator() который. Написать его совсем не сложно. Меня заинтересовало именно обобщённое решение для различных представлений.

                                        Добавлено
                                        Потратил я, кстати, часа два. Сегодня после обеда решил передохнуть от дидлайна. Счас комментов только накидал.
                                          Цитата Qraizer @
                                          Ну и зря. Тут вся сложность в алгоритме компаратора.

                                          Ну что тут сказать ... я рад, что и ты тут нашел себе развлечение :lol:
                                            На вот для примера.
                                            ExpandedWrap disabled
                                                std::list<std::valarray<int>> super({{1,12}, {2,4,15}, {111,1,1}, {3,4}, {1,1}});
                                               
                                                auto res = doTest(super);
                                               
                                                // вывод
                                                for (const auto& i : res)
                                                {
                                                  std::cout << '{';
                                                  for (const auto& j : i)
                                                    std::cout << ' ' << j << ' ';
                                                  std::cout << "};";
                                                }
                                                std::cout << std::endl;
                                            Список std::valarray<>ев. :lol: Всего-то понадобилось:
                                            ExpandedWrap disabled
                                              // стратегия для недоSIMDей
                                              struct ValArrayAccessor
                                              {
                                                using value_type = std::valarray<int>;
                                               
                                                static size_t getSize(const value_type& cont)             { return cont.size();  }
                                                static int    getItem(const value_type& cont, size_t idx) { return cont[idx];    }
                                                static void   addItem(      value_type& cont, int    val)
                                                {
                                                  value_type newCont(cont.size()+1);
                                                  std::slice toCopy(0, cont.size(), 1);
                                               
                                                  newCont[toCopy] = cont[toCopy];
                                                  newCont[newCont.size()-1] = val;
                                                  std::swap(newCont, cont);
                                                }
                                              };
                                               
                                              template <>           struct Selector<std::valarray<int>>
                                              {
                                                using ValueType = ValArrayAccessor;
                                              };
                                            Вроде даже работает.

                                            Добавлено
                                            Что там на очереди? std::queue<std::tuple<>>? :crazy:
                                              Цитата Qraizer @
                                              Собрано на коленке. Доводить до ума некогда, сорри.

                                              Попробовал откомпилячить в С++20 - выдает ошибки :(

                                              Штото типа:
                                              ExpandedWrap disabled
                                                main.cpp: In function ‘auto doTest(const T&)’:
                                                main.cpp:108:7: error: need ‘typename’ before ‘decltype (product)::value_type’ because ‘decltype (product)’ is a dependent scope
                                                  108 |       decltype(product)::value_type newItem;            // чем добавлять все, кроме последнего
                                                      |       ^~~~~~~~~~~~~~~~~
                                                main.cpp:108:36: error: expected ‘;’ before ‘newItem’
                                                  108 |       decltype(product)::value_type newItem;            // чем добавлять все, кроме последнего
                                                      |                                    ^~~~~~~~
                                                      |                                    ;
                                                main.cpp:111:32: error: ‘newItem’ was not declared in this scope
                                                  111 |         selector_type::addItem(newItem, selector_type::getItem(i, k));
                                                      |                                ^~~~~~~
                                                main.cpp:112:22: error: ‘newItem’ was not declared in this scope
                                                  112 |       product.insert(newItem);                          // добавить в результат
                                                      |                      ^~~~~~~
                                                main.cpp: In instantiation of ‘auto doTest(const T&) [with T = std::vector<std::vector<int> >]’:
                                                main.cpp:121:31:   required from here
                                                main.cpp:108:26: error: dependent-name ‘decltype (product)::value_type’ is parsed as a non-type, but instantiation yields a type
                                                  108 |       decltype(product)::value_type newItem;            // чем добавлять все, кроме последнего
                                                      |                          ^~~~~~~~~~
                                                main.cpp:108:26: note: say ‘typename decltype (product)::value_type’ if a type is meant
                                                main.cpp: In instantiation of ‘auto doTest(const T&) [with T = std::vector<std::__cxx11::basic_string<char> >]’:
                                                main.cpp:137:31:   required from here
                                                main.cpp:108:26: error: dependent-name ‘decltype (product)::value_type’ is parsed as a non-type, but instantiation yields a type
                                                main.cpp:108:26: note: say ‘typename decltype (product)::value_type’ if a type is meant

                                              :-?
                                                Компилил в C++17, пропустил typename впереди.
                                                Вообще, изначально было C++14, но понадобилось structure binding, чтобы избавиться от уродливого std::tie().
                                                  Цитата Majestio @
                                                  Дубль цифры "1"

                                                  Небольшой фикс
                                                  ExpandedWrap disabled
                                                    #include <iostream>
                                                    #include <vector>
                                                    #include <algorithm>
                                                    #include <string>
                                                    #include <unordered_set>
                                                     
                                                    int main()
                                                    {
                                                        const std::vector<std::string> arr = {"1.12.1", "2.4.15", "1.11.1", "33.4"};
                                                        std::vector<std::vector<int>> int_arr;
                                                        std::vector<std::vector<int>> int_out_arr;
                                                        std::vector<std::string> out_arr;
                                                        for (const std::string& s : arr)
                                                        {
                                                            std::vector<int> x;
                                                            size_t i = 0;
                                                            for ( ; ; )
                                                            {
                                                                const size_t j = s.find('.', i);
                                                                x.emplace_back(std::stoi(s.substr(i, j != std::string::npos ? (j - i) : j)));
                                                                if (j == std::string::npos)
                                                                    break;
                                                                i = j + 1;
                                                            }
                                                            int_arr.emplace_back(std::move(x));
                                                        }
                                                        std::sort(int_arr.begin(), int_arr.end());
                                                        for (size_t i = 0; i < int_arr.size(); ++i)
                                                        {
                                                            size_t j = 0;
                                                            if (i != 0)
                                                            {  
                                                                const size_t min_len = std::min(int_arr[i].size(), int_arr[i - 1].size());
                                                                for ( ; j < min_len; ++j)
                                                                    if (int_arr[i][j] != int_arr[i - 1][j])
                                                                        break;
                                                            }
                                                            for (++j; j <= int_arr[i].size(); ++j)
                                                                int_out_arr.emplace_back(std::vector<int>(int_arr[i].begin(), int_arr[i].begin() + j));
                                                        }
                                                        std::sort(int_out_arr.begin(), int_out_arr.end(), [](const std::vector<int>&a, const std::vector<int>&b){
                                                            if (a.size() == b.size())
                                                                return a < b;
                                                            return a.size() > b.size();
                                                        });
                                                        for (const std::vector<int>& line : int_out_arr)
                                                        {
                                                            std::string s;
                                                            for (int value : line)
                                                            {
                                                                if (!s.empty())
                                                                    s += '.';
                                                                s += std::to_string(value);
                                                            }
                                                            out_arr.emplace_back(std::move(s));
                                                        }
                                                        for (const std::string& s : out_arr)
                                                            std::cout << s << std::endl;
                                                        return 0;
                                                    }
                                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                  0 пользователей:


                                                  Рейтинг@Mail.ru
                                                  [ Script execution time: 0,0785 ]   [ 16 queries used ]   [ Generated: 27.04.24, 05:43 GMT ]