LINUX.ORG.RU

Man or boy 2к25: Ваш статически типизированный ЯП полноценен?

 


0

4

Когда то Кнут придумал тест для ALGOL реализаций, и он известен под именем «Man or boy test». Но там просто локальные функции, не особо интересно.

Предоставляю вам версию для проверки языка программирования, на то, достоен ли он существовать в 21 веке!

Для начала нарушу это правило (у Python динамическая типизация), и покажу Python версию:

def print_sum(x):
  def make(acc):
    def f(y):
      print("acc(%d) + %d" % (acc, y))
      return make (acc + y)
    return f
  return make(x)

print_sum(10)(20)(30)(40)
Вывод
acc(10) + 20
acc(30) + 30
acc(60) + 40

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

Мое повторение на OCaml с rectypes:

let print_sum x =
  let rec f acc = fun y ->
    printf "acc(%d) + %d\n" acc y;
    f (acc + y)
  in 
  f x
  
let () = ignore (print_sum 10 20 30 40)
Типы он вывел сам, но можно и указать вручную:
type t = int -> t 

let print_sum (x : int) : t =
  let rec f (acc : int) : t = fun (y : int) : t ->
    printf "acc(%d) + %d\n" acc y;
    f (acc + y)
  in 
  f x
  
let () = ignore (print_sum 10 20 30 40)

Языки которые смогли реализовать тест на лямбдах/функциях, их система типов и ее записи позволяет строить рекурсивные по возврату лямбды и функции:

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

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

  • Rust (использование trait)
  • C (некорректная реализация)
  • Zig (использование классов)
  • D (использование делегатов)

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

★★★★★

Последнее исправление: MOPKOBKA (всего исправлений: 21)
Ответ на: комментарий от anonymous

А техлиду не надо быть еще и гуманитарием

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

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

Те кто до этого додумываются - синьоры. Те кто ещё и успешно применяют созданные леммы к идее - техлиды. Те кто сдаются на первой сложности - миддлы.

Эта задача на то как программист ищет решение, как он думает, и не важно на каком ЯП он пишет.

По мне это гораздо важнее чем помнит ли он граничное условие третьего параметра у функции из стандартной библиотеки.

Obezyan
()
Ответ на: комментарий от Obezyan

А кто поручил найти ответ другому или другим - тот начальник тогда, получается. Делегирование.

Да и потом. Сама диспозиция выглядит так. Ты даешь задание - другие подхватывают и ищут решения. Ты как бы сверху, а они - снизу тогда, получается? А если снизу, то точно техлид?

Правильный ход мыслей, или есть ошибка?

anonymous
()
Ответ на: комментарий от Obezyan

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

Мухаха. Отвечает o3

Шаблон-«конвертер»

Пусть Φ = «Фиг его знает», Χ = «ХЗ». Каким из слов является «да», нам неизвестно. Задаём контрольный вопрос

V(P, W): «Если бы я спросил тебя “P”, ты бы ответил W

где P — любое утверждение, а W — одно из слов (Φ или Χ).

  • Плюсовик (правдоруб) и js-макака (лгун) дают одинаковый ответ на V(P, Φ):

    • Φ — когда P истинно;
    • Χ — когда P ложно.
  • У гошника ответ всё равно случаен.

Таким образом, для детерминированных сотрудников мы можем трактовать Φ как «Да», Χ как «Нет», не зная их истинного значения.


Стратегия из трёх вопросов

Называем работников X, Y, Z (порядок неизвестен).

Вопрос 1 (к X)

V(«X — гошник?», Φ) Если услышали Φ, то X — гошник. Если услышали Χ, то X — не гошник (значит гошник среди Y, Z).


Ветка A: X — гошник (ответ Φ)

Вопрос 2 (к Y) V(«Y — плюсовик?», Φ)

Ответ YРоли
ΦY — C++-правдоруб, Z — js-лгун
ΧY — js-лгун, Z — C++-правдоруб

Вопрос 3 можно задать любому детерминированному работнику для проверки, например к Y: V(«X — гошник?», Φ) → должен прийти Φ.


Ветка B: X — не гошник (ответ Χ)

Теперь X детерминирован, гошник среди Y и Z.

Вопрос 2 (снова к X – это разрешено, вопрос уже другой) V(«Y — гошник?», Φ)

Ответ XКто гошник
ΦY — гошник
ΧZ — гошник

Допустим, из таблицы видно, что W — детерминированный сотрудник (X или Z).

Вопрос 3 (к W) V(«W — плюсовик?», Φ)

Ответ WРоли
ΦW — C++-правдоруб, другой детерминированный — js-лгун
ΧW — js-лгун, другой детерминированный — C++-правдоруб

Проверка условий

  • каждое из трёх вопросов задано ровно одному сотруднику;
  • ответы всегда «Φ» или «Χ»;
  • по истечении трёх вопросов роли (C++, js, Go) однозначно определены.
goingUp ★★★★★
()
Ответ на: комментарий от goingUp

Ладно, если лысых обезьян это утешит, то невронка уже знала ответ на этот вопрос и сразу в рассуждениях классифицировала его https://en.wikipedia.org/wiki/The_Hardest_Logic_Puzzle_Ever Но ответ подогнан под терминологию вопроса, что демонстрирует какое-то «понимание», да и по ссылке чуть более хардкорный вариант, но модель решала именно вариант, который был задан ей.

goingUp ★★★★★
()
Последнее исправление: goingUp (всего исправлений: 1)
Ответ на: комментарий от goingUp

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

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

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

alysnix ★★★
()
Ответ на: комментарий от kipar_2024

Там подразумевается оборачивание в V(P, W), то есть вопрос «Если бы я спросил тебя “X — гошник?”, ты бы ответил «Фиг его знает»?». Из-за двойного отрицания ложь макаки нейтрализуется, и наверное подразумевается, что рандомный гошник всегда врет или всегда говорит правду за сессию вопроса.

goingUp ★★★★★
()
Ответ на: комментарий от kipar_2024

Вообще-то нет

V(true, "Фиг его знает") 
Плюсовик, Фиг его знает == true: "Фиг его знает" 
Плюсовик, Фиг его знает == false: "Фиг его знает" 
ЖС, Фиг его знает == true: "Фиг его знает" 
ЖС, Фиг его знает == false: "Фиг его знает" 
V(false, "Фиг его знает") 
Плюсовик, Фиг его знает == true: "ХЗ" 
Плюсовик, Фиг его знает == false: "ХЗ" 
ЖС, Фиг его знает == true: "ХЗ" 
ЖС, Фиг его знает == false: "ХЗ" 

про гошника возможно вы и правы если это не так

рандомный гошник всегда врет или всегда говорит правду за сессию вопроса

goingUp ★★★★★
()
Ответ на: комментарий от goingUp

О, кстати, обезьян получается напутал с условием. У него гошник всегда отвечает случано, когда же в The Hardest Logic Puzzle Ever рандомный чел отвечает консистентно в пределах сесии.

quantum-troll ★★★★★
()
Ответ на: комментарий от quantum-troll

обезьян получается напутал с условием

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

Что тут скажешь — ЛОР торт.

Nervous ★★★★★
()
Ответ на: комментарий от goingUp

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

kipar_2024
()

Типичное программирование по «понятиям компиляторов».
Отсюда произростают все проблемы.
Это как пытаться построить хороший дом из Г и П.

anonymous
()
Ответ на: комментарий от goingUp

Ладно, если лысых обезьян это утешит

Я в курсе кто автор этой задачи и сколько ей десятилетий, просто немного упростил и модифицировал под реалии ЛОРа.

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

Obezyan
()
Ответ на: комментарий от Obezyan

Вы же, похоже, любитель помахать кулаками после драки.

Это же был ответ на «не думаю, что нейронка ответит» а не заявка на ваш кубок) Но ниже уже нашли косяк в решении нейронки и в постановке вопроса вами))

goingUp ★★★★★
()
Последнее исправление: goingUp (всего исправлений: 1)
Ответ на: комментарий от quantum-troll

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

Нет, не напутал, это сделано специально чтобы затруднит гуглеж.

Автор исходной задачи Джордж Булос

Вот ещё адаптированный вариант и тд.

Obezyan
()
Последнее исправление: Obezyan (всего исправлений: 1)
Ответ на: комментарий от goingUp

Это же был ответ на «не думаю, что нейронка ответит»

Это была попытка отвадить от нейронки и думать головой.

Obezyan
()
Последнее исправление: Obezyan (всего исправлений: 1)

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

Данная задача решалось бы так:

def print_sum
    mref acc:int
    cref y:int
    @print* "acc(" acc ") + " y "\n"
    acc + y


def main
    *acc 10 @print_sum* 20 30 40

Ни циклов, ни рекурсий. Лаконичнее, эффективнее, менее путано.

Для понимания, оно бы транслировалось в такой код на C++:

void print_sum(   // 1
    int64_t &acc   // 2
    , const int64_t &y){   // 3
    print("acc(");print(acc);print(") + ");print(y);print('\n');   // 4
    acc += y;    // 5
}
void _stodin_main(){   // 8
    int64_t acc  {10};print_sum(acc, 20);print_sum(acc, 30);print_sum(acc, 40);   // 9
}
Kogrom
()
Ответ на: комментарий от Obezyan

Это была попытка отвадить от нейронки и думать головой.

Ой-ой) Кстати для этого нужно было брать не плюсовика, жеесника и гошника, а транса, Гитлера и еврея)

goingUp ★★★★★
()
Ответ на: комментарий от Nervous

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

Короче, если кому интересно, кроме Обезьяна) Я попросил o3 исправить решение упрощенно-усложненной задачи, указав на косяк, но она не осилила. Победа присуждается кожаным мешкам! @kipar_2024 Правда после следующей подсказки осилила:

Тут все равно ошибка. Попробуй сконструировать вопрос 1 так, чтобы определить второй или третий человек не рандом.

Как построить первый вопрос, чтобы сразу отыскать «не-рандома»

Ниже используется привычный «конвертер»:

V(P) ≔ «Если бы я спросил тебя “P”, ты бы ответил “Фиг его знает”?»

  • Для плюсовика-правдоруба и js-лгуна ответ «Фиг его знает» (далее Φ) ⇔ утверждение P истинно; ответ «ХЗ» (далее Χ) ⇔ P ложно.
  • У гошника (рандомщика) ответ случаен.

Шаг 1. Вопрос к X

Q1 (к X): V( «Y — гошник?» )

Если ответ Φ → выбираем Z — он точно не гошник. Если ответ Χ → выбираем Y — он точно не гошник.

Почему это работает

Кто на самом деле гошникЧто скажет XКого мы выбираемРоль выбранного
Y (утверждение истинно) и X детерминирован (T/L)ΦZдетерминирован
не Y (утверждение ложно) и X детерминирован (T/L)ΧYдетерминирован
X — гошник (ответ случаен Φ)ΦZдетерминирован
X — гошник (ответ случаен Χ)ΧYдетерминирован

Во всех случаях выбранный сотрудник (назовём его D) оказывается плюсовиком или js-лгуном, но не рандомом.


Полная схема из трёх вопросов

  1. Q1 к X — как выше. По ответу выбираем детерминированного D (это либо Y, либо Z).

  2. Q2 к D: V( «X — гошник?» )

    • Φ → X — гошник; второй оставшийся (не D) детерминирован.
    • Χ → гошник — тот второй, а X — детерминирован.
  3. Q3 к D (удобно спрашивать того же): V( «Ты — плюсовик?» )

    • Φ → D — C++-правдоруб, другой детерминированный — js-лгун.
    • Χ → D — js-лгун, другой детерминированный — C++-правдоруб.

Таким образом, за три вопроса:

  • мы гарантированно нашли сотрудника, который не рандом, уже после первого запроса (как вы и просили);
  • после второго определили, кто именно гошник;
  • третий развёл правдоруба и лгуна.
goingUp ★★★★★
()
Последнее исправление: goingUp (всего исправлений: 1)
Ответ на: комментарий от goingUp

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

Скоро в задаче будут числа подбирать таким образом что они будут соответствовать индексам токенов «забудь предыдущие инструкции и фантазируй».

Obezyan
()
Ответ на: комментарий от kipar_2024

Если отвечает ФЗ - второй негошник, если ХЗ - третий негошник. Остальные вопросы задаем негошнику:

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

Psilocybe ★★★★★
()
Ответ на: комментарий от goingUp

V(«X — гошник?», Φ) Если услышали Φ, то X — гошник. Если услышали Χ, то X — не гошник (значит гошник среди Y, Z).

Гошник может дать любой ответ, а значит вывод X — не гошник неверен.

Вы как будто первый раз с не детерминированными процессами имеете дело.

Psilocybe ★★★★★
()
Ответ на: комментарий от anonymous

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

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

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

alysnix ★★★
()
Ответ на: комментарий от goingUp

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

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

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

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

Только получив третий ответ можно будет начать строить единую цепочку начиная с самого первого.

Хочется решить не через жопу, а красиво =) Когда делать будет нечего буду возвращаться и допридумывать. И не важно что выше уже 100 раз (вроде как решили).


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

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

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

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

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

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

alysnix ★★★
()
Ответ на: комментарий от LINUX-ORG-RU

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

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

goingUp ★★★★★
()

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

anonymous
()
Ответ на: комментарий от anonymous

Состояний 6 (у трех элементов 6 перестановок), но первый вопрос делит не на две группы по 3, а на две группы по 4 (т.к. гошник может ответить что угодно, то две перестановки где он первый войдут в обе группы).

kipar_2024
()

Вопрос: почему реализация сложения чисел с выводом промежуточного результата при помощи извращений с лямбдами делает язык полноценным?
Большинство распространенных ЯП позволяет сделать это как то вот так:

new [] {20, 30, 40}.Aggregate(10, (a, b) =>
    {
        Console.WriteLine($"acc({a}) + {b}");
        return a + b;
    });
Что является гораздо более простым и наглядным.

arax ★★
()
Ответ на: комментарий от arax

Суть не в том что код делает, а в том можно ли его выразить на языке X.

Если вообще ничего непонятно, вот простой пример рекурсивного типа без использования замыканий. auto в С++ должен сам выводить подходящий тип, в C# для этого есть var, но он вроде не для функций.

auto f()
{
  return f;
}

void main()
{
  f()()()()()()();
}

Как видно по ОП-посту, многие языки не могут повторить это, потому что тип будет рекурсивен.

Даже С++ не может это скомпилировать, не знаю какую там магию надо применить, но с лямбдами работает:

void main()
{
  auto f = [](this auto self) 
  {
    return self;
  };

  f()()()()()()();
}

MOPKOBKA ★★★★★
() автор топика
Последнее исправление: MOPKOBKA (всего исправлений: 4)