生成通用二进制函数查找表


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


是否接受前导或尾随的换行符?
泰特斯(Titus)

是的,多余的换行符就可以了。
luser droog

Answers:


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

我们需要删除空格吗?综观其他Ĵ答案似乎我们这样做,我们将需要增加3个字符,并借1":一月的答案


1
很好的解释风格。+1(该死的短片,也是!)
luser droog

一看到彼得的Golfscript答案,我就知道自己可以做得更好。好吧,您已经做到了。
John Dvorak

很高兴看到比Golfscript短的东西...
fuenfundachtzig 2013年


@luserdroog哇。那是很多代码。虽然比J源代码更具可读性。:-) 很酷。
Gareth

13

python 2,40

for n in 1,2,4,8:print 8/n*('0'*n+'1'*n)

7

APL(14)

假设⎕IO=0(这是一个设置):

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

说明:

  • ⍳16:数字[0,16)
  • (4⍴2)⊤:使用4位数字以2为基数编码每个数字
  • :水平反转(因此MSB最终位于顶部)
  • ⎕D[... ]:从⎕D字符串中选择这些值0123456789。(在数值矩阵之间显示有空格,而在字符矩阵之间没有空格。因此,这会将每个数值转换为char之一'0' '1')。

源代码中的第一个字符应该看起来像正方形,还是我仍然缺少某些字体?
Tim Seguine 2014年

@TimSeguine是的,它是一个正方形,在APL文献中称为四边形。以quad开头的变量名称是会更改环境的系统变量。IO =“索引原点”。
luser droog

保存一个字节:(4⍴2)⊤2⊥⍣¯1
亚当

6

Jelly42个 7 字节(无竞争)

⁴ḶBUz0Y

在线尝试!

感谢丹尼斯的帮助。是第一个消息,是最后一个消息(也进行了其他讨论)。在他的帮助下,我显然(几乎)将比分平方根了。


由于该语言比问题新颖,因此我无法接受它作为答案。绝对是在争取赏金,,!
luser droog

@luserdroog很好。但是,我认为挑战是新的。
Erik the Outgolfer

我知道您的意思,很早以前我就发布了。但是,即使我自己2岁的inca2语言也太年轻。
luser droog

为42到7的代码高尔夫+1。那是您每天都看不到的东西(除非有目的地这样做)。
凯文·克鲁伊森

1
@KevinCruijssen为什么要故意这样做?我只是Jelly的新手(我非常了解Python 2和3),所以我以字符串的方式做到了这一点,而我“则需要将Jelly视为数组操作语言”。
暴民埃里克


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数据类型中的任何一种都不相同。您是对的,','-似乎可以将它们转换为普通数组:不错的技巧。
彼得·泰勒

似乎在这里输出4条额外的零线
aditsu

@aditsu, 从事在线演示。我想知道为什么会有所不同。Ruby版本,也许吗?
彼得·泰勒

3

果酱-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

这些按位异或给我们

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| 将[每个单元格]除以2后计算出余数
  • <. 值为0或1的楼层
  • 1": 每个单元格用一个字符格式化表格

我觉得floor应该没有必要。的域2|已经是0或1,对吧?
luser droog 2015年

@luserdroog |在浮点数上运行2|3.251.25。我们不想要那个。
John Dvorak 2015年

2

GolfScript,19个字符

另一种GolfScript方法

4,{2\?{&!!}+16,%n}%

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)

say照常为+1 。双0不是错别字:)

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

无需为加1 sayperl -e'...'是标准的,这要求perl -E'...'字节数不增加。无论如何,我认为它是在决定代码高尔夫元-M5.01是免费的。
msh210 '16

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'))。这种方法使用换行符而不是4 alert()s。
NinjaBearMonkey 2014年


2

MATL非竞争),8个字节

16:qYB!P

在线尝试!

说明

16:    % Generate range [1 2 ... 16]
q      % Subtract 1, element-wise
YB     % Convert to binary. Gives a 16×4 char array. Each original number is a row
!      % Transpose
P      % Reverse vertically. Implicitly display

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)可以表示为X:的第Y位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)

@Titus-好吧。乍一看,我对此没有任何好的解决方案。这是一次(非常糟糕的)尝试:(f=(n=64)=>n--?f(n)+(n>>(n>>4)&1):'')().match(/.{16}/g).join`\n` (63个字节)
Arnauld

嗯...,并.replace(/.{16}/g,"$0\n")具有相同的长度。太糟糕了。
泰特斯

2

Bash + coreutils,65个字节

不是最短的,也不是最长的:

for i in {1,2,4,8};{ eval echo \$\[\({0..15}\&$i\)/$i];}|tr -d \ 

(最后一个字符是空格)

在线尝试


1

NARS2000 APL,22

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

源自marinus的APL答案,该答案在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个字符。
EliasMårtenson2014年

是的,但是我担心这与APL的其他答案过于相似,根本不值得在这里出现。
luser droog 2014年

1

C,73个字符

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

这只是在四个16位块中输出64位的通用解决方案。您只需要更改号码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

JavaScript(ES5)69

for(x="";4>x;x++){z="";for(n=0;16>n;)z+=1-!(n++&1<<x);console.log(z)}


1

印加233 27 24

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

这是基于Jan Dvorak的答案。从昨天的错误修正中开始,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

而且无论如何我在这里作弊时,我都将其设为内置函数。但是,即使它是一个niladic函数(不需要参数),也不支持niladic函数,并且必须为其提供伪参数。

印加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']

还挺cheaty因为它使用由和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(_) -将字符串拆分为char数组。
  • map(x->_,0:15) -对范围的前16位数字执行此操作。
  • hcat(_...) -Splat并水平连接成矩阵。

1

C 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 ++
彼得·泰勒

通过更改main为保存了3 f。大声笑
luser droog'n

1

R,53 41字节

@grc的python答案的翻译。通过使用rep()eachlength参数(和部分参数匹配),并记住与0:1等效的内容,从原始翻译中削减了12个字节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的J答案,类似以下内容(34字节):

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

但是,它使用的函数不是base R的一部分,并且输出一个矩阵,该矩阵很难像规范中那样格式化为精确的打印文本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.