Попробуем ещё раз сократить заголовки для статей в ленте новостного сайта. Давайте сделаем программу, которая сокращает длинный заголовок до требуемой длины и завершает его многоточием ...
, если это требуется.
Формат ввода
Вводится натуральное число L — необходимая длина заголовка.
Вводится натуральное число N — количество строк в заголовке новости.
В каждой из последующих N строк записано по одной строке заголовка.
Формат вывода:
Сокращённый заголовок.
Примечание
Многоточие учитывается при подсчёте длины заголовка.
Символ перевода строки при подсчёте длины не учитывается.
Пример
Ввод
144
5
Энтузиаст написал программу для управления громкостью с помощью жестов, чтоб не вставать с дивана
Благодаря ей он может регулировать громкость,
показывая расстояние между большим и указательным пальцами.
Для этого ему понадобилась веб-камера, знания Python и
библиотека для работы с компьютерным зрением.
Вывод
Энтузиаст написал программу для управления громкостью с помощью жестов, чтоб не вставать с дивана
Благодаря ей он может регулировать громкость...
Ввод
121
5
Энтузиаст написал программу для управления громкостью с помощью жестов, чтоб не вставать с дивана
Благодаря ей он может регулировать громкость,
показывая расстояние между большим и указательным пальцами.
Для этого ему понадобилась веб-камера, знания Python и
библиотека для работы с компьютерным зрением.
Вывод
Энтузиаст написал программу для управления громкостью с помощью жестов, чтоб не вставать с дивана
Благодаря ей он может...
Решение
Довольно сложная задача. Особенно ситуации, когда последняя строка, после обрезания меньше трех символов.
Существует несколько способов решения задачи:
Например, можно сложить все строки в одну большую и запомнить позиции всех знаков переноса строки, после чего, если длина строки больше заданной, просто обрезать до нужной длины и заменить последние три буквы на точки. Остается только восстановить положение переносов и вы получите ответ. Это можно сделать за два прохода, но в решебнике представлен менее оптимальный вариант, дающий возможность потренироваться в использовании поиска и вставке символа в строку.
Можно пойти другим путем – добавлять строки в список, каждый раз увеличивая счетчик общей длины текста. Если длина списка превысила лимит, то нужно позаботится о том, что лимит сократится на 3 знака, которые потребуются для размещения трех точек. По окончании ввода, удаляем последний элемент списка до тех пор пока общая длина всех строк за исключением последней не будет укладываться в лимит.
Если это произошло, значит мы нашли последнюю значимую строку. и дальше будем работать с ней. Тут возможно два варианта развития событий: длина оставшихся строк полностью умещается в лимит и длина все еще больше.
Если длина оказалась больше, надо обрезать последнюю строчку. Осталось дописать три точки и вывести правильный ответ.
Задача покрыта тестами не очень качественно и поэтому можно сдать неправильный, с точки зрения постановки задачи ответ.
Он будет показан последним.
Возможно, авторы имели в виду похожий вариант решения и не рассмотрели некоторые комбинации входных данных на которых он не работает. В любом случае, не стоит на него ориентироваться, как на абсолютно правильный.
По состоянию на лето 2024 года известно 4 разных варианта неправильных решений, каждое из которых неправильно в своем определенном случае, и тем не менее успешно проходит все тесты.
Например, если ввести
10
2
12345
123
То правильный ответ должен быть
12345
123
Потому, что заголовок умещается в отведенное пространство целиком.
тем не менее Яндекс согласится и на такой ответ:
12345
12...
Один из неправильных вариантов решения, проходящий тесты будет показан последним.
Посмотреть код
Решение
# Вариант с изъятием переносов строк, обрезкой и добавлением переносов обратно
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)
Решение
# Вариант с определением наличия "хвоста" и контроля его длины
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))
Решение
# Вариант с посимвользным накоплением результата
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)
Решение
# Вариант дающий ошибки при строгом тестировании, но тем не менее способный пройти тесты хэндбука
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)
ещё вот такое решение есть
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
Большое спасибо за обратную связь!
Это решение проходит тест в Яндексе, но у него есть один минус.
Если на вход дать
то несмотря на то, что все строки можно вывести без изменения, этот код выведет
Это не совсем соответствует условию задачи. По этой причине аналогичное решение было включено в подборку под номером три с пометкой, что оно не совсем правильное.
Доброго времени,
громоздкое решение
лишнее условие решает вопрос с выводом меньших либо равных ограничению на вывод
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
Спасибо, что поделились решением.
Тут не очень корректно – использовать переменные-счетчики из цикла за пределами цикла не очень хорошая практика. от языка к языку результат может сильно меняться.
Предлагаю такое решение:
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)
Данный вариант решения проходит и тест яндекса, и тот тест, который не проходит последний приведенный вариант решения здесь. При этом мне кажется проще чем те два которые приведены выше.
Да, это неплохое решение. По сути разновидность первого, представленного в статье, когда вместо извлечения и вставки переносов строки учитывается их наличие за счет создания дополнительной “чистой” строки.
Есть и другие способы решить эту задачу. А способ придуманный самим субъективно всегда лучше других. Это относится в том числе и ко мне.
Не сочтите за претензию к вам, но есть одно замечание. Очень полезного метода replace в тексте параграфа Хенбука почему то нет…
Нет проблем.
У меня на главной странице есть такие слова:
Практически все задачи решены в пределах знаний, данных в предшествовавших материалах, но некоторые задания в том числе, содержат решения, которые заглядывают немного вперед.
Каждый раз, когда я выбираю какие инструменты использовать для решения той или иной задачи, я задумываюсь насколько можно выйти за пределы материала, так чтобы не убежать сильно далеко. В данном случае, я счел, что разумно познакомить читателей с методом replace, если он самостоятельно не открыл его из документации к методам строк. Каждый редкий раз, когда я выхожу за рамки знаний, я либо ссылаюсь на материалы (в том числе на этом сайте), либо оставляю еще как минимум одно решение, основанное на только на данном материале.
У меня такой вариант получился, вроде на всём проверил: