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
9 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Ник
03.11.2023 09:44

ещё вот такое решение есть

max_symb = int(input()) – 3
line = int(input())
list = []
for i in range(line):
    list.append(input())
    count_symb = 0
for elem in list:
    if len(elem) + count_symb < max_symb:
        print(elem)
        count_symb += len(elem)
    else:
        print(elem[:max_symb – count_symb] + ‘…’)
        break

Последний раз редактировалось 1 год назад Сергей Клочко ем
Виктор
Виктор
29.01.2024 15:15

Доброго времени,

громоздкое решение

лишнее условие решает вопрос с выводом меньших либо равных ограничению на вывод

long = int(input())
count = int(input())
heading = list()
long_heading = 0

for i in range(count):
    input_line = input()
    len_line = len(input_line)
    heading.append([input_line, len_line])
    long_heading += len_line

if long_heading <= long:
    #[print(i[0]) for i in heading]
    for i in heading:
        print(i[0])
else:
    index = 0
    long_heading = 0
    for line in heading:
        if long_heading + line[1] + 3 >= long:
            # прогон по line
            cuted = long – long_heading
            for i in range(index):
                print(heading[i][0])
            print(heading[i + 1][0][:cuted – 3], ‘…’, sep = ”)
            break
        else:
            long_heading += line[1]
            index += 1

Последний раз редактировалось 10 месяцев назад Виктор ем
Иван
Иван
08.05.2024 16:58

Предлагаю такое решение:

L = int(input())
N = int(input())
news = “”
news_stripped = “”
news_stripped_length = 0
newline_amount = 0
for i in range(N):
  headline = input()
  news = news + headline + ‘\n’
  news_stripped += headline
  news_stripped_length += len(headline)
  if news_stripped_length < L – 3:
    newline_amount += 1
if len(news_stripped) > L:
  x = (news[:L + newline_amount – 3] + ‘…’)
  print(x)
else:
  print(news)

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

Александр
Александр
30.08.2024 14:55

Не сочтите за претензию к вам, но есть одно замечание. Очень полезного метода replace в тексте параграфа Хенбука почему то нет…

Последний раз редактировалось 3 месяцев назад Александр ем
Роман
Роман
25.12.2024 17:44

У меня такой вариант получился, вроде на всём проверил:

L = int(input())
N = int(input())
s = []
s_len = []
s_all = ''
for _ in range(N):
    inp = input()
    s_all += inp
    if inp != '':    # пропустим пустые строки
        s += [inp]
        s_len += [len(inp)]
if len(s_all) <= L:
    for w in s:
        print(w)
else:
    for i in range(len(s)):
        if (s_len[i] + 4) <= L:
            print(s[i])
            L -= s_len[i]
        else:
            print(s[i][:(L - 3)] + '...')
            break