实现Malbolge的“疯狂”运营商


41

Malbolge编程语言的许多独特功能之一是其高度直观的OP运算符,在文档和源代码中仅称为“ op”,而通常称为“ crazy”运算符。正如该语言的创建者本·奥尔姆斯特德(Ben Olmstead)在其文档中所描述的那样:“ 不要寻找模式,它就在那里。”

op是“ tritwise”运算符-它对两个自变量的相应三进制数进行运算。对于每个trit(三进制位),op的结果由以下查找表给出:

           a
op(a,b)  0 1 2
       +-------
     0 | 1 0 0
   b 1 | 1 0 2
     2 | 2 2 1

例如,要进行计算op(12345, 54321),请首先在三进制中写出两个数字,然后在表中查找每对三叉戟:

   0121221020   (12345_3)
op 2202111220   (54321_3)
--------------
   2202220211   (54616_3)

最后重要的一点是在Malbolge所有值都是10个trits宽,所以输入值应该用零到10的宽度被填充(例如,op(0, 0)1111111111在三元)。

您的任务是取两个0≤ ab<59049的整数作为输入,并输出的整数值op(a,b)

测试用例(格式为a b op(a,b)):

0 0 29524
1 2 29525
59048 5 7
36905 2214 0
11355 1131 20650
12345 54321 54616

这是参考实现(直接从Malbolge源代码复制)。


28
马尔博能回答这个问题吗?;)
显示名称

3
我猜Malbolge现在是一种很好的高尔夫语言!
伊桑(Ethan)'18年

7
对于它的价值,54616_3并不意味着“另一件事是十进制数54616,但表示为基数三”。它的意思是“ 54616以3为底读”。当然,您不能做到这一点(Valve无法在其中数位)。如果您_3完全放弃了它,那么它仍然可能是一样清晰,而且更加准确。
尼克·哈特利

@Orangesandlemons我猜只是在Malbolge中使用运算符会属于标准漏洞。可以使用其他代码重新实现它。
圣保罗Ebermann

7
@PaŭloEbermann不,这不是漏洞
user202729

Answers:



28

JavaScript(ES7),56个字节

f=(a,b,k=9)=>~k&&(a%3|b%3<<9|8)**2%82%3+3*f(a/3,b/3,k-1)

在线尝试!

怎么样?

鉴于b[ 0..2 ],我们计算:一种b[0..2]

F一种b=一种+512b+82823

导致:

 a | b | 512b | a + 512b |  + 8 | squared | MOD 82 | MOD 3
---+---+------+----------+------+---------+--------+-------
 0 | 0 |    0 |      0   |    8 |      64 |   64   |   1                  a
 1 | 0 |    0 |      1   |    9 |      81 |   81   |   0                0 1 2
 2 | 0 |    0 |      2   |   10 |     100 |   18   |   0              +-------
 0 | 1 |  512 |    512   |  520 |  270400 |   46   |   1            0 | 1 0 0
 1 | 1 |  512 |    513   |  521 |  271441 |   21   |   0    -->   b 1 | 1 0 2
 2 | 1 |  512 |    514   |  522 |  272484 |   80   |   2            2 | 2 2 1
 0 | 2 | 1024 |   1024   | 1032 | 1065024 |    8   |   2
 1 | 2 | 1024 |   1025   | 1033 | 1067089 |   23   |   2
 2 | 2 | 1024 |   1026   | 1034 | 1069156 |   40   |   1

功能选择

表单还有其他几种可能的候选函数:

FķCp一种b=一种+ķb+Cp3

最短的一种是:

F一种b=一种+5b+24253

但是的好处是,它可以用按位运算符执行,因此隐式丢弃了一种+512b+8 b。这就是为什么我们可以将它们简单地除以 3,而无需在每次迭代之间舍入。一种b3

已评论

f = (a, b,            // given the input integers a and b
           k = 9) =>  // and starting with k = 9
  ~k &&               // if k is not equal to -1:
    ( a % 3           //   compute (a mod 3)
      | b % 3 << 9    //   add 512 * (b mod 3)
      | 8             //   add 8
    ) ** 2            //   square the result
    % 82              //   apply modulo 82
    % 3               //   apply modulo 3, leading to crazy(a % 3, b % 3)
    + 3 * f(          //   add 3 times the result of a recursive call with:
      a / 3,          //     a / 3  \__ no rounding required
      b / 3,          //     b / 3  /   (see 'Function choice')
      k - 1           //     k - 1
    )                 //   end of recursive call

我认为(1581093>>b%3*2+a%3*8&3)可以节省整个字节!
尼尔

@Neil不幸的是,我通过a/3并且b/3没有舍入。因此会失败。
阿纳尔德

9
有趣的是,您发现了不存在的模式。
暴民埃里克(Erik the Outgolfer)'18年

没有任何理由,更喜欢k = 9 ... => ~k && ...k = 10 ... => k && ...
法尔科

1
@Falco不,它既不短也不高效。我倾向于使用0索引的东西,所以我宁愿模仿而for(k=9;k>=0;k--)不是for(k=10;k>=1;k--)
Arnauld

13

05AB1E,18个字节

码:

3Tm+3Bø5+3m5(^3%3β

使用05AB1E编码。在线尝试!


算法说明

为了获得用零填充的数字,我们需要将两个数字相加59049(因为三进制中的59049是10000000000)。我们不必离开了领先1。我们将数字从十进制转换为三进制,并将每对数字作为自己的数字连接起来。1个1个0

例如,对于输入1234554321,这些映射到:

123451个01个21个221个020543211个22021个1个1个220

给出以下连接的整数列表:

1121220122121112220

这些整数需要由OP中的给定查找表映射。我们目前使用的公式这些数字映射到其相应trits(01个100)为:

FX=X+53-5 模 3

表示按位异或功能。

最终,在将此函数映射到连接的整数列表之后,我们将此结果列表视为以3为底的数字,并将其从3转换为十进制。


代码说明

3Tm+                  # Add 59049 to pad the ternary number with zeroes.
    3B                # Convert to base 3.
      ø               # Zip the list to get each joined integer.
       5+             # Add 5 to each element.
         3m           # Raise each element to the power of 3.
           5(^        # XOR each element with -5.
              3%      # Modulo each element with 3.
                3β    # Convert from base 3 to decimal.

可以3Tm+3Bø19sm74%3%3β打高尔夫球吗?
乔纳森·艾伦

@JonathanAllan尼斯找到了!但是,如果不使用其他种类的黑魔法公式,似乎无法进一步打高尔夫球。
阿德南'18

11

R64 62字节

function(a,b,x=3^(9:0))30801%/%x[a%/%x%%3*3+b%/%x%%3+1]%%3%*%x

在线尝试!

感谢JAD的一些黑魔法高尔夫技巧和-2个字节!

30801转换为10-trit三进制整数1120020210时,当读取各列时,它只会在操作表中添加尾随零。然后,我们转换的三元数字ab的elementwise成整数和使用,作为一个索引的三元数字30801


1
62字节的操作符优先级!
JAD

1
是的,您首先要x使用编制索引[.*]。然后所有的%any%操作发生。有趣的是,如果您看到的30801%/%x%%3f=function(x)30801%/%x%%3,那f(x[index]) == (f(x))[index]。保存括号:)
JAD

@JAD令人着迷!正如我上面评论的,基本上是黑魔法。
朱塞佩

1
我会很高兴地承认,这花了很多时间:P
JAD 18'7

10

C(gcc)74 72 71字节

f(a,b,i,r){for(r=0,i=59049;i/=3;)r+=(108609>>a/i%3*2+b/i%3*6&3)*i;i=r;}

在线尝试!

分解

真相表

           a
op(a,b)  0 1 2
       +-------
     0 | 1 0 0
   b 1 | 1 0 2
     2 | 2 2 1

可以认为是3x3数组,其中a是列,b是行。将其转换为一维列表可以得到100102221。为节省空间,我们避免使用列表和字符串,而是将其改为数字。为此,我们翻转顺序并将每个Trit转换为2位数字。将它们粘在一起,我们有一个二进制数,可以通过向右移动2 * (b * 3 + a)和屏蔽来“索引” :

 1 0 0 1 0 2 2 2 1
 1 2 2 2 0 1 0 0 1
011010100001000001

接下来,我们使用运算优先级的力量对表达式进行按摩,使其成为上面的可憎之处。

3 ^ 9 = 19683,所以这是一个很好的循环限制。由于我们每次将计数器乘以3,因此我们可以将限制写为2e4。同样,我们也避免了麻烦pow()或类似的麻烦。

再次考虑,让我们从3 ^ 10开始,然后进行预循环除法和向下测试。




6

果冻 23  18 字节

-1感谢Outgolfer的Erik(重新安排3*⁵¤⁵3*

⁵3*+b3Zḅ3ị⁽½Ṡb3¤ḅ3

接受两个整数列表的单子链接。

在线尝试!或见一个测试套件

⁹*%733%3 比一个长 ị⁽½Ṡb3¤ :(

怎么样?

⁵3*+b3Zḅ3ị⁽½Ṡb3¤ḅ3 - Link: [a, b]      e.g. [11355,1131]
⁵                  - literal ten            10
 3                 - literal three          3
  *                - exponentiation         59049
   +               - addition (vectorises)  [70404,60180]
     3             - literal three          3
    b              - to base (vectorises)   [[1,0,1,2,0,1,2,0,1,2,0],[1,0,0,0,1,1,1,2,2,2,0]]
      Z            - transpose              [[1,1],[0,0],[1,0],[2,0],[0,1],[1,1],[2,1],[0,2],[1,2],[2,2],[0,0]]
        3          - literal three          3
       ḅ           - from base (vectorises) [4,0,3,6,1,4,7,2,5,8,0]
               ¤   - nilad followed by link(s) as a nilad:
          ⁽½Ṡ      -   literal 3706         3706
              3    -   literal three        3
             b     -   to base              [1,2,0,0,2,0,2,1]
         ị         - index into             [0,1,0,0,1,0,2,2,2,1,1]
                 3 - literal three          3
                ḅ  - from base              20650

同样是18:(⁵3*+b3ZḌ19*%74%3ḅ3在从成对的三位转换成10进制然后取19到该幂的模数后使用魔术公式,以74为模,以3为模以获取所需的输出Trits-在Python中通过搜索找到)


18个字节(注意:确实应该y 0内置一个“ prepend s”)
Outgolfer的Erik,18年

gh,我觉得这很尴尬。谢谢!
乔纳森·艾伦

许多事情看起来很尴尬,有时您必须习惯它们。:P
暴民埃里克(Erik the Outgolfer)'18年


4

J,37个字节

((3 3$d 30801){~{@,.)&.(d=.(10$3)&#:)

说明:

((3 3$d 30801){~{@,.)&.(d=.(10$3)&#:)   
                       (d=.(10$3)&#:)   convert to 10 trits, and name this function as d
                     &.                 ... which is done on both args and inverted on the result
                {@,.                    make boxed indices: 1 2 3 4 {@,. 5 6 7 8  ->  1 5 ; 2 6 ; 3 7 ; 4 8
              {~                        index out of a lookup table
 (3 3$d 30801)                          reusing the trits conversion function to make the table

最终变得相对可读,tbh。


欢迎来到PPCG!是一个测试套件-我从Galen Ivanov的答案中窃取了包装代码。
乔纳森·艾伦

欢迎使用PPCG!不错的解决方案!是指向它的TIO链接。
加伦·伊凡诺夫



@FrownyFrog真好!
约拿


3

木炭,31字节

I↨³⮌⭆χ§200211⁺∨﹪÷θX³ι³¦⁴﹪÷ηX³ι³

在线尝试!链接是详细版本的代码。说明:

     χ                          Predefined variable 10
    ⭆                           Map over implicit range and join
                    ι        ι  Current index
                  X³       X³   Power of 3
                 θ              Input `a`
                          η     Input `b`
                ÷        ÷      Integer divide
               ﹪     ³  ﹪     ³ Modulo by 3
              ∨       ¦⁴        Replace zero ternary digit of `a` with 4
             ⁺                  Add
      §200211                   Index into literal string `200211`
   ⮌                            Reverse
 ↨³                             Convert from base 3
I                               Cast to string
                                Implicitly print

替代解决方案,也是31个字节:

I↨³E↨⁺X³χ賧200211⁺∨ι⁴§↨⁺X³χη³κ

在线尝试!链接是详细版本的代码。

        χ                  χ    Predefined variable 10
      X³                 X³     Power of 3 i.e. 59049
         θ                      Input `a`
                            η   Input `b`
     ⁺                  ⁺       Sum
    ↨     ³            ↨     ³  Convert to base 3
   E                            Map over elements
                    ι           Current ternary digit of `a`
                   ∨ ⁴          Replace zero with 4
                      §       κ Index into ternary digits of `b`
                  ⁺             Add
           §200211              Index into literal string `200211`
 ↨³                             Convert from base 3
I                               Cast to string
                                Implicitly print

2

Ruby,70个字节

->a,b,l=10{l>0?6883.digits(3)[8-b%3*3-a%3]*3**(10-l)+f[a/3,b/3,l-1]:0}

在线尝试!

分解ab递归直到每个得到10位数字。6883给出展平的三元表(反转)。通过将乘以从三进制重构为十进制3**(10-l)



2

J,43个字节

3#.((3 3$t 6883){~<@,~"0)&(_10{.t=.3&#.inv)

当然可以打得更远。

说明:

                         &(               ) - for both arguments
                                t=.3&#.inv  - convert to base 3 (and name the verb t)
                           _10{.            - pad left with zeroes
   (              <@,~"0)                   - box the zipped pairs (for indexing)
    (3 3$t 6883)                            - the lookup table
                {~                          - use the pairs as indeces in the table
3#.                                         - back to decimal  

在线尝试!



2

Pyth 26 25 24字节

由于@ErikTheOutgolfer,节省了1个字节

保存另一个字节,灵感来自@JonathanAllan的答案

im@j3422 3id3Cm.[0Tjd3Q3

输入是一个2元素列表[a,b]。在线试用这里,或验证所有测试用例在这里

im@j3422 3id3Cm.[0Tjd3Q3   Implicit: Q=eval(input())
              m       Q    Map each element d of the input using:
                   jd3       Convert to base 3
               .[0T          Pad to length 10 with 0's
             C             Transpose
 m                         Map each element d of the above using:
   j3422 3                   The lookup table [1,1,2,0,0,2,0,2]
  @                          Modular index into the above using
          id3                Convert d to base 10 from base 3
i                      3   Convert to base 10 from base 3, implicit print



1

Japt24 23字节

让Japt成为本月语言来助您一臂之力来助您一臂之力-我完全希望对此感到不满!

以相反的顺序将输入作为整数数组(即[b,a])。

ms3 ùTA y_n3 g6883ì3Ãì3

试试吧

ms3 ùTA y_n3 g6883ì3Ãì3      :Implicit input of array U=[b,a]
m                            :Map
 s3                          :  Convert to base-3 string
    ù                        :Left pad each
     T                       :  With zero
      A                      :  To length 10
        y                    :Transpose
         _                   :Map
          n3                 :  Convert from base-3 string to decimal
             g               :  Index into
              6883ì3         :    6883 converted to a base-3 digit array
                    Ã        :End map
                     ì3      :Convert from base-3 digit array to decimal

0

Perl -p 5,102字节

sub t{map{("@_"%3,$_[0]/=3)[0]}0..9}@a=t$_;@b=t<>}{$\=(1,1,2,0,0,2,0,2,1)[(3*pop@a)+pop@b]+$\*3while@a

在线尝试!


0

Wolfram语言(Mathematica)75 72 60字节

(d=IntegerDigits)[6883,3][[{1,3}.d[#,3,10]+1]]~FromDigits~3&

在线尝试!

非高尔夫版本:

M[{a_, b_}] := 
  FromDigits[{1, 0, 0, 1, 0, 2, 2, 2, 1}[[
    IntegerDigits[a, 3, 10] + 3*IntegerDigits[b, 3, 10] + 1
  ]], 3];

ab都转换为十重触发列表,然后成对使用,作为2D索引进入数字查找表{1, 0, 0, 1, 0, 2, 2, 2, 1}。结果再次被解释为十重列表,然后转换回整数形式。

查找表被编码为IntegerDigits[6883,3],这很短,因为我们正在回收IntegerDigits符号。

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.