Створіть таблицю пошуку універсальної бінарної функції


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

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 (чорт теж короткий!)
luser droog

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

Приємно бачити щось коротше, ніж Гольфскрипт ...
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. Імена змінних, що починаються з quad, є системними змінними, які змінюють середовище. IO = "індекс походження".
luser droog

Збережіть байт: (4⍴2)⊤2⊥⍣¯1
Адама

6

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

⁴ḶBUz0Y

Спробуйте в Інтернеті!

Дякуємо Деннісу за допомогу. Ось перше повідомлення, ось останнє (також відбулися інші дискусії). З його допомогою я, мабуть, (майже) зафіксував партитуру.


Оскільки мова є новою, ніж питання, я не можу прийняти її як відповідь. Однозначно в бігу за щедротою, тхо!
luser droog

@luserdroog Це добре. Але, я вважав, що виклик є новішим.
Ерік Аутгольфер

Я знаю, що ти маєш на увазі, це здається не так давно, як я це розмістив. Але навіть моя власна інка2, у 2 роки, занадто молода мова.
luser droog

+1 для кодового гольфу від 42 до 7. Це те, що ви не бачите щодня (якщо це не зроблено навмисно).
Kevin Cruijssen

1
@KevinCruijssen Чому це потрібно робити коли-небудь спеціально? Я просто новичок Jelly (добре знаю Python 2 і 3), тому я це робив на строковому шляху, тоді як мені "потрібно ставитися до Jelly як до мови, що керує масивом".
Ерік Аутгольфер

5

/// , 51 байт

Спробуйте в Інтернеті

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

1
Ласкаво просимо до PPCG! Ти побив мене до цього.
Erik the Outgolfer

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

Я переношу це до Sprects.
Ерік Аутгольфер

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}%
Говард

@Howard, я думаю, що це zipмає повернути масив масивів, але насправді, здається, він повертає масив Ruby масивів (це моя найкраща здогадка). Якими б елементами не були, застосування `` `` `до них не впливає на спосіб друку, що на відміну від будь-якого із 4 типів даних GolfScript. Ти маєш рацію, що, ','-здається, перетворює їх у звичайні масиви: приємний трюк.
Пітер Тейлор

Здається,
виведете

@aditsu, працює над демонстрацією в Інтернеті . Цікаво, чому різниця. Рубінна версія, можливо?
Пітер Тейлор

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)

Бітшіфт!
А також XOR і трохи рекурсії.

Перше, що слід помітити, це те, що якщо ми візьмемо будь-який рядок, і ви змістить його (# безперервного 0) / 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.
Зауважте, що сума, яку ми зміщуємо вдвічі, наполовину.
Тепер ми просто називаємо цю функцію рекурсивно, з 2 аргументами. Ціле значення цього рядка і N, на скільки нам потрібно зрушити. Коли ми повторюємось, просто передайте зміщене значення XOR'ed і n / 2.

"0".repeat(n)

полягає в прокладці 0 на початку кожного рядка, оскільки ToString виводить 0 з початку.


+1 Дуже круто. Я раніше не помічав цієї картини.
luser droog

Пару байтів можна відрізати, перемістивши біт на 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))})

(Перерва лінії для зручності).

Прикро, що мені довелося возитися з прокладкою з провідними нулями, але суть цього коду є просто відображенням цільового бінарного результату в Базі 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()s.
NinjaBearMonkey




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, не компільований в exapme, вище, є один нехай більше .... Добре уявлення про одну рекурсивну функцію ...
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 => переформатувати" насправді незграбно: карта повинна бути розумнішою. Редагувати: виправлення помилок дозволяють видалити паролі.


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

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

І хоча я тут все одно обманюю, я пішов вперед і зробив це вбудованою функцією. Але, незважаючи на те, що це ніладієва функція (не вимагає аргументу), немає підтримки ніладичних функцій, і вона повинна поставлятися з фіктивним аргументом.

інка2, 2

U0

1

Піф 24/26

Найкоротший метод був GRC в відповідь переведений на Pyth , який я відчував був дешевий , тому я зробив свій власний метод:

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

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

grc: 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']

Якийсь хитрий, оскільки він використовує транспонирование з Data.List і реплікаціюM з 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(_) - Розділити рядок на масив char.
  • map(x->_,0:15) - Зробіть це для перших 16 цифр у діапазоні.
  • hcat(_...) - Плеска та горизонтальне з'єднання в матрицю.

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 за допомогою не використання ?:, а інше збереження за допомогою переміщення a ++.
Пітер Тейлор

Збережено 3, змінивши mainна f. lol
luser droog

1

R, 53 41 байт

Переклад відповіді python @ grc. Поголив 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))

Ви також можете спробувати переклад J-відповіді @ Gareth приблизно так (34 байти):

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

Однак він використовує функцію, яка не є частиною базової R, і виводить матрицю, яку важко відформатувати в точний друкований текст, як у специфікації.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.