Помогите слегка доработать задачу

Пытаюсь решить вот такую задачу: введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

Было несколько совершенно разных попыток решения задачи:

Сначала я написал на питоне с помощью itertools.groupby

from itertools import groupby
from sys import stdin
keys = input().split()
repeat_counts = '-c' in keys
only_repeats = '-d' in keys
ignore_reg = '-i' in keys
only_uniq = '-u' in keys
args = {}
if ignore_reg:
    args = {'key': str.lower}

for st in groupby(map(str.strip, stdin.readlines()), **args):
    counts = sum(1 for _ in st[1])
    if only_repeats and only_uniq:
        continue
    if repeat_counts:
        if only_repeats:
            if counts > 1:
                print(counts, st[0])
        elif only_uniq:
            if counts == 1:
                print(1, st[0])
        else:
            print(counts, st[0])
    else:
        if only_repeats:
            if counts > 1:
                print(st[0])
        elif only_uniq:
            if counts == 1:
                print(st[0])
        else:
            print(st[0])

Задача прошла 11 тестов.

Дальше я решил написать код на С++ что ни наесть топорным методом. То есть считать количество повторений.

#include <iostream>
#include <sstream>
#include <algorithm>

using namespace std;
bool
    repeat_count = false,
    only_repeats = false,
    without_reg = false,
    only_unique = false;

char change_case(char c) {
    if (isupper(c))
        return tolower(c);
    return c;
}

string pass(string st) {
    return st;
}

string lower(string st) {
    transform(st.begin(), st.end(), st.begin(), change_case);
    return st;
}
void answer(int count, string old){
    if (only_repeats) {
        if (count > 1) {
            if (repeat_count) {
                cout << count << " " << old << '\n';
            } else
            {
                cout << old << "\n";
            }
        }

    } else if (only_unique) {
        if (count == 1) {
            if (repeat_count) {
                cout << 1 << " " << old << "\n";
            }
            else {
                cout << old << "\n";
            }
        }
    }
    else {
        if (repeat_count) {
            cout << count << " " << old << "\n";
        }
        else {
            cout << old << "\n";
        }
    }
}

int main() {
    ios::sync_with_stdio(false);
    string keys, key, st;
    getline(cin, keys);
    istringstream ss(keys);
    while (ss >> key) {
        st = key.c_str();
        if (st == "-c") {
            repeat_count = true;
        } else if (st == "-d") {
            only_repeats = true;
        } else if (st == "-i") {
            without_reg = true;
        } else if (st == "-u") {
            only_unique = true;
        }
    }
    if (only_unique and only_repeats)
        return 0;
    string old, cur;
    cin >> old;
    int count = 1;
    auto func = pass;
    if (without_reg) {
        func = lower;
    }
    while (cin >> cur) {
        if (func(cur) == func(old)) {
            count++;
        }
        else {
            answer(count, old);
            count = 1;
            old = cur;
        }
    }
    answer(count, old);

}

Задача зашла на 10 баллов. Потом я придумал решить её через дек, мне показалось это более надёжным методом. Она выглядела так:

#include "iostream"
#include "algorithm"
#include "sstream"
#include "deque"
using namespace std;

char change_case(char c) {
    return isupper(c) ? tolower(c) : c;
}

string pass(string st) {
    return st;
}

string lower(string st) {
    transform(st.begin(), st.end(), st.begin(), change_case);
    return st;
}

bool
        repeat_count = false,
        only_repeats = false,
        without_reg = false,
        only_unique = false;

auto func = pass;

void init() {
    string keys, key, temp;
    getline(cin, keys);
    istringstream ss(keys);
    while (ss >> key) {
        temp = key.c_str();
        if (temp == "-c") {
            repeat_count = true;
        }
        else if (temp == "-d") {
            only_repeats = true;
        }
        else if (temp == "-i") {
            without_reg = true;
        }
        else if (temp == "-u") {
            only_unique = true;
        }
    }
    if (without_reg)
        func = lower;
}

void answer(const deque <string> &a){
    string out;
    int sz = a.size();
    if (repeat_count){
        if (only_unique){
            if (sz == 1){
                cout << sz << " " << a.front() << "\n";
            }
        }
        else if (only_repeats){
            if (sz != 1){
                cout << sz << " " << a.front() << "\n";
            }
        }
        else{
            cout << sz << " " << a.front() << "\n";
        }
    }
    else{
        if (only_unique){
            if (sz == 1){
                cout << a.front() << "\n";
            }
        }
        else if (only_repeats){
            if (sz != 1){
                cout << a.front() << "\n";
            }
        }
        else{
            cout << a.front() << "\n";
        }
    }
}

int main() {
    init();
    if (only_unique and only_repeats)
        return 0;
    string cur;
    cin >> cur;
    deque <string> st = {cur};
    while (cin >> cur) {
        if (func(cur) == func(st.front())){
            st.push_back(cur);
        }
        else{
            answer(st);
            st.clear();
            st.push_back(cur);
        }
    }
    answer(st);
}

И тут она упала на 10 тесте. Видимо в обоих решениях ошибка в какой-то мелочи, которую я забыл учесть. Подскажите, что тут надо подправить/заменить?


Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

Ваш вариант с itertools вполне рабочий после некоторых доработок. Его можно было бы поправить так:

for st in groupby(map(str.strip, stdin.readlines()), **args):
    value = next(st[1]) # получаем первое значение из группы, печатать надо его
    counts = 1 + sum(1 for _ in st[1])

Я его немного причесал и в других местах:

import itertools
import sys

keys = next(sys.stdin).split()
ignore_case = '-i' in keys
print_count = '-c' in keys
unique_only = '-u' in keys
duplicates_only = '-d' in keys

if duplicates_only:
    if unique_only:
        check = lambda count: False
    else:
        check = lambda count: count > 1
else:
    if unique_only:
        check = lambda count: count == 1
    else:
        check = lambda count: True

if print_count:
    emit = lambda count, value: print(count, value, end='')
else:
    emit = lambda count, value: print(value, end='')

key = str.lower if ignore_case else None
for k, g in itertools.groupby(sys.stdin, key=key):
    value = next(g)
    count = 1 + sum(1 for _ in g)
    if check(count):
        emit(count, value)

Ваши варианты на C++ читают слова а не строки. Их надо серьезно переделывать. Путаница в циклах и так далее.

→ Ссылка