P. Анонс новости 2.0

Попробуем ещё раз сократить заголовки для статей в ленте новостного сайта. Давайте сделаем программу, которая сокращает длинный заголовок до требуемой длины и завершает его многоточием ..., если это требуется.

Формат ввода

Вводится натуральное число L — необходимая длина заголовка.
Вводится натуральное число N — количество строк в заголовке новости.
В каждой из последующих N строк записано по одной строке заголовка.

Формат вывода:

Сокращённый заголовок.

Примечание

Многоточие учитывается при подсчёте длины заголовка.
Символ перевода строки при подсчёте длины не учитывается.

Пример

Ввод

144
5
Энтузиаст написал программу для управления громкостью с помощью жестов, чтоб не вставать с дивана
Благодаря ей он может регулировать громкость,
показывая расстояние между большим и указательным пальцами.
Для этого ему понадобилась веб-камера, знания Python и
библиотека для работы с компьютерным зрением.

Вывод

Энтузиаст написал программу для управления громкостью с помощью жестов, чтоб не вставать с дивана
Благодаря ей он может регулировать громкость...

Ввод

121
5
Энтузиаст написал программу для управления громкостью с помощью жестов, чтоб не вставать с дивана
Благодаря ей он может регулировать громкость,
показывая расстояние между большим и указательным пальцами.
Для этого ему понадобилась веб-камера, знания Python и
библиотека для работы с компьютерным зрением.

Вывод

Энтузиаст написал программу для управления громкостью с помощью жестов, чтоб не вставать с дивана
Благодаря ей он может...

Решение

Довольно сложная задача. Особенно ситуации, когда последняя строка, после обрезания меньше трех символов.

Существует несколько способов решения задачи:

Например, можно сложить все строки в одну большую и запомнить позиции всех знаков переноса строки, после чего, если длина строки больше заданной, просто обрезать до нужной длины и заменить последние три буквы на точки. Остается только восстановить положение переносов и вы получите ответ. Это можно сделать за два прохода, но в решебнике представлен менее оптимальный вариант, дающий возможность потренироваться в использовании поиска и вставке символа в строку.

Можно пойти другим путем – добавлять строки в список, каждый раз увеличивая счетчик общей длины текста. Если длина списка превысила лимит, то нужно позаботится о том, что лимит сократится на 3 знака, которые потребуются для размещения трех точек. По окончании ввода, удаляем последний элемент списка до тех пор пока общая длина всех строк за исключением последней не будет укладываться в лимит.
Если это произошло, значит мы нашли последнюю значимую строку. и дальше будем работать с ней. Тут возможно два варианта развития событий: длина оставшихся строк полностью умещается в лимит и длина все еще больше.
Если длина оказалась больше, надо обрезать последнюю строчку. Осталось дописать три точки и вывести правильный ответ.

Задача покрыта тестами не очень качественно и поэтому можно сдать неправильный, с точки зрения постановки задачи ответ.
Он будет показан последним.
Возможно, авторы имели в виду похожий вариант решения и не рассмотрели некоторые комбинации входных данных на которых он не работает. В любом случае, не стоит на него ориентироваться, как на абсолютно правильный.
По состоянию на лето 2024 года известно 4 разных варианта неправильных решений, каждое из которых неправильно в своем определенном случае, и тем не менее успешно проходит все тесты.

Например, если ввести

10
2
12345
123

То правильный ответ должен быть

12345
123

Потому, что заголовок умещается в отведенное пространство целиком.
тем не менее Яндекс согласится и на такой ответ:

12345
12...

Один из неправильных вариантов решения, проходящий тесты будет показан последним.

Посмотреть код

Решение

Python
# Вариант с изъятием переносов строк, обрезкой и добавлением переносов обратно

length = int(input())

newline = '\n'
header = ''
newlines = []

for _ in range(stings_number := int(input())):
    header += input() + newline

header.strip('\n')

for pos in range(len(header)):
    if header[pos] == newline:
        newlines.append(pos)

header = header.replace(newline, "")

if len(header) > length:
    header = header[:length - 3] + '...'

for pos in newlines:
    if (header[-3:] != '...') or (length - pos >= 4):
        header = header[:pos] + newline + header[pos:]
        length += 1

print(header)

Решение

Python
# Вариант с определением наличия "хвоста" и контроля его длины

limit = int(input())

new_line = '\n'
header = []
length = 0

for _ in range(int(input())):
    string = input()
    header.append(string)
    length += len(string)

if length > limit:
    limit -= 3

    while header and length - len(header[-1]) >= limit:
        length -= len(header[-1])
        header.pop()

    if header:
        if length > limit:
            header[-1] = header[-1][:-(length - limit)]
        header[-1] += '...'
    else:
        header.append('...')

while header and not header[-1]:
    header.pop()

print('\n'.join(header))

Решение

Python
# Вариант с посимвользным накоплением результата

limit = int(input())

header = ''
total = 0

# накопление данных
for _ in range(int(input())):
    string = input()
    total += len(string)
    header += string + '\n'

result = ''
symbols = 0
dots = total > limit  # проверка необходимости точек

# формирование сырого заголовка, удовлетворяющего требованиям длины
for char in header:
    if symbols < limit:
        if char != '\n':
            symbols += 1
        result += char
    else:
        break

if dots:  # если нужно поставить точки
    pos = len(result) - 1
    to_cut = 3
    # удаление лишних точек и переводов строк
    while pos and to_cut:
        if result[pos] != '\n':
            to_cut -= 1
        pos -= 1
    # удаление оставшихся ненужных переводов строк перед точками (тест 22)
    while pos and result[pos] == '\n':
        pos -= 1
    result = result[:pos + 1] + '...'

print(result)

Решение

Python
# Вариант дающий ошибки при строгом тестировании, но тем не менее способный пройти тесты хэндбука

length = int(input())
lines = []

for _ in range(int(input())):
    lines.append(input())

for line in lines:
    if length > 3:
        if len(line) >= length - 3:
            line = line[:length - 3] + "..."
        else:
            if length == 4:
                line = line + "..."

        print(line)
        length -= len(line)

Подписаться
Уведомить о
guest
6 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии