Implementiere den "verrückten" Operator von Malbolge

41

Eines der vielen einzigartigen Merkmale der Programmiersprache Malbolge ist der äußerst unintuitive OPOperator, der in der Dokumentation und im Quellcode nur als "op" bezeichnet wird, im Volksmund aber als "crazy" -Operator bezeichnet wird. Wie von Ben Olmstead, dem Schöpfer der Sprache, in seiner Dokumentation beschrieben: " Suche kein Muster, es ist nicht da ."

op ist ein "tritweiser" Operator - er bearbeitet die entsprechenden ternären Ziffern seiner beiden Argumente. Für jedes Trit (ternäres Bit) ergibt sich das Ergebnis von op aus der folgenden Nachschlagetabelle:

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

Um beispielsweise zu berechnen op(12345, 54321), schreiben Sie zuerst beide Zahlen ternär aus und schlagen dann jedes Paar von Trits in der Tabelle nach:

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

Der letzte wichtige Punkt ist , dass alle Werte in Malbolge sind Trits 10 breit, so dass Eingangswerte sollten mit Nullen bis zu einer Breite von 10 aufgefüllt werden (beispielsweise op(0, 0)ist 1111111111in ternären.)

Ihre Aufgabe ist es, zwei Ganzzahlen 0 ≤ a, b<59049 als Eingabe zu verwenden und den Ganzzahlwert von auszugeben op(a,b).

Testfälle (im Format a b op(a,b)):

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

Hier ist eine Referenzimplementierung (direkt aus dem Malbolge-Quellcode kopiert).

Türknauf
quelle
28
Kann das in Malboge beantwortet werden? ;)
Anzeigename
3
Ich denke, Malbolge ist jetzt eine gute Golfsprache!
Ethan
7
Für das, was es wert ist, 54616_3heißt das nicht "dieses andere Ding ist die Dezimalzahl 54616, sondern als Basis drei dargestellt". Es bedeutet "Read 54616as base 3". Was Sie natürlich nicht können (es gibt Ziffern, auf die Valve nicht zählen kann). Es wäre wahrscheinlich immer noch genauso klar, wenn Sie sich des _3Ganzen und Genaueren entledigen würden .
Nic Hartley
@Orangesandlemons Ich denke, nur die Verwendung des Operators in Malbolge würde unter die Standardlücke fallen. Eine Neuimplementierung mit anderem Code wäre in Ordnung.
Paŭlo Ebermann
7
@ PaŭloEbermann Nein, das ist keine Lücke .
user202729

Antworten:

43

C (GCC) , 99 98 96 Bytes

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

Probieren Sie es online!

Jonathan Frech
quelle
14
Ich mag das Namensschema!
Matthieu M.
28

JavaScript (ES7), 56 Byte

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

Probieren Sie es online!

Wie?

Mit und in berechnen wir:b [ 0..2 ]ab[0..2]

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

Führen zu:

 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

Funktionswahl

Es gibt mehrere andere mögliche Kandidatenfunktionen des Formulars:

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

Eine der kürzesten ist:

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

Das Gute an ist jedoch, dass es mit bitweisen Operatoren durchgeführt werden kann, wodurch implizit die Dezimalteile von und . Deshalb können wir sie einfach durch teilen, ohne zwischen den einzelnen Iterationen zu runden.(a+512b+8)ab3

Kommentiert

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
quelle
Ich denke, (1581093>>b%3*2+a%3*8&3)spart ein ganzes Byte!
Neil
@Neil Ich komme leider vorbei a/3und b/3ohne Rundung. Das würde daran scheitern.
Arnauld
9
Interessant, wie Sie ein Muster gefunden haben, das es nicht gibt.
Erik der Outgolfer
Gibt es einen Grund bevorzugen k = 9 ... => ~k && ...zu k = 10 ... => k && ...?
Falco
1
@ Falco Nein, es ist weder kürzer noch effizienter. Ich bevorzuge einfach Sachen mit einem Index von 0, also ahme ich lieber nach for(k=9;k>=0;k--)als for(k=10;k>=1;k--).
Arnauld
13

05AB1E , 18 Bytes

Code:

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

Verwendet die 05AB1E- Codierung. Probieren Sie es online!


Algorithmus Erklärung

Um die Zahl mit Nullen aufzufüllen , müssen wir zu beiden Zahlen 59049 addieren (weil 59049 im Ternary 10000000000 ist ). Wir müssen die führende 1 nicht als . Wir konvertieren die Zahlen von dezimal nach ternär und verbinden jedes Paar als eigene Zahl.(1,1)0

Für die Eingaben 12345 und 54321 werden diese beispielsweise wie folgt zugeordnet:

12345101212210205432112202111220

Das gibt die folgende Liste der verbundenen ganzen Zahlen:

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

Diese Ganzzahlen müssen durch die angegebene Nachschlagetabelle im OP abgebildet werden. Die derzeit verwendete Formel, mit der diese Zahlen den entsprechenden Trits ( ) zugeordnet werden, lautet:01,100,

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

Während die bitweise xor- Funktion bezeichnet.

Nachdem wir diese Funktion in der Liste der verbundenen Ganzzahlen abgebildet haben, behandeln wir diese resultierende Liste als eine Zahl, die in der Basis 3 dargestellt ist, und konvertieren sie von der Basis 3 in eine Dezimalzahl.


Code-Erklärung

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
quelle
Kann 3Tm+3Bø19sm74%3%3βman Golf spielen?
Jonathan Allan
@ JonathanAllan Schöne Entdeckung! Es scheint jedoch unmöglich, weiter Golf zu spielen, ohne eine andere Art von schwarzer Magie zu verwenden.
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

Probieren Sie es online!

Vielen Dank an JAD für ein paar Black Magic Golf Tricks und -2 Bytes!

30801Wenn es in eine ternäre 10-Trit-Ganzzahl konvertiert wird 1120020210, fügt es der Operationstabelle nur eine nachgestellte Null hinzu, wenn es die Spalten abliest . Dann konvertieren wir die ternären Ziffern von aund belementweise in eine ganze Zahl und verwenden diese als Index für die ternären Ziffern von 30801.

Giuseppe
quelle
1
62 Bytes Ja für Operator-Priorität!
JAD
1
Ja, auf diese Weise indexieren Sie zuerst xmit [.*]. Dann %any%passieren alle Operationen. Der lustige Teil ist, dass, wenn Sie 30801%/%x%%3als sehen f=function(x)30801%/%x%%3, dass f(x[index]) == (f(x))[index]. Speichern der Hosenträger :)
JAD
@ JAD faszinierend! Und wie ich oben kommentiere, im Grunde schwarze Magie.
Giuseppe
1
Ich gebe gerne zu, dass dies viel Fummelei gekostet hat: 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;}

Probieren Sie es online!

Nervenzusammenbruch

Die Wahrheitstabelle

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

Man kann sich ein 3x3-Array vorstellen, bei dem a die Spalte und b die Zeile ist. Wenn wir das in eine eindimensionale Liste umwandeln, erhalten wir 100102221. Um Platz zu sparen, vermeiden wir Listen und Zeichenfolgen und machen es stattdessen zu einer Zahl. Dazu kehren wir die Reihenfolge um und wandeln jeden Trit in eine 2-Bit-Zahl um. Kleben Sie sie zusammen und wir haben eine Binärzahl, in die wir "indexieren" können, indem wir sie nach rechts verschieben 2 * (b * 3 + a)und maskieren:

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

Als nächstes massieren wir den Ausdruck unter Verwendung der Kraft der Vorrangstellung, um den obigen Gräuel zu werden.

3 ^ 9 = 19683, das ist also eine gute Schleifengrenze. Da wir den Zähler jedes Mal mit 3 multiplizieren, können wir 2e4stattdessen das Limit als schreiben . Auch ersparen wir uns die Mühe pow()oder ähnliches.

Beginnen wir beim zweiten Gedanken bei 3 ^ 10 und arbeiten nach unten mit einem Divide-and-Test vor der Schleife.

Gastropner
quelle
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

Probieren Sie es online!

Weizen-Assistent
quelle
6

Jelly ,  23  18 Bytes

-1 dank Erik the Outgolfer (neu anordnen 3*⁵¤nach ⁵3*)

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

Ein monadischer Link, der eine Liste mit zwei ganzen Zahlen akzeptiert.

Probieren Sie es online! Oder sehen Sie sich eine Testsuite an .

⁹*%733%3ist ein Byte länger als ị⁽½Ṡb3¤:(

Wie?

⁵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

Ebenfalls 18: ⁵3*+b3ZḌ19*%74%3ḅ3(Verwendet eine Zauberformel, nachdem die paarweisen Trits der Konvertierung von der Basis 10 erhalten wurden, und nimmt dann 19 zu dieser Potenz, Modulo 74, Modulo 3, um die erforderlichen Trits der Ausgabe zu erhalten - gefunden mit einer Suche in Python)

Jonathan Allan
quelle
18 Bytes (Hinweis: Es sollte wirklich ein "Prepend y 0s" eingebaut sein)
Erik der Outgolfer
Ugh, ich dachte, das sieht unangenehm aus. Vielen Dank!
Jonathan Allan
Viele Dinge sehen unangenehm aus, manchmal muss man sich daran gewöhnen. : P
Erik der Outgolfer
4

J , 37 Bytes

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

Erläuterung:

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

Letztendlich relativ gut lesbar, tbh.

dram
quelle
Willkommen bei PPCG! Hier ist eine Testsuite - ich habe den Code aus Galen Ivanovs Antwort gestohlen.
Jonathan Allan
Willkommen bei PPCG! Schöne lösung! Hier ist ein TIO-Link dazu.
Galen Ivanov
30
FrownyFrog
2
28
FrownyFrog
@FrownyFrog schön!
Jonah
3

Kohle , 31 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

     χ                          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

Alternativlösung, auch 31 Bytes:

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes.

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

Probieren Sie es online!

Zerlegt aund brekursiv, bis wir jeweils 10 Stellen erhalten. 6883gibt die abgeflachte ternäre Tabelle (umgekehrt) an. Rekonstruiert von ternär zu dezimal durch Multiplikation mit 3**(10-l).

crashoz
quelle
2

J , 43 Bytes

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

Es kann sicherlich weiter golfen werden.

Erläuterung:

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

Probieren Sie es online!

Galen Ivanov
quelle
2

Pyth 26 25 24 Bytes

Dank @ErikTheOutgolfer 1 Byte gespeichert

Speichern Sie ein weiteres Byte, inspiriert von @ JonathanAllans Antwort

im@j3422 3id3Cm.[0Tjd3Q3

Die Eingabe ist eine Liste mit 2 Elementen [a,b]. Probieren Sie es hier online aus oder überprüfen Sie alle Testfälle hier .

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
quelle
.Tkann sein C.
Erik der Outgolfer
1

Japt , 24 23 Bytes

Japt's Lauf als Sprache des Monats zum Laufen zu bringen - ich gehe davon aus, dass ich diesbezüglich überfordert bin!

Übernimmt die Eingabe in umgekehrter Reihenfolge als ganzzahliges Array (dh [b,a]).

ms3 ùTA y_n3 g6883ì3Ãì3

Versuch es

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
Zottelig
quelle
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

Probieren Sie es online!

Xcali
quelle
0

Wolfram Language (Mathematica) , 75 72 60 Bytes

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

Probieren Sie es online!

Ungolf-Version:

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

Beide aund bwerden in Zehn-Trit-Listen konvertiert und dann paarweise als 2D-Index in eine Nachschlagetabelle mit Zahlen verwendet {1, 0, 0, 1, 0, 2, 2, 2, 1}. Das Ergebnis wird erneut als Zehn-Trit-Liste interpretiert und zurück in die Ganzzahlform konvertiert.

Die Nachschlagetabelle ist als codiert IntegerDigits[6883,3], was kurz ist, da wir das IntegerDigitsSymbol recyceln .

römisch
quelle