Задачка на питоне ноутпад
Имеем файл имена.тхт в нем один столбец, с допустим 100 именами девушек:
Евлампия
Гликерия
Степанида
Ива
Муза
Хлоя
Ляля
....
надо преобразовать в группы со сдвигом в одно имя, по пять девушек и сохранить его в отдельный файл группа.тхт
Евлампия Гликерия Степанида Ива Муза
Гликерия Степанида Ива Муза Хлоя
Степанида Ива Муза Хлоя Ляля
и так далее...

Вы уже спрашивали что-то подобное, только раньше это были не девушки, а какие-то майнерские цифири. ))
Вы реально вообще программирование не знаете? Тут простой цикл и чтение/запись в файл.
Вы уже спрашивали что-то подобное...
Не мешайся в моих темах. Это программирование, тебе это наверное уже никогда не понять, я же уже 100 раз объяснял как работает блокчейн.
Там было на яваскрипт, тема боковое смещение каретки, из большого числа рубил маленькие по 42 знака, адреса куда складывать деньги,
А тут девушки, рабочая неделя, сечёшь? Значит я уже нарубил бабла, к тому же тут питон, хотя можно и на скрипте, потом скопирую мышкой.

примитифф. что-то такое:
names = []
with open (filename) as f:
for line in f:
array.append(line)
#имеем list с именами. делаем группьі
groups = []
i = 0
while i < len(names) - 5 #проверь, нужно ли меньше/меньшеравно и 5 или что-то другое, неохота думать
groupline = ' '.join (names[i:i+5]
groups.append(groupline)
i+=1
записать list в файл тоже сам не справишься? ну и отступьі поделай красиво.
зі. а зачем єто?
Так наверное:
items = [] #items массив r = open("имена.txt", "r") #Открываем файл имена.txt для чтения w = open("группа.txt", "w") #Открыввем файл группа.тхт для записи #цикл, читаем из файла имена.txt for i in r: items.append(i.replace("\n", " ")) #заменяем новую строку на пробел и добавляем в массив items #Пока массив не пустой... while len(items) > 0: #Считываем из массива, и записываем в файл for i in items: w.write(i) w.write("\n") #Новая строка items.pop(0) #Удаляем первый элемент в массиве
Второй вариант:
items = [] #items массив r = open("имена.txt", "r") #Открываем файл имена.txt для чтения w = open("группа.txt", "w") #Открыввем файл группа.тхт для записи #цикл, читаем из файла имена.txt for i in r: items.append(i.replace("\n", " ")) #заменяем новую строку на пробел и добавляем в массив items #Пока массив не пустой... while len(items) > 0: #Считываем из массива, и записываем в файл for i in range(0, 5): w.write(items[ i ]) w.write("\n") #Новая строка items.pop(0) #Удаляем первый элемент в массиве
Ужс какой... я вам как художник художнику скажу... (с)
А так не легче?
with open('/home/me/some_names.txt') as f: names = f.read().splitlines() for i, group in enumerate([ names[names.index(n):names.index(n) + 5] for n in names ]): with open(f'names_group_{i}.txt', 'w') as fw: fw.writelines(' '.join(group))
with open(f'names_group_{i}.txt'
Насколько я понял из постановки задачи, на выходе должен получиться один файл.
names[names.index(n):names.index(n) + 5] for n in names
А что будет, если имена девушек не уникальны в исходном файле?
Старый, твой код это хороший пример как не надо писать на Питоне. Так даже не джуны пишут, а какие-то переученые существа. Завел кучу явных циклов хотя надо чем меньше циклов тем лучше. Далее ручная итерация через i - это на каком языке? Ну и явно пихать все пятерки в список это финиш.
да мне насрать. конечно, если бьі нужно "красиво", то я бьі вообще никаких огромньіх массивов не создавал, а читал бьі по пять штук в группу и записьівал в файл. но для на один раз, бьістро и каждому говнюку с дивана чтобі сразу понятно, а кому-то еще и редкий случай себя гением почудить. так что мой код - лучше всего того, что за ним последовало. и где все бьіли? и где твой код как надо писать? надо писать чтобьі надежно результат правильньій получить. а вариантов - тьісячи. даже для полиньі с евдокией
зі. все дружно ждем твой правильньій pythonian код.
Да, с одним файлом проглядел, ну тогда ж еще проще.
with open('/home/me/some_names.txt') as f: names = f.read().splitlines() groups = [names[names.index(n):names.index(n) + 5] for n in names] with open('groups_result.txt', 'w') as fw: for group in groups: fw.write(f"{' '.join(group)}\n")
Про "уникализацию" записываемых в итоговый файл значений, я в задаче не вижу.
Более того, если там ожидается четкое структурное смещение на одну позицию и вот такая разбивка по группам, то подозреваю, что удаление дубликатов - сильно похерит это ожидание )) Ой, но даже если бы, ну еще одна доп. проверка, перед вставкой в лист. Идею-то вы поняли.
names = (line.strip() for line in open("input.txt")) groups = (",".join(names[i:i + 5]) for i, n in enumerate(names)) # TODO: убрать последние элементы with open("output.txt", "w") as f: f.write("\n".join(groups))
Вариант 2: генератор комбинация имен автоматом (третья строка)
from more_itertools import windowed names = (line.strip() for line in open("input.txt")) groups = windowed(names, 5) # Генератор всех комбинаций из 5 элементов with open("output.txt", "w") as f: f.write("\n".join(groups))
Если хочется запись в файл также делать lazy, то надо делать так:
with open("output.txt", "w") as f: for п in groups: f.write(",".join(п) + "\n")
Ты проглядел еще раз. Я не говорил про итоговый файл. Я говорил про исходный файл.
Я не проглядел, а смотрел в исходную задачу, а не в твой коммент.
Ну ок, чтение исходных значений просто оборачивается в сет.
names = set(f.read().splitlines())
pandas Rolling apply() с окном 5 (и мин элементов тоже 5) где функция возвращает список
Ну да, а еще можно поднять rabbitmq с селери, заскейлить, пусть каждый воркер пишет свою группу, а потом сливать в монгу, а через триггер дергать еще один питон-скрипт, который будет все это завершать ))))
Вариантов с чисто академическим оверхедом можно навалить кучу, вот только зачем?
Set'ом ты теряешь упорядочивание элементов и исходное количество. Результат в итоговом файле не будет соответствовать задаче.
Сеты заявлены как неупорядоченные, но в переписке core developers можно почитать, что фактическая имплементация такова, что при отсутствии дальнейших манипуляций с сетом, если им оборачивали лист, то ordering гипотетически останется. На практике, для простых задач, этого хватает.
Ну и никто не мешает сделать стандартное
names = list(dict.fromkeys(f.read().splitlines()).keys())
Но конечно, дофантазировывать исходную задачу можно до бесконечности.
но в переписке core developers можно почитать, что фактическая имплементация такова, что при отсутствии дальнейших манипуляций с сетом, если им оборачивали лист, то ordering гипотетически останется.
Знать внутреннюю имплементацию хорошо, а полагаться на нее плохо - никогда не знаешь, когда она изменится.
https://docs.python.org/3/tutorial/datastructures.html#set...
dict.fromkeys
Этим ты теряешь исходное количество элементов.
.keys()
В данном примере, полагаю, можно опустить. Просто list(dict) даст тот же результат.
Но конечно, дофантазировывать исходную задачу можно до бесконечности.
Я не фантазирую. В задаче не сказано ни про уникальность, ни про дубликаты. Иходить надо из того, что может быть и так и этак.
Н.П.
Посмотрел предлагаемый код. Если бы мне было нужно разовое решение для небольшого списка с гарантированной длинной >=5 - удовлетворился бы.
Но вот если бы мне нужно было проверить навыки работы с файлами - все бы получили "неуд"... смущ
Ну с таким подходом к анализу кода и задачи, вы бы у меня по software design тоже бы получили неуд.
Задача была поставлена простая и примитивная и притом на высокоуровневом python (какие "навыки работы с файлами", серьезно? Или вы хотели тут увидеть дескрипторы, буферы, параллельный доступ и пр.? xD). И решение к ней должно быть соответствующее.
А пилить бесконечные (и притом кривые, а-ля подходы из 90-х) академические решения, цель которых просто потрясти уже порядком подряхлевшей пиписькой - забавно ) И не нужно. В практических проектах - это еще хуже, чем неопытный джун.
И не нужно.
-----
Хи-хи...
Типичная ситуация - мы тебе заказали... и не работает.
Что заказали? 100 девок сгруппировать?
А где не работает? 100 гигабайт девок сгруппировать?
Хи-хи...
И постановка задачи - похожа на учебную - что именно проверяется/закрепляется - вне постановки задачи.
Вот дураки - финансовому спекулянту, криптомагнату бабки бесплатно делаете. А он знай себе сидит, да лучшие варианты нахаляву перебирает.
))
Вообще, очередь с фиксированным размером на 5 элементов, и цикл с итерацией по именам (не сразу все читаем, не по 5 штук за раз, а одно имя за раз), где в каждой итерации содержимое очереди записывается в файл, если очередь полная - лучший вариант.
А где не работает? 100 гигабайт девок сгруппировать?
Такое и в 20 лет сгруппировать не получится, когда питон колом даже во сне. ))
можно еще так. чем-то лучше, чем-то нет
devo4ek_v_ku4ke = 5
ku4ka = []
with open('names.txt') as fr:
with open('groups.txt', 'w') as fw:
for line in fr:
ku4ka.append(line.rstrip())
if len(ku4ka) == devo4ek_v_ku4ke:
gang = ' '.join(ku4ka)
fw.write (f'{gang}\n')
ku4ka.pop(0);
и вообще: вам код нужен, или файл с именами по группам?
(нет времени проверять):
времени только на поп-еть, єто - святое!
- написать кастомный итератор. Либо класс, либо функцию (легче) c yield
лучше сервер с микросервисами. с облаке на виртуальном сервере. и обязательно чтобьі юнитьі (деффки) протестировать, и тдд. и скрам. и дженкинс с докером.
и вообще: вам код нужен, или файл с именами по группам?
Мне нужен был результат, с самым простым решением этой задачки (quick and dirty).
вариант от uscheswoi_82 для меня более доступен для понимания из предложенных:
#8, Вариант от uscheswoi_82, сработал,
#17, Вариант от VornerX, сработал,
#29, Вариант от max2_2000, ошибка:
File "C:\...путь к скрипту.py", line 4
with open('groups.txt', 'w') as fw:
^
IndentationError: expected an indented block
записать list в файл тоже сам не справишься? ну и отступьі поделай красиво.
зі. а зачем єто?
Я деньги люблю, а программировать не умею, такое в нашем мире часто случается,
допустим задачки на яваскрипт потом используются на странице, в общем доступе.
Задачку на питоне решили, это как кирпичик для других несложных экспериментов.
Всем спасибо.

Вариант 1: генераторное выражение вручную (вторая строка)
names = (line.strip() for line in open("input.txt")) groups = (",".join(names[i:i + 5]) for i, n in enumerate(names)) # TODO: убрать последние элементы with open("output.txt", "w") as f: f.write("\n".join(groups))
Вариант 2: генератор комбинация имен автоматом (третья строка)
from more_itertools import windowed names = (line.strip() for line in open("input.txt")) groups = windowed(names, 5) # Генератор всех комбинаций из 5 элементов with open("output.txt", "w") as f: f.write("\n".join(groups))
Если хочется запись в файл также делать lazy, то надо делать так:
with open("output.txt", "w") as f: for п in groups: f.write(",".join(п) + "\n")
так не легче?
with open('/home/me/some_names.txt') as f: names = f.read().splitlines() for i, group in enumerate([ names[names.index(n):names.index(n) + 5] for n in names ]): with open(f'names_group_{i}.txt', 'w') as fw: fw.writelines(' '.join(group))
Ты надеюсь понимаешь какова сложность этого
names[names.index(n):names.index(n) + 5] for n in names
В цикле по элементам списка, получать элемент, и искать его же индекс (что долго, это линейно). Глупее алгоритма не придумаешь.
Сеты заявлены как неупорядоченные, но в переписке core developers можно почитать, что фактическая имплементация такова, что при отсутствии дальнейших манипуляций с сетом, если им оборачивали лист, то ordering гипотетически останется. На практике, для простых задач, этого хватает.
Я надеюсь это ты так шутишь. Доверяться слухам и полагаться на то что сеты вроде бы остаются упорядоченными.
Использовать дикты для дедуплицирования это тоже маразм. Хотя работать конечно будет.
В общем, главное такой код не коммитить, а то получится как здесь:
если нихрена в пайтоне, так, что даже индентьі не можешь подкорректировать, то почему на нем? ладно, вот и индентьі как надо
devo4ek_v_ku4ke = 5 ku4ka = [] with open('names.txt') as fr: with open('groups.txt', 'w') as fw: for line in fr: ku4ka.append(line.rstrip()) if len(ku4ka) == devo4ek_v_ku4ke: gang = ' '.join(ku4ka) fw.write (f'{gang}\n') ku4ka.pop(0);
maybe AI, deep learning, machine learning or something similar should be used for such a complex problem?
создать робота, обучить его распознавать имена девичьи, читать, писать, группировать, и потом: КЛАЦ! и он все Зделает как надо!
В общем, главное такой код не коммитить, а то получится как здесь:
Разве не бывает "промежуточных" коммитов, которые не надо в прод? Это просто коммит, чтобы зафиксировать промежуточный результат работы, но после которого твоя часть пока что не работает.
Ты надеюсь понимаешь какова сложность этого
Надеюсь ты понимаешь, как работает итерация листов и for в питоне вообще? Как идет обращение к индексам листа и что sequence for-a генерит себе при этом и как получает доступ к элементам? Мне лениво читать лекцию, но раз ты пугаешься таких вещей - то явно не знаешь. Хотя внутренняя имплементация не для тебя, т.к. переписка собственно разрабов питона для тебя "слухи" ))
Использовать дикты для дедуплицирования это тоже маразм. Хотя работать конечно будет.
Ну да, а изобретать велосипеды, когда есть подход, который пусть и не предназначался конкретно для решения таких задач, но в итоге широко сейчас используется - конечно же не маразм, велосипеды наше все )) Почаще ходи по исходникам либ, которые импортишь.
Если хочется запись в файл также делать lazy, то надо делать так:
Пфф, а что тут lazy? Тебе вообще смысл этого термина известен? ) Или это потому что ты генератор заюзал? )))
Разве не бывает "промежуточных" коммитов, которые не надо в прод? Это просто коммит, чтобы зафиксировать промежуточный результат работы, но после которого твоя часть пока что не работает.
Это шутка, Но в каждой шутке ... В общем смысл в том, что когда ты коммитишь или постишь, то делаешь это публично, и потом будет трудно оправдаться. Это как в другой поговорке:
Это в точь про VornerX
Пфф, а что тут lazy? Тебе вообще смысл этого термина известен? ) Или это потому что ты генератор заюзал? )))
names = (line.strip() for line in open("input.txt")) # 1: Ничего не делает и ждет пока результат понадобится groups = windowed(names, 5) # 2: Тоже ничего не делает никакой обработки with open("output.txt", "w") as f: for п in groups: f.write(",".join(п) + "\n") # Только здесь начинает работать цикл 2, который крутит цикл 1 (пошагово)
Ничего не делается до последнего цикла. Это простейший дата пайплайн.
Если ты таких вещей не знаешь, вперед на курсы и изучай генераторные выражения и вообще генераторы и итераторы. Вот тебе ссылка навскидку, а дальше сам https://towardsdatascience.com/what-is-lazy-evaluation-in-...
Я просто не понимаю как ты можешь кого-то еще учить. Это типа как в поговорке: Кто не может работать идет преподавать, а кто не может преподавать идет в политику. И эти люди учат нас не ковырять в носу.
Придется макнуть тебя еще раз, но уже глубже. Это ведь твой код, правильно?
Ты умудрился написать алгоритм сложностью N^2 вместо одного прохода. А еще зачем-то два раза один и тот же дорогой метод вызвать, хотя его надо 0 раз вызывать поскольку индекс тебе сразу дается. Ты думал, что повторный вызов другой индекс найдет? Я сразу вспоминаю определение: "Безумие: повторять одно и то же действие и ожидать других результатов"
Далее. Это же ты родил эту фразу, правильно?
Сеты заявлены как неупорядоченные, но в переписке core developers можно почитать, что фактическая имплементация такова, что при отсутствии дальнейших манипуляций с сетом, если им оборачивали лист, то ordering гипотетически останется. На практике, для простых задач, этого хватает.
Ну тогда не поленись и проверь сам какой будет порядок:
Так что это уже не глупость (как выше), а тянет на криминальную статью (в программировании). Перевести стрелки на core developers вряд ли удастся - бить за такое будут тебя сильно если ты это "применишь на практике".
Так что перестань скакать, гнуть пальцы, быковать и переводить стрелки на celery или core developers. А лучше наморщи мозг и начни думать.
Как тогда сделать, если написать надо много, а задача на подзадачи не разбита? Ну или если разбить, то она в общем и целом выполняться не будет - т.е. промежуточные коммиты не добавят фичу, а лишь подготовят "платцдарм" для неё.
А в главную коммитить только полностью готовые фичи и полностью исправленные баги
Вопрос только в том что есть главная ветка.
Пример: вот коммиты (типа по номерам)
1-2-3-4-5
5 - плохой. Я беру 4 (команда "Get This Version" в клиенте Azure DevOps для Студии), оставаясь в той же ветке, правлю код и делаю коммит номер 6, который теперь является текущей последней версией. Так можно, без создания параллельных веток и мёрджей?
Так можно
Если один в репо, то делаешь как удобно. Но варианты есть
https://www.cloudbees.com/blog/git-revert-commit
Смотря что делает команда "get this version".
Что говорит git status до и после выполнения этой команды?
А я её ещё не выполнял. Я только последнюю версию загружал и коммитил в одну и ту же ветку. Один раз не то закоммитил. Ну я просто поправил код и закоммитил снова - написал, что это за исправление.
Однажды я захотел поэксперементировать на проекте, но при этом: 1) я не знал что выйдет и захочу ли это комитить в основной проект 2) эксперименты жестокие (с кровью) с кучей ковнокода а потому не хотел все это выставлять на показ в публичной ветке. 3) но хотел все-таки историю (по привычке, да и опасно не сохранять историю)
В общем я решил создать отдельный (личный) репо из последнего комита проекта, и далее развивать уже этот новый форк как отдельный проект. Но логически это была ветка, поскольку я не собирался что-то отдельное делать - чисто для экспериментов. Через пару месяцев я подумал, что жалко выкидывать, а потому подчистил и замержил обратно в основной проект (а этот форк удалил). Ну понятно что пришлось конфликты
разруливать, а потом еще вручную чистить после мержа (он не все делает, остается мусор), но на удивление все сработало. Это конечно исключение, я так один раз делал, но просто как пример, как можно экспериметны делать.
Не понятен смысл отдельного репо. Можно же было просто не "передавать" в публик.
Ну да. Но это надо push правильно использовать, а я наверное (по незнанию) опасался, что что-нибудь закину наверх из экспериментов, поэтому выбрал радикальную изоляцию и спал спокойно. В целом наверное неправильный подход, но работает.
А вы пушите лишь то, что в тикете указано? Ну скажем сделал тикет, но заметил неопрятный кусок кода, или опечатку, или ещё что по-мелочи. Правите заодно, заводите новый тикет по помарке, или просто оставляете как есть?
Так-то случайно можно и Ctrl+K, D нажать (автоформатирование - у меня вообще привычка часто эту комбинацию дрюкать) - сразу полно изменений может в трекер изменений залететь.
Ну скажем сделал тикет, но заметил неопрятный кусок кода, или опечатку, или ещё что по-мелочи.
Кладешь новый бранч (FixBugs), и правишь там.
Так-то случайно можно и Ctrl+K, D нажать (автоформатирование - у меня вообще привычка часто эту комбинацию дрюкать) - сразу полно изменений может в трекер изменений залететь.
У команды должен быть айнхатлихер стиль написания кода.
Автоформатирование тогда (если оно противоречит стилю) - является ошибкой.
Лечится легко:
git stash
git stash drop
Разве нельзя настроить стили так, чтобы они автоформатировали код при отправке-загрузке? Ну а анализатор изменений в репе анализировал бы код на изменения только после автоформата под ваш выработанный стиль?
Мне непонятно, почему "сколько пробелов в отступе" это до сих пор какая-то проблема и тема для обсуждения.
чтобы они автоформатировали код при отправке-загрузке?
Странный триггер для авто форматирования. Rider или Resharper нормально справляются с этим, но конечно не автоматом.
"сколько пробелов в отступе" это до сих пор какая-то проблема
Было, есть и будет. Где то удобнее/привычнее 2, где то 4
Про автоформатирование я имел ввиду, что код Пети, отформатированный как ему надо, попадая к Васе, автоматом форматируется под Васю. А в репе - под общие требования для репы. Т.е. миддл Петя не орёт на джуна Васю, а тим лид Костя - на них обоих из-за того, что их вкусы по форматированию различаются, т.к. каждый автоматом получает то, что хочет.
Профили форматирования - это рокет сайенс?
всех по-умолчанию в профилях форматирования
для решарпера это происходит на автомате project wide/mashine wide. Визуал студия вроде тоже позволяет для проекта делать, хотя никогда не пробовал, слишком там уж мало всего.
https://docs.microsoft.com/en-us/visualstudio/ide/code-sty...
что вьі имеете ввиду - настройки "стиля"? у каждого свой "вкус", хотя иногда к казусам приводит. если разработку ведет команда, лучше у всех чтобьі бьіло одинаково. однаждьі передал разработку другому, захотел глянуть, что он там развил, и не смог, т.к. он - любитель скроллинга, чтобьі каждая скобочка - на отдельную строку, куча пробелов между методами, группами и т.д., то есть "необ'ять". он вьібрал проект, поменял какую-то из завершающих скобок, и весь код стал триждьі длинее, и каждая строчка изменилась. т.е. отследить изменения по сравнению с переданньім кодом - невозможно.
последние дни работаю с двумя ветками (сивиес): HEAD, и branch, отпочкованньій после последнего релиза клиенту, чтобьі в хеде разрабатьівать его новьіе желания, а в бранче - только что он хочет подправить в поле. гемороойненько.
как уже где-то писал, в бранче для "свободного полета" мне отказали, посему сделал три скрипта: для каждьіе два часа, ежедневньій, еженедельньій. crontab их вьіполняет соответственно. делают банч из тех файлов, которьіе я узазал для редактироватия. двухчасовьіе (с 8:00 до 18:00) прячутся прямо здесь у меня, остальньіе - на сервере.
все вроде хорошо, но удобнее бьіло бьі коммитить каждьій значимьій тег "для сабе", чем, если понадобится, рьіться в єтих архивах.
завтра попробую git установить на мою линукс-машину. есть один "гуру", но я пару раз к нему обратился, он так "прошелся" по машине, что я потом полдня работать не мог, восстанавливал работоспособность. он, конечно, "хотел как лучше", и он реально - опьітньій в линуксах, но уж слишком часто я от него
сльішу "что єто! я такого никогда не видел!". будто бьі єто я виноват, что ИХ машина, которую они мне дали, так брьікается у него под седлом. лучше самому разбираться, будет надежнее, и порой - бьістрее.
т.е. отследить изменения по сравнению с переданньім кодом - невозможно
для "минимизации потерь" и нужны хоть какие то соглашения. Например, разрешили менять форматирование, так сначала измени формат, закоммить, а после исправляй.
Ну или если бы у вас было автоформатирование, так можно было к старому формату привести.
Кстати для отслеживания изменений во всём проекте удобен beyound compare, платный, но он того стоит.
завтра попробую git установить на мою линукс-машину
А что какие то проблемы с этим есть на линуксах?
посему сделал три скрипта
Интересно зачем? Что они делают?
завтра попробую git установить на мою линукс-машину
А что какие то проблемы с этим есть на линуксах?
--------------------
уже нет. оказалось, он изначально там установлен.
посему сделал три скрипта
Интересно зачем? Что они делают?
---------------------
сохраняют бєкапьі моих творений на сервер, где регулярно проводятся бекапьі. просто зиповались все измененньіе (по мнению CVS, используемой фирмой) файльі и прятались. сегодня добавил еще один, которьій делает ежедневно только
$git --git-dir bundle create --all
или что-то похожее, сейчас не помню.
теперь могу, наконец, весь мусор из кода повьібрасьівать. до сих пор две недели только оставлял закомментированньім: а вдруг єто - не совсем мусор? а так - в єтих бандлах теперь все, что нужно, причем с возможностью прослеживания изменений.
А вы пушите лишь то, что в тикете указано? Ну скажем сделал тикет, но заметил неопрятный кусок кода, или опечатку, или ещё что по-мелочи. Правите заодно, заводите новый тикет по помарке, или просто оставляете как есть?
Не пушить, а коммитить - это разные вещи. И правил тут жестких нет, надо решать по обстановке, ну и всегда иметь отмазку на крайний случай, если что-то пошло не так, как здесь: