Генерация таблицы поиска универсальной бинарной функции


19

Это связано с моим стремлением изобрести эзотерический язык программирования .

Таблица двоичных чисел 0 .. 15 может использоваться для реализации универсальной двоичной функции с использованием операций индексирования. Учитывая два 1-битных входа X и Y, все 16 возможных функций могут быть закодированы в 4-битный код операции.

X Y  F|0 1 2 3 4 5 6 7 8 9 A B C D E F
- -    - - - - - - - - - - - - - - - -  
0 0    0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1    0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
1 0    0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
1 1    0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
       -     -   - -   -   -   -   - -
       0    ~X  ~Y ^   &   Y   X   | 1
      ZERO    NOT-Y   AND         OR
          NOT-X   XOR              ONE

Таким образом, этот набор из 16 функций может быть применен к двоичным входам в качестве функции

U (f, x, y): (f >> ((x << 1) | y)) & 1 ,

или

U (f, x, y): (f / 2 ^ (x × 2 + y))% 2 ,

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

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

Цель:

Создайте этот точный текстовый вывод:

0101010101010101
0011001100110011
0000111100001111
0000000011111111

Это оно! Кратчайший код выигрывает.


2
У меня была интуиция, что семья APL преуспеет здесь. :)
luser droog


Принимаются ли новые или конечные переводы строк?
Тит

Да, дополнительные переводы строки в порядке.
luser droog 20.09.16

Ответы:


20

J, 10 (13?) Символов

|.|:#:i.16

Список номеров:

   i.16
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15`

в двоичный файл:

   #:i.16
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1
1 1 0 0
1 1 0 1
1 1 1 0
1 1 1 1

Транспонирование:

   |:#:i.16
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

Задний ход:

   |.|:#:i.16
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1

Нужно ли убирать пробелы? Глядя на другой ответ J, кажется, что мы делаем, поэтому нам нужно добавить 3 символа и позаимствовать ответ1": из Яна .


1
Очень хороший стиль объяснения. +1 (чертовски мало тоже!)
Люзер Дрог

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

Приятно видеть что-то короче, чем Golfscript ...
fuenfundachtzig


@luserdroog Вау. Это много кода. Гораздо более читабельный, чем исходный код J :-) Очень круто.
Гарет


7

APL (14)

Предполагая ⎕IO=0(это настройка):

⎕D[⊖(4⍴2)⊤⍳16]

Объяснение:

  • ⍳16: цифры [0,16)
  • (4⍴2)⊤: кодировать каждое число в базе 2, используя 4 цифры
  • : горизонтальный реверс (так что MSB заканчивается сверху)
  • ⎕D[... ]: выберите эти значения, из ⎕Dкоторых будет строка 0123456789. (Числовая матрица отображается с пробелами между значениями, а символьная матрица - нет. Таким образом, каждый числовой бит преобразуется в один из символов '0' '1').

Первый персонаж в источнике должен выглядеть как квадрат, или мне все еще не хватает некоторых шрифтов?
Тим Сегин

@TimSeguine Да, это квадрат, называемый четырехъядерный в APL литературе. Имена переменных, начинающиеся с четырехугольника, являются системными переменными, которые изменяют среду. IO = "происхождение индекса".
Люсер Дрог

Сохраните байт: (4⍴2)⊤2⊥⍣¯1
Adám

6

Желе , 42 7 байт (не конкурирует)

⁴ḶBUz0Y

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

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


Так как язык новее, чем вопрос, я не могу принять его как ответ. Определенно в бегах за награду, Тхо!
Люзер Дрог

@luserdroog Это нормально. Но я думал, что проблема была новее.
Эрик Outgolfer

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

+1 для 42 до 7 Codegolf. Это то, что вы не видите каждый день (если не сделано специально).
Кевин Круйссен

1
@KevinCruijssen Почему это нужно делать нарочно? Я просто новичок в Jelly (я хорошо знаю Python 2 и 3), поэтому я сделал это по-строково, в то время как мне «нужно относиться к Jelly как к языку, управляющему массивами».
Эрик Outgolfer

5

/// , 51 байт

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

/a/0101/aaaa
/b/0011/bbbb
/z/0000//o/1111/zozo
zzoo

1
Добро пожаловать в PPCG! Ты подтолкнул меня на это.
Эрик Outgolfer

@EriktheGolfer Не стесняйтесь улучшать, но я думаю, что это самая короткая версия. :)
Седрик Райхенбах

Я портирую это на Sprects.
Эрик Outgolfer

4

GolfScript ( 18 17 15 символов)

(С благодарностью Говарду)

16,zip{','-~n}%

Я не понимаю, почему 10-символ

16,zip{n}/

не работает; Я подозреваю, что ошибка в стандартном интерпретаторе приводит к неподдерживаемым типам в стеке.

Альтернатива из 18 символов, которую я полностью понимаю:

4,{2\?.2,*$8@/*n}%

Более математический подход немного длиннее, на 28 символов:

4,{2.@??)2.4??.@/+2base(;n}/

Многое из этого для базового преобразования и заполнения нулями. Без этого он падает до 19 символов,

4,{2.@??)2.4??\/n}/

с выходом

21845
13107
3855
255

Был задан вопрос о точном выводе текста - зачем 16,zip{n}/тогда работать?
Говард

С другой стороны, вы можете сделать16,zip{','-~n}%
Говард

@ Ховард, я думаю, что это zipдолжно возвращать массив массивов, но на самом деле кажется, что он возвращает массив массивов Ruby (это мое лучшее предположение). Какими бы ни были элементы, применение к ним `` `` `не влияет на способ их печати, что не похоже ни на один из 4 типов данных GolfScript. Вы правы, что, ','-кажется, превращаете их в обычные массивы: хороший трюк.
Питер Тейлор

Кажется, вывести 4 дополнительные строки нулей здесь
aditsu

@aditsu, работает над онлайн-демонстрацией . Интересно, почему разница. Возможно, версия для Ruby?
Питер Тейлор

3

CJam - 16

4,{G,f{\m>2%}N}/

Эквивалентный Java-код (как объяснение):

public class Lookup {
    public static void main(final String... args) {
        for (int i = 0; i < 4; ++i) {
            for (int j = 0; j < 16; ++j) {
                System.out.print((j >> i) % 2);
            }
            System.out.println();
        }
    }
}

3

Javascript (ECMA6), 67

s=(k,n)=>n-.5?s((k<<n/2)^k,n/2)+"0".repeat(n)+k.toString(2)+"\n":"" 

Чтобы использовать это, позвоните

s(255,8)

Bitshift!
А также XOR и немного рекурсии.

Первое, на что нужно обратить внимание, это то, что если мы возьмем какую-либо строку и вы сдвинете ее (число непрерывных нулей) / 2 влево, мы получим хороший XOR, чтобы получить следующую строку.

Например,

0000000011111111 //line 4
0000111111110000 //shifted 4 to the left

XOR эти побитовые дают нам

0000111100001111 //XOR'ed. This is line 3!

это следующая строка вверх (строка 3).
Применяя тот же процесс к строке 3, сдвиньте 2 влево, и мы получим ...

0000111100001111
0011110000111100

XOR'ed дает

0011001100110011

это строка 2.
Обратите внимание, что сумма, которую мы сдвигаем, уменьшается вдвое.
Теперь мы просто вызываем эту функцию рекурсивно с двумя аргументами. Целочисленное значение этой строки и N, это то, сколько нам нужно сдвинуть. Когда мы делаем рекурсию, просто передаем смещенное значение XOR и n / 2.

"0".repeat(n)

должен дополнить 0 до начала каждой строки, потому что toString удаляет ведущие 0.


+1 Очень круто. Я не заметил эту модель раньше.
Люсер Дрог

Пару байсов можно обрезать, сдвинув бит n вместо деления и заменив новую строку строкой шаблона:s=(k,n)=>n?s((k<<n/2)^k,n>>1)+"0".repeat(n)+k.toString(2)+` `:""
Shaun H

2

J, 21 символов

1":<.2|(2^i.4)%~/i.16
  • i.16 это список 0..15
  • 2^i.4 это список (1,2,4,8)
  • %~/ создает таблицу делений, где левый аргумент формирует строки, но является правильным аргументом для деления
  • 2| вычисляет остаток после деления [каждой ячейки] на два
  • <. этажи, которые имеют значение 0 или 1
  • 1": форматирует таблицу одним символом на ячейку

Я чувствую, что floorне должно быть необходимости. Домен 2|уже равен 0 или 1, верно?
luser droog

@luserdroog |работает на поплавках . 2|3.25есть 1.25. Мы этого не хотим.
Джон Дворак


2

Рубин (44)

Скучно и долго: просто печатать двоичные представления чисел с добавлением 0.

[21845,13107,3855,255].map{|i|puts"%016b"%i}

2

постскриптум 108 177 126 77 74 70

[43690 52428 61680 65280]
{16{dup 2 mod =only 2 idiv}repeat<>=}forall

Поменял значения для более простого метода модуляции .

151 131 119

Применение более APL -ного подхода. редактирование: заменена обрезка строк и архивирование массивов с индексированием и циклами for.

[[0 1 15{}for]{16 add 2 5 string cvrs}forall]4 
-1 1{0 1 15{2 index exch get 1 index 1
getinterval =only}for pop<>=}for

Отступ:

[[0 1 15{}for]{16 add 2 5 string cvrs}forall]
4 -1 1{ % [] i
    0 1 15{ % [] i j
        2 index exch get % [] i [](j)
        1 index 1  % [] i [](j) i 
        getinterval  % [] i [](j)<i>
        =only  % [] i
    }for 
    pop<>= % []
}for

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

-1 16 i + #: |: |.{{==only}forall()=}forall

iвот 1-й вектор, описанный в Элементарных функциях Айверсона , следовательно, -1 ... +для получения 0 .. 15.


2

Perl (36 + 1)

+1 за say, как обычно. двойной 0не опечатка :)

map say((00x$_,1x$_)x(8/$_)),1,2,4,8

Не нужно добавлять 1 для say. perl -e'...'является стандартным, и это не требует perl -E'...'увеличения количества байтов. Во всяком случае, я думаю , что было принято решение о Code Golf Meta , который -M5.01является бесплатным.
msh210

2

JavaScript (ECMA6), 108

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

['gut','a43','2z3','73'].forEach(n=>{a=parseInt(n,36).toString(2);
alert(('00000000'+a).substr(a.length-8))})

(Разрыв строки для удобства).

Жаль, что мне пришлось возиться с заполнением ведущими нулями, но смысл этого кода просто представляет целевой двоичный результат в Base 36, который является именно этими gut, a43, 2z3, 73значениями.

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


1
Я собирался сделать то же самое, когда увидел твою. Я получил его до 92 байт , используя технику от моего ответа на подобный вопрос : alert(['gut','a43','2z3',73].map(n=>(1e8+parseInt(n,36).toString(2)).slice(-16)).join('\n')). Этот подход использует новые строки вместо четырех alert()с.
NinjaBearMonkey



2

CJam ( неконкурентный ), 10 9 байт

Спасибо @Dennis за 1 байт!

Y4m*zW%N*

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

объяснение

Y     e# Push 2
4     e# Push 4
m*    e# Cartesian power of 2 (interpreted as [0 1]) with exponent 4
z     e# Zip
W%    e# Reverse the order of rows
N*    e# Join with newlines. Implicitly display

2

JavaScript (ES6), 58 52 байта

Строит строку рекурсивно.

f=(n=64)=>n--?f(n)+(!n|n&15?'':`
`)+(n>>(n>>4)&1):''

Как это устроено

Эта рекурсия основана на том факте, что шаблон состоит из вертикального двоичного представления полубайтов от 0x0 до 0xF:

  0101010101010101 bit #0 <- Y = 0
  0011001100110011 bit #1
  0000111100001111 bit #2
  0000000011111111 bit #3 <- Y = 3
  ----------------
  0123456789ABCDEF
  ^              ^
X = 0          X = 15

Таким образом, каждое положение (X, Y) в этой схеме может быть выражен в виде Y-го бита X: X & (1 << Y). Мы также можем изолировать этот бит с: (X >> Y) & 1. Вместо того , чтобы отслеживать X и Y, мы итерация по одной переменной в nдиапазоне от 0 до 63. Таким образом, формула приобретает следующий вид : (n >> (n >> 4)) & 1. На самом деле проще выполнить итерацию от 63 до 0, поэтому строка строится в обратном порядке. Другими словами, символ n-1 добавляется слева от символа n .

Как примечание, рекурсия не приносит ничего кроме короткого кода.

Код без переноса строки имеет длину 35 байт:

f=(n=64)=>n--?f(n)+(n>>(n>>4)&1):''

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

демонстрация

f=(n=64)=>n--?f(n)+(!n|n&15?'':`
`)+(n>>(n>>4)&1):''

console.log(f());


В ideone с обоими языками JavaScript, не скомпилированными в приведенном выше примере, есть еще один… Хорошо, что идея одной рекурсивной функции ...
RosLuP

Что потребуется для разделения после 35 байтов?
Тит

@ Titus - Хорошо. На первый взгляд, у меня нет хорошего решения для этого. Вот (очень плохая) попытка: (f=(n=64)=>n--?f(n)+(n>>(n>>4)&1):'')().match(/.{16}/g).join`\n` (63 байта)
Арно

хм ... и .replace(/.{16}/g,"$0\n")имеет такую ​​же длину. Печалька.
Тит


1

NARS2000 APL, 22

"01"[⊖1+(4⍴2)⊤(⍳16)-1]

Получено из ответа APL от Marinus, который, похоже, не работает на NARS2000.

Создать вектор

      ⍳16
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

Изменить на ноль

      (⍳16)-1
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Создать форму для кодирования

      (4⍴2)
2 2 2 2

шифровать

      (4⍴2)⊤(⍳16)-1
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1

Настроить для индексации на основе 1

      1+(4⍴2)⊤(⍳16)-1
1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2
1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2
1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2
1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2

Обратная основная ось

      ⊖1+(4⍴2)⊤(⍳16)-1
1 2 1 2 1 2 1 2 1 2 1 2 1 2 1 2
1 1 2 2 1 1 2 2 1 1 2 2 1 1 2 2
1 1 1 1 2 2 2 2 1 1 1 1 2 2 2 2
1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2

Показатель

      "01"[⊖1+(4⍴2)⊤(⍳16)-1]
0101010101010101
0011001100110011
0000111100001111
0000000011111111

Вы можете установить ⎕IO на 0, чтобы вам не пришлось настраивать индексирование на основе 1. Это снижает его до 16 символов.
Элиас Мартенсон,

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

1

C 73 символа

i;main(){for(;i<64;)i&15||puts(""),putchar(48|1&~0xFF0F0F33335555>>i++);}

Это всего лишь общее решение для вывода 64 бит в четыре 16-битных блока; вам просто нужно изменить номер0xFF0F0F33335555 чтобы вывести другую битовую последовательность.

упрощенный и безгольфовый:

int main() {
    int i;
    for(i = 0; i < 64; i++) {
        if(i % 16 == 0) {
            puts("");
        }
        int bit = ~0xFF0F0F33335555 >> i;
        bit &= 1;
        putchar('0' + bit);
    }
}

1

Хаскелл, 73

Yikes, 73 символа! Я не могу, ради бога, сделать это хоть немного меньше.

r=replicate
f n=r(div 8n)("01">>=r n)>>=id
main=mapM(putStrLn.f)[1,2,4,8]

Самое печальное в этом то, что если вы хотите отобразить вывод, используя bash, вам понадобится всего 74 символа.



1

инка2 ,33 27 24

4 16#(,`2|(~16)%.2^~4){D

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

Объяснение:

4 16#(,`2|(~16)%.2^~4){D
          (~16)               integers 0 .. 15 
                 2^~4         first 4 powers of 2: 1 2 4 8
          (~16)%.2^~4         division table
        2|                    mod 2 (and floor)
       `                      transpose
      ,                       ravel
     (               ){D      map to chars '0'..'9'
4 16#                         reshape to 4x16

Некоторые скобки должны быть излишними, но, очевидно, есть некоторые остающиеся проблемы с моей интерпретацией грамматики. И "ravel => map => reshape" действительно неуклюжий: карта должна быть умнее. Редактировать: исправления позволяют устранить паренсы.


Факторинг базового преобразования в отдельную функцию N:x|y%.x^~1+[]/x.yдает19 16- символьная версия.

4 16#(,`2N~16){D

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

инка2, 2

U0

1

Пиф 24/26

Самым коротким методом был ответ grc, переведенный на Pyth, который мне показался дешевым, поэтому я сделал свой собственный метод:

Шахта: 26 символов

 mpbjk*/8dS*d[0 1)[1 2 4 8

grc's: 24 символа

Fd[1 2 4 8)*/8d+*\0d*\1d

1

C ++ 130

Преобразует шестнадцатеричное в двоичное

#define B std::bitset<16>
#define C(x) cout<<x<<endl;
void main(){
B a(0xFF),b(0xF0F),c(0x3333),d(0x5555);
C(d)C(c)C(b)C(a)
}

1

Haskell (Lambdabot), 47 байт

unlines$reverse$transpose$replicateM 4['1','0']

Это обманчиво, потому что он использует transpose из Data.List и replicateM из Control.Monad, однако оба загружаются по умолчанию из Lambdabot.

Также я уверен, что есть возможности для улучшения, просто хотел поделиться идеей


1

Юлия (39 байт)

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

hcat(map(x->collect(bin(x,4)),0:15)...)

Возвращает

[0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
 0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 
 0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1
 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1]  

Объяснение:

  • bin(x,4) - Преобразовать int в двоичное целое число с отступом до 4 символов.
  • collect(_) - Разбить строку на массив символов.
  • map(x->_,0:15) - Сделайте это для первых 16 цифр в диапазоне.
  • hcat(_...) - Splat и горизонтально объединить в матрицу.

1

С 83 77 76 74 71

x;f(n){for(;x<4;x++,puts(""))for(n=0;n<16;)putchar(49-!(n++&(1<<x)));}

Довольно просто.

x;
f(n){
    for(;x<4;x++,puts(""))
        for(n=0;n<16;)
            putchar(49-!(n++&(1<<x)));
}

1
Есть простое сохранение 2, если не использовать ?:, и другое сохранение 1, перемещая a ++.
Питер Тейлор

Сохранено 3 путем изменения mainна f. lol
luser droog

1

R, 53 41 байт

Перевод ответа @ grc на python. Урезал 12 байтов от исходного перевода с помощью аргументов rep()'s' eachи lengthаргументов (и частичного сопоставления аргументов) и запоминания того, что 0:1эквивалентно c(0,1).

for(n in 2^(0:3))print(rep(0:1,e=n,l=16))

for(n in 2^(0:3))print(rep(c(rep(0,n),rep(1,n)),8/n))

Вы также можете попытаться перевести ответ @ Gareth's J примерно так (34 байта):

t(e1071::bincombinations(4))[4:1,]

Однако он использует функцию, которая не является частью base R, и выводит матрицу, которую трудно отформатировать в точный печатный текст, как в спецификации.

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