Comments 472

Хорошо, а теперь оцените объем памяти, требуемый для исполнения этой функции.

Время интервью вышло, так что отвечу кратко: возьму uniqueness types, а дальше достаточно умный компилятор всё сделает без дополнительных аллокаций.

Так же формально за полчаса не получится. Чуть менее формально — потому что компилятор знает, что каждый элемент используется не более одного раза, поэтому он спокойно может мутировать указатели вместо создания новых элементов.


Компилятор Idris'а, на самом деле, не настолько умён, в него слишком мало ресурсов вкладывается (я удивлюсь, если reverse с uniqueness types он скомпилирует в инплейс), но вот какой-нибудь ghc, когда может подобные вещи вывести (ибо в хаскеле пока нет афинных типов), вполне себе так оптимизирует код.


Чё-то я тут слишком серьёзный, похоже.

Это наверное такой мем от функциональщиков — я раз несколько на Хабре в статьях о ФП видел утверждение, что "компилятор оптимизирует", или что "оптимальный код — забота компилятора". Кажется, иногда это говорили всерьез.

Ну насчет хаскелля не скажу, но, например, в лиспе, lparallels действительно даёт возможность просто писать многопоточный код по сравнению с императивными языками. Да и вообще выявлять, и, главное, оптимизировать узкие места проще (впрочем, не исключаю confirmation bias задач, которые я решал на лиспе)
А кто ещё может оптимизировать? Людям это доверять нельзя, они баги вносят, когда пытаются оптимизировать.
Подчиненный перед лицом начальствующим должен иметь вид лихой и придурковатый, чтобы умом своим не смущать начальства.

Потому что это и не цитата. Просто забавная выдумка, автор которой не известен.

Ну, как минимум, потому, что с телефона это оформлять неудобно. Да и:
"Главная проблема цитат в интернете в том, что люди сразу верят в их подлинность". (с) В. И. Ульянов (Ленин)

UFO landed and left these words here
— В чем состоит наипервейшая обязанность придворного? — спросил эмир.
Ходжа Насреддин ответил ему так:
— О великий и блистательный повелитель! Наипервейшая обязанность придворного состоит в каждодневном упражнении спинного хребта, дабы последний приобрел необходимую гибкость, без чего придворный не может достойным образом выразить свою преданность и свое благоговение. Спинной хребет придворного должен обладать способностью изгибаться, а также извиваться во всех направлениях, в отличие от окостеневшего хребта какого-нибудь простолюдина, который даже и поклониться не умеет как следует.

(Повесть о Ходже Насреддине)

Статья вызывает улыбку. Но кроме всего прочего поднимет проблему важности soft skill наряду с развитыми hard skill.

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

Это для вас они скучные.
А у меня знакомый набирал людей на разработку — так кандидаты не знали, сколько бит в байте и сколько байт в 32-разрядном инте. Что такое указатель — вообще страшная тайна, шаманство какое-то…
Угу. Там работа с оборудованием на довольно низком уровне — посему кандидатам неплохо было бы знать, как типы данных лежат в памяти.
Когда меня брали на, то давали схемы и потом просили описать пути электронов после подачи питания.
И да — это важно знать, если ты пишешь микрокод контроллера шины.

А скорость движения электронов спрашивали?
А то бывают интересные версии...

>не знали, сколько бит в байте
Это вы им показали 9-битные и попросили обосновать?
Там действительно мой знакомый, и проект у них вполне практический. И оборудование достаточно стандартное — процессоры x86 почти везде, кое-где вроде как пытались внедрить ARMы. Так что байты там нормальные, восьмибитные.
Но выясняется страшное: приходят собеседоваться специалисты, которые вообще никогда не задумывались о том, как именно данные хранятся в памяти. А им по работе надо пакеты между нодами туда-сюда гонять по чахлым каналам связи…

Неспроста в университетах обучение идёт с основ: базовая логика, структуры данных, ассемблер, С и только потом уже идут C#, Java, Python. Многим это не нравится, потому что не получается сразу начать писать практический код. Но по факту если человек начинает изучение программирования сразу с языка скриптового уровня, то ему потом становится сложно подтягивать базу, потому что это требует времени.

А если с языка низкого уровня, то многие заболевают преждевременной оптимизацией.

Возможно, наоборот aka эффект декомпрессии. Не надо байтики руками перекладывать, можно использовать композицию функций, объекты, часть паттернов и гуй из коробки… В итоге код легко пишется, неплохо читается и поддерживается, но жрёт много памяти и проца и местами подтекает.

Нет, чаще народ начинает искать, что быстрее i < n или i <= n — 1, и заменять деление на сдвиги.

Такая фигня обычно проходит после первого коммерческого проекта на языке, особенно если сроки горят.

Я видел такое от программистов с годами опыта. В основном они любят утверждать, что софта на ГЦ нет потому что на нем нельзя писать рилтайм приложения, и скоро С++ захватит мир. Невыдуманная история.

Насколько я знаю, специфика и подходы к написанию риалтаймовых приложений одинаковы, но дополнительно надо очень хорошо знать устройство виртуальной машины. Имхо, какую-нибудь RTOS я бы на условной Java писать не стал, просто из экономии времени на разработку.

Я к тому, что люди отказываются верить, что за пределами рилтайма и хай-перфоманс плюсов кому-то нужны "тормознутые" жавасишарпоскалы. То есть как раз "преждевременная оптимизация" у людей возведена в абсолют даже после многих лет работы в продакшне.

А за это не бьют на ревью или просто тимлды/архитекторы? В кровавом энтерпрайзе опыта работы нет, потому не знаю, что из того, что как бы должно быть, есть на самом деле.

Оно не то, что проходит, а даже становится хуже.
Конструкции вида OrderBy(...).First() появляются всё чаще и чаще.

т.е. вместо поиска условно максимума сначала сортируют весь массив/лист/etc и получают вместо O(n) O(nlogn)?

Суть в том, что если в массиве максимум 10 элементов, такой код проще и понятнее оптимального (придется либо писать свой экстеншн, либо переписывать на ручной цикл), и имеет право а жизнь. Но многие триггерятся на сам факт неоптимальности (Как же так! Тут логарифм появился просто так!). Не знаю, предпочел бы я в данном случае читаемость или цикломатику, но я прекрасно понимаю людей, которые не будут сильно париться над этим. Не потому, что они говнокодеры и им лишь бы пожрать лишних циклов CPU, а потом что там дальше пересылка по сети и выигрышь 10 тактов процессора не даст ничего.

Самый читаемый вариант тут всё же- MaxBy(...) или MinBy(...). И этот же вариант как раз даёт нужный профиль исполнения — это ж вообще праздник, согласитесь.

Безусловно, но, увы, в стандартной поставке его нет.


А писать свою стд и тасказть за собой — у многих разных разработчиков "разные" библиотеки хелперов, и дружить их такое себе занятие.

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

Так я тоже не знаю.


Сколько бит в байте, зависит от архитектуры. Стандарт С определяет байт как размер char, для связи которого с разрядностью тоже нужно знать об архитектуре и настройках компилятора.

Стандарт С ISO 9899:1999 http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
определяет что в char можно записать как минимум значения 0..255 или -127..128 (0..UCHAR_MAX, SCHAR_MIN..SCHAR_MAX) 5.2.4.2.1 Sizes of integer types "Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown, with the same sign." и что в char должно быть не менее 8 бит (CHAR_BIT 8), т.е. стандартом допускаются машины с более длинным char.
Байт определен независимо от char как адресуемая единица памяти, без уточнения числа бит: 3.6 byte "addressable unit of data storage large enough to hold any member of the basic character set of the execution environment" "A byte is composed of a contiguous sequence of bits, the number of which is implementation defined"
(POSIX определяет байт как октет, т.е. 8 бит)
Книга комментариев к стандарту http://www.coding-guidelines.com/cbook/cbook1_1.pdf на стр 190 приводит примеры
"Motorola DSP56300 which has a 24 bit word… Analog Devices SHARC has a 32-bit word" и уточняет на 191 стр, что в байте не может быть менее 8 бит "The number of bits must be at least 8, the minimum value of the CHAR_BIT macro" (в стандарте это 6.2.6.1 General сноска 40 "A byte contains CHAR_BIT bits")

Хм, там же последняя фраза в той сноске (в 6.2.6.1/3) говорит


A byte contains CHAR_BIT bits, and the values of type unsigned char range from 0 to 2CHAR_BIT− 1
Выходит, что в байте CHAR_BIT бит, а в char — не менее CHAR_BIT бит. Значит, в общем случае неверно, что
Стандарт С определяет байт как размер char

5.2.4.2.1/2 намекает на ограничение сверху, так что там, по идее, строгое равенство.

То есть, такая машина невозможна в C:

1. Память — набор 16-битных ячеек, т.е. прибавляя к указателю 1,
void* next = (void*)((size_t)current+1);
получается указатель на следующий 16-битный байт.

2. Регистры есть как 16-битные (int), так и 8-битные (char)
При этом, загрузка ячейки в char урезает содержимое до младших 8 бит, как и при любых конвертациях в целый тип меньшего размера.
int* ptr;
char value = *ptr; // младшие 8 бит
int value = *ptr; // весь 16-битный байт из одной ячейки памяти.

Похоже на то (по крайней мере, 8-битные регистры будут оперировать чем-то отличным от char): минимально адресуемый кусок памяти — 16 бит, значит, CHAR_BIT должен содержать 16 бит, значит, в char должно быть 16 бит (или даже «хотя бы 16 бит», если ослабить формулировку и взять вашу).


Я недостаточно хорошо знаю стандарт С, чтобы судить, разрешает ли он типы меньшие, чем char, в конкретных реализациях. В плюсах-то всё просто: есть bool с очевидно меньшим пространством возможных значений.

Ну хорошо, а если в машине есть 24-битные регистры (char) и 32-битные (int), а память остаётся 16-битной. В этом случае я не вижу противоречий со стандартом.
the values of type unsigned char range from 0 to 2CHAR_BIT − 1.

Мне сходу не удалось найти причины char и unsigned char совпадать по размеру, но ЕМНИП это так. Так что, получается, charы могут быть только 16-битными.

Правильно.
А ещё посмотрите, как в Си++ и в Си (в stdbool.h) определяется тип bool и как они бинарно совместимы между собой на уровне библиотек (т.е. если взять библиотеку от С и подключить к проекту с Си++). :)
Ох, знали бы вы, сколько багов происходят от того, что два куска программы компилируются с разным определением bool!
так кандидаты не знали, сколько бит в байте

Хм… недавно была новость, что кто-то там судился с гуглом, что их на собеседовании завалили, потому что они старые были. Один из аргументов был, что интервьювер посмел допустить, что в байте 8 бит. А ведь "senior" разработчики предположительно с очень старым железом работали. А там от 6 до 40 бит могло быть.


Так что, если ваши кандидаты было достаточно в возрасте, то вы зря на них серчаете.

Так что, если ваши кандидаты было достаточно в возрасте, то вы зря на них серчаете.

Мопед не мой, и контора не моя — так что набирал не я. :)
Насколько я знаю, приходили в основном довольно молодые люди — лет 27-35.
И если бы кандидат просто сказал, что по-разному бывает и вот работал он на системе, где в байте 6 бит — никто бы не осерчал, я вас уверяю. Наоборот, это ж прекрасный повод обсудить разные архитектуры. Но у кандидатов просто был ступор — что, мол, за вопросы такие дурацкие, кому в здравом уме может понадобиться знание о размерах типов данных?
IMHO это троллинг. Популярная архитектура — 8бит.
Где используется нестандартная — менее 1% от всего?

IMHO это не причина вообще зацикливаться на этом.

Да, поэтому достаточно сказать «стандарт утверждает то-то и то-то, поэтому в общем случае это зависит от целевой архитектуры и настроек компилятора, но в интересующих нас случаях это почти наверняка будет 8 бит».


Если интервьювер ожидал два слова «8 бит!», и такой ответ будет для него минусом, то лучше это выяснить сразу.

А вы знаете сколько бит в байте? Я вот оже думал, что знаю. Сказал что 8 — обсмеяли с пруфами.
Теперь прежде чем отвечать про биты и байты, я спрашиваю о том, какая архитектура подразумевается.
Пруфы были предоставлены в железном виде, или в музей водили?
Надо было обсмеять их в ответ и спросить, когда последний раз программировали для невосьмибитной архитектуры для продакшена.
Меня в википедию сводили, так что чувствую себя как девушка, которую на свидание в макдональдс пригласили. (Им это вроде бы не нравится) А так общение было целиком и полностью теоретическим и за кружечкой водки, поэтому почему нет?

До этого момента я шибко не задумывался о размерностях байтов. Думал восьмерку выбрали как наиболее удобную и о существовании невосьмерок не подозревал.
А с порядком байт в многобайтных переменных вас познакомили? :) Не все архитектуры little-endian. Очень прикольно переносить какой-нибудь С/С++ с одной платформы на другую, если используются низкоуровневые фишки (например, чтобы протокол обмена реализовать).
Не, про такое не рассказывали, но я сам где-то и что-то читал. Да и какой в задницу C++ если я тихонько быдлокодерствую на php? Там вообще можно с улицы прийти и сбацать.
А есть ещё дополнительный и прямой код для знаковых чисел. Вояки что-то прямой код любят, как я смотрю. То ли они допкода не знают, то ли это какой-то пережиток 50-х.
Кстати, ip-адреса на big-endian построены в сокетных библиотеках. И функция переворачивания в подарок тоже предусмотрена. :)

Ничего, из C++20 поддержку отличных от two's complement представлений выпилили.

Это хорошо, что она предусмотрена, а то по ощущениям очень скоро никто не сможет написать сокетную библиотеку. XD

Ещё иногда strict aliasing rule по рукам бьёт. Взять для примера труктуры для описания типа сокета:



При этом разработчики компиляторов понимают, что что-то не так в консерватории и, как минимум, GCC разрешает type punning:



Хотя, с т.з. стандарта это тоже UB.

Вот как раз это очень даже полезная и актуальная информация, поскольку встречается сплошь и рядом. И не только на Си возникают проблемы.

Есть ещё и middle endian. А тот же ARM вообще можно переключать между Big и Little.

Не поверите — сейчас тоже есть всякие DSP с 32 битным char (особенно, отечественные современные копии привета из 80-х). И, что характерно, оно используется. Мы, например, такое используем прямо сейчас.

Ну, размер байта — это сама по себе хорошая тема сразу оценить, сидит ли перед вами чисто практик, или у человека есть ещё и более глубокие знания.
(8-битные числа — это октеты так-то)

Вот кстати да. Мимоходом всегда интересуюсь, сколько различных целых значений может хранить один байт. И знаете, процентах в 30 люди не знают. Кто-то говорит, что 2^256 или 2^128. Из знающих же многие пишут 2^8 (это хороший знак, в принципе).


Как-то жаловался одному товарищу, что, может, я зря это спрашиваю. Он такой: «Да ты чо, это ж самые самые азы computer science, которые проходят на первых лекциях, их просто обязаны понимать все» — это меня немного успокоило.

Слышал историю, как в Гугле знакомый знакомого проводил заключительное интервью с чуваком, у которого было уже 4 собеса с идеальным фидбеком.


Он дал ему следующее задание для разогрева — есть массив из n даблов, это курс обмена USD <-> EUR по каждому из n дней. В начале есть 1 USD. Нужно ровно один раз поменять его в EUR, а потом в один из последующих дней назад в USD. Сколько может быть максимум в конце?


Он не смог решить это за ЧАС, и чуть не попал на работу, если бы не этот знакомый знакомого.

Есть ли решение со сложностью лучше, чем O(n^2)? Может, кандидат его искал больше часа, подумав, что очевидное решение «в лоб» не подходит?
В целом я придумал решение за O(n∙logn).
Spoiler header
Нужно использовать двоичную кучу. Перебирая первый искомый индекс (цикл по n), выбирая в оставшейся части массива макс. элемент из кучи, и просеивая кучу, удаляя текущий элемент (log n).

Есть же за линию решение! Идем по массиву и поддерживаем минимум. Каждый раз смотрим, является ли лучшим решение поменять в известном минимуме и назад по текущему курсу.


Это как ваше решение с кучей, но, если цикл пустить с конца, то максимум можно просто пересчитывать за константу.

Первоначальный поиск одного минимального элемента — O(n), но как поддерживать минимум за константу, выкидывая пройденный элемент?

Например, в массиве 1,8,12,4,1 минимум = 1.
Когда мы выкинули первый (или последний) элемент, как за O(1) пересчитать минимум?

Мы пересчитываем минимум в префиксе массива:


Для массива {3, 4, 2, 5, 1} — минимумы будут {3, 3, 2, 2, 1}. Пересчитывается тупо cur_min = min(a[i], cur_min).


А потом для каждого элемента сначала берем предыдущий минимум, а потом текущий элемент.


Вы уже заметили, что для каждого первого дня надо в качестве второго дня брать максимум в суффиксе массива. Аналогично можно для каждого второго дня (обмена назад) брать минимум из всех дней до него. Этот минимум для всех префиксов можно вот так за O(1) пересчитать, потому что тут каждый раз ровно один элемент добавляется в множество, по которому берется минимум.

Конечно. O(N), причём за 1 проход. Это пример очень простой задачи на динамическое программирования. Итерируем по дням и для каждого дня храним 2 числа: MaxUSD и MaxEUR:
MaxEUR[k] — максимальное количество EUR, которое у нас может быть на руках на k-й день.
MaxUSR[k] — максимальное количество USD, которое у нас может быть на руках на k-й день, при условии ровно одного обмена 1 USD -> EUR -> USD.
c[k] — курс обмена


0-й день — база индукции: MaxUSD[0] = 0, MaxEUR[0] = 0.
k-й день: MaxUSD[k] = max(MaxUSD[k — 1], MaxEUR[k — 1] / c[k])
MaxEUR[k] = max(MaxEUR[k — 1], c[k])

Вы даже более сложную задачу решили. В условии надо менять ровно один раз туда и ровно один раз обратно. Ваше же решение может менять сколько угодно раз.


И у вас опечатка в последней строчке кода — забыли c[k] на MaxUSD[k-1] умножить.

MaxEUR[k] = max(MaxEUR[k — 1], c[k])
Как раз это учитывает ваше предыдущее замечание: если в k-тый день меняем доллары на евро, то все предыдущие обмены игнорируются, начинаем с суммы $1 (я ещё подумал, почему граничное условие MaxUSD[0] = 0, так оно и гарантирует, что был хотя бы один обмен и сработало MaxEUR[k] = c[k]).
И у вас опечатка в последней строчке кода — забыли c[k] на MaxUSD[k-1] умножить.

Нет, не забыл. c[k] надо умножать на MaxUSD[k-1], если мы можем сколько угодно раз менять валюту. Но по условию мы можем менять только один раз, а изначально у нас был только 1 USD.

Идея интересная, и даже проще для понимания, чем суффиксы.
Ммм… Пусть у нас в массиве хранится USD/EUR. Ищем в нём самый правый по позиции максимум. Пусть это будет позиция k. Берём подмассив [0; k-1], ищем там минимум. Делим максимум на минимум, получаем количество USD на выходе. Потом ищем самый левый минимум во всём массиве, затем максимум в [k+1; n]. Считаем ещё одно соотношение максимум/минимум. Сравниваем результаты и берём больший. Где я ошибаюсь?
Контр-пример:
3,11,2,3,10,1,3
Лучший вариант: 2-10
Ваш алгоритм находит 2 не лучшие пары: 1,3 и 3,11
function find(x)
	local min,max,p0,p1,p2=x[1],1,1,1,1
	for i=2,#x do
		local v=x[i]/min
		if v>max then max=v p1=p0 p2=i end
		if x[i]<min then min=x[i] p0=i end
	end
	return max,x[p1],x[p2]
end 
Здесь не выполнено требование, что нужен обмен, даже если он невыгоден.
Тестовый пример: 20,10
Нет просто обмен в тот же день. 20,20
Но если сильно надо то можно и не выгодный обмен сделать
function find(x)
	local min,max,p0,p1,p2=x[1],0,1,1,1
	for i=2,#x do
		local v=x[i]/min
		if v>max then max=v p1=p0 p2=i end
		if x[i]<min then min=x[i] p0=i end
	end
	return max,x[p1],x[p2]
end
Нет просто обмен в тот же день. 20,20
Это запрещено по условиям задачи.
так кандидаты не знали, сколько бит в байте

Ну так это смотря в каком байте. Не любой байт октет.

Скучные задачи, увы, обязательны. И для интервьюера они скучны намного больше, т.к. кандидат видит эту задачу впервые (ну или второй-третий раз), а интервьюер эту задачу видит десятый или сотый раз. Но если такую задачу не дать, а дать сразу интересную (как для Senior'a) и кандидат с ней не справится — то не ясно, то ли задача была слишком сложной (кандидат — джун или миддл), то ли кандидат слабый (даже не джун). А т.к. большинство кандидатов по уровню не выше мидла, то и до интересных задач обычно не доходит дело.
Это из своего личного опыта говорю (как в роли кандидата, так и в роли интервьюера).

Тут у интервьюэра софт скилз на нуле. Или :) он умно дождался конца, чтобы формально отфутболить знающего идрис чувака.

Пока читал пост, было ощушение, что вернулся на пятнадцать лет назад и сижу на лекции в университете, где понимаю только знаки препинания.
Вероятно вашему собеседнику вы сломали всю логику собеседования и он пропустил всю часть собеседования и перешёл к шагу «попить кофе после дурацкого собеседования, как же они меня все достали»
Всёж большинство собеседований (по собственному опыту) состоят из обязательной части, где задают очевидные вопросы и ожидают ответы в стиле ЕГЭ и дополнительной, где уже можно обсудить интересные особенности.
Статья однозначно мегазачет, а за ссылку на Aphyr вам отдельное спасибо. Я полнейший балбес, раз умудрился такое пропустить.

А каким образом ваши формальные доказательства покрывают отсутствие багов в Irdis? Т.е. я много раз видел ситуацию, когда программист был 100% уверен в результате (оно не может быть другим) — а оно было, причём по самым дурацким причинам. Например, потому что в динамическом линкере именно данная последовательность бинарных байт вызывала ошибочку и перезаписывала INC на NOOP (бага, бага, закрыта в новой версии, но в продакшене старая непатченная версия). Т.е. логика нам говорит "баги нет", а ядро нам говорит "segmentation fault" для нашего бинаря.


Тесты — они такие...

Более того, формальные доказательства не покрывают правильное понимание решаемой задачи. Если заказчик от меня веб-сайт хотел, а я ему формально верифицированную криптовалюту сделал, то толку-то.


А с юнит-тестов ровно по вашей логике толку примерно столько же. Все скомпилированное приложение целиком надо тестировать.

На самом деле, скомпилированные юнит-тесты уже проверят этот код. Упор на слово "скомпилированные", потому что получится, что unit-test'ы — это такие неявные интеграционные тесты между компилятором, исходным текстом и ОС, где это всё запускается.


… Потому что может быть даже печальнее, например,


idris 1.irdis 
  File "1.irdis", line 1
    revDumb : List a -> List a
            ^
SyntaxError: invalid syntax

(да, alias irdis=python).

Но ведь, опять же, по вашей же логике их вовсе недостаточно. Вдруг в компиляторе/линкере/етц есть баги такие, что юнит-тесты отрабатывают, а всё вместе в составе конечного приложения — нет?

Только юнит тестов никогда не достаточно для полноценной проверки того, что всё работает в сборе. Совсем без юнит тестов тоже может быть тяжело, потому что полноценные интеграционные тесты обычно идут долго, и соответственно не дают фидбека сразу. Получается, что лучше иметь и то и другое (в идеале :))

Ну, если всерьез говорить, то я пишу тесты, чтобы убедиться, что я правильно понял целевую задачу (этакие интеграционные тесты-спеки), и в идеале доказательства на все остальное.

Надеюсь, вы всё-таки не используете Idris в продакшене :). Ну или у компании, в которой вы работаете, будут большие проблемы с поиском замены для Вас, когда вы уволитесь.

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

Ну так они и в FAQ честно пишут, мол, «Idris is primarily a research tool for exploring the possibilities of software development with dependent types, meaning that the primary goal is not (yet) to make a system which could be used in production.» (С)

Главное — чтобы Эдвин Брэди после переписывания идриса (изначально написанного на хаскеле) на идрисе не начал переписывать идрис снова. А то так никогда до продакшена и не дойдет.

Тестирование программы может весьма эффективно продемонстрировать наличие ошибок, но безнадежно неадекватно для демонстрации их отсутствия.
Edsger Wybe Dijkstra
Это ведь не отменяет необходимости (не совсем правильно подобранное слово) писать тесты, а ваше утверждение
А они не нужны. Мы же формально доказали, что мы обращаем список.
выглядит весьма категорично.

А что добавят тесты в этом случае?


Ну, кроме проверок, что ядро тайпчекера работает корректно, но по этой же логике вам надо писать тесты на фреймворк тестов.

А что добавят тесты в этом случае?

+100 к уверенности.
Я не понимаю ваш код, напишите тесты для меня/интервьюера/etc

Ну уверенность дело субъективное, у меня от тестов при наличии доказательства не сильно больше не становится.


А непонимание кода… Ну для него не тесты нужны.

В штате компании будут работать программисты разной квалификации, да и вполне вероятно, что вы когда-нибудь уволитесь, а код-то останется.
Как ни крути, с тестами лучше, чем без тестов.
А непонимание кода… Ну для него не тесты нужны.
Но тесты могут поспособствовать понимаю.
но по этой же логике вам надо писать тесты на фреймворк тестов.

Вообще-то надо. Тесты — код первого порядка и должен подчиняться всем требованиям релизного кода: стили, ревью, ограничения на выбор зависимостей (и расширений в случае Хаскеля) и наличие тестов.
Другое дело, что писать тесты на внешний код — ну такое.

Ну вот так же и код ядра тайпчекера — внешний код.


Тут языкам с тактиками вообще хорошо, которые критерию de Bruijn'а удовлетворяют.

Тесты в данном случае повысит вероятность, что когда кто нибудь поменяет код по какой нибудь причине, изменения в поведении заметят.

Так доказательство корректности придется менять точно так же, как тесты.

А можно автоматически проверить что доказательство по прежнему относится к этому коду?

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

А если недостаточным для тайпчека, но достаточным для лёгкого изменения логики?

Значит, вы доказали не все существенные аспекты вашего алгоритма.


Я бы даже сказал, что в этом всем формальном программировании есть обратная проблема: при не влияющих на семантику изменениях иногда (или даже часто) приходится менять доказательство. По крайней мере, в языках с явным построением proof term'а (вроде идриса).

Тесты не только для вас. Если в коде нет опечаток, то код работает именно так, как вы его написали. Довольно много программистов абсолютно уверенны в своем коде. Они же прочитали его 100500 раз и, может быть, в уме или на бумажке уже доказали его. Но иногда такой код все-таки делает не то, что нужно.


Ваше доказательство тут — это тоже код. Вы уверенны что нигде не допустили ошибки? Напишите-ка доказательство для доказательства?


Наличие тупо тестов, которые как пробка простые и без логики, все-таки необходимо. Во-первых, для Вас, чтобы убедится что в доказательстве нет ошибок. Во-вторых, для тех, кто ваш код читать будет, чтобы было очевидно что он делает хотя бы в некоторых случаях.

Ваше доказательство тут — это тоже код. Вы уверенны что нигде не допустили ошибки? Напишите-ка доказательство для доказательства?

А вы просите написать тесты для тестов?

Обычно тесты сильно проще той магии, что вы тут используете. Буквально input = ...; output = Call(input); Assert(output = ...).

Так доказываемое утверждение тоже достаточно простое. Буквально revDumb xs = revAcc xs — проще любых тестов. Или, если отталкиваться от определения обращения, foldl f init (revDumb xs) = foldr (flip f) init xs. Тоже легко прочитать и понять, что утверждается.

А вот само доказательство — с двумя леммами и кучей кода — ну нифига не простое.

Я не очень понимаю, как эта проверка работает. Можно ли там в доказательстве написать какой-нибудь бред вида True = False, только завуалированный, и из него вывести правильность любого утверждения?

Нет, иначе толку с этих формальных доказательств-то.


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

Просим, и пишем.
У меня уже дважды по-крупному случалось, что тестовая среда начинала гнать false positives.
Да, может, в чём-то сами виноваты — переусложнили обстановку. Но не уверен, что более простая схема взлетела бы.
Поэтому приёмы убедиться, что тесты сами что-то проверяют — обязательны.
И это не TDDʼшное «сначала должно упасть» — нет, проверяться на это должно и давно существующее, хотя бы в характерных избранных точках и ситуациях.

Но тут существенно, конечно, что тест должен читаться в разы проще тестируемого кода. Иначе — нет смысла. В исходном постинге это явно не соблюдается…
Как вы только что процитировали, тесты позволяют реально только продемонстрировать наличие ошибок. Но не их отсутствие. Что бы вы хотели ими продемонстрировать? Что код работает правильно? Так они этого не показывают (в общем случае). Что правильно работает один случайно выбранный пример?

Если мы формально доказали, то стоит обсудить доказательство, допущения, сделанные в процессе доказательства, и т.п.

А если вы не понимаете доказательство, то скорее всего вы не понимаете, что формально означает обратить список (и это в общем типично для многих нетривиальных задач) — то откуда у вас после тестов уверенность-то возьмется +100%, что задача решена верно? Для этого уж как минимум придется прикрутить что-то типа property based testing, а там снова будут доказательства, и все по-новой…

Ну то есть, что для вас субъективно это важно — верю, но это именно суббъективное чувство. У меня вот тоже от наличия тестов его не прибавляется — а только от наличия того самого «понимания кода». Тесты к нему имеют некоторое отношение, но не прямое.
Как вы только что процитировали, тесты позволяют реально только продемонстрировать наличие ошибок. Но не их отсутствие. Что бы вы хотели ими продемонстрировать?

То, что код протестирован. Чем выше процент покрытия тестами, тем проще отладка. А отсутствие тестов, что демонстрирует?
откуда у вас после тестов уверенность-то возьмется +100%, что задача решена верно?

не +100%, а +100 к параметру уверенность. И не задача решена верно, а программа компилируется и запускается.
Чем выше процент покрытия тестами, тем проще отладка.

Смысл всей этой формальной ерунды в том, что вы формализовали спеку, доказали соответствие этой спеке, и потом вам ничего в рантайме проверять или отлаживать не надо, потому что вы уже всё доказали.

>То, что код протестирован
Ну мыж только что обсудили, что это не дает гарантий? Никаких. Или вы Дейкстру процитировали, но с ним не согласны?

>А отсутствие тестов, что демонстрирует?
На мой взгляд — что кто-то дурью маялся. Не вообще, а конкретно вот тут.

Ну то есть, я хочу сказать что — бывают языки, где вы не можете доказать формально почти ничего. Бывают сложные системы, где стоимость такого доказательства запредельно велика. В таком случае я соглашусь, что лучше иметь тесты, и какое-никакое покрытие ими.

Но при возможности и наличии формального доказательства? Зачем?
Или вы Дейкстру процитировали, но с ним не согласны?

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

Тесты могут показать наличие ошибок, а могут и не показать, но они никогда не покажут наличие отсутствия ошибок. Акцент на второй части предложения после запятой.
Тесты практически ничего не гарантируют, кроме покрытия.
Ну то есть, я хочу сказать что — бывают языки, где вы не можете доказать формально почти ничего. Бывают сложные системы, где стоимость такого доказательства запредельно велика. В таком случае я соглашусь, что лучше иметь тесты, и какое-никакое покрытие ими.

Вот именно, дело в покрытии, а какой именно процент покрытия должен быть и на что вообще писать тесты, а на что нет — зависит от бизнеса.
>Акцент на второй части предложения после запятой.
Ну я ровно так это и понимаю. Вы можете писать мало тестов, или много — но гарантии отсутствия ошибок все равно нет. При этом тесты стоят денег, и требуют времени (что где-то одно и тоже).

А тут у нас реальный, достаточно редкий на сегодня случай, когда есть формальное доказательство правильности некоторого небольшого куска кода. Ну и зачем нам вот прямо тут тесты? У нас правда нет более нужных вещей, на которые можно деньги потратить?

Скажем, запустить, и убедиться что все заработало — ну я еще могу это понять. В конце концов — померять время выполнения и потребляемые ресурсы (которые формальным доказательством не были охвачены). Ну то есть — нефункциональные тесты.
А тут у нас реальный, достаточно редкий на сегодня случай, когда есть формальное доказательство правильности некоторого небольшого куска кода. Ну и зачем нам вот прямо тут тесты? У нас правда нет более нужных вещей, на которые можно деньги потратить?

Насколько я понял — случай выдуманный.
Может действительно нет причин писать тест в этом случае, а может есть косвенные причины, но мы этого не знаем.
С одной стороны имеем формальное доказательство, что задача выполнена. С другой стороны, есть достаточно явное указание на то, что решение задачи не может быть верифицировано, ввиду отсутствия тестов.
>Насколько я понял — случай выдуманный.
Насколько я понял, верификация обращения списка — не выдуманная ни разу.

> мы этого не знаем
Ну мы может и не знаем Idris, но это вообще-то не повод говорить, что он не работает.

У нас есть доказательство работоспособности. Правильно ли оно само — я сказать не могу, но идея доказательства по крайней мере вопросов не вызывает (что левая свертка на оригинальном списке работает так же, как правая на инвертированном). Оно использует вполне фундаментальные свойства списков, и чтобы написать любой осмысленный тест (кроме самых тривиальных), вам все равно придется такие же свойства сформулировать, и проверить, что они выполняются.
Ну мы может и не знаем Idris, но это вообще-то не повод говорить, что он не работает.

Мы не знаем по каким причинам интервьюер указывал на отсутствие тестов. Насколько я понимаю, прямых причин нет, но могут быть косвенные — установленные требования бизнеса, например.
Вы не уловили. foldl для оригинального списка с любой функцией и любым начальным значением == foldr для инвертированного. Доказательство — это и есть тест. Берете любую пригодную функцию, и любое значение, и проверяете, что результаты идентичны. Тесты из доказательства выводятся на раз-два, по крайней мере в этом частном случае. Наоборот — далеко не так просто.
Я понимаю то, что бессмысленно писать тесты, если есть формальное доказательство в целях проверки кода.
Но есть и другие требования бизнеса и коммуникация с другими разработчиками, я это уже писал.
В штате компании будут работать программисты разной квалификации, да и вполне вероятно, что вы когда-нибудь уволитесь, а код-то останется.
Как ни крути, с тестами лучше, чем без тестов.

Толку-то если приняв оффер, на работе вы будете писать доказательства такого уровня, что их мало кто будет понимать. А тесты дублируют код, их почти всегда просто понять.
>А тесты дублируют код, их почти всегда просто понять.
Ну вот напишите (на любом удобном языке ;) тест к данному примеру? На самом деле это нифига не просто, и понять такие тесты будет не всегда просто.

>вы будете писать доказательства такого уровня
Боюсь что не будете, к сожалению. На сегодня это слишком сложно для промышленного применения.
unit-test'ы — это такие неявные интеграционные тесты между компилятором, исходным текстом и ОС, где это всё запускается.

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

А теперь представим, что он irdis не знает, следовательно в вашем коде он разобраться не может. Если предположить. что это метаязык, суто может быть и уловит, но главное было все-таки хотя бы просто запустить на нескольких примерах, чтобы увидеть что ваша программа действительно работает.

А вы этого не сделали, тестов рабочих не предоставили, просто углубились в математические формальности.

Предположим, они берут вас на работу, и просят реализовать простую вещь. В результате получают множество раз переписанный, оптимизированный и вылизанных пулл реквест, который ни разу не запускался на локальном дев енвайрнменте, и в CI он идет без единого теста, то есть первый запуск будет где-то аж на UAT, а то и вообще в PROD?
А вы этого не сделали, тестов рабочих не предоставили, просто углубились в математические формальности.

А вы правда тесты ставите выше доказательств корректности алгоритмов? Речь же не об особенностях операционной семантики языка, скажем.


В результате получают множество раз переписанный, оптимизированный и вылизанных пулл реквест, который ни разу не запускался на локальном дев енвайрнменте, и в CI он идет без единого теста, то есть первый запуск будет где-то аж на UAT, а то и вообще в PROD?

Так вакансия ж на C++ была, поэтому, увы, так не получится, придётся тесты писать :(

А вы снова суть не уловили.

Интервьювер правильно сказал — что вы программу даже не запустили, я уж не говорю про тесты. Тесты даже необязательно писать, просто запустить программу и показать что она обратила список, который вы туда передали аргументов, или даже захардкодили.

Если я не знаю вашего irdis, то формальному доказательству я может и поверю, но как я могу проверить что он правильно реализован с точки зрения кода?

Ведь нельзя сказать, что любой математик, который может формально доказать теорему пифагора, способен запрограммировать ее решение?
Тесты даже необязательно писать, просто запустить программу и показать что она обратила список, который вы туда передали аргументов, или даже захардкодили.

Зачем? Какую дополнительную информацию это даёт, при условии, что вы знаете Idris?


Если я не знаю вашего irdis

А если не знаете, то какая разница, запустил я программу или нет? Может, я там в обработке нажатий от клавиатуры системную функцию reverse вызвал, а не свои эти вот, и она все ваши проверки отработает. Или захардкодил входной список и захардкодил выходной.


то формальному доказательству я может и поверю, но как я могу проверить что он правильно реализован с точки зрения кода?

А вам не надо это проверять. Реализацию проверяет сам язык (в этом вся прелесть proofs-as-terms и тайпчекинга).


Утверждение, которое доказывается, во-первых, ИМХО, достаточно читабельно. Во-вторых, даже если я сильно ошибаюсь, то чем тесты лучше? Может, опять же, я там захардкодил ответ на пару входных списков, и где-то в коде у меня что-то вроде


if input == "1 2 3" then print "3 2 1"
if input == "1" then print "1"

Ведь нельзя сказать, что любой математик, который может формально доказать теорему пифагора, способен запрограммировать ее решение?

Нельзя, конечно. Но если математик доказал, что запрограммированное решение правда решает теорему Пифагора (что бы это ни значило), то этому верить, наверное, можно, по меньшей мере, с той же уверенностью, что и тестам?

С таким подходом я нисколько не удивляюсь, что не позвонили. Они просто сразу поняли весь спектр возможных проблем, начиная с межличностных.

А если вас попросят написать тесты для фреймворка тестов на интервью, вы это тоже с радостью сделаете или будете отказываться?


Я не очень люблю делать бессмысленные действия, и, действительно, лучше это выяснить сразу. Не назвал бы это межличностной проблемой, впрочем.

А завтра вам в голову придёт, что весь продукт компании, над которым вам предстоит работать — бессмысленный. Не стоит вам с таким подходом вообще наниматься на работу.

Вы абсолютно правы, и вопрос о том, связан проект с какой-то ерундой, или же им заниматься интересно, он важный.


Впрочем, если уж мы заговорили об этом… Вы никогда не задаётесь вопросами целесообразности того, что вам предлагают делать?

Всё не просто, а очень просто. Что-то доказывать нужно человеку, а не компилятору. Потому что именно он принимает решение и берёт на себя ответственность. И если что, фейсом по клаве будут возюкать его. Ну а потом он будут делать тоже самое с тобой. И есть вероятность, что все остальные тоже присоединятся к этому увлекательному действу. Даже те, кто плюсовал карму и ржал в комментах. Ну я вот тоже ржал — смешно же. По не позвонил бы.
Потому что вся статья это просто попытка поднять чсв за чужой счет. А нарциссизм он того — до добра не доводит. Потому что всегда нужно помнить одну простую вещь — даже теория относительности относительна.
А тут какие-то формальные доказательства, безоглядная надёжа на компилятор, и вера в постановщика задачи, ну и задранное чсв.
В общем, я бы не взял такого сотрудника, ибо страшно далёк он от реальности.
безоглядная надёжа на компилятор, и вера в постановщика задачи

Вера в тесты, получается, лучше?

Нееет, дело не в вере, а в ответственности. А ответственность на вере это такая зыбкая штука. А у тебя получается вера. Вера в формальное доказательство правильности решения, в правильность задачи, в яп, в компилятор/интерпретатор, библиотеки и тд. Вера, как известно, не приемлет логики. Критерий истины — практика. Поэтому тебя и спрашивают " где тесты, Карл?". Где результат?
«не верю (с)»
Где результат?

Вон терм нужного типа, он тайпчекается. Вот и результат. Вполне себе на практике.


" где тесты, Карл?"

А в чём их смысл при таких вводных-то? Ведь то, что тесты проходят, опирается на веру в компилятор/интерпретатор, библиотеки, фреймворк тестов и прочее подобное.

Насколько я понял Kemet и некоторых прочих комментаторов, они пытаются указать на разницу между текстом программы и собственно программой. Программа является рабочей, если она хоть раз выполнила своё предназначения, иначе она просто объект современного искусства. Так что в описанной ситуации программу стоило бы хоть раз запустить.

А чем запуск тайпчекера на тексте программы принципиально отличается? Вы же не маркером на доске доказательство пишете, а в виде кода в компьютере, и проверку этого доказательства в том или ином виде регулярно запускаете.

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

Ну вот написанный код, который ни разу не был выполнен, практически ничем от написанного на доске маркером не отличается.

По коду, написанному маркером на доске, тайпчекер не пробегается, и машина его корректность не проверяет.

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

Вы вот взяли и написали такой крутой алгоритм разворота списка. Доказали его формально. Залили на прод. А завтра пришел программист Вася, у которого с математикой всё не так хорошо, и добавил/изменил пару строчек. И сразу вылил, тестов же нет. А на следующий день боевой сервер упал и фирма потеряла 100500 тысяч долларов.

Любая мало-мальски крупная разработка, в первую очередь, про безопасность и тройные проверки, которые, с вашей точки зрения, бессмысленные.
чтобы, как минимум, обезопасить код и проект от неочевидных ошибок при изменении реализации.

«Тестирование программного обеспечения не может доказать, что система, алгоритм или программа не содержит никаких ошибок и дефектов и удовлетворяет определённому свойству. Это может сделать формальная верификация.» (С)
И сразу вылил, тестов же нет. А на следующий день боевой сервер упал и фирма потеряла 100500 тысяч долларов.

Ну если в фирме считается нормальным «сразу выливать» без пул-реквестов и код-ревью, то поделом.
Ну а если код ревью может сделать единственный математик в компании, а потом он уволится, что делать?

Вы, видимо, не до конца понимаете суть формальных доказательств.


Доказательства — они там, рядом, в том же файле, что и основная реализация, и проверяются при каждой сборке. У вас физически не получится изменить реализацию так, что доказательство станет ложным, и при этом что-то куда-то вылить: модуль просто не соберётся.


Спасибо за ваш комментарий, я стал чуть лучше понимать суть претензий.

Даже не просто overqualified, а что то уровня профессора computer science, который почему то пришёл на позицию junior programmer, с которой он сбежит на следующий же день.
что то уровня профессора computer science

Ну точно надо мне прекращать метания, бросать тырпрайз и идти в академию.

Кажется, я видел похожий пост, только там, как в анекдоте, не "развернуть список", а "решить FizzBuzz", и не "функциональное программирование", а "машинное обучение", и не "тесты не нужны — мы формально доказали", а "надо было взять более глубокую нейронную сеть": https://habr.com/ru/post/301536/

О, прекрасно, спасибо! Я как раз, наконец, начал писать пост про формальную верификацию fizzbuzz.

Разруха не в клозетах языках, а в головах! (с) Собачье сердце

Говнокодить и оверэнженерить можно на любом языке, так же практически на любом современном высокоуровневым мало-мальски популярном языке можно писать хороший и эффективный код.

Тот же FizzBuzzEnterpriseEdition можно переписать абсолютно на любом языке.
Вот-вот, где-то на этот счет была хорошая фраза. Что-то вроде «некоторые плохие программисты пишут код для того, чтобы каждым его символом напомнить о своем остроумии»
UFO landed and left these words here

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


И надо, видимо, мне потюнить свои писательские навыки, раз это можно всерьёз воспринять. Ну или не надо.

Действительно можно подумать, что это произошло на самом деле, но тюнить не надо — щепотка юмора придала пикантности.
На телефонных скринингах часто просят развернуть строку или список, чтобы отличить настоящих кандидатов с опытом от проходимцев, сочинивших себе резюме от начала до конца.
А в чем некорректность, кстати? Интервьюер сказал — можете писать на том языке, на котором вам удобнее. Автору было удобно на Idris, в чем проблема?
Как говорил Ленин: формально все верно, а по сути — издевательство.

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

Я не спорю, что по сути издевательство, в этом-то и есть весь лирический конфликт и трагедия лишнего человека, но вот


не задал ни одного вопроса на тему функциональных и нефункциональных требований для разработки и эксплуатации приложения: кто, для чего и в каких условиях им будет пользоваться. Системные требования. Требования по развертыванию и поддержке.

Это точно ожидается, когда вас просят перевернуть список или, я не знаю, проверить сбалансированность скобочного выражения?

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

У инженерных задач, в отличие от абстрактно математических, есть как минимум пара отличий. Во-первых, это всегда задачи с ограничениями. Во-вторых, отсутствие каких-либо требований в исходной постановке говорит о необходимости их уточнить.

Решение такогонебыловтребованияхуменяналокалхостевсеработает это далеко не продукт. А сам такой подход к работе говорит об уровне специалиста.

Кажется, я где-то видел аналогичную иронию на тему написания функции копирования файла, с уточнением требований уровня поддержки имён файлов, содержащих одновременные RTL и LTR письменности, плагинов для протоколов и подключаемых стратегий обработки ошибок. Но не суть.


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

Отличная статья. Тоже читал. На мой взгляд история показывает, что невозможно найти контакт, если собеседники придерживаются граничных условий. На то они и граничные. Точки соприкосновения, общие интересы всегда где то по середине. Это и надо искать. Универсальное решение может быть неподходящим, из-за необходимости учесть множество факторов, подчас противоречивых. Грамотный инженер должен уметь получить нужные для решения задачи сведения, задав минимум вопросов по существу, а не вообще все, что может только придумать.
UFO landed and left these words here

Не, я так себе им владею, до сих пор elaborator reflection даже не осилил.


А что за система типов — это долгая история. В пятничную статью, боюсь, не уложусь.

При должном количестве усилий можно любую задачу решать бесконечно ))

Двоякое впечатление на самом деле. Я сейчас работаю в большой аутсорсинговой компании и у нас есть определенный регламент интервью, который приходится соблюдать. И он даже на позицию solution architect подразумевает вопросы типа «что такое виртуальный метод?».
Но я вас прекрасно понимаю :). Поэтому заранее предупреждаю от том, что начну с детских вопросов, потому что их основная цель — снять первое напряжение на собеседовании.

У меня коллега любит спрашивать очевидные детские вопросы, и про виртуальный метод, и даже про указатели. Конечно, не на такие высокие должности, но когда я своими глазами увидел, как люди, утверждающие, что пишут на С или С++ плавают на таких вопросах...

У меня человек, утвердающий что хорошо знает баш, не знал что такое шебанг и код возврата.

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

У меня как-то был собес на с++ позицию. Человек по резюме выглядел как твёрдый миддл, с претензией на сеньора. Но собеседование закончилось, когда он не смог объяснить чем ссылка отличается от указателя. Ответ «я всегда использую указатели» меня по понятным причинам не устроил.

По большому счету они ничем не отличаются, по каким причинам вас не устроил ответ непонятно, если человек качественно и эффективно решает задачи только с применением указателей то в чем проблема, в данном случае вы проявили формализм, граничащий с идиотизмом.
Как минимум, есть синтаксические различия, и их можно было назвать.
если человек качественно и эффективно решает задачи только с применением указателей то в чем проблема
В том, что этот человек не сможет читать/понимать/поддерживать чужой код со ссылками.
-Чем отличается А от Б?
-Не знаю…
-Вы что, не видите, есть же синтаксические различия, А — это А, а Б — это Б. Пишутся по-разному! Как можно не видеть такую простую вещь? No hire.
Но ссылки настолько core feature, что мидлу не знать её просто нельзя.

— Чем отличаются десятичные и шестнадцатеричные целочисленные константы?
— Ну, не знаю, я пользовался только десятичными…

Лично я бы с позиции интервьювера более чем удовлетворился бы ответом «ссылки — это указатели, которые нельзя ребиндить и которые нельзя создать неинициализированными».

Проблема в том, что код построенный на указателях значительно усложняет raii подход и нужно лишний раз напрягать мозг касательно владения обьектом.
А ответ меня не устроил по той причине, что нужно хотя-бы минимально знать язык и его базовые возможности (были и другие вопросы, на которых кандидат свалился).
Если человек качественно использует только базовые вещи из си, то это вовсе не значит, что он подходит на си++ вакансию. Особенно на проект, где нормальный ООП. Ваш комментарий про формализм/идиотизм тут вообще не к месту, поскольку вы не знаете, как я провожу интервью.

Прочитал первый абзац, написал разворот списка на С++ со старыми добрыми указателями, а потом прочитал остальную статью и немного выпал.

О, а на плюсах можно развлечься с разворотом списка типов на вариадик темплейтах в компил-тайме.

То есть, время компиляции в зависимости от длины списка? В рантайме-то оно, если я правильно понял идею, будет линейным (поскольку сведётся к цепочке копирований).

да, думаю зависит от компилятора, не уверен что стандарт такие моменты задает

В рантайме оно будет вообще константным, ибо темплейты — чистый компил-тайм.

Слишком просто
template<class T>
struct def
{
    using type = T;
};

template<class T>
using type = typename T::type;

template<class T, class T2>
struct cat {};

template<template<class...> class T, class... ArgsT, class... ArgsT2>
struct cat<T<ArgsT...>, T<ArgsT2...>> : def<T<ArgsT..., ArgsT2...>> {};

template <class T>
struct revert : def<T> {};

template <template<class> class T, class A>
struct revert<T<A>> : def<T<A>> {};

template <template<class...> class T, class Head, class... Tail>
struct revert<T<Head, Tail...>> : cat<type<revert<T<Tail...>>>, T<Head>> {};

template <class TypeList>
using revert_t = type<revert<TypeList>>;

//check is it works
static_assert(std::is_same_v<std::tuple<short, int, long>, revert_t<std::tuple<long, int, short>>>);
Двоякое чувство. Взглянем со стороны нанимателя. С одной стороны любознательность, кругозор и нестандартный взгляд на вещи это прикольно. С другой — цель технического интервью понять: интересна ли кандидату работа и будет-ли он справляться. Если нужен с++ разработчик, то не брать это вполне логичный вывод. Ведь за отведенное время соискатель не продемонстрировал ни интереса к языку, ни практических навыков. Это совсем не значит, что лирический герой не крут, просто на данную должность нужны другие супермены.

Предлагаю порефлексировать и с позиции нанимающегося. Вот, например, если мне самому встать на место лирического героя, то я вспомню, что у меня в резюме примерно на второй строчке (сразу после имени) есть ссылка на гитхаб, а на гитхабе у меня довольно много кода на C++, и часть этого кода на момент написания не собиралась релизными версиями доступных компиляторов (хотя последние несколько месяцев я почти не коммичу ничего плюсового, но это неважно, там до того порядком). И если после этого работодателю необходимо, чтобы я продемонстрировал интерес к языку и практические навыки, то я могу представить следующие варианты:


  1. Работодателю, ну, просто не очень интересно. Но тогда зачем он сейчас проверяет мои навыки, если они ему неинтересны?
  2. Работодателю интересно, но у него процесс. Но это неинтересно уже мне, потому что опыт подсказывает, что у него процесс будет и чтобы жалюзи отрегулировать (нет, я не смеюсь, работал в фирме, где для этого надо заводить тикет во внутреннюю систему учёта чего-то там), и чтобы мне на этом гитхабе ещё один проектик создать.
  3. Работодатель мне тупо не доверяет, что это мой гитхаб, а не чей-то левый или что кто-то другой мне там не коммитит.

То есть, возможно, работодатель очень крут, просто ему нужны другие супермены.

Предлагаю порефлексировать и с позиции нанимающегося.


Давайте определим цели технического интервью. Они не только в определении умения программировать. Цели:

1. Определить общую адекватность и будет ли кандидат следовать установленным правилам компании,

2. Психологическую совместимость с будущим начальникам и коллегами,

3. Умение адекватно работать с требованиями и вести диалог с «заказчиком» (даже если это тот же коллега), в том числе с закачиками, которые просят нарисовать "семь перпендикулярных линий".

4. Собственно навыки программирования,

Если ответ на любые из первых трех пунктов резко негативный, то собственно навыки программирования уже вряд ли будут иметь значение. Если на вопрос вроде развернуть список, человек встанет и уйдет, вполне очевидно ответ на первые 3 пункта будет получен за минимальное время.

Предложение начать интервью с пения гимна компании справится с этим куда быстрее и эффективнее (и я знаю места, где практикуют что-то немного похожее).

Это зависит от того какой психологический профиль сотрудника нужен компании (черезмерное подчинение это тоже не всегда хорошо для бизнеса), если нужен именно тот, который без возражений будет петь — попросят спеть.

Тут надо понимать, что у работодателя вполне четкие критерии, кто им нужен, поэтому сразу отсееять тех, кто по каким-то причинам не подходит — разумно.

Ну, вот возьмут они героя этой статьи, а он так же будет троллить коллег и заказчиков при реальных заданиях. Вот если бы вы были владельцем бизнеса, вы бы считали что разумно иметь такого сотрудника?

P.S. Я не говорю, что нужно у всех просить развернуть список. Я о том, что нужно понимать, что и зачем у тебя спрашивают, очень часто техническое интервью это не только и не столько проверка именно технических навыков.

Про владельца бизнеса не скажу, но если бы я набирал себе команду, то списки вертеть просил бы только у джунов (и то не факт, это больно избитая задача). А там, авось, и троллить в ответ не будут.


А вопросы ведь в две стороны работают. Даже в две с половиной: они показывают не только то, кого ищет мой будущий тимлид, условно, но и с кем мне в среднем предстоит работать.

Вопросы ничего не показывают. Это может быть тест на адекватность, может быть у них очень много тех кто пытается выдать себя за эксперта, может это просто вопрос для «разогрева», может в компании строгая форма интервью и т.п.
Я бы задумался, если все вопросы на интервью оказались бы такими или там начали спрашивать, что-то вообще странное вроде точной даты выпуска 1 версии Java и т.п.
Поддерживаю, инженер в современном проекте должен уметь не только писать код. Софт скиллы не менее важны. Потребность в соло-разработчиках, с навыками коммуникации как у «склонного к насилию психопата, который знает, где вы живёте» (sic), даже у поддержки случается крайне редко. Троллинг как квинтэссенция формализма хорош в меру и определенных местах. На Хабре поржать, да людей в пятницу развлечь — это супер (ещё раз спасибо автору за материал). Однако выбор троллинга в качестве основного инструмента для переговоров, таких как собеседование, ну так себе решение.

Обычно начинаю интервью с внешне простых вопросов. Если кандидат в принципе адекватен, то быстро предлагает варианты. По ходу вместе с кандидатом немного меняем требования, докидываем деталей. Смотрим граничные случаи, области применимости текущего решения, возможности для расширения. Формат создаёт определенный стресс, но таковы реали итеративной разработки. Это становится отправной точкой для дальнейшей дискуссии относительно других требований, предъявляемым к сотрудникам в компании, инженерной культуре, прцессах (стек технологий, таск трекинг, quality gates, change management, документирование, ревью, тестирование, ci/cd, активности, и вот это все). Интересно наличие как общей эрудиции, так и практического опыта использования или внедрения (в зависимости от уровня и позиции).
Давайте определим цели технического интервью

Определить общую адекватность

Психологическую совместимость

Умение адекватно работать с требованиями

А это точно техническое интервью?
точно техническое интервью

Разумеется. Кто вам сказал, что на техническом интервью проверяют только технические навыки? Вопросы, конечно, обычно технические, но по ответам и поведению практически всегда смотрят и на soft skills.

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

А это точно техническое интервью?


Ну первое и третье — вполне даже технические вещи. Рекрутеры, в большинстве случаев, неспособны определить адекватность человека и умение работать с техническими требованиями.
На собеседованиях я нередко вижу, что человек не понимает суть вопроса. Его спрашиваешь одно, а человек, как двоечники в институте, начинают отвечать на совершенно другое, словно надеясь что пронесет.
Иногда даже пытаешься выяснить — человек не знает, и пытается таким образом съехать с темы, или человек реально неспособен понять что его спрашивают, но бывает что он действительно не понимает, еще и идет в агрессию.

При этом рекрутер такой момент проверить не может в силу отсутствия технических знаний.
Я недавно был на стороне интервьювера, только по удаленке. Несколько человек тоже присылали ссылку на Гитхаб, пара человек даже в категоричной форме «если не устраивает, адьос».

Я ваш Гитхаб не видел, конечно, но вот у тех, кто присылал — просто код без комментариев, без README — непонятно, какую задачу решали. Я же хочу решение задачи увидеть — как человек мыслит, как знает свой инструмент, что у него с архитектурой.

А по такому коду могу разве что Code Style посмотреть. И что толку от этого?
Я же хочу решение задачи увидеть — как человек мыслит, как знает свой инструмент, что у него с архитектурой.

Но вы ведь для этого не будете просить переворачивать списки или считать скобки?

Но вы говорите, что ваш код на гитхабе даже не компилится современными компиляторами…?
Получается что его ни запустить, ни отдебажить нельзя, только почитать readme?

Теперь уже можно (увы, ибо раньше в этом был свой шарм, когда релизный компилятор это не осиливает). Просто было время, когда C++17 (а чуть раньше — 14) уже вышел, а полноценных компиляторов к нему не завезли.


Ничего, скоро выйдет C++20, можно будет снова поупарываться.


Ну и да, для оценки шаблонной магии код запускать тоже не обязательно.

Верно, я не прошу решать «задачки», но если честно, наше тестовое тоже не особо интересное. Приходится идти на эту «жертву», потому что я понимаю — никто не будет тратить пару дней на выполнение «интересного» задания. То, что даем мы — просто точка, от которой можно оттолкнуться.
Попробую ответить только за гитхаб) так как остальные моменты с отсутствием общих интересов очевидны — можно закончить интервью или финализировать за печенюшками на кухне и экскурсией по офису.

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

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

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


А вот с контрибьютингом — поддерживаю, это важно. Конкретно мой гитхаб в этом плане выглядит весьма уныло, масштаба тыщи коммитов в этом году и пара-тройка ничего не значащих PR'ов да полтора issue.


И если после этого работодателю необходимо, чтобы я продемонстрировал интерес к языку и практические навыки

Т.е. наниматель — редиска, потому что посмел пригласить самого Вас на позицию жалкого C++ разработчика? В некотором смысле, условная девочка из HR, которая прислала вам приглашение, немножечко не права.


Но, корректное поведение с Вашей стороны было бы проигнорировать эту вакансию. Или, возможно, потроллить рекрутера. Но если Вы согласились на интервью, а тем более пришли куда-то — то тут ваш троллинг уже совсем ни к месту. Вы приняли условие вакансии и создаете драму совершенно на пустом месте.

Э, почему ж редиска, если я на позицию С++-разработчика претендую?


Редиски скорее те работодатели, которым свой гитхаб указываешь, а они phone screening устраивают с проверками на базовое понимание программирования. Или списки разворачивать просят.

Гитхаб может быть набит кучей чужого кода. Резюме просто списано с первого найденного в гугле резюме.


Кандидатов обычно много и все такие замечательные. По душам поговорить про высокие материи с каждым слишком дорого. Поэтому phone screening, где вас спросят написать FizzBuzz или развернуть список — это вполне адекватно.


Вас же не бесит, что надо анкеты какие-то заполнять, CV по общепринятому стандарту делать? Ну вот решение тривиальных задачек — это еще одна бюрократическая неприятность, которую надо преодолеть.

Гитхаб может быть набит кучей чужого кода.

См. п. 3.


где вас спросят написать FizzBuzz

Да без проблем!


Вас же не бесит, что надо анкеты какие-то заполнять, CV по общепринятому стандарту делать?

А какие анкеты? Единственные бумажки, которые я заполнял за последнее время — это NDA на задачки и/или проприетарную информацию, которую я могу узнать на собеседовании (второе прям даже воодушевило, это ж значит, что мы будем реальные задачи обсуждать, а не как списки переворачивать!).


А CV у меня… Ну я скачал где-то шаблон для латеха и в нём делаю.

Да без проблем!

О боже ж ты мой! 450+ строк кода без комментариев! Это даже круче FizzBuzz Enterprise Edition. Стесняюсь спросить, но… Все это нужно для реализации, или большая часть — это доказательство?

Это даже круче FizzBuzz Enterprise Edition.

Спасибо, я старался!


Большая часть — доказательство и, ээ, формализация (ну вот что такое деление, например?), плюс вспомогательные вещи — те же натуральные числа или процедуру деления я реализовал с нуля сам. Реализация — последние 5-6 строк.

Большая часть — доказательство и, ээ, формализация (ну вот что такое деление, например?), плюс вспомогательные вещи — те же натуральные числа или процедуру деления я реализовал с нуля сам.
Насколько велика «стандартная библиотека» Идриса? Просто хочется из коробки иметь ряд доказанных вещей, натуральные числа своими руками это не сколько неудобно.

Натуральные числа и, например, их неравенства там точно есть. Формально верифицированного деления в нужном мне виде, ЕМНИП, нет.


Думаю, если воспользоваться стандартной библиотекой, то можно будет выкинуть процентов 60 кода. Что, впрочем, для такой задачи всё равно неинтересно, так как мне было любопытно, сколько арифметики мне придётся реализовать для такой задачи.

Я начинаю сомневаться, что 0xd34df00d разработчик.
Зачем ему вакансия разработчиков, если ему прямая дорога в прикладные математики или как это называется?

На работе обычного senior С++ разработчика, или не дай бог тимлида, он же просто перегорит от необходимости писать обычный код, без формальных доказательств, еще и писать тесты.

Я, кстати, таки всерьёз подумываю в чистую математику идти. Так-то в дипломе у меня написано «прикладной математик», но там как раз всей этой ерунды с формальными доказательствами не было, увы.


Но да, то, какой код (все эти темплейты на плюсах, кстати, с тестами) и как надо писать — вполне себе послужило критерием недавнего выбора нового места работы.

Хм. Знаете, это вероятно выдуманное интервью, и в реальном случае было бы примерно так (где-то посредине): «Достаточно, а теперь перейдем к технической части нашей беседы ;)». У соискателя спросили о чем-то одном. Если интервьюирующий не смог быстро оценить ответ, и перейти к следующим вопросам — это его проблемы, вам не кажется? Если ему интересны реально навыки в разработке на C++ — ну тогда не надо разрешать писать примеры на любом языке, уточнил бы сразу. Ну т.е. — ССЗБ.
И не перезвонят. В резюме же было написано, требуется программист С++, а не тролль 80lv со знанием Idris :)
Занятно. На Прологе через аккумулятор синтаксически покороче будет, хотя по сути то же самое:

revOnto([H|T],A,R):- revOnto(T,[H|A],R). 
revOnto([],A,A).
revAcc(L,R):-revOnto(L,[],R).


А вот «тупенький» вариант выглядит более неуклюже:

revDumb([],[]). 
revDumb([H|T],R):- revDumb(T,RevT),  append(RevT,[H],R).


Было бы, конечно, круто использовать предикаты второго порядка:

revDumb([],[]). 
revDumb([H|T], R):- append(revDumb(T, RevT), H,R).


Но доказать не могу.
UFO landed and left these words here
И я. Не подскажете, языки идеологически близки, или автор Индриса не это имел в виду?
Я именно про идеологию. Пролог создавался с идеей, что для решения задачи достаточно описать «мир», начальное состояние и конечное желаемое состояние. Дли Идриса насколько подробно надо очерчивать сам путь от исходного к конечному состоянию?

Весьма подробно.


Наверное, самое близкое к автоматическому поиску пути — поиск доказательства утверждения. У идриса из коробки для этого довольно мало средств (но есть elaborator reflection, который по факту позволяет скриптовать тайпчекер, и который я пока не осилил), и ближайшим аналогом тут скорее будут тактики из Coq.

Я недавно на собеседовании со стороны работодателя задавал вот такой нескучный вопрос:

image

Два конфокальных зеркальных эллипсоида соединены зеркальным же кольцом, как показано на рисунке, внутри вакуум.
В фокусах два горячих тела Alice и Bob (не отвлекайтесь), для краткости А и В.
Все фотоны из А попадают в В, но только часть фотонов из В попадает в А, некоторые отражаются обратно в В.
В итоге имеем перекачку тепла из А в В без внешнего источника энергии, то есть вечный двигатель второго рода.

Вопрос: где засада?

Тянуто отсюда


Парень был тоже из ИТМО(как и я), очень толковый, хорошо пообсуждали. Но не прошел других коллег (они, что интересно, тоже из ИТМО).
Я нифига не физик, но предположу, что фотоны из A и из B будут иметь разную энергию. Соответственно, один фотон из B в А перенесет энергии больше, чем один фотон из A в B или типа того.

Если до начала эксперимента А и Б были одинаковой температуры, а в равновесном состоянии Б оказалось горячее А, то это означало бы, что тепло из А передалось в Б без совершения работы. Добавляя/удаляя малый полу-эллипсоид можно было бы получить постоянную перекачку тепла из А в Б и обратно, т.е. вечный двигатель.

Является ли вечным двигателем маятник, перекачивающий энергию из потенциальной в кинетическую, и обратно?

Нет, не является, но он и не является термодинамической системой. Если у вас есть способ вывести систему из термодинамического равновесия (т.е. уменьшить энтропию), не совершая над ней работы, то вы можете построить вечный двигатель второго рода, выкачивающий бесплатную энергию из окружающей среды. См. ниже вариант такого двигателя.

Тепло перекачивается из А в Б и обратно, но суммарная энергия системы остаётся неизменной. В чём заключается вечный двигатель-то?


P.S. Суть вечного двигателя — в возможности неограниченного извлечения энергии. Здесь же энергия не извлекается.

Видимо, проблема в вышеприведённых рассуждениях в том, что предполагается, что энергия сконцентрирована только в точках A и B. Температуры A и B должны сравняться, а весь излишек энергии будет летать между зеркалами. При изменении геометрии что будет с теми фотонами, которые окажутся в «откусываемой» области?
При изменении геометрии что будет с теми фотонами, которые окажутся в «откусываемой» области?

Окажут давление на зеркало, если область именно откусывать.

Тогда бы и солнечные электростанции были бы нарушением второго начала термодинамики. А ведь ничего не нарушается!


Кстати, парадокс с эллипсами можно даже упростить: взять белое тело и поместить его в полость чёрного тела. Даже если тела будут неидеально белые и чёрные, белое тело всегда будет холоднее чёрного, и можно извлекать энергию из разности температур.


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

  1. Открываем систему и приводим её в равновесие с окружающей средой. Температуры тел А и Б становятся равными Т.
  2. Закрываем систему, вводим малый эллипс. А остывает ниже Т, Б нагревается выше Т.
  3. Используем разницу температур A и Б для совершения работы.
  4. Повторяем до бесконечности.

Получили вечный двигатель второго рода.

Засада в том, что если фотон из А попадает в Б, то по той же самой траектории фотон из Б попадает в А.
Это не модель АЧТ в виде камеры-обскуры с дыркой: тут дырка будь здоров какая.


Можем посмотреть, при каких условиях наступает равновесие.
Пусть А и Б равномерно светят во все стороны.
При этом весь поток из А направлен в Б.
Некоторая доля q потока из Б направлена в А, а остальная (1-q) направлена в Б.
Тогда, если Б излучает ровно в q раз больше, чем А, потоки энергии уравниваются.


Как связаны пропорции размеров эллипсоидов и телесный угол облучения Алисы Бобом — хз, надо считать. Было бы желание.


У doctor-notes притянуты разговоры про температуру вселенной, всё такое… это совершенно избыточно.

UFO landed and left these words here
Я тоже не физик, но идея zabbius'а мне кажется более близкой к истине.
Длина волны теплового излучения обратно пропорциональна температуре излучающего тела, и заодно энергии излучаемого фотона. Как только В нагреется выше А, он начнет излучать более синие фотоны, доставляя А с каждым фотоном большее количество энергии. При установившемся равновесии В будет горячее А, но вот посчитать это мне уже слабО.
И разумеется, это если высказанная идея верна.

Ну, это уже нюансы.
Главное, что потоки энергии уравновешены, а как это выражается в температуре и спектре, "оставим решить любознательному читателю".


Для модели, где оба излучателя — АЧТ, — тело Б нагреется и станет отдавать вдвое больше тепла.
Для какой-нибудь там квантовой модели, — произойдёт накачка тела Б, и оно залпом отдаст все лишние фотоны на своей частоте.
Для модели с теннисистами, — тело А кинет десять мячиков, тело Б — двадцать (десять прилетит обратно к А).

При этом весь поток из А направлен в Б.

Это неверно: при конечных размерах A и Б (строго точечные АЧТ вообще не излучают) на "верхушках" эллипсоидов будут зоны, где отражённый луч будет падать обратно на излучившее их тело. Телесный угол этой зоны будет тем больше, чем ближе тело к стенке. Тело А ближе к верхушке малого эллипсоида чем Б к верхушке большого, значит А будет греть саму себя сильнее, чем Б самого себя без учёта зеркала. Зеркало восстанавливает баланс.

При достаточно большом размере зеркала не-точечностью источников можно пренебречь.
Конечно, телесный угол, с которого свет с поверхности А через макушку эллипсоида падает обратно на А, ненулевой, — но всё равно он маленький.
Окей, если так хочется, введите в уравнение размер этого телесного угла.


Пусть А излучает 1 единицу энергии в сторону Б и α обратно на себя.
Пусть Б излучает β обратно на себя и 1 в сторону А.
α≪β
И та самая 1 единица энергии летает туда и обратно.


σα/(1+α) — телесный угол, под которым А видно из А,
σβ/(β+1) — телесный угол, под которым Б видно из Б,
σ = полный телесный угол, 4π стерадиан

Ещё нужно учесть, что при конечных размерах тел все точки их излучающих поверхностей находятся не в фокусе (причём А больше не в фокусе, чем Б), и что каждая точка поверхности излучает в полусферу, а не строго по нормали, и что распространение лучей уже не такое простое, как в модели. Там такой эллиптический биллиард получается, что я не возьмусь считать всё это :)


Мне думается, что с учётом всех возможных хаотических переотражений, срез малого эллипсоида можно было бы свести к простому АЧТ, находящемуся в тепловом равновесии с Б и его излучением. Чую, но доказать не могу :)

Что вы спорите? Уберите зеркало совсем — оно только запутывает. Идеального зеркала не существует, равно как идеально чёрных тел, сжатых до материальной точки. Просто поместите белое тело внутрь чёрного. Не обязательно тела должны быть идеальны, главное, чтобы белое возвращало большую часть фотонов, которые прилетают от чёрного.

Я не уловил — что именно в указанной задаче вы моделируете белым телом внутри чёрного? А и Б — оба чёрные, и они внутри белого (зеркального эллипсоида).


Зеркала действительно просто запутывают. Кольцевое можно убрать, просто достроив большой полу-эллипсоид до полного (зеркальная симметрия). Малый полуэллипсоид, наверное, можно тоже убрать, так как неточечность тел приведёт к тому, что фотоны будут летать хаотично и заполнят всё пространство более-менее равномерно, и все эти фокусы-шмокусы не будут играть особой роли.

Вы еще больше упростите — 2 тела в полностью зеркальном шаре, поделенном пополам односторонним зеркалом (с одной стороны отражает много фотонов, с другой — мало. Остальное — пропускает). Тела по разную сторону от перегородки. Эффект такой же: излучение от одного тела передается другому более интенсивно, чем в обратную сторону.


Тут форма зеркал, тел и их положение уже неважны. Из допущений только идеальные зеркала и полу-зеркало, которые ни единого фотона не поглощают.

поделенном пополам односторонним зеркалом (с одной стороны отражает много фотонов, с другой — мало. Остальное — пропускает).

Демон Максвелла, что-ли? :)


Вы можете такое устроить только для фотонов строго определённой длины волны, приходящих со строго определённого направления, но не для всего спектра излучения чёрного тела приходящего со всех направлений.

Таких односторонних зеркал, отражающих с одной стороны и пропускающих с другой, нет в природе, и их существование нарушило бы второй закон термодинамики. Это фактически демон Максвелла.


Если вы имели в виду зеркало Гезелла, через которое следователи в кино наблюдают за допросом, оставаясь невидимыми для допрашиваемого, то это обычное полупрозрачное зеркало, одинаково отражающее в обе стороны.

Я не уловил — что именно в указанной задаче вы моделируете белым телом внутри чёрного? А и Б — оба чёрные, и они внутри белого (зеркального эллипсоида).

Белое тело — тело А + зеркало, чёрное — тело Б. Мы же хотим добиться перекачки энергии из А в Б, нет?


Зеркала действительно просто запутывают.

Именно. Перекачка энергии из А в Б возможна только если температура зеркала ниже температуры в точке А.

Белое тело — тело А + зеркало

Если в зеркальную полость с излучением внести чёрное тело, оно войдёт в равновесие с излучением (даже если излучение изначально было неравновесным), и эта система никак не станет белым телом. Это вроде бы ещё Планк показал.


Мы же хотим добиться перекачки энергии из А в Б, нет?

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


Перекачка энергии из А в Б возможна только если температура зеркала ниже температуры в точке А.

Опять непонятно. Температура всех зеркал — ровно ноль градусов (или миллион, это неважно, так как мы их принимаем за идеальные, а раз они всё отражают, то значит ничего не поглощают и не излучают). Это никак не влияет на перекачку энергии.


И у нас нет точки А, а есть тело А ненулевых размеров, потому что точка нулевой площади излучала бы ровно ноль энергии, согласно формуле теплового излучения.

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

не позволит. Тут работа совершается при изменении конфигурации зеркал. Таким же макаром можно собрать вечный двигатель из магнитов. Все что надо делать, это периодически переворачивать магнит на сердечнике, что бы двигатель продолжал крутится.

Т.е. на тела А и Б действует сила со стороны излучения?


Если мы начнём перемещать тело А вплотную к телу Б, и поставим оба тела симметрично относительно оси симметрии зеркал, так что облучаться они будут симметрично, совершим мы при этом работу?

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

Ну как же нет? А я привёл в пример солнечную электростанцию. Берём тело некоторого размера с температурой 6000K, например, Солнце. Берём систему зеркал и фокусируем свет в какой-нибудь точке меньшего размера, получая температуру выше 6000K.


Опять непонятно. Температура всех зеркал — ровно ноль градусов (или миллион, это неважно, так как мы их принимаем за идеальные, а раз они всё отражают, то значит ничего не поглощают и не излучают). Это никак не влияет на перекачку энергии.

А это как раз важно. Зеркало тоже имеет тепловое излучение. Если зеркало горячее — оно будет отдавать тепло находящимся внутри него телам. Если оно холодное — оно будет отражать лучи, перекачивая энергию, при это само зеркало будет нагреваться. И так до тех пор, пока система не войдёт в равновесие.


А не нагреваться зеркало не может, потому что существование идеальных отражателей противоречит физическим законам. Если какое-то тело что-то излучает, то оно должно поглощать волны той же длины, иначе получается демон Максвела. Идеальными отражателями могут быть только тела нулевой температуры, но их не существует (впрочем, возможны варианты на квантовом уровне).

Берём систему зеркал и фокусируем свет в какой-нибудь точке меньшего размера, получая температуру выше 6000K.

Не выйдет — тело нагреется до 6000К и начнёт излучать навстречу зеркалам (и Солнцу) точно с такой же плотностью излучения, и всё придёт в равновесие. Зеркала не меняют спектр излучения, поэтому как был пик на 6000К, так и останется.


существование идеальных отражателей противоречит физическим законам. Если какое-то тело что-то излучает, то оно должно поглощать волны той же длины, иначе получается демон Максвела.

Нет тут противоречия, отражение и собственное излучение — это разные процессы. Если зеркало отражает 100%, то оно ничего не излучает и ничего не поглощает. Неидеальное зеркало можно заменить моделью из слегка полупрозрачного зеркала, нанесённого на чёрный материал, система получается неизолированной, так как зеркала будут излучать наружу своей наружней поверхностью, будет утечка. Если принять поток утечки много меньшим, чем поток обмена энергией между телами А и Б, то нас он не должен сильно интересовать, какое-то равновесие должно быть достигнуто раньше, чем утечка что-то изменит.

Обратно фотоны не вернутся простым путем через 2 отражения в точку В, так как должно быть 90 градусов угол в нижнем углу, а там изза скругления он не равен 90. Второй эффект в том, что объекты неточечные и свет не ходит простыми путями. Есть куча нелинейных эффектов, связанная с волновой природой света.

Могу ошибаться, но засада состоит в том, что по условиям задачи А и Б стоят в фокальных точках конфокальных зеркал, без указания к какому именно зеркалу фокус относится (к близлежащему или удалённому), но это и не так интересно. Ошибка состоит в том, что находясь в фокусе зеркала фотоны падая на него должны идти паралельно оптической оси, а так как А и Б на ней лежат (согласно рисунку), то условие все фотоны из А попадаю в Б не выполняется.

Вы свойства параболы и эллипса не спутали? Любой фотон из одного фокуса эллипса всегда попадает в другой фокус.

А нет никакой засады. Да, в замкнутой системе тело В будет горячее, чем тело А — это глупо отрицать. До бесконечности этот процесс идти не может, т.к. чем горячее тело, тем больше энергии оно испускает, поэтому рано или поздно наступит равновесие.


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

Думаете, невзлетит?
Ну, давайте по-новой.


Бегущая навстречу дорожка за счёт вязкости воздуха создаёт встречный ветер.
Тяга двигателей тоже создаёт встречный ветер.
Поэтому, даже если через трение качения удалось обездвижить самолёт в горизонтальном направлении, подъёмная сила всё равно будет.
И, чем больше разгружается шасси, тем большую скорость придётся развивать дорожке, создавая ещё больший ветер.


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

А второе начало термодинамики вообще доказано? Я слышал такое утверждение, что второе начало — это никакой не закон, а лишь статистическая закономерность, не более строгая, чем "грязь обычно переходит от грязных вещей к чистым". Я долго пытался найти в интернете доказательство или опровержение этого высказывания, но ничего достаточно убедительного так и не нашёл. Вот к примеру первое начало доказано теоремой Нётер, а второе чем?

Физические законы (если они внутренне непротиворечивы) не доказываются. Ставятся эксперименты с целью обнаружить нарушения закона.


Второе начало — это, в общем, утверждение, что замкнутые системы эволюционируют в сторону более вероятных макросостояний. И наблюдения показывают, что — да, действительно эволюционируют именно в этом направлении.

Эээ, вот если бы автор комментария предоставил мне таблицу с данными реального эксперимента, то я бы принял такой аргумент. Но здесь абстрактное изображение, математическая модель, в которой свет, зеркала и эллипсы идеальны. Как только вместо реального мира мы имеем дело с математической моделью, мы попадаем в область строгой математики, а не физики.
Смотрите, рассмотрим систему следующую аксиом:
1. скорость излучения фотонов телом прямо пропорциональна температуре тела
2. фотоны излучаются телом в случайном направлении, с равномерной плотностью распределения по всем направлениям
3. Пусть для простоты все массы единичные, а тела неподвижные, и поэтому энергия тела = температура тела.
4. Когда фотон излучается, он забирает 1 единицу энергии, а когда поглощается он отдаёт 1 единицу энергии в то тело, которое его поглатило.
5. Зеркала отражают фотоны по правилу угол падения равен углу отражения.

Это — строгая математическая система. В ней второе начало термодинамики можно либо доказать, либо опровергнуть (либо это один из тех редких случаев, когда невозможно ни доказать ни опровергнуть из-за теоремы Гёделя о неполноте, но такое бывает крайне редко).
Если из данной аксиоматики не следует второе начало термодинамики, то никакого парадокса и нет, и в этой аксиоматике одно из тел действительно станет теплее другого.
Можно возразить, что данная аксиоматика недостаточно точно отражает реальный мир для решения поставленной задачи, но тогда это не загадка на логику, а тема для диссертации.

Не хватает дополнительного условия:
 6. Фотоны излучаются поверхностью тела. Излучение пропорционально площади поверхности и равномерно распределяется по ней.
Тогда доказательство получается достаточно простое.

https://habr.com/ru/post/463957/#comment_20535187 — закон сохранения геометрического фактора. Ни одно из тел не сможет нагреть другое.


Можно возразить, что данная аксиоматика недостаточно точно отражает реальный мир для решения поставленной задачи, но тогда это не загадка на логику, а тема для диссертации.

Если добавить условие точечности тел (чтобы фотоны не промахивались мимо фокусов), то получим явно нефизическую систему, так как точечные тела с ненулевой массой/энергией будут окружены сферой Шварцшильда, и излучать будет уже она.

Так и есть. Насколько я понял, учёные до сих пор не могут полностью доказать, выполяется ли второй закон термодинамики на квантовом уровне или нет.

Могу предположить, что не перезвонили из-за того, что ожидали написание программы на бумаге.
Иногда собеседование — это просто собеседование.
HR'ы делают вид, что работают, набирая десятки резюме для конкурса, в которых победитель известен заранее, а количество интервью нужно только для отчетов и премий.
Кандидаты уже имеют хорошую работу, но периодически ходят на собеседования для поддержки знаний в тонусе, поднятие скила.

Ну вот… очередной кандидат завалил простейший тест. ИТ вырождается. Нынче нормального спеца не найти.

И не говорите. А потом эти же кандидаты вопрошают, нужно ли высшее образование для ИТ.

Я бы тоже не взял вас на работу. У каждой задачи есть область решений, приведу пример. Где-то в 6 классе я в решении квадратного уравнения написал ответ в виде комплексных чисел (в поле действительных корней не было). И потом с чувством всезнайства доказывал учительнице, что я прав. Формально — да. Фактически — это была задача на проверку конкретного набора знаний, и в этих рамках правильный ответ: корней нет. Да, можно презирать рамки и лететь в бескрайние просторы разума. Вот только я кучу времени от урока потратил на споры, вреда от того умничания было больше, чем пользы. Также и здесь: вопросы собеседования нужны для проверки знаний в области структур данных и алгоритмов. Это набор решений, применяемых в индустрии. В том числе это важно для того, чтобы ваше решение было понятно коллегам. Да, от этого отдаёт некой обыденностью, но 90% повседневных задач программиста базируются на уже известных алгоритмах и подходах. Из кубиков складывается домик. Вы приходите и приносите свои круглые кубики, понятные далеко не всем, и как бы удивляетесь, а что не так. Это высокомерно, а попросту говоря «понт».
Ещё один пример. Был у меня на работе такой же коллега, знает всё, на каждую задачу выдавал крутые презентации с кучей формул, алгоритмов, мозг! Только вот в итоге он не довёл ни одной задачи до конца, и был уволен. Он просто тонул в сложности своих же решений, деталях, там где нужно было просто взять и сделать. Его «правильное» и очень продвинутое решение занимало слишком много времени, его тяжело было поддерживать всем остальным, т.е. человек жил в своей, удобной ему реальности.

Где-то в 6 классе я в решении квадратного уравнения написал ответ в виде комплексных чисел (в поле действительных корней не было). И потом с чувством всезнайства доказывал учительнице, что я прав.

Я надеюсь, что учительница все же знала, что такие числа существуют?


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

Значит не такой уж и "мозг". Мозг — это способность балансирования между знаниями и практичностью.

Фактически — это была задача на проверку конкретного набора знаний, и в этих рамках правильный ответ: корней нет.

Ну так вы это и показали: действительных корней нет.


Ещё один пример. Был у меня на работе такой же коллега, знает всё, на каждую задачу выдавал крутые презентации с кучей формул, алгоритмов, мозг! Только вот в итоге он не довёл ни одной задачи до конца, и был уволен. Он просто тонул в сложности своих же решений, деталях, там где нужно было просто взять и сделать. Его «правильное» и очень продвинутое решение занимало слишком много времени, его тяжело было поддерживать всем остальным, т.е. человек жил в своей, удобной ему реальности.

Ну вот, думается, уволен он не потому, что формулы-алгоритмы, а потому, что тонул и не успевал. Первично таки второе.

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


Возможно, вы на столько круты, что разгон не нуждаетесь, но большинство кандидатов нервничают. Собеседование — это стресс для людей.


Или вы изначально не очень заинтересовались данной вакансией, или вас все устраивает в вашей текущей работе, а пошли скорее для внутренней галочки. И тд.
Возможно, если бы это была компания, в которую вы хотели годами, с предложением на 20-30 процентов больше от вашей текущей зарплаты, с великолепными бонусами(от наши кофе леди принесут вам свежевыжатый смузи на экологически чистых фруктах и не тяжёлой воде по утрам, до наш эксклюзивный шеф-повар приготовит авторский ужин), в шаговой доступности от дома. Ну или возможностью работать удаленно, не знаю, о чем вы там мечтаете. В команду с Тим лидом, книги которого читаете и в душе считаете кумиром. Вы бы повели себя несколько иначе на собеседовании.

вы рассуждаете таким образом только потому что сами не в состоянии оценить уровень знаний интервьюируемого(как, собственно, и сам интервьюер в рассказе). Это словно мало что понимающие и ограниченные школьники, собеседующие взрослого и умного человека, которым непонятно о чем им говорят, ввиду чего и нанять они способны только такого же школьника, не более, потому и вся команда у них состоит из таковых. Брать или не брать на работу специалиста определенного уровня познаний и навыков — решение конечно за работодателем, кому-то нужны спецы, а кому-то команда посредственным кодеров, зато умеющих между собой взаимодействовать. Только правда в том, что зачастую работодатель ввиду собственной ограниченности считает, что набирает команду неплохих разработчиков, а на деле это совершенно не так. Потому что оценивать должен тот, кто на голову превосходит испытуемого, а не просто а-ля «психолог-кодер», который вообще не понимает о чем речь идет(причем ни в коде, ни в психологии)
непонятно, почему вы считаете хороших специалистов, которые умеют решать бизнес задачи и писать отличный код ограниченными школьниками?

Далеко не на каждой работе нужна продвинутая математика, и это никак не ставит человека выше или ниже социально. Востребованность в определенной области нужна там, где она нужна, а не везде. И если «оверинженеринг» не требуется — он просто не требуется. Не нужно обвешивать ярлыками типа «говноработа, посредственные кодеры, ограниченность» и так далее.

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