Гольф все 16 логических вентилей с 2 ​​входами и 1 выходом!


63

Например, вентиль A and Bпредставляет собой логический вентиль с 2 входами и 1 выходом.

Их ровно 16, потому что:

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

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

Ваши функции / программы должны быть независимыми .

Они действительны до тех пор, пока они выводят значения true / falsey, что означает, что вы можете реализовать их A or Bв Python как lambda a,b:a+b, даже если они 2созданы для A=Trueи B=True.

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

Список логических ворот

  1. 0,0,0,0 ( false)
  2. 0,0,0,1 ( and)
  3. 0,0,1,0 ( A and not B)
  4. 0,0,1,1 ( A)
  5. 0,1,0,0 ( not A and B)
  6. 0,1,0,1 ( B)
  7. 0,1,1,0 ( xor)
  8. 0,1,1,1 ( or)
  9. 1,0,0,0 ( nor)
  10. 1,0,0,1 ( xnor)
  11. 1,0,1,0 ( not B)
  12. 1,0,1,1 ( B implies A)
  13. 1,1,0,0 ( not A)
  14. 1,1,0,1 ( A implies B)
  15. 1,1,1,0 ( nand)
  16. 1,1,1,1 ( true)

Если первое число является выходом для A=false, B=false, второе число является выходом для A=false, B=true, третье число является выходом для A=true, B=false, четвертое число является выходом для A=true, B=true.

Leaderboard


2
Ваши функции / программы могут делиться кодом. Что это значит? Кроме того, программы могут быть на разных языках?
Линн

2
Меня смущает объяснение: «из 4 возможных входов каждый может иметь и вывод правдивых и ложных». Разве это не означает 8 (4 * 2) состояний?
DavidC

4
Имена, которые вы пропускаете, - это ворота И-НЕ (А И НЕ В и В И НЕ А).
Mego

14
Так и случилось снова. Есть 18 ответов, в основном простые и правильные, тогда из ниоткуда вопрос стал «непонятным, о чем ты спрашиваешь». Если тебе не нравится вызов, продолжай, возьми другой, не закрывай его!
edc65

4
@dorukayhan См .: пустая правда
Sp3000

Ответы:


110

Домино , 122 000 байт или 72 тайла

Количество байтов - это размер сохраненного файла, который есть 0.122 MB.

Вычисление Domino было вдохновением. Я проверил все это вплоть до симметрии (и даже дальше!) В виртуальной реальности Steam-игре под названием Tabletop Simulator .

подробности

  • I / O
    • Начало - это включено для ясности (не учитывается в общем) и является тем, что «вызывает» или «выполняет» функцию. Должен быть «нажат» после ввода [Желтого] .
    • Вход A - Это включено для ясности (не в счет к общему количеству) и «нажато» для обозначения a 1и не нажато в противном случае [Зеленый] .
    • Вход B - Это включено для ясности (не в счет к общему количеству) и «нажато» для обозначения a 1и не нажато в противном случае [Синий] .
    • Вывод - это считается к общему количеству. Именно домино объявляет результат логических ворот [черный] .
  • T / F
    • Падение выходного домино представляет собой результат Trueили1
    • Постоянный выход домино представляет собой результат Falseили0
  • прессование
    • Чтобы ввести или запустить цепочку, возродить металлический мрамор
    • Установите силу подъема на 100%
    • Поднимите мрамор над нужным домино
    • Брось мрамор

введите описание изображения здесь

ворота

  • ложь, 1
    • введите описание изображения здесь
  • и 6 4
    • введите описание изображения здесь
  • А, а не В, 4 3
    • введите описание изображения здесь
  • А, 1
    • введите описание изображения здесь
  • не А а Б, 4 3
    • введите описание изображения здесь
  • Б, 1
    • введите описание изображения здесь
  • xor, 15 11
    • введите описание изображения здесь
  • или 1
    • введите описание изображения здесь
  • ни, 3 2
    • введите описание изображения здесь
  • xnor, 17 13
    • введите описание изображения здесь
  • не B, 2
    • введите описание изображения здесь
  • B подразумевает A, 7 6
    • введите описание изображения здесь
  • не А, 2
    • введите описание изображения здесь
  • А подразумевает Б, 7 6
    • введите описание изображения здесь
  • нанд, 16 15
    • введите описание изображения здесь
    • правда, 1
    • введите описание изображения здесь

TL; DR

Я ждала / хотела бросить вызов домино, и когда я увидела это, я не смогла пройти мимо. Единственная проблема заключалась в том, что, очевидно, никто больше не владеет домино! Так что в конце концов я сдался и купил Дважды двенадцать . Этот набор имеет 91 плитку, что дало мне идею иметь «вызов функции» / старт домино вместо обычного (длительного) метода «временной задержки». Кредит на поворот на 90 градусов принадлежит каналу dominoesdouble07 .

После построения их с физическим домино, было исключено на мета , что действительные решения должны быть цифровыми. Поэтому я воссоздал эти ворота в Tabletop Simulator . К сожалению, TS и реальность не согласуются с физикой домино. Это потребовало от меня добавления 11 домино, но я также сэкономил 8. В целом, виртуальные домино примерно в 150 раз эффективнее в плане сборки и тестирования ( Ctrl+ Z).

Обновить

  • -9 [17-03-13] Укороченныйxor xnor nand
  • [17-03-04] Добавлена ​​ссылка на файл семинара
  • +11 [17-03-03] Добавлены цифровые xnorиxor
  • -8 [17-03-03] Оцифровали все ворота (кроме xorи xnor). Для блокировки на столешнице требуется только 1 домино вместо 2.
  • [16-09-23] Сокращенные изображения
  • -11 [16-09-18] Почти снова разрезать xor пополам. Спасибо @DJMcMayhem за xnor и Джо за xor.
  • -31 [16-08-31] Обновил несколько фото, побрил плитку и разрезал xor пополам
  • [16-08-28] Добавлены картинки

43
+1 Нам нужно больше игры в домино на PPCG
Beta Decay


7
Ух ты. Это один из самых оригинальных ответов, которые я когда-либо видел на этом сайте.
DJMcMayhem

3
Похоже, вы могли бы снять одно домино, если вы сожмете кснора и будете иметь 4 на вершине, а не 5. Но опять же, я вообще не проверял это.
DJMcMayhem

2
Спасибо, что нашли время, чтобы сделать правильный ответ. Однако найти ссылку на исходный файл довольно сложно. Обычно ссылка в шапке ведет на сам язык. Так что я бы связал его с steam игрой, а затем поместил ссылку на фактический «исходный файл» в отдельную, четко обозначенную ссылку где-то в теле ответа.
Мартин Эндер

45

Гексагония , 89 байт

Спасибо FryAmTheEggman за необходимое вдохновение для решения XOR.

0000 !@
0001 ?.|@!
0010 #?#!)@
0011 ?!@
0100 +?|@!?
0101 ??!@
0110 ?<@!!<_\~(
0111 ?<<@!
1000 )\!#?@{
1001 (~?/@#!
1010 ??|@!)
1011 \#??!1@
1100 ?(~!@
1101 ?.|@!)
1110 ?$@#)!<
1111 1!@

Все программы используют 0для false и 1для true.

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

Вышеупомянутое решение находится в пределах 2 байтов оптимальности (я полагаю, если мы не ослабим интерпретацию правдивости / ложности). Я пусть перебор баллотироваться около двух дней по всем программам , которые вписываются в боковой длину 2, то есть до 7 байт (не совсем все программы - я сделал несколько предположений о то , что каждых действительных потребностях программы и что нет действительная программа могла бы иметь). Поиском были найдены решения для 15 из 16 возможных ворот - и зачастую гораздо больше, чем один. Вы можете найти список всех альтернативных решений в этой папке, где я также сгруппировал их по эквивалентному поведению. Те, что я показываю выше, я выбрал, потому что это либо самое простое, либо самое интересное решение, и я добавлю их объяснения завтра.

Что касается 16-го шлюза: XOR - единственный вентиль, который, очевидно, не может быть реализован в 7 байтах. К сожалению, поиск по более крупным программам невозможен с кодом, который у меня есть в настоящее время. Так что XOR нужно было писать от руки. Самая короткая, которую я нашел до сих пор, - это вышеуказанная 10-байтовая программа, основанная на неудачной (но очень близкой) попытке FryAmTheEggman. Возможно, что существует 8-байтовое или 9-байтовое решение, но, кроме этого, все решения действительно должны быть оптимальными.

Пояснения

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

0000: Ложь

Я не думаю, что нам понадобится диаграмма для этого:

 ! @
. . .
 . .

Поскольку вся сетка памяти инициализируется нулями, !просто печатает ноль и @завершает программу.

Это также единственное 2-байтовое решение.

0001: А также

 ? .
| @ !
 . .

Это в основном реализует короткое замыкание . Серая диаграмма ниже показывает начало программы, где читается первый ввод, ?а указатель инструкций (IP) оборачивается в левый угол, где его |отражает зеркало. Теперь угол действует как условный, так что есть два разных пути выполнения в зависимости от значения первого ввода. Красная диаграмма показывает поток управления для A = 0и зеленая диаграмма для A = 1:

я я я

Как вы можете видеть, когда Aесть 0, тогда мы просто распечатываем его и завершаем (помните, что все .они не используются). Но когда Aесть 1, то IP снова пересекает первый ряд, читая Bи печатая его.

Всего существует шестнадцать 5-байтовых решений для этих ворот. Четырнадцать из них, по сути, такие же, как и выше, либо используют >вместо, |либо заменяют .команду, которая фактически не выполняет никаких действий, либо ставят ?во вторую позицию:

?.|@!    .?|@!    ?=|@!    =?|@!    ?_|@!    _?|@!    ?0|@!
?.>@!    .?>@!    ?=>@!    =?>@!    ?_>@!    _?>@!    ?0>@!

И тогда есть два других решения (которые эквивалентны друг другу). Они также реализуют ту же логику короткого замыкания, но пути выполнения немного сумасшедшие (и оставлены в качестве упражнения для читателя):

?<!@|
?<!@<

0010: А а не Б

 # ?
# ! )
 @ .

Это также реализует форму короткого замыкания, но из-за использования #потока управления намного сложнее. #является условным IP-коммутатором. Hexagony фактически поставляется с шестью IP - адресов , помеченных 0к 5, которые начинаются в шести углах сетки, указывая вдоль их по часовой стрелке края (и программа всегда начинается с IP 0). Когда #встречается, текущее значение берется по модулю 6, и поток управления продолжается с соответствующим IP. Я не уверен, какой приступ безумия заставил меня добавить эту функцию, но она, безусловно, допускает некоторые удивительные программы (вроде этой)

Мы будем различать три случая. Когда A = 0, программа довольно проста, потому что значение всегда 0когда #встречается так, что IP-переключение не происходит:

я

#ничего не делает, ?читает A(то есть тоже ничего не делает), #все еще ничего не делает, !печатает 0, )увеличивает его (это важно, иначе IP не будет переходить на третью строку), @завершает программу. Достаточно просто. Теперь давайте рассмотрим случай (A, B) = (1, 0):

я

Красный путь все еще соответствует IP 0, и я добавил зеленый путь для IP 1. Мы видим, что после ?чтения A(на 1этот раз) #переключается на IP, который начинается в верхнем правом углу. Это означает, что ?можете читать B( 0). Теперь )увеличивает это значение до 1такого, что #в левом верхнем углу ничего не происходит, и мы остаемся с IP 1. В !печатает 1и IP обтекает левую диагональ. #по-прежнему ничего не делает и @завершает программу.

Наконец, действительно странный случай, когда оба входа 1:

я

На этот раз второй вход также 1и )увеличивает его до 2. Это означает, что #в левом верхнем углу другой IP-переключатель переключается на IP 2, обозначенный синим цветом. На этом пути мы сначала увеличиваем его до 3(хотя это не имеет значения), а затем передаем ?третий раз. Так как мы теперь нажали EOF (т.е. ввод исчерпан), ?возвращает 0, !печатает это и @завершает программу.

Примечательно, что это единственное 6-байтовое решение для этих ворот.

0011: A

 ? !
@ . .
 . .

Это достаточно просто, и нам не понадобится диаграмма: ?читает A, !печатает, @завершает работу.

Это единственное 3-байтовое решение для этих ворот. (В принципе, это также было бы возможно сделать ,;@, но поиск не включал ;, потому что я не думаю, что он когда-либо сможет сэкономить байты !для этой задачи.)

0100: B, а не A

 + ?
| @ !
 ? .

Этот намного проще, чем его "брат" 0010. Поток управления фактически такой же, как мы видели выше для 0001(А). Если A = 0, то IP пересекает нижнюю строку, считывая Bи распечатывая ее перед завершением. Если A = 1затем IP снова пересекает первую строку, также считывая B, но +добавляет два неиспользуемых края памяти, все, что он делает, - сбрасывает текущее значение 0, чтобы !всегда печатать 0.

Существует довольно много 6-байтовых альтернатив этому (всего 42). Во-первых, существует масса решений, эквивалентных вышеперечисленным. Мы снова можем свободно выбирать между |и >и +можем быть заменены любой другой командой, которая дает нам пустое ребро:

"?|@!?    &?|@!?    '?|@!?    *?|@!?    +?|@!?    -?|@!?    ^?|@!?    {?|@!?    }?|@!?
"?>@!?    &?>@!?    '?>@!?    *?>@!?    +?>@!?    -?>@!?    ^?>@!?    {?>@!?    }?>@!?

Кроме того, мы также можем использовать ]вместо ?. ]переходит к следующему IP (т.е. выбирает IP 1), так что вместо этого эта ветвь использует ?в правом верхнем углу. Это дает еще 18 решений:

"?|@!]    &?|@!]    '?|@!]    *?|@!]    +?|@!]    -?|@!]    ^?|@!]    {?|@!]    }?|@!]
"?>@!]    &?>@!]    '?>@!]    *?>@!]    +?>@!]    -?>@!]    ^?>@!]    {?>@!]    }?>@!]

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

/[<@!?    ?(#!@]    ?(#>@!    ?/@#/!    [<<@!?    [@$\!?

0101: B

 ? ?
! @ .
 . .

Woohoo, еще один простой: читать A, читать B, печатать B, прекратить. Хотя на самом деле есть альтернативы этому. Поскольку Aэто только один символ, мы также можем прочитать его ,:

,?!@

И есть также возможность использовать одно ?и использовать зеркало, чтобы пройти через него дважды:

?|@!    ?>@!

0110: Xor

  ? < @
 ! ! < _
\ ~ ( . .
 . . . .
  . . .

Как я уже говорил выше, это были единственные ворота, которые не вписывались бы в длину стороны 2, так что это рукописное решение от FryAmTheEggman и меня, и есть большая вероятность, что оно не оптимально. Есть два случая, чтобы различать. Если A = 0поток управления довольно прост (потому что в этом случае нам нужно только напечатать B):

я

Мы начинаем по красной дорожке. ?читает A, <это ветвь, которая отклоняет ноль слева. IP переносится вниз, затем _- другое зеркало, а когда IP попадает в угол, он переносится в верхний левый угол и продолжается по синему пути. ?читает B, !печатает это. Теперь (уменьшает это. Это важно, потому что это гарантирует, что значение не положительное (оно 0или -1сейчас). Это заставляет IP переноситься в правый угол, где @завершается программа.

Когда A = 1все становится немного сложнее. В этом случае мы хотим напечатать not B, что само по себе не так уж сложно, но путь исполнения немного триповый.

я

На этот раз <IP отклоняет право, а затем следующий <просто действует как зеркало. Таким образом, IP пересекает тот же путь в обратном направлении, читая Bпри ?повторном обнаружении IP переходит в правый угол и продолжается по зеленой дорожке. Она следующие встречи , (~которые являются «декремент, умножить на -1», которые свопы 0и 1поэтому рассчитывает not B. \это просто зеркало и !печатает желаемый результат. Затем ?пытается вернуть другое число, но возвращает ноль. IP теперь продолжается в левом нижнем углу на синем пути. (уменьшает, <отражает,(снова уменьшается, так что текущее значение является отрицательным, когда IP достигает угла. Он перемещается по нижней правой диагонали, а затем, наконец, нажимает, @чтобы завершить программу.

0111: Или же

 ? <
< @ !
 . .

Более короткое замыкание.

я я

A = 0Случай (красный контур) немного запутанным здесь. IP отклоняется влево, переносится в нижний левый угол, сразу же отражается <и возвращается ?к чтению B. Затем он заворачивает к rigt углу, печатает Bс !и заканчивается.

A = 1Случай (зеленый путь) немного проще. <Филиал отклоняет IP право, поэтому мы просто напечатать !, завернуть обратно в левом верхнем углу, и заканчиваются в @.

Есть только одно 5-байтовое решение:

\>?@!

Он работает по сути одинаково, но фактические пути выполнения весьма различны и используют угол для ветвления вместо a <.

1000: Ни

 ) \
! # ?
 @ {

Это может быть моя любимая программа, найденная в этом поиске. Самое классное, что эта реализация на norсамом деле работает до 5 входов. Мне придется немного углубиться в детали модели памяти, чтобы объяснить это. Таким образом, для быстрого освежения модель памяти Hexagony представляет собой отдельную шестиугольную сетку, где каждое ребро содержит целочисленное значение (изначально все ноль). Есть указатель памяти (MP), который указывает ребро и направление вдоль этого ребра (так, что есть два соседних ребра перед и за текущим ребром, с значимыми левыми и правыми соседями). Вот диаграмма ребер, которые мы будем использовать, начиная с MP, как показано красным:

я

Давайте сначала рассмотрим случай, когда оба входа 0:

я

Мы начинаем с серого пути, который просто увеличивает ребро A до 1так, чтобы #переключиться на IP, 1который является синим путем, начиная с правого верхнего угла. \ничего не делает там и ?читает вход. Мы переносим в верхний левый угол, где )увеличивается этот вход. Теперь, пока ввод равен нулю, это приведет к 1, так что #ничего не делает. Затем {перемещает MP влево, то есть на первой итерации от к B . Так как у этого края все еще есть свой начальный ноль, IP возвращается в верхний правый угол и на новый край памяти. Так что этот цикл будет продолжаться до тех пор, пока он читает нули, перемещая MP вокруг шестиугольника от B?от C до D и так далее. Неважно, ?возвращает ли ноль, потому что это был вход или потому что это был EOF.

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

А что если какой-либо из входов есть 1?

я

Затем ?читает это 1в какой-то момент и )увеличивает его до 2. Это означает, #что теперь снова переключатся IP-адреса, и мы продолжим в правом углу по красной дорожке. ?читает другой ввод (если он есть), который на самом деле не имеет значения, и {перемещается на один край дальше. Это должен быть неиспользуемый фронт, следовательно, он работает до 5 входов. IP переносится в верхний правый угол, где он сразу отражается, и переносится в левый угол. !печатает 0на неиспользованном крае и #переключается обратно на IP 0. Этот IP-адрес все еще находился на #юго-западе (серый путь), поэтому он сразу же нажимает на @и завершает программу.

Всего существует семь 7-байтовых решений для этих ворот. 5 из них работают так же, как это, и просто используют другие команды для перемещения к неиспользуемому краю (и могут ходить по другому шестиугольнику или в другом направлении):

)\!#?@"    )\!#?@'    )\!#?@^    )\!#?@{    )\!#?@}

И есть еще один класс решений, который работает только с двумя входами, но пути выполнения которых на самом деле еще более беспорядочные:

?]!|<)@    ?]!|<1@

1001: Равенство

 ( ~
? / @
 # !

Это также делает очень умным использование условного выбора IP. Нам нужно еще раз различать A = 0и A = 1. В первом случае мы хотим напечатать not B, во втором мы хотим напечатать B. Ибо A = 0мы также различаем два случая B. Давайте начнем с A = B = 0:

я

Мы начинаем на сером пути. (~может быть проигнорировано, IP переносится в левый угол (все еще на сером пути) и читает Aс ?. (уменьшает это, так что мы получаем -1и IP обернуть в левый нижний угол. Теперь, как я уже говорил ранее, #принимает значение по модулю, 6прежде чем выбрать IP, так что значение -1фактически получает IP 5, который начинается в левом углу на красном пути. ?читает B, (уменьшает это так, чтобы мы оставались на IP, 5когда мы #снова нажмем. ~отрицает -1так, что IP переносится в правый нижний угол, печатает 1и завершается.

я

Теперь , если Bэто 1вместо того, чтобы , текущее значение будет , 0когда мы попали #во второй раз, поэтому мы переходим обратно в IP 0( в настоящее время на зеленом пути). Это ударяет ?в третий раз, уступает 0, !печатает это и @заканчивается.

я

Наконец, случай, когда A = 1. На этот раз текущее значение уже равно нулю, когда мы нажимаем #в первый раз, так что это никогда не переключается на IP 5в первую очередь. Мы просто продолжаем немедленно на зеленой тропе. ?теперь не просто дает ноль, а возвращает Bвместо этого. !печатает его и @завершает снова.

Всего есть три 7-байтовых решения для этих ворот. Два других работают очень по-разному (даже друг от друга) и используют еще более странно #. В частности, они читают одно или несколько значений с помощью ,(чтение кода символа вместо целого числа), а затем используют это значение по модулю 6, чтобы выбрать IP. Это довольно орешки.

),)#?@!

?~#,~!@

1010: Не B

 ? ?
| @ !
 ) .

Это довольно просто. Путь выполнения - это горизонтальная ветвь, о которой мы уже знали andранее. ??читает, Aа потом сразу B. После отражения в |и разветвления, для B = 0мы выполним нижнюю ветвь, где )увеличивает значение, на 1которое затем печатается !. В верхней ветви (если B = 1) ?просто сбрасывается край, на 0который затем также печатается !.

Для этих ворот есть восемь 6-байтовых программ. Четыре из них в значительной степени одинаковы, используя либо >вместо, |либо 1вместо )(или оба):

??>@!)    ??>@!1    ??|@!)    ??|@!1

Два используют один, ?который используется дважды из-за зеркала. Отрицание тогда происходит, как мы сделали xorс или (~или ~).

?>!)~@    ?>!~(@

И, наконец, два решения используют условный IP-коммутатор, потому что зачем использовать простой способ, если извилистый также работает:

??#)!@    ??#1!@

1011: B подразумевает A

 \ #
? ? !
 1 @

Это использует довольно сложную IP-коммутацию. На A = 1этот раз я начну со случая, потому что это проще:

введите описание изображения здесь

Мы начинаем с серого пути, который читает Aс, ?а затем нажимает на #. Так Aкак 1это переключается на IP 1(зеленый путь). !Сразу печатает того, IP - обертывания в левом верхнем углу, читает B(излишне) и завершает работу .

Когда A = 0все становится немного интереснее. Сначала давайте рассмотрим A = B = 0:

введите описание изображения здесь

На этот раз, #ничего не делает, и мы остаемся на IP 0(красный путь с этого момента). ?читает Bи 1превращает его в 1. После переноса в верхний левый угол мы #снова нажимаем, и в конце концов оказываемся на зеленом пути, и печатаем, 1как и прежде, перед завершением.

Наконец, вот (A, B) = (0, 1)ложный случай:

введите описание изображения здесь

Обратите внимание, что я удалил начальный серый путь для ясности, но программа начинается так же, и мы в конечном итоге на красный путь, как и раньше. Так что на этот раз второй ?возвращается 1. Теперь мы сталкиваемся с 1. На этом этапе важно понять, что на самом деле делают цифры в гексагонии (пока мы использовали их только в нулях): когда встречается цифра, текущее значение умножается на 10, а затем цифра добавляется. Это обычно используется для записи десятичных чисел дословно в исходный код, но это означает, что B = 1на самом деле отображается в значение 11. Поэтому, когда мы нажимаем #, это принимается по модулю, 6чтобы дать, 5и, следовательно, мы переключаемся на IP 5(а не 1как раньше) и продолжаем идти по синему пути. Удары?третий раз возвращает ноль, поэтому !печатает, что, а после еще двух ?, IP оборачивается внизу справа, где программа завершается.

Для этого есть четыре 7-байтовых решения, и все они работают по-разному:

#)/!?@$    <!?_@#1    \#??!1@    |/)#?@!

1100: Не А

 ? (
~ ! @
 . .

Просто простой линейный один: чтение Aс ?, свести на нет с (~, печатать !, оканчиваются @.

Есть одно альтернативное решение, и ~)вместо этого оно отрицает :

?~)!@

1101: A подразумевает B

 ? .
| @ !
 ) .

Это намного проще, чем противоположное значение, о котором мы только что говорили. Это снова одна из тех горизонтальных программ ветвления, например, для and. Если Aесть 0, он просто увеличивается до 1нижней ветви и печатается. В противном случае верхняя ветвь выполняется снова, где ?читает Bи затем !печатает это вместо.

Там в тонну альтернатив здесь (66 решений в целом), в основном за счет свободного выбора эффективных нет-OPS. Для начала мы можем варьировать вышеупомянутое решение теми же способами, что andи мы, и мы также можем выбирать между )и 1:

?.|@!)    .?|@!)    ?=|@!)    =?|@!)    ?_|@!)    _?|@!)    ?0|@!)
?.|@!1    .?|@!1    ?=|@!1    =?|@!1    ?_|@!1    _?|@!1    ?0|@!1
?.>@!)    .?>@!)    ?=>@!)    =?>@!)    ?_>@!)    _?>@!)    ?0>@!)
?.>@!1    .?>@!1    ?=>@!1    =?>@!1    ?_>@!1    _?>@!1    ?0>@!1

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

"?#1!@    &?#1!@    '?#1!@    )?#1!@    *?#1!@    +?#1!@    -?#1!@    .?#1!@    
0?#1!@    1?#1!@    2?#1!@    3?#1!@    4?#1!@    5?#1!@    6?#1!@    7?#1!@    
8?#1!@    9?#1!@    =?#1!@    ^?#1!@    _?#1!@    {?#1!@    }?#1!@

"?#)!@    &?#)!@    '?#)!@              *?#)!@    +?#)!@    -?#)!@    
0?#)!@              2?#)!@              4?#)!@              6?#)!@    
8?#)!@                        ^?#)!@    _?#)!@    {?#)!@    }?#)!@

1110: Nand

 ? $
@ # )
 ! <

Последний сложный. Если вы все еще читаете, вы почти сделали это. :) Давайте посмотрим A = 0сначала:

введите описание изображения здесь

?читает, Aа затем мы ударили $. Это команда перехода (например, Befunge #), которая пропускает следующую инструкцию, чтобы мы не заканчивались на @. Вместо этого IP продолжает в #. Однако , так как Aесть 0, это ничего не делать. )увеличивает его 1так, чтобы IP продолжался по нижнему пути, где 1печатается. В <отклоняет IP - вправо , где он заворачивает к левому углу , и программа завершается.

Далее, когда на входе (A, B) = (1, 0)мы получаем эту ситуацию:

введите описание изображения здесь

Это по сути то же самое , как и раньше , за исключением , что на #мы переходим к IP 1(зеленый путь), но так как Bэто 0мы вернуться к IP , 0когда мы попали #во второй раз (теперь синий путь), где он печатает , 1как и раньше.

Наконец, A = B = 1дело:

введите описание изображения здесь

На этот раз, когда мы #во второй раз, текущее значение все еще 1так, чтобы мы не изменили IP снова. <Отражает это и в третий раз мы попали , ?мы получаем ноль. Следовательно, IP оборачивается внизу слева, где !печатается ноль, и программа заканчивается.

Для этого существует девять 7-байтовых решений. Первая альтернатива просто использует 1вместо ):

?$@#1!<

Тогда есть два решения, которые помогут вам оценить количество IP-коммутаций:

)?#_[!@    1?#_[!@

Это на самом деле поразило меня: интересная часть заключается в том, что IP-переключение можно использовать в качестве условного отсрочки. Языковые правила переключения IP таковы, что текущий IP делает еще один шаг, прежде чем произойдет переключение. Если этот шаг проходит через угол, то текущее значение решает, на какой ветви будет продолжаться IP, если мы когда-нибудь переключимся на него. Именно это происходит, когда ввод A = B = 1. Хотя все это согласуется с тем, как я проектировал язык, я никогда не знал об этом значении спецификации, поэтому приятно, когда мой язык учит меня новым трюкам: D.

Тогда есть третье решение, степень IP-переключения которого еще хуже (хотя он не использует этот отложенный условный эффект):

>?1]#!@

А потом еще один:

?$@#)!<

И затем есть эти четыре эквивалентных решения, которые используют некоторую безусловную IP-коммутацию и вместо этого реализуют всю логику через ответвления и углы:

]<?<@!)    ]<?<@!1    ]|?<@!)    ]|?<@!1

1111: Правда

 1 !
@ . .
 . .

Вы заработали себе что-то простое для конца: установите преимущество 1, напечатайте !, завершите с @. :)

Конечно, есть одна альтернатива:

)!@

Как обычно, все блок-схемы управления созданы с помощью HexagonyColorer Тимви и диаграммы памяти с его EsotericIDE .


9
А-а-а-а-а награда д-ра достается ... (шучу, очевидно, отличный ответ и очень хорошо написано +1)
Bassdrop Cumberwubwubwub

4
Это причина, по которой вы больше не активны в чате ??
Оптимизатор

Вроде поздно, но не могли бы вы добавить ссылку на ваш код перебора?
nedla2004

@ nedla2004 Обычно я их не держу, но это всегда модифицированная версия этого скрипта .
Мартин Эндер

40

APL, 22 20 18 байт

Истинные и ложные записи являются полными программами, а остальные 14 являются функциями. (Спасибо Адаму.)

0000 false              0 (complete program)
0001 p and q            ∧
0010 p and not q        >
0011 p                  ⊣
0100 not p and q        <
0101 q                  ⊢
0110 xor                ≠
0111 p or q             ∨
1000 not p and not q    ⍱
1001 eq                 =
1010 not q              ~⊢
1011 p or not q         ≥
1100 not p              ~⊣
1101 not p or q         ≤
1110 not p or not q     ⍲
1111 true               1 (complete program)

Попробуй это здесь.


1
+1 Хорошее использование atops! Вы можете сохранить два байта, превратив 0000 и 1111 в trad-fns 0и 1.
Адам

Существует консенсус, чтобы разрешить tfns, но не считать первую строку. Это соответствует отсутствию подсчета имени файла в языках, которые используют файлы в качестве контейнеров программ с именем программы = имя файла.
Адам


10
Желе: 19 байт. Это: 18 байт. Разве это не значит, что ты переиграл Денниса ? +1 за это.
NoOneIsHere

29

Шахматист / посредственный шахматист в эндшпиле, 70 штук

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

Обратите внимание, что я взял несколько правил того, как движутся фигуры. Поскольку мне не хочется изучать оптимальные ходы для каждой ситуации, правила для хода белых просты: не поддавайтесь проверке, захватите фигуру с самым высоким рейтингом, которую он может сделать в этот ход, потеряв при этом как можно меньше материала, и остановите пешку. от продвижения в таком порядке приоритета. Если есть два пространства, в которые он может перейти, с одинаковой благоприятностью, он может перейти в любое из них (следовательно, в них, если он может перейти в более чем один квадрат, они одного цвета). Обратите внимание, что белые будут захватывать что-то, даже если они захвачены, если фигура, которую они атакуют, имеет более высокую ценность, чем потерянная. Значения здесь:pawn<knight=bishop<rook<queen

Вход - наличие грача или нет. Обратите внимание, что ладьи помечаются именами A и B, только когда это имеет значение: если ворота ведут себя одинаково, когда ладьи переключаются, они не помечаются.

Вывод цвета квадратного белого короля заканчивается: белый = 1, черный = 0

Перед изображениями я хочу извиниться за плохие изображения. Я не очень хорошо держу камеру устойчиво.

Неверно, 4:

Ложь

И, 4:

введите описание изображения здесь

A, а не B, 5 (я думаю, что могу уменьшить это до трех, но сейчас у меня нет доски):

введите описание изображения здесь

А, 4:

введите описание изображения здесь

Не A и B, 5 (я думаю, я могу уменьшить это до трех, но сейчас у меня нет доски):

введите описание изображения здесь

Б, 4:

введите описание изображения здесь

Xor, 5 (я знаю, как сделать это 4, но у меня сейчас нет доски):

введите описание изображения здесь

Или 4:

введите описание изображения здесь

Ни 4:

введите описание изображения здесь

Xnor, 5 (я знаю, как сделать это 4, но у меня сейчас нет доски):

введите описание изображения здесь

Не B, 4:

введите описание изображения здесь

B подразумевает A, 5 (я думаю, я могу уменьшить это до трех, но сейчас у меня нет доски):

введите описание изображения здесь

Не А, 4:

введите описание изображения здесь

A подразумевает B, 5 (я думаю, я могу уменьшить это до трех, но сейчас у меня нет доски):

введите описание изображения здесь

Нанд, 4:

введите описание изображения здесь

Правда, 4:

введите описание изображения здесь


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

2
хм, у меня сейчас нет доступа к шахматной доске. Я бы, вероятно, сказал, что A подразумевает, что B / B подразумевает, что / / etc труднее всего понять из-за влияния пешек на движение королей. Я, вероятно, должен добавить лучшее объяснение этим двум
Разрушаемый Лимон

Рад вдохновлять: D Если я правильно понимаю, расположение доски и фигуры эквивалентны программе. Ладьи - это входные данные, так что я могу разместить их на любом квадрате до тех пор, пока это правильный цвет?
Нелинейный

Нет, вклад ладей заключается в том, присутствуют они или отсутствуют на доске. Они помечены как a и b, когда они не являются симметричными воротами (когда это имеет значение для различных a и b). Также я понял, как я могу сыграть в гольф на 2 фигуры, но у меня сейчас нет доски. Кисть должна быть использована :)
Разрушаемый Лимон

В случае «И», если вы уберете правую ладью, что мешает королю спуститься вниз (к белому)?
Натан Меррилл

27

Желе , 19 байт

0 0 0 0 ¤  1 byte  Empty niladic chain. Returns default argument 0.
0 0 0 1 &  1 byte  Bitwise AND.
0 0 1 0 >  1 byte  Greater than.
0 0 1 1    0 bytes Empty link. Returns left argument.
0 1 0 0 <  1 byte  Less than.
0 1 0 1 ị  1 byte  At-index (x,y -> [y][x]). Returns right argument.
0 1 1 0 ^  1 byte  Bitwise XOR.
0 1 1 1 |  1 byte  Bitwise OR.
1 0 0 0 |¬ 2 byte  Logical NOT of bitwise OR.
1 0 0 1 =  1 byte  Equals.
1 0 1 0 ¬} 2 bytes Logical NOT of right argument.
1 0 1 1 *  1 byte  Exponentiation.
1 1 0 0 ¬  1 byte  Logical NOT of left argument.
1 1 0 1 >¬ 2 bytes Logical NOT of greater than.
1 1 1 0 &¬ 2 bytes Logical NOT of bitwise AND.
1 1 1 1 !  1 byte  Factorial.

Попробуйте онлайн!


13
Мне нравится использование Factorial для преобразования 0 или 1 в 1.
Нил

Это желе UTF-8? Если да, то ¤и ¬2 байта, а не 1.
Vi.

1
@Vi. Jelly поддерживает UTF-8, но также поддерживает пользовательскую кодовую страницу, которая кодирует каждый из 256 символов, которые он понимает как один байт каждый. В байтах ссылаются в точках заголовка к нему.
Деннис

0 0 1 0 > 1 byte Greater than.не потерпит ли это неудачу, если второй вход будет отрицательным?
MD XF

@MFXF Мы можем выбрать, какую правдивую и какую ложную ценность мы поддерживаем.
Деннис

24

Логические ворота NAND - 31 вентиль

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

введите описание изображения здесь

На каждой из этих диаграмм верхний вход - А, а нижний - Б.


5
@xnor может быть польщен, узнав, что его логические врата - это те, которые требуют большинство ворот NAND, чтобы сделать D:
Джо З.

Не могли бы вы хотя бы использовать Logisim для форматирования своего кода?
mbomb007

1
@ mbomb007 Я отредактирую это позже. Я не так опытен с Logisim, так что это может занять некоторое время.
Джо З.

3
Но почерк мне нравится больше.
Утренняя монахиня

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

22

Побитовая циклическая метка , 118 бит = 14,75 байт

Побитовая циклическая метка, пожалуй, самый простой Turing-Complete язык, когда-либо разработанный. Существует программная лента и лента данных, состоящая из списка битов. Программная лента интерпретируется циклически, пока лента данных не станет пустой, следующим образом:

  • 0: удалить первый бит с ленты данных.
  • 1x: если первый бит ленты данных равен 1, добавьте этот бит xна ленту данных.

Мы инициализируем ленту данных с 1, за которым следуют два входных бита (1 необходим, потому что невозможно создать 1, если лента с данными полностью состоит из 0), и мы используем последний бит удаленных данных в качестве выхода шлюза ,

  • 0,0,0,0 ( false):001
  • 0,0,0,1 ( and):1001001
  • 0,0,1,0 ( A and not B):0110100
  • 0,0,1,1 ( A):1001
  • 0,1,0,0 ( not A and B):0100
  • 0,1,0,1 ( B):0
  • 0,1,1,0 ( xor):0110110010
  • 0,1,1,1 ( or):0110
  • 1,0,0,0 ( nor):1101001000
  • 1,0,0,1 ( xnor):110101001100
  • 1,0,1,0 ( not B):1100100
  • 1,0,1,1 ( B implies A):110101101000
  • 1,1,0,0 ( not A):11010000
  • 1,1,0,1 ( A implies B):11010011001
  • 1,1,1,0 ( nand):10110100100010
  • 1,1,1,1 ( true):1100

Поздравляем!
Утренняя монахиня

Является тянущаяся 1по falseнеобходимости?
CalculatorFeline

@CalculatorFeline Да, нам нужно добавить 0к ленте, чтобы она могла быть удалена последней.
Андерс Касеорг

Ах. Забыл про это + упаковка. Умная!
CalculatorFeline

20

Python 2, 137 байт

[].sort
min
int.__rshift__
round
range
{}.get
cmp
max
lambda a,b:a<1>b
lambda a,b:a==b
lambda a,b:b<1
pow
{0:1,1:0}.get
{0:1}.get
lambda a,b:a+b<2
slice

Принимает данные как min(True,False)(или как min(1,0)). Получает большое преимущество от результатов, требующих только правильного значения Truthy-Falsey. По возможности, используется встроенный, чтобы избежать дорогостоящих lambda. Я использовал код для поиска встроенных модулей, которые работают.

Мой любимый {0:1}.get, о котором я думал вручную. Словарь {0:1}сопоставляет ключ 0со значением 1. Его getметод принимает ключ и значение по умолчанию, выводя значение, соответствующее ключу, или значение по умолчанию, если такого ключа нет. Таким образом, единственный способ вывести a 0- это {0:1}.get(1,0)с отсутствующим ключом 1и значением по умолчанию 0. Можно найти другие варианты с разными словарями, но только этот был самым коротким.

built_in_names = list(__builtins__) 

object_names = ["int","(0)","(1)"] + \
["True","False","0L","1L","0j","1j"] + \
["str", "''", "'0'","'1'","'a'"] + \
["list", "[]", "[0]", "[1]","['']","[[]]","[{}]"] + \
["set","set()","{0}","{1}","{''}"] + \
["dict","{}","{0:0}","{0:1}","{1:0}","{1:1}","{0:0,1:0}", "{0:0,1:1}","{0:1,1:0}","{0:1,1:1}"] + \
["id"]

object_method_names = [object_name+"."+method_name 
for object_name in object_names 
for method_name in dir(eval(object_name))]

additional_func_names = [
"lambda a,b:0",
"lambda a,b:1",
"lambda a,b:a",
"lambda a,b:b",
"lambda a,b:b<1",
"lambda a,b:a<1",
"lambda a,b:a+b",
"lambda a,b:a*b",
"lambda a,b:a==b",
"lambda a,b:a-b",
"lambda a,b:a<=b",
"lambda a,b:a>=b", 
"lambda a,b:a>b", 
"lambda a,b:a<b", 
"lambda a,b:a<1>b", 
"lambda a,b:a+b<2"]

func_names = built_in_names + object_method_names + additional_func_names

t=True
f=False

cases = [(f,f),(f,t),(t,f),(t,t)]

def signature(func):
    table = [bool(func(x,y)) for x,y in cases]
    table_string = ''.join([str(int(val)) for val in table])
    return table_string

d={}

for func_name in func_names:
    try:
        func = eval(func_name) 
        result = signature(func)
        if result not in d or len(func_name)<len(d[result]):
            d[result]=func_name
    except:
        pass

total_length = sum(len(func) for sig,func in d.items())

print total_length
print

for sig in sorted(d):
    print d[sig]

Разве вы не можете использовать методы встроенных функций, таких как int __lt__или __eq__? Это еще больше уменьшит количество байтов: int.__gt__вместо lambda a,b:b<1, int.__eq__вместо lambda a,b:a==bи так далее
Габор Фекете

@ GáborFekete Те, которые не существуют в Python 2, потому что intсравнения разгрузки с cmp. Я не пробовал это для Python 3.
xnor

О, прямо сейчас я вижу!
Габор Фекете

Сохранение 4 байта с помощью функции notдля 0001, False- ideone
Джонатан Аллана

1
@JonathanAllan Это умно, но я думаю, что notэто не соответствует требованиям функции, потому что вы не можете сделать f=not;f(3,4). Строка notработает, потому что предполагаемые аргументы функции выглядят как кортеж, точно так же 3+, как 3+(4)если бы они 3+не работали 4как входные данные.
xnor

20

Go (игра), 33 камня, 73 перекрестка

Если домино и шахматы приемлемы, то это. На полной доске размером 19х19 Го не может быть слишком много гольфа. Поэтому я использовал маленькие прямоугольные доски. Входные данные - присутствуют ли камни, отмеченные 1 и 2. Вывод - победит ли черный. Используется оценка по площади, 0,5 коми, ситуационная суперко, без самоубийств. Все черное, чтобы играть. Некоторым дается несколько решений.

Белые победы (2, 1х5):

➊━━━➋

1 и 2 (3, 2х3):

➊◯➋
┗┷┛

1 а не 2 (2, 1х5):

╺➊━➁╸

1 (2, 1x5):

╺➊➁━╸ 
╺➊━━➁
➀━➁━╸

Не 1 и 2 (2, 1х5):

╺➋━➀╸

2 (2, 1x5):

╺➋➀━╸

1 xor 2 (2, 2x3):

➀┯➁
┗┷┛

1 или 2 (2, 1x5):

╺➊━➋╸
➀━━━➁

1 или 2 (2, 1x4):

➊━━➋
╺➀➁╸

1 = 2 (2, 1x7):

╺━➀━➁━╸

Не 2 (2, 1х3):

➀➁╸

1 или нет 2 (2, 1x4):

➀➁━╸
➀━➁╸
╺➊➁╸
➋➊━╸
➋━➊╸

Не 1 (2, 1x3)

➁➀╸

Не 1 или 2 (2, 1x4):

➁➀━╸

1 и 2 (2, 1x3):

➊━➋

Черные победы (2, 1x3):

➊➋╸
➀━➁
➊━➁

Эта страница мне немного помогла: http://www.mathpuzzle.com/go.html

Может быть, кто-то мог бы найти решение 2 камня для 1 и 2 на доске 1x9 ...


1
Каковы ваши правила самоубийства? Недопустимое? А что происходит, когда одна сторона заполняет всю доску? Это считается самоубийством?
Мартин Эндер

@MartinEnder Запрещено. И да, это считается самоубийством.
jimmy23013

Решение 1х7 казалось неправильным. Я пытаюсь это исправить ...
jimmy23013

15

Javascript ES6, 124 байта

a=>0
Math.min
parseInt
a=>a
a=>b=>a<b
a=>b=>b
a=>b=>a^b
Math.max
a=>b=>~a&~b
a=>b=>a==b
a=>b=>~b
Math.pow
a=>~a
a=>b=>a<=b
a=>b=>~a|~b
a=>1

Я серьезно ненавижу лямбды прямо сейчас.


1
Если мне позволено писать некоторые программы и некоторые функции ... Я думаю , что вы могли бы изменить , a=>b=>0чтобы a=>0и сказать , что грамматика называть это является (a=>0)(a,b)только для тех 4 записей.
jimmy23013

О да, спасибо!
Mama Fun Roll

2
Math.minвместо a=>b=>a&b. Math.maxвместо a=>b=>a|b. Math.powвместо a=>b=>a>=b.
Конор О'Брайен

1
Кроме того, так как NaN фальшивый, вы можете сделать parseIntвместо a=>b=>a>b.
Конор О'Брайен

1
@algmyr !NaN=> true, !!NaN=>false
Мама Ролл

14

Сетчатка , 62 39 байт

23 байта благодаря @MartinEnder !

0000 false              1 byte : 2
0001 p and q            2 bytes: 11
0010 p and not q        2 bytes: 10
0011 p                  2 bytes: ^1
0100 not p and q        2 bytes: 01
0101 q                  2 bytes: 1$
0110 xor                5 bytes: 01|10
0111 p or q             1 byte : 1
1000 not p and not q    2 bytes: 00
1001 xnor               5 bytes: (.)\1
1010 not q              2 bytes: 0$
1011 p or not q         5 bytes: ^1|0$
1100 not p              2 bytes: ^0
1101 not p or q         5 bytes: ^0|1$
1110 not p or not q     1 byte : 0
1111 true               0 bytes: 

Принимает вход как PQ.

Выводит целое число между 0до 3. 0ложь, другие правдивы.

объяснение

Все они просто регулярные выражения .

Например, 01|10просто соответствует 01или 10.

В 0000, 2никогда не будет на входе, поэтому он никогда не совпадает.

В 1111, это соответствует пустой строке, которая есть 4.


^1|0$должен соответствовать только 1 символьной строке. Что тут происходит?
CalculatorFeline

@CalculatorFeline Соответствует [ 1в начале ввода] ИЛИ [ 0в конце ввода]. Мне
потребовалась

Приоритет, ребята ....
Leaky Nun

Я думаю ^1|0$, труднее читать, чем 1.|.0. Кажется, что в целом
чтение становится

10

Стека кошек , 67 + 64 = 131 байт

Обратите внимание, что +64 от применения -nmфлагов к каждой программе. -nуказывает на числовой ввод-вывод и -mотражает исходный код по последнему символу - эти флаги технически нужны не для всех представлений, но для последовательности и простоты я все равно их оцениваю.

-2 -2 -3 -3     !I                0 0 0 0     <I!+
-4 -4 -4  1     |!T*I             0 0 0 1     [>I=I_
-4 -4  3 -2     *I*_              0 0 1 0     :I*=I:
-2 -2  3  3     T*I               0 0 1 1     [<!>X
-2  1 -2 -2     _*T*I             0 1 0 0     *|!TI:
-2  1 -3  1     !-|_I             0 1 0 1     <!I!>X
-2  3  3 -2     ^T*I              0 1 1 0     ^:]<_I
-2  3  3  3     -_T*I             0 1 1 1     *I<-I!
 2 -3 -3 -3     -*|_I             1 0 0 0     ^{!:}I_
 2 -3 -3  2     _|*I              1 0 0 1     _|[<I!:
 1 -2  1 -2     :]I*:             1 0 1 0     _!:|]X
 1 -2  1  1     *I\<X             1 0 1 1     *>I>!I
 2  2 -3 -3     -*I               1 1 0 0     I^:!
 2  2 -3  2     _*I_              1 1 0 1     |I|^:!
 1  2  2 -1     |!:^I             1 1 1 0     -I*<*I
 1  1  1  1     *<X               1 1 1 1     +I+

()в Stack Cats проверяет, является ли элемент положительным или неположительным (т. е. 0 или отрицательным), поэтому мы используем его для истинности / ложности соответственно. Второй столбец только для интереса, и в нем перечислены лучшие ворота с 0/ 1s в качестве выходных данных (с общим счетом 90).

Ввод разделенных разделителями бит через STDIN. Попробуйте онлайн!


Stack Cats - это обратимый эзотерический язык, в котором программы обладают отражающей симметрией. Учитывая фрагмент f(например >[[(!-)/), зеркальное изображение (например \(-!)]]<) вычисляет обратное f^-1. Таким образом, программы четной длины ничего не делают (или застревают в бесконечном цикле), и единственные нетривиальные программы имеют нечетную длину, вычисляя f g f^-1где gоператор центра.

Поскольку половина исходного кода всегда является избыточной, ее можно исключить, а выполнение кода с -mфлагом указывает, что исходный код должен быть зеркально отображен поверх последнего символа для получения фактического исходного кода. Например, программа *<Xна самом деле *<X>*, которая является симметричной.

Гольф в Stack Cats крайне не интуитивен, поэтому вышеперечисленные программы нужно было искать грубой силой. Большинство из них удивительно сложны, но я объясню несколько и добавлю к этому ответу, когда у меня будет время. На данный момент некоторые объяснения и альтернативные решения для версий 0/ 1можно найти здесь в репозитории Github .


1
Note that the +64 is from applying the -nm flags to each program.3 * 16 = 48 или 2 * 16 = 32, в любом случае 64 - это хай
кот

@cat Флаги стоят 4 за программу, так как нужно учитывать и пространство.
FryAmTheEggman

@cat соответствующая мета запись: meta.codegolf.stackexchange.com/questions/273/…
Мартин Эндер,

Это было больше года. У тебя еще есть время?
CalculatorFeline

8

Haskell, 78 76 75 байт

  1. _#_=2<1
  2. &&
  3. >
  4. pure
  5. <
  6. _#b=b
  7. /=
  8. ||
  9. (not.).max
  10. ==
  11. _#b=not b
  12. >=
  13. a#_=not a
  14. <=
  15. (not.).min
  16. _#_=1<2

Редактировать: -1 байт благодаря @cole.


Я как раз собирался комментировать "чувак, _#_это не стандартный оператор!" И тогда я понял ... Молодец.
Математическая

4 может бытьpure
Коул

@cole: Спасибо. Ничего себе, pureбыл введен в Preludeдалеком 2015 году, поэтому он был доступен во время этого испытания.
Ними

6

Брахилог , 36 34 байта

0000 false              \     Backtrack (always false)
0001 p and q            1.    Unify input and output with 1
0010 p and not q        >.    Input > Output
0011 p                  1     Unify input with 1
0100 not p and q        <.    Input < Output
0101 q                  ,1.   Unify output with 1
0110 xor                '.    Input and output cannot unify
0111 p or q             1;1.  Unify input with 1 or unify output with 1
1000 not p and not q    0.    Unify input and output with 0
1001 eq                 .     Unify input with output
1010 not q              ,0.   Unify output with 0
1011 p or not q         >=.   Input >= Output
1100 not p              0     Unify input with 0
1101 not p or q         <=.   Input <= Output
1110 not p or not q     0;0.  Unify input with 0 or unify output with 0
1111 true                     Empty program (always true)

Это ожидает 0как ложную ценность и 1как истинную ценность. Возвращает trueили false. р есть Inputи д есть Output.


Как вы вводите вывод?
Дрянная Монахиня

1
@LeakyNun Так же, как вход. Основной предикат, который вы запрашиваете, имеет два аргумента, которые вызываются Inputи Outputпо соглашению, но вы можете установить значения для обоих или вернуть значения из обоих.
Роковая

1
Это правильный инструмент для работы: P
Конор О'Брайен

6

Пролог, 147 145 байт

Получил 2 байта благодаря @SQB

a(a,a).       % 0000 false
b(1,1).       % 0001 P and Q
c(1,0).       % 0010 P and not Q
d(1,_).       % 0011 P
e(0,1).       % 0100 not P and Q
f(_,1).       % 0101 Q
g(P,Q):-P\=Q. % 0110 P xor Q
h(1,_).       % 0111 P or Q
h(0,1).
i(0,0).       % 1000 not P and not Q
j(P,P).       % 1001 P == Q                 
k(_,0).       % 1010 not Q
m(P,Q):-P>=Q. % 1011 P or not Q
n(0,_).       % 1100 not P              
r(P,Q):-P=<Q. % 1101 not P or Q         
s(0,_).       % 1110 not P or not Q
s(1,0).
t(_,_).       % 1111 true

Запросить x(P,Q).с xсоответствующей буквы и Pи Qустановить либо 0 или 1.
Возвращает trueили false.

Пример SWISH, включая тесты - введите runTest.для запуска.


Поддерживает ли это a(2,2).ложь?
jimmy23013

@ jimmy23013 Полагаю, можно, если предположить, что 2 - ложь. Не уверен, что это приемлемо.
Роковая

@ jimmy23013 На самом деле a(a,a).(или любая другая буква) тоже работает и aне является приемлемым источником правдивости, так что это хорошо. Спасибо за предложение.
Роковая

6

NTFJ, 86 байт

0000 false              ~
0001 p and q            |:|
0010 p and not q        :||:|
0011 p                  $
0100 not p and q        #{:||:|
0101 q                  #{$
0110 xor                :#{:#{:||#}:|||
0111 p or q             :|#{:||
1000 not p and not q    :|#{:||:|
1001 eq                 :#{:#{:||#}:|||:|
1010 not q              #{$:|
1011 p or not q         #{:||
1100 not p              $:|
1101 not p or q         :||
1110 not p or not q     |
1111 true               #

Попробуй это здесь! Но сначала прочтите ниже.

Ввод неявно в стеке. Результат помещен в стек. Добавьте 16 байтов (по одному *в конец каждого), если хотите, 0x00или 0x01выведите 0 и 1. Добавьте еще 160 байтов, если хотите 0или 1напечатали. (Поставьте ~~##~~~#{@перед каждым *.)

Единственный двоичный оператор NTFJ - это NAND, поэтому каждый из них записан в форме NAND.

Давайте пройдемся по каждому из них.

0: ложь

~

~представляет ложный бит. Достаточно просто. Так как ввод неявен внизу стека, он остается вверху.

1: p и q

|:|

NTFJ работает в стеке. :это команда для дубликата. Соблюдайте это p and qnot (p nand q)и это not q = q nand q.

Command | Stack
        | p q
   |    | (p nand q)
   :    | (p nand q) (p nand q)
   |    | (p nand q) nand (p nand q)
        | => not (p nand q)
        | => p and q

(Обратите внимание, тогда :|можно сказать, что отрицание и |:|можно сказать, что соединение )

2: р а не д

:||:|

Заметьте, что это просто отрицание :|и соединение |:|.

Command | Stack
        | p q
  :|    | p (not q)
  |:|   | p and (not q)

3: р

$

$выталкивает предмет из стека. Так что да.

4: не р и д

#{:||:|

Это то же самое, что и 2, кроме #{как в начале. #нажимает 1 (истинный бит) и {поворачивает стек влево один раз. Достаточно просто.

5: q

#{$

Поверните налево один раз, опустите.

6: XOR

:#{:#{:||#}:|||

Заметим:

p xor q = (p and (not q)) or ((not p) and q)                ; by experimentation (trust me)
        = (not ((not p) nand q)) or (not (p nand (not q)))  ; by definition of nand
        = not (((not p) nand q) and (p nand (not q)))       ; by De Morgan's laws
        = ((not p) nand q) nand (p nand (not q))            ; by definition of nand

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

Command | Stack
        | p q
   :    | p q q
  #{    | q q p
   :    | q q p p
  #{    | q p p q
  :|    | q p p (not q)
   |    | q p (p nand (not q))
  #}    | (p nand (not q)) q p
  :|    | (p nand (not q)) q (not p)
   |    | (p nand (not q)) (q nand (not p))
   |    | (p nand (not q)) nand (q nand (not p))

И, таким образом, у нас есть xor.

7: p или q

:|#{:||

Отрицание сверху, доведение снизу вверх, отрицание этого и nand их вместе. В основном p or q = (not p) nand (not q).

8: не р и не д

:|#{:||:|

Это просто отрицание 7. Легко.

9: экв

:#{:#{:||#}:|||:|

Это просто xnor или не xor. Просто снова.

10: не q

#{$:|

Отрицание 5.

11: р или нет д

#{:||

Отрицание р, нанд. (not p) nand q = not ((not p) and q) = p or (not q) (by De Morgan's laws),

12: не р

$:|

Бросай, останавливайся и отрицай.

13: не р или д

:||

Законы де Моргана, чтобы спасти день, снова! Тот же процесс, что и 11, только отрицание qвместо p.

14: не р или не д

|

Это просто мимик Нанд.

15: правда

#

# это правда.


только почему ...> _>
Rɪᴋᴇʀ

Я точно знаю, как это работает, но это выглядит довольно круто +1
Downgoat

Почему 5 не просто пустая программа, а 10 просто :|?
Джоффан

6

Майнкрафт, 89 блоков

На всех следующих фотографиях синие блоки предназначены для входа A, а оранжевые - для входа B

16. ВЕРНЫЕ ворота - 1 блок

введите описание изображения здесь

15. NAND ворота - 1x2x3 = 6 блоков

введите описание изображения здесь

14. A => B - 1x2x3 = 6 блоковвведите описание изображения здесь

13. НЕ А - 2 блока введите описание изображения здесь

12. B => A - 1x2x3 = 6 блоковвведите описание изображения здесь

11. НЕ Б - 2 блока введите описание изображения здесь

10. XNOR - 1x3x4 = 12 блоков введите описание изображения здесь

9. NOR - 1x2x3 = 6 блоковвведите описание изображения здесь

8. ИЛИ - 1 блок введите описание изображения здесь

7. XOR - 1x3x4 = 12 блоков введите описание изображения здесь

6. Б - 1 блок введите описание изображения здесь

5.! A & B - 1x2x5 = 10 блоков введите описание изображения здесь

4. А - 1 блоков введите описание изображения здесь

3. A &! B - 1x2x5 = 10 блоков введите описание изображения здесь

2. И - 2х2х3 = 12 блоков введите описание изображения здесь

1. ЛОЖЬ - 1 блок введите описание изображения здесь


2
От второго до последнего изображения (И) вы можете сохранить 6 блоков, поместив факелы сверху на заднюю часть блоков, то есть напротив рычагов. Поменяйте горелку посередине на кусочек пыли и удалите пыль сверху, снизив ее до 1x2x3 = 6 блоков.
Лука Х

5

Mathematica, 67 байт

0>1&
And
#&&!#2&
#&
!#&&#2&
#2&
Xor
Or
Nor
Xnor
!#2&
#||!#2&
!#&
!#||#2&
Nand
1>0&

Каждый из них оценивает функцию, поэтому вы можете использовать их как

#&&!#2&[True, False]
Xor[True, False]

Ах, если бы в Mathematica только целые числа были истинными / ложными, эти четыре более длинные могли бы быть значительно сокращены.


Если целые числа не являются истиной / ложью, что произойдет, если вы поместите их в оператор if?
Конор О'Брайен

3
@ CᴏɴᴏʀO'Bʀɪᴇɴ это остается неоцененным.
Мартин Эндер

5

MATL, 34 23 байта

Я надеюсь, что я получил заказ в порядке! Ноль - это ложь, ненулевое - это правда. Каждая функция принимает два неявных входа (хотя может игнорировать некоторые входные данные). Первый вход A, а второй B. Вы можете ввести 0/ 1для true / false, или T/ F.

Вот пример TryItOnline для контрольного примера 3.

Сэкономили 4 байта, используя *for and, и еще 4, используя >/ <вместо ~wY&/ w~Y&после того, как я увидел ответ Денниса!

1.  0,0,0,0 0 (ignores input, just returns a zero)
2.  0,0,0,1 * (and)
3.  0,0,1,0 < (not-A and B)
4.  0,0,1,1 D (A)
5.  0,1,0,0 > (not-B and A)
6.  0,1,0,1 xD (discard A, display B)
7.  0,1,1,0 Y~ (xor)
8.  0,1,1,1 + (or)
9.  1,0,0,0 +~ (not-or)
10. 1,0,0,1 = (A=B)
11. 1,0,1,0 x~ (not-B)
12. 1,0,1,1 <~ (not-B or A)
13. 1,1,0,0 ~ (not-A)
14. 1,1,0,1 ~+ (not-A or B)
15. 1,1,1,0 *~ (not(A and B))
16. 1,1,1,1 1 (just returns 1)

10
Номер шесть думает, что это смешно.
Конор О'Брайен

@ CᴏɴᴏʀO'Bʀɪᴇɴ Номер 6 - лучший, мне тоже нравится номер 12! XD!
Дэвид

У вас нет "неравной" функции?
Дрянная Монахиня

Нет (я так не думаю)
Дэвид

2
@ Давид, я думаю, номер 7 можно заменить на -
Луис Мендо

5

постоянный ток, 37 байт

dc(«настольный калькулятор») - это стандартная команда unix, основанный на стеке постфиксный калькулятор. В нем отсутствуют битовые операции, а операторы сравнения могут использоваться только для выполнения макросов (что не стоит байтов). Целочисленное деление восполняет некоторые из этого.

Эти сценарии ожидают 0и 1значения в стеке, и оставляют результат в стеке.

0,0,0,0 (false)              0
0,0,0,1 (and)                *         a*b
0,0,1,0                      -1+2/     (a-b+1)/2
0,0,1,1 (A)                  r         reverse a, b: a now on top
0,1,0,0                      -1-2/     (a-b-1)/2
0,1,0,1 (B)                            (0 bytes) do nothing: b on top
0,1,1,0 (xor)                -         a-b
0,1,1,1 (or)                 +         a+b                  
1,0,0,0 (nor)                +v1-      sqrt(a+b) -1
1,0,0,1 (xnor)               +1-       a+b-1
1,0,1,0 (not B)              1-        b-1
1,0,1,1 (if B then A)        -1+       a-b+1
1,1,0,0 (not A)              r1-       a-1
1,1,0,1 (if A then B)        -1-       a-b-1            
1,1,1,0 (nand)               *1-       a*b - 1
1,1,1,1 (true)               1

5

Лабиринт , 85 байт

Спасибо Sp3000 за сохранение 2 байта.

!@
??&!@
??~&!@
?!@
?~?&!@
??!@
??$!@
??|!@
??|#$!@
??$#$!@
?#?$!@
?#?$|!@
?#$!@
?#$?|!@
??&#$!@
1!@

Все это полные программы, которые читают два целых числа 0или 1из STDIN (используя любой нецифровый разделитель) и печатают результат как 0или 1в STDOUT.

Попробуйте онлайн! (Не тестовый набор, поэтому вам придется вручную пробовать разные программы и входы

Что касается объяснений, все они довольно просты. Все программы являются линейными, и используемые команды выполняют следующее:

?   Read integer from STDIN and push.
!   Pop integer and write to STDOUT.
@   Terminate program.
&   Bitwise AND of top two stack items.
|   Bitwise OR of top two stack items.
$   Bitwise XOR of top two stack items.
~   Bitwise NOT of top stack item.
#   Push stack depth (which is always 1 when I use it in the above programs).
1   On an empty stack, this pushes 1.

Обратите внимание, что я использую #всегда используется для его объединения $, то есть для вычисления XOR 1или, другими словами, для логического отрицания. Только в нескольких случаях я смог использовать ~вместо этого, потому что последующий &отбрасывает все ненужные биты из результирующего -1или -2.


5

Машинный код IA-32, 63 байта

Hexdump кода, с разборкой:

0000  33 c0     xor eax, eax;
      c3        ret;

0001  91        xchg eax, ecx;
      23 c2     and eax, edx;
      c3        ret;

0010  3b d1     cmp edx, ecx;
      d6        _emit 0xd6;
      c3        ret;

0011  91        xchg eax, ecx;
      c3        ret;

0100  3b ca     cmp ecx, edx;
      d6        _emit 0xd6;
      c3        ret;

0101  92        xchg eax, edx;
      c3        ret;

0110  91        xchg eax, ecx;
      33 c2     xor eax, edx;
      c3        ret;

0111  8d 04 11  lea eax, [ecx + edx];
      c3        ret;

1000  91        xchg eax, ecx; // code provided by l4m2
      09 d0     or eax, edx;
      48        dec eax;
      c3        ret;

1001  3b ca     cmp ecx, edx;
      0f 94 c0  sete al;
      c3        ret;

1010  92        xchg eax, edx;
      48        dec eax;
      c3        ret;

1011  39 d1     cmp ecx, edx; // code provided by l4m2
      d6        _emit 0xd6;
      40        inc aex;
      c3        ret;

1100  91        xchg eax, ecx;
      48        dec eax;
      c3        ret;

1101  3b d1     cmp edx, ecx; // code inspired by l4m2
      d6        _emit 0xd6;
      40        inc aex;
      c3        ret;

1110  8d 44 11 fe   lea eax, [ecx+edx-2] // code provided by l4m2
      c3        ret;

1111  91        xchg eax, ecx;
      40        inc eax;
      c3        ret;

Код длиннее, чем мог бы быть, потому что он использует стандартное соглашение о кодировании: вход в ecxи edx, и вывод в al. Это может быть выражено в C как

unsigned char __fastcall func(int, int);

Кажется, что MS Visual Studio не понимает недокументированные SALC код операции, поэтому мне пришлось использовать его код, а не имя.

Спасибо вам l4m2 за улучшение некоторых примеров кода!


1
1110 8D4411FE LEA EAX, [ECX+EDX-2]
17

5

C 34 байта

#define g(n,a,b)((n-1)>>3-b-2*a)&1

Где n - это номер функции, которую нужно использовать, но я думаю, что в ней будет отказано, поэтому я предлагаю другую:

C 244 байта (используя память)

typedef int z[2][2];
z a={0,0,0,0};
z b={0,0,0,1};
z c={0,0,1,0};
z d={0,0,1,1};
z e={0,1,0,0};
z f={0,1,0,1};
z g={0,1,1,0};
z h={0,1,1,1};
z i={1,0,0,0};
z j={1,0,0,1};
z k={1,0,1,0};
z l={1,0,1,1};
z m={1,1,0,0};
z n={1,1,0,1};
z o={1,1,1,0};
z p={1,1,1,1};

он использует двойной индексированный массив. n[0][1]является(A implies B)(0,1)

Далее 138 байт

Я только что узнал Форт. Я полагаю, что это совместимо с Ansi Forth, поскольку оно работает и на gforth.

: z create dup , 1+ does> @ -rot 3 swap - swap 2* - rshift 1 and ; 
0 
z a z b z c z d z e z f z g z h z i z j z k z l z m z n z o z p 
drop

Функция z создает новую функцию с указанным именем, затем помещает номер логического элемента из вершины стека в адрес новой функции. Он оставляет следующую (n + 1) функцию логического элемента в стеке для следующего объявления.

Вы можете проверить это:
и AB

0 0 b . cr 
0 1 b . cr
1 0 b . cr 
1 1 b . cr   

(«.» печатает верхнюю часть стопки, «cr» - возвращение кариеса)


Вам нужно только предоставить фрагменты кода для каждой функции.
КалькуляторFeline

4

C 268 байт

#define c(a,b)0      // 0000 
#define d(a,b)a&b    // 0001 
#define e(a,b)a>b    // 0010 
#define f(a,b)a      // 0011 
#define g(a,b)a<b    // 0100 
#define h(a,b)b      // 0101 
#define i(a,b)a^b    // 0110 
#define j(a,b)a|b    // 0111 
#define k(a,b)!b>a   // 1000 
#define l(a,b)a==b   // 1001 
#define m(a,b)!b     // 1010 
#define n(a,b)!b|a   // 1011 
#define o(a,b)!a     // 1100 
#define p(a,b)!a|b   // 1101 
#define q(a,b)!b|!a  // 1110 
#define r(a,b)1      // 1111 

Макросы кажутся короче функций.


4

Брайан и Чак , 183 байта

Спасибо Sp3000 за сохранение 4 байта.

Некоторые из программ содержат непечатаемый символ. В частности, каждый \x01должен быть заменен <SOH>управляющим символом (0x01):

0000
?
#>.
0001
,-?,-?>?\x01
#}>.
0010
,-?,?>?\x01
#}>.
0011
,?\x01+?
#>.
0100
,?,-?>?\x01
#}>.
0101
,,?\x01+?
#>.
0110
,?>},?>?_\x01
#}+{>?_}>.
0111
,\x01?,?>?
#{>.
1000
,?,?>?\x01
#}>.
1001
,-?>},?>?_\x01
#}+{>>?_}>.
1010
,,-?\x01+?
#>.
1011
,\x01?,-?>?
#{>.
1100
,-?\x01+?
#>.
1101
,\x01-?,?>?
#{>.
1110
,\x01-?,-?>?
#{>.
1111
?
#>+.

Входные и выходные данные используют байтовые значения , поэтому на входе должны быть два байта 0x00 или 0x01 (без разделителя), и на выходе будет один такой байт. На самом деле это также наиболее разумное определение истинности / ложности для B & C, потому что единственная команда потока управления ?считает нули ложными, а все остальное - правдивыми.

Пояснения

Сначала быстрый B & C учебник для начинающих:

  • Каждая программа состоит из двух экземпляров, похожих на Brainfuck, каждый из которых написан в отдельной строке. Мы называем первого Брайана, а второго Чака . Казнь начинается на Брайана.
  • Лента каждой программы является исходным кодом другой программы, а указатель инструкций каждой программы является головкой ленты другой программы.
  • Только Брайан может использовать команду ,(входной байт), и только Чак может использовать команду .(выходной байт).
  • Brainfuck в []цикле не существует. Вместо этого у вас есть единственный поток управления, ?который переключает управление на другой экземпляр, если текущее значение под головкой ленты отлично от нуля.
  • В дополнении к >и <, есть {и }которые по существу эквивалентны фрагменты Brainfuck [<]и [>], то есть, они двигают голову ленты к следующей нулевой позиции в этом направлении. Основное отличие заключается в том, что {его также можно остановить на левом конце ленты, независимо от того, какое значение она имеет.
  • Для удобства любые _s в исходном коде заменяются нулевыми байтами (так как они очень полезны в нетривиальных программах, чтобы поймать {и }).

Обратите внимание, что во всех программах лента Чака начинается с #. Это действительно может быть что угодно. ?работает так, что головка ленты перемещается на одну ячейку перед началом выполнения (так что само условие не выполняется, если оно оказывается действительной командой). Поэтому мы никогда не сможем использовать первую ячейку Чака для кода.

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

0000, 1111: Постоянные функции

?
#>.
?
#>+.

Это очень просто. Мы переключаемся на Чака безоговорочно. Чак перемещает головку ленты в неиспользуемую ячейку справа и либо печатает ее напрямую, либо увеличивает ее в первую очередь для печати 1.

0011, 0101, 1010, 1100: Функции в зависимости от только один вход

,?\x01+?
#>.
,,?\x01+?
#>.
,,-?\x01+?
#>.
,-?\x01+?
#>.

В зависимости от того, начинаем ли мы с ,или ,,мы работаем с Aили B. Давайте посмотрим на первый пример 0011(т.е. A). После прочтения значения мы используем его ?в качестве условия. Если A = 1, то это переключается на Чака, который перемещает головку ленты вправо и печатает буквально встроенный 1-байт. В противном случае контроль остается за Брайаном. Здесь 1-байт не работает. Затем мы хорошо увеличиваем вход, +чтобы убедиться, что он ненулевой, а затем переключаемся на Чака с помощью ?. На этот раз >перемещается в неиспользуемую ячейку справа, которая затем печатается как 0.

Чтобы опровергнуть одно из значений, мы просто уменьшаем его -. Это превращается 1в 0и 0в -1, что является ненулевым и, следовательно, правдивым, насколько ?это касается

0001, 0010, 0100, 1000: Бинарные функции с одним truthy результат

,-?,-?>?\x01
#}>.
,-?,?>?\x01
#}>.
,?,-?>?\x01
#}>.
,?,?>?\x01
#}>.

Это расширение предыдущей идеи для работы с двумя входами. Давайте посмотрим на пример 1000(NOR). Мы (потенциально) читаем оба ввода с ,?. Если что-то из этого есть 1, ?переключается на Чака. Он перемещает головку ленты до конца }(на пустую ячейку после кода Брайана), перемещает другую ячейку с >(все еще ноль) и печатает ее с помощью ..

Тем не менее, если оба входа равны нулю, управление все равно остается за Брайаном. >затем перемещает головку ленты так }, что эта команда не выполняется, когда мы переключаемся на Чака с помощью ?. Теперь все, что делает Чак, это >.только перемещается на 1-клетку и печатает это.

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

0111, 1011, 1101, 1110: Бинарные функции с тремя truthy результатами

,\x01?,?>?
#{>.
,\x01?,-?>?
#{>.
,\x01-?,?>?
#{>.
,\x01-?,-?>?
#{>.

Незначительная модификация предыдущей идеи, чтобы свести на нет результат (например, распечатать, 0когда мы прошли через Брайана и т. Д. 1). Давайте посмотрим на 0111(ИЛИ) в качестве примера. Обратите внимание, что встроенный 1-byte не используется, поэтому он все еще начинается с ,?,?. Если любой из этих входов - 1мы переключаемся на Чака, который перемещает головку ленты обратно в начало {. >.перемещает головку ленты на этот 1байт и печатает ее.

Если оба входа равны нулю, мы останемся с Брайаном, переместим головку ленты, {чтобы пропустить ее, а затем переключимся на Чака. Когда он выполняет >.это время, он перемещается в пустую ячейку после кода Брайана и печатает 0.

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

0110, 1001: Двоичные функции с двумя достоверными результатами

,?>},?>?_\x01
#}+{>?_}>.
,-?>},?>?_\x01
#}+{>>?_}>.

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

Основная идея состоит в том, чтобы использовать первый вход, чтобы решить, выбирать ли второй вход между 0и 1или между 1и 0. Давайте возьмем 0110(XOR) в качестве примера:

Посмотрим A = 0. В этом случае мы хотим вывести Bкак есть. ,читает A, ?ничего не делает. >переходит на следующую (ненулевую) ячейку, что }приводит нас к _Чаку. Здесь мы читаем Bс ,и использовать ?снова. Если бы Bбыло 0так же, мы все еще на Брайане. >пропускает }Чак и ?переключается так, чтобы >.печатать 0встроенный в исходный код Брайана. Если Bбыл 1с другой стороны, Чак делает выполните }который движется в _в коде Брайана уже, так что >.затем печатает 1-байт вместо этого.

Если A = 1, тогда мы сразу переключаемся на Чака, который будет казнить }+{>?. Что он делает, так это перемещается к _исходному коду Брайана, превращает его в a, 1а +затем возвращается к началу {и пропускает Брайана, ?перемещая одну ячейку вправо >перед тем, как передать управление ему. На этот раз, после того, как Брайан Рида B, если B = 0, и Чак использует >.ячейку рядом с Брайан ?будет 1вместо 0. Кроме того, когда B = 1Чак }пропускает то, что раньше было пропуском, и перемещается полностью до конца ленты, так что >.вместо этого печатается ноль. Таким образом, мы печатаем not B.

Чтобы реализовать эквивалентность, мы просто отрицаем ее Aперед использованием в качестве условия. Обратите внимание, что из-за этого нам также нужно добавить еще один >в Чака, чтобы пропустить это -и при возвращении к началу.


4

ClojureScript, 88 84 76 74 байта

nilи falseложны, все остальные ценности правдивы. Булевы значения приводят к 0/1 для арифметики и неравенств. Функции могут принимать неверное количество аргументов.

0000   nil?            ; previously: (fn[]nil)
0001   and
0010   <
0011   true?           ; previously: (fn[x]x)
0100   >
0101   (fn[x y]y)
0110   not=
0111   or
1000   #(= 0(+ % %2))
1001   =
1010   #(not %2)
1011   <=
1100   not
1101   >=
1110   #(= 0(* % %2))
1111   /               ; previously: (fn[]4), inc

Разве это не 0обман?
Дрянная Монахиня

2
Не в ClojureScript.
MattPutnam

@LeakyNun Не в большинстве LISP или функциональных языков программирования, которыми определенно является Clojure
кошка

@cat Да, в большинстве функциональных языков программирования! Python, например, оценивает , not not(0)чтобы False, который является falsey значение.
Эрик Outgolfer

3
@ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ Э-э ... Python не является ни чисто функциональным, ни типом функционального языка, о котором я говорю. Python является обязательным, в основном, и с некоторыми меньшими (плохо выполненными) функциональными аспектами. Erlang, Haskell (я думаю), Common LISP, Clojure, ракетка, схема, фактор, Standard ML, Objective CAML и т.д. 0 это просто другое значение , и в результате truthy, и символ ложной ( #f, f, falseи т.д.) является ложный. Все остальные ценности правдивы в большинстве функциональных языков.
кот

4

Brainfuck , 184 178 174 байта

Ввод / вывод использует U + 0000 и U + 0001.

0000 .
0001 ,[,[->+<]]>.
0010 ,[,-[+>+<]]>.
0011 ,.
0100 ,-[,[->+<]]>.
0101 ,,.
0110 ,>,[-<->]<[>>+<]>.
0111 ,-[,-[+>-<]]>+.
1000 ,-[,-[+>+<]]>.
1001 ,>,[-<->]<[>>-<]>+.
1010 ,,-[+>+<]>.
1011 ,-[,[->-<]]>+.
1100 ,-[+>+<]>.
1101 ,[,-[+>-<]]>+.
1110 ,[,[->-<]]>+.
1111 +.

Ваше чтение условного второго ввода выглядит дорого. Например, 0001не могли бы вы просто сделать ,[,>]<.(учитывая переводчика, который позволяет вам идти слева от начальной ячейки)?
Мартин Эндер

@MartinEnder Я подумал, что я не просто скопировать ответ Денниса здесь.
Дрянная Монахиня

4

Brain-Flak , 418 , 316 байт

Попробуйте онлайн!

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

false, 4 байта (Предоставлено Leaky Nun )

(<>)

и 36 байтов

(({}{}[(())()])){{}{}(((<{}>)))}{}{}

А, а не В, 40 байт

((({}){}{}[(())()])){{}{}(((<{}>)))}{}{}

А, 6 байт

({}<>)

не А и В, 38 байт

((({}){}{}[(())])){{}{}(((<{}>)))}{}{}

B, 2 байта

{}

xor, 34 байта

(({}{}[(())])){{}{}(((<{}>)))}{}{}

или 6 байтов

({}{})

ни 34 байта

(({}{}<(())>)){{}{}(((<{}>)))}{}{}

xnor, 10 байт

({}{}[()])

не B, 34 байта

{}(({}<(())>)){{}{}(((<{}>)))}{}{}

B подразумевает A, 14 байтов

(({}){}{}[()])

не A, 34 байта

(({}<{}(())>)){{}{}(((<{}>)))}{}{}

A подразумевает B, 16 байтов

(({}){}{}[()()])

nand, 12 байт

({}{}[()()])

правда, 6 байтов

<>(())

объяснение

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

Во-первых, это ворота, которые возвращают три одинаковых значения (т. Е. 2, 3, 5, 8, 9, 12, 14 и 15). Все они следуют той же схеме. Сначала вы конвертируете входные данные в двухбитное число, где в качестве двойки ставите a, а в качестве B - единицы. Это сделано с этим фрагментом (({}){}{}). Затем вы вычитаете значение двухбитового входа, который вы хотите изолировать ({}[value]). (В реальном коде вычитание и преобразование выполняются за один шаг для сохранения байтов). Это может сочетаться с не в случае необходимости: (({}<(())>)){{}{}(((<{}>)))}{}{}.

Далее: и, ни, или, xor, и xnor. Они работают так же, как и выше. Фактически некоторые из них включены выше, однако этот метод короче. Уловка, которую я здесь использовал, заключается в том, что каждый из них соответствует сумме A B. Например, xor оценивается как true, если A + B = 1, и false в противном случае. Сначала вы добавляете AB и вычитаете соответствующую сумму. Выражается как ({}{}[0,1,2 or 3]). Затем при необходимости провести не

Далее: A, B, а не A и не B. Это в значительной степени говорит само за себя. Мы начинаем с удаления ненужного значения, а затем либо отменяем, либо заканчиваем.

Наконец, два простакона: истина и ложь. Для этого мы помещаем правильное значение в стек выключения. В <>nilad возвращает ноль , поэтому мы можем сохранить два байта с помощью переключателя в качестве нулевого значения.

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


(<>)достаточно для false; также (<{}{}>)8 байтов
Утренняя монахиня

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

Что вы имеете в виду?
Дрянная Монахиня

Я думал, что должен был удалить существующие входные данные и поместить результат в его место. (<>)оставит входы и поместит ноль в другой стек.
Пшеничный Волшебник

1
Не <>достаточно ли falseиз-за неявных нулей? Также, думаю, aможет быть пустая программа. trueможет быть <>[][](не сохраняет байты, но выглядит здорово: P).
CalculatorFeline

4

ProgFk , 18,5 17,5 байт

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

3
E1
DE 2D
<empty>
DE 1
1
E3
E2
E2 D
E3 D
1D
DE 2
D
DE 1D
E1 D
4

объяснение

ProgFk - это основанный на ленте esolang (аналог Brainfuck), в котором каждая ячейка является битом, а инструкции приведены в виде полубайтов (4 байта). Инструкции работают с ячейкой, на которую указывает указатель инструкции. Входные дан в первой и второй клеток (с Aи Bбыть первой и второй клетки , соответственно), а указатель команд начинается с первой ячейки. Вывод сохраняется в первой ячейке.

Каждая используемая инструкция объясняется ниже.

1   Increment the instruction pointer.
2   Decrement the instruction pointer.
3   Set the current bit to 0.
4   Set the current bit to 1.
D   Perform a NOT on the current bit.
E   The next instruction is an extended instruction.

Extended instructions:
1   Set the current bit to the current bit AND the next bit.
2   Set the current bit to the current bit OR the next bit.
3   Set the current bit to the current bit XOR the next bit.
6   Swap the current bit and the next bit.

Сохраненный байт благодаря @LeakyNun!


4

На самом деле, 24 байта

Эти программы принимают ввод как A\nB\nпредставлением новой строки), который оставляет B на вершине стека, а A ниже. Falseпредставлен 0и Trueпредставлен любым положительным целым числом.

é0  (false: clear stack, push 0)
*   (and: multiply)
<   (A and not B: less-than)
X   (A: discard B)
>   (B and not A: greater-than)
@X  (B: discard A)
^   (A xor B: xor)
|   (A or B: or)
|Y  (A nor B: or, boolean negate)
=   (A xnor B: equals)
@XY (not B: discard A, boolean negate B)
≤   (if B then A: less-than-or-equal)
XY  (not A: discard B, boolean negate)
≥   (if A then B: greater-than-or-equal)
*Y  (A nand B: multiply, boolean negate)
é1  (true: clear stack, push 1)

Спасибо Leaky Nun за 3 байта

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.