Implemente el operador "loco" de Malbolge

41

Una de las muchas características únicas del lenguaje de programación Malbolge es su OPoperador muy poco intuitivo , conocido como "op" en la documentación y el código fuente, pero conocido popularmente como el operador "loco". Según lo descrito por Ben Olmstead, el creador del lenguaje, en su documentación: " no busque el patrón, no está allí ".

op es un operador "tritwise": opera en los dígitos ternarios correspondientes de sus dos argumentos. Para cada trit (bit ternario), el resultado de op viene dado por la siguiente tabla de búsqueda:

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

Por ejemplo, para calcular op(12345, 54321), primero escriba ambos números en ternario y luego busque cada par de trits en la tabla:

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

El último punto importante es que todos los valores en Malbolge tienen 10 trits de ancho, por lo que los valores de entrada deben rellenarse con ceros a un ancho de 10. (Por ejemplo, op(0, 0)es 1111111111ternario).

Su tarea es tomar dos enteros 0 ≤ a, b<59049 como entrada y generar el valor entero de op(a,b).

Casos de prueba (en el formato a b op(a,b)):

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

Aquí hay una implementación de referencia (copiada directamente del código fuente de Malbolge).

Pomo de la puerta
fuente
28
¿Se puede responder esto en Malboge? ;)
Nombre para mostrar
3
¡Supongo que Malbolge es un buen lenguaje de golf ahora!
Ethan
77
Por lo que vale, 54616_3no significa "esta otra cosa es el número decimal 54616, pero se representa como base tres". Significa "Leer 54616como base 3". Lo cual, por supuesto, no puede hacer (hay dígitos que Valve no puede contar allí). Probablemente todavía sería igual de claro si se deshiciera del _3todo, y más preciso.
Nic Hartley
@Orangesandlemons Supongo que solo usar el operador en Malbolge estaría dentro del vacío legal estándar. Reimplementarlo usando un código diferente estaría bien.
Paŭlo Ebermann
77
@ PaŭloEbermann No, eso no es una escapatoria .
user202729

Respuestas:

43

C (gcc) , 99 98 96 bytes

  • Guardado un byte gracias a ceilingcat ; golf 19683a L'䳣'.
  • Guardado dos bytes; golf 108609a L'𚡁'.
M,a,l,b,o;L(g,e){for(o=b=L'䳣',l=0;o/=2.4;b/=3)M=g/b,g%=b,a=e/b,e%=b,l+=b*(L'𚡁'>>M+6*a+M&3);g=l;}

Pruébalo en línea!

Jonathan Frech
fuente
14
¡Me gusta el esquema de nombres!
Matthieu M.
28

JavaScript (ES7), 56 bytes

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

Pruébalo en línea!

¿Cómo?

Dado y b en [ 0..2 ] , calculamos:ab[0..2]

f(a,b)=((a+512b+8)2mod82)mod3

Llevando a:

 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

Elección de funciones

Hay varias otras posibles funciones candidatas del formulario:

fk,c,p,m(a,b)=((a+kb+c)pmodm)mod3

Uno de los más cortos es:

f(a,b)=((a+5b+2)4mod25)mod3

(a+512b+8)ab3

Comentado

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
Arnauld
fuente
Creo que (1581093>>b%3*2+a%3*8&3)ahorra un byte completo!
Neil
@Neil Desafortunadamente, estoy pasando a/3y b/3sin redondear. Eso fallaría por eso.
Arnauld
99
Interesante cómo encontraste un patrón que no existe.
Erik the Outgolfer
¿Hay alguna razón para preferir k = 9 ... => ~k && ...a k = 10 ... => k && ...?
Falco
1
@Falco No, no es más corto ni más eficiente de ninguna manera. Yo acababa tienden a preferir las cosas 0-indexada, por lo que prefiero imitan for(k=9;k>=0;k--)a for(k=10;k>=1;k--).
Arnauld
13

05AB1E , 18 bytes

Código:

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

Utiliza la codificación 05AB1E . Pruébalo en línea!


Explicación del algoritmo

(1,1)0

Por ejemplo, para las entradas 12345 y 54321 , estas se asignan a:

12345101212210205432112202111220

Lo que da la siguiente lista de enteros unidos:

11,2,12,20,12,21,21,11,2,22,0

01,100,

f(x)=((x+5)35) mod 3

Finalmente, después de asignar esta función en la lista de enteros unidos, tratamos esta lista resultante como un número representado en la base 3 y la convertimos de la base 3 a decimal.


Explicación del Código

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.
Adnan
fuente
Se 3Tm+3Bø19sm74%3%3βpuede jugar al golf?
Jonathan Allan
@JonathanAllan ¡Buen hallazgo! Sin embargo, parece imposible seguir jugando al golf sin usar otro tipo de fórmula de magia negra.
Adnan
11

R , 64 62 bytes

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

Pruébalo en línea!

¡Gracias a JAD por algunos trucos de golf de magia negra y -2 bytes!

30801, cuando se convierte en un entero ternario de 10 trits, es el 1120020210que simplemente agrega un cero final a la tabla de operaciones, cuando se leen las columnas. Luego convertimos los dígitos ternarios de ay belementwise en un número entero y lo usamos como índice en los dígitos ternarios de 30801.

Giuseppe
fuente
1
62 bytes ¡ Yay para la precedencia del operador!
JAD
1
Sí, de esta manera, primero indexas xusando [.*]. Entonces todas las %any%operaciones suceden. La parte divertida es que si ves 30801%/%x%%3como f=function(x)30801%/%x%%3, eso f(x[index]) == (f(x))[index]. Salvar las llaves :)
JAD
@JAD fascinante! Y como comento anteriormente, básicamente magia negra.
Giuseppe
1
Felizmente admitiré que esto tomó mucho tiempo: P
JAD
10

C (gcc) , 74 72 71 bytes

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;}

Pruébalo en línea!

Descompostura

La mesa de la verdad

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

Se puede considerar como una matriz de 3x3, donde a es la columna y b es la fila. Transformar eso en una lista unidimensional nos da 100102221. Para ahorrar espacio, evitamos listas y cadenas y lo convertimos en un número. Para hacer eso, cambiamos el orden y transformamos cada trit en un número de 2 bits. Pegarlos juntos y tenemos un número binario en el que podemos "indexar" desplazándonos hacia la derecha 2 * (b * 3 + a)y enmascarando:

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

Luego, masajeamos la expresión usando el poder de la precedencia de la operación para convertirnos en la abominación anterior.

3 ^ 9 = 19683, entonces ese es un buen límite de bucle. Como multiplicamos el contador por 3 cada vez, podemos escribir el límite como en su 2e4lugar. También nos ahorramos la molestia de pow()o similar.

Pensándolo bien, comencemos en 3 ^ 10 y trabajemos hacia abajo con una división y prueba previa al bucle.

gastropner
fuente
8

Haskell , 108 bytes

2%2=1
_%2=2
0%_=1
2%1=2
_%_=0
g=take 10.map(`mod`3).iterate(`div`3)
(foldr((.(3*)).(+))0.).(.g).zipWith(%).g

Pruébalo en línea!

Asistente de trigo
fuente
6

Jalea ,  23  18 bytes

-1 gracias a Erik the Outgolfer (reorganizar 3*⁵¤a ⁵3*)

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

Un enlace monádico que acepta una lista de dos enteros.

Pruébalo en línea! O ver un conjunto de pruebas .

⁹*%733%3es un byte más largo que ị⁽½Ṡb3¤:(

¿Cómo?

⁵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

También 18: ⁵3*+b3ZḌ19*%74%3ḅ3(usa una fórmula mágica después de obtener los trits en pares de convertir de la base diez y luego tomar 19 a esa potencia, módulo 74, módulo 3 para obtener los trits requeridos de la salida, que se encuentra usando una búsqueda en Python)

Jonathan Allan
fuente
18 bytes (nota: realmente debería haber un "prepend y 0s" incorporado)
Erik the Outgolfer
Ugh, pensé que eso parecía incómodo. ¡Gracias!
Jonathan Allan
Muchas cosas se ven incómodas, a veces hay que acostumbrarse a ellas. : P
Erik the Outgolfer
4

J , 37 bytes

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

Explicación:

((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

Terminó siendo relativamente legible, tbh.

dracma
fuente
Bienvenido a PPCG! Aquí hay un conjunto de pruebas: robé el código de respuesta de Galen Ivanov.
Jonathan Allan
Bienvenido a PPCG! Buena solución! Aquí hay un enlace TIO a él.
Galen Ivanov
30
FrownyFrog
2
28
FrownyFrog el
@FrownyFrog agradable!
Jonás
3

Carbón , 31 bytes

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

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

     χ                          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

Solución alternativa, también 31 bytes:

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

Pruébalo en línea! El enlace es a la versión detallada del código.

        χ                  χ    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
Neil
fuente
2

Ruby , 70 bytes

->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}

Pruébalo en línea!

Se descompone ay brecursivamente hasta obtener 10 dígitos de cada uno. 6883da la mesa ternaria aplanada (invertida). Reconstruye de ternario a decimal multiplicando por 3**(10-l).

crashoz
fuente
2

J , 43 bytes

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

Ciertamente se puede jugar más al golf.

Explicación:

                         &(               ) - 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  

Pruébalo en línea!

Galen Ivanov
fuente
2

Pyth 26 25 24 bytes

Guardado 1 byte, gracias a @ErikTheOutgolfer

Guarde otro byte, inspirado por la respuesta de @ JonathanAllan

im@j3422 3id3Cm.[0Tjd3Q3

La entrada es una lista de 2 elementos [a,b]. Pruébelo en línea aquí , o verifique todos los casos de prueba aquí .

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
Sok
fuente
.Tpuede ser C.
Erik the Outgolfer
1

Japt , 24 23 bytes

Poner la pelota en marcha en la carrera de Japt como idioma del mes . ¡Espero ser superado por esto!

Toma la entrada en orden inverso como una matriz de enteros (es decir, [b,a]).

ms3 ùTA y_n3 g6883ì3Ãì3

Intentalo

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
Lanudo
fuente
0

Perl 5 -p , 102 bytes

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

Pruébalo en línea!

Xcali
fuente
0

Wolfram Language (Mathematica) , 75 72 60 bytes

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

Pruébalo en línea!

versión sin golf:

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

Ambos ay bse convierten en listas de diez trits, luego se usan por pares como un índice 2D en una tabla de búsqueda de números {1, 0, 0, 1, 0, 2, 2, 2, 1}. El resultado se interpreta de nuevo como una lista de diez puntos y se convierte de nuevo a forma entera.

La tabla de búsqueda está codificada como IntegerDigits[6883,3], que es corta porque estamos reciclando el IntegerDigitssímbolo.

romano
fuente