Помогите слегка доработать задачу
Пытаюсь решить вот такую задачу:

Было несколько совершенно разных попыток решения задачи:
Сначала я написал на питоне с помощью 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 шт):
Ваш вариант с 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++ читают слова а не строки. Их надо серьезно переделывать. Путаница в циклах и так далее.

