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

Последний раз редактировалось 1 год назад Виктор ем
Иван
Иван
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 в тексте параграфа Хенбука почему то нет…

Последний раз редактировалось 7 месяцев назад Александр ем
Роман
Роман
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
Сергей
Сергей
09.02.2025 16:08

Поделюсь своим решением, которое прошло проверку. Возможно, оно не учитывает какие-то сценарии

length = int(input())
rows = int(input())

sum_ = 0

for i in range(rows):
  string = input()
   
  if sum_ + len(string) < length – 3:
    print(string)
    sum_ += len(string)
  else:
    remaining_length = length – 3 – sum_
    print(string[:remaining_length] + ‘…’)
    break

Vlad
Vlad
21.04.2025 22:50

Вот такое Яндекс принял:

le = int(input())
n = int(input())
s = []

#Записываем в список каждый символ отдельно, разделяя переносом
for i in range(n):
s += (list(input()))
s.append(‘\n’)

x = int()
y = int()
del s[-1] #Удаляем последний перенос

#считаем длину списка без переносов
for i in s:
if i != ‘\n’:
x += 1

i = int(0)
y = x – le #считаем разницу между длиной списка и ограничением вывода

#присваиваем ограничению новое значение в зависимости от разницы
if y > 4:
le -= 3
elif 0 < y < 4:
le -= 3 + y

#выводим посимвольно за исключением переноса строки
for q in s:
if q != ‘\n’:
print(q, end=)
i += 1
else:
print()
if i == le and y > 0: #если символ последний – выводим ‘…’, тормозим
print(‘…’)
break

Vlad
Vlad
21.04.2025 22:53

А еще есть вариант от ИИ:

L = int(input()) # Максимальная длина заголовка
N = int(input()) # Количество строк в заголовке
lines = [input().strip() for _ in range(N)] # Сохраняем строки отдельно

# Общая длина без пробелов и переносов строк (каждый символ из каждой строки)
total_length = sum(len(line) for line in lines)

if total_length <= L:
  # Если укладываемся в лимит, выводим строки как есть
  print(‘\n’.join(lines))
else:
  # Нужно обрезать и добавить ‘…’
  remaining_length = L – 3 # Оставляем место для ‘…’
  shortened_lines = []
  current_length = 0

  for line in lines:
    if current_length + len(line) <= remaining_length:
      shortened_lines.append(line)
      current_length += len(line)
    else:
      # Обрезаем последнюю строку, чтобы уложиться в remaining_length
      available_length = remaining_length – current_length
      if available_length > 0:
        shortened_line = line[:available_length]
        shortened_lines.append(shortened_line)
      break # Дальше не поместится

  # Собираем результат и добавляем ‘…’
  result = ‘\n’.join(shortened_lines)
  if sum(len(line) for line in shortened_lines) < L:
    result += ‘…’
  print(result)