Zaimplementuj „szalonego” operatora Malbolge

41

Jedną z wielu unikalnych cech języka programowania Malbolge jest jego wysoce nieintuicyjny OPoperator, określany tylko jako „op” w dokumentacji i kodzie źródłowym, ale popularnie znany jako „zwariowany” operator. Jak opisuje Ben Olmstead, twórca języka, w swojej dokumentacji: „ nie szukaj wzoru, nie ma go ”.

op jest operatorem „trójstronnym” - działa na odpowiednich cyfrach trójskładnikowych dwóch argumentów. Dla każdego trytu (bitu trójskładnikowego) wynik operacji jest podawany przez następującą tabelę wyszukiwania:

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

Na przykład, aby obliczyć op(12345, 54321), najpierw wypisz obie liczby w trójce, a następnie sprawdź każdą parę tritów w tabeli:

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

Ostatnim ważnym punktem jest to, że wszystkie wartości w Malbolge mają szerokość 10 tritów, więc wartości wejściowe należy uzupełnić zerami do szerokości 10. (Na przykład op(0, 0)jest 1111111111trójskładnikowy).

Twoim zadaniem jest przyjęcie dwóch liczb całkowitych 0 ≤ a, b<59049 jako wartości wejściowej i wyprowadzenie wartości całkowitej op(a,b).

Przypadki testowe (w formacie a b op(a,b)):

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

Oto implementacja referencyjna (skopiowana bezpośrednio z kodu źródłowego Malbolge).

Klamka
źródło
28
czy można odpowiedzieć na to pytanie w Malboge? ;)
Wyświetl nazwę
3
Myślę, że Malbolge jest teraz dobrym językiem golfowym!
Ethan,
7
To, co jest warte, 54616_3nie oznacza „ta druga rzecz to liczba dziesiętna 54616, ale reprezentowana jako podstawa trzy”. Oznacza to „Odczytaj 54616jako podstawę 3”. Czego oczywiście nie możesz zrobić (są tam cyfry, których Valve nie może policzyć). Prawdopodobnie byłoby tak samo jasne, jeśli pozbyłeś się _3całkowicie i dokładniej.
Nic Hartley,
@Orangesandlemons Chyba użycie operatora w Malbolge byłoby objęte standardową luką. Ponowne wdrożenie przy użyciu innego kodu byłoby w porządku.
Paŭlo Ebermann
7
@ PaŭloEbermann Nie, to nie jest luka .
user202729,

Odpowiedzi:

43

C (gcc) , 99 98 96 bajtów

  • Zapisano bajt dzięki pułapowi cat ; grać 19683w golfa L'䳣'.
  • Zapisano dwa bajty; grać 108609w golfa 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;}

Wypróbuj online!

Jonathan Frech
źródło
14
Lubię schemat nazewnictwa!
Matthieu M.,
28

JavaScript (ES7), 56 bajtów

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

Wypróbuj online!

W jaki sposób?

Biorąc i w , obliczamy:b [ 0..2 ]ab[0..2]

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

Prowadzący do:

 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

Wybór funkcji

Istnieje kilka innych możliwych funkcji kandydata w formularzu:

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

Jednym z najkrótszych jest:

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

Ale dobrą zaletą jest to, że można go wykonać za pomocą operatorów bitowych, w ten sposób domyślnie odrzucając części dziesiętne i . Dlatego możemy po prostu podzielić je przez bez zaokrąglania między każdą iteracją.a b 3(a+512b+8)ab3

Skomentował

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
źródło
Myślę, że (1581093>>b%3*2+a%3*8&3)oszczędza cały bajt!
Neil
@Neil Niestety, przechodzę a/3i b/3nie zaokrąglam. Z tego powodu to by się nie udało.
Arnauld
9
Ciekawe, jak znalazłeś wzór, który nie istnieje.
Erik the Outgolfer
Czy istnieje jakikolwiek powód, aby wolą k = 9 ... => ~k && ...się k = 10 ... => k && ...?
Falco
1
@Falco Nie, nie jest ani krótszy, ani bardziej wydajny w żaden sposób. Po prostu wolę rzeczy indeksowane na 0, więc wolę naśladować for(k=9;k>=0;k--)niż for(k=10;k>=1;k--).
Arnauld
13

05AB1E , 18 bajtów

Kod:

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

Wykorzystuje kodowanie 05AB1E . Wypróbuj online!


Algorytm Wyjaśnienie

Aby uzyskać liczbę uzupełnioną zerami, musimy dodać 59049 do obu liczb (ponieważ 59049 w trójce to 10000000000 ). Nie musimy pomijać wiodącej 1 jako . Konwertujemy liczby z dziesiętnego na trójskładnikowe i łączymy każdą parę jako każdą własną liczbę.(1,1)0

Na przykład dla danych wejściowych 12345 i 54321 są one mapowane na:

12345101212210205432112202111220

Co daje następującą listę połączonych liczb całkowitych:

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

Te liczby całkowite muszą być odwzorowane przez podaną tabelę odnośników w PO. Stosowana obecnie formuła mapuje te liczby na odpowiadające im tryty ( ):01,100,

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

Natomiast oznacza bitową funkcję xor .

Ostatecznie po odwzorowaniu tej funkcji na listę połączonych liczb całkowitych traktujemy tę wynikową listę jako liczbę reprezentowaną w podstawie 3 i przekształcamy ją z podstawy 3 na dziesiętną.


Objaśnienie kodu

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
źródło
Czy 3Tm+3Bø19sm74%3%3βmożna grać w golfa?
Jonathan Allan
@JonathanAllan Nice find! Wydaje się jednak, że dalsza gra w golfa jest niemożliwa bez użycia innej formuły czarnej magii.
Adnan
11

R , 64 62 bajtów

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

Wypróbuj online!

Dzięki JAD za kilka sztuczek golfowych z czarną magią i -2 bajty!

30801, po przekonwertowaniu na dziesiętną trójwartościową liczbę całkowitą, to 1120020210po prostu dodaje końcowe zero do tabeli operacyjnej po odczytaniu kolumn. Następnie przekształcamy cyfry trójskładnikowe ai belementarne na liczbę całkowitą i używamy tego jako indeksu na cyfry trójskładnikowe 30801.

Giuseppe
źródło
1
62 bajty Yay dla pierwszeństwa operatora!
JAD
1
Tak, w ten sposób najpierw indeksujesz xza pomocą [.*]. Potem mają miejsce wszystkie %any%operacje. Część zabawy jest to, że jeśli widzisz 30801%/%x%%3jako f=function(x)30801%/%x%%3, że f(x[index]) == (f(x))[index]. Ratowanie aparatów ortodontycznych :)
JAD
@JAD fascynujące! I jak komentuję powyżej, w zasadzie czarna magia.
Giuseppe,
1
Z radością przyznam, że zajęło to wiele zabawy: P
JAD
10

C (gcc) , 74 72 71 bajtów

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

Wypróbuj online!

Awaria

Tabela prawdy

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

Można go traktować jako tablicę 3x3, gdzie a to kolumna, a b to rząd. Przekształcenie tego w jednowymiarową listę daje nam 100102221. Aby zaoszczędzić miejsce, unikamy list i ciągów znaków, a zamiast tego przekształcamy je w liczbę. Aby to zrobić, odwracamy kolejność i przekształcamy każdą trit w liczbę 2-bitową. Sklej je ze sobą, a mamy liczbę binarną, na którą możemy „indeksować”, przesuwając w prawo 2 * (b * 3 + a)i maskując:

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

Następnie masujemy to wyrażenie, używając mocy pierwszeństwa działania, aby stać się ohydą powyżej.

3 ^ 9 = 19683, więc jest to dobry limit pętli. Ponieważ mnożymy licznik przez 3 za każdym razem, możemy zapisać limit jak 2e4zamiast tego. Również oszczędzamy sobie kłopotów pow()lub podobnych.

Po zastanowieniu zacznijmy od 3 ^ 10 i pracujmy w dół z podziałem i testem przed pętlą.

gastropner
źródło
8

Haskell , 108 bajtów

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

Wypróbuj online!

Kreator pszenicy
źródło
6

Galaretka ,  23  18 bajtów

-1 dzięki Eryka Outgolfer (Przegrupuj 3*⁵¤się ⁵3*)

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

Monadyczny link akceptujący listę dwóch liczb całkowitych.

Wypróbuj online! Lub zobacz zestaw testowy .

⁹*%733%3jest bajtem dłuższym niż ị⁽½Ṡb3¤:(

W jaki sposób?

⁵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

Również 18: ⁵3*+b3ZḌ19*%74%3ḅ3(używa magicznej formuły po uzyskaniu par tritów konwersji z bazy dziesięciu, a następnie wzięciu 19 do tej mocy, modulo 74, modulo 3, aby uzyskać wymagane trity wyniku - znalezione przy użyciu wyszukiwania w Pythonie)

Jonathan Allan
źródło
18 bajtów (uwaga: naprawdę powinno być wbudowane „prepend y 0s”)
Erik the Outgolfer
Ugh, myślałem, że to wygląda niezręcznie. Dzięki!
Jonathan Allan
Wiele rzeczy wygląda niezręcznie, czasem trzeba się do nich przyzwyczaić. : P
Erik the Outgolfer
4

J , 37 bajtów

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

Wyjaśnienie:

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

Skończyło się to względnie czytelnością, tbh.

naparstek
źródło
Witamy w PPCG! Oto zestaw testów - ukradłem kod opakowania z odpowiedzi Galena Iwanowa.
Jonathan Allan
Witamy w PPCG! Fajne rozwiązanie! Oto link do niego TIO.
Galen Iwanow
30
FrownyFrog,
2
28
FrownyFrog,
@FrownyFrog nice!
Jonasz
3

Węgiel drzewny , 31 bajtów

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

Wypróbuj online! Link jest do pełnej wersji kodu. Wyjaśnienie:

     χ                          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

Alternatywne rozwiązanie, również 31 bajtów:

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

Wypróbuj online! Link jest do pełnej wersji kodu.

        χ                  χ    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
źródło
2

Rubinowy , 70 bajtów

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

Wypróbuj online!

Rozkłada się ai brekurencyjnie, dopóki nie otrzymamy 10 cyfr każdego. 6883daje spłaszczony trójskładnikowy stół (odwrócony). Odtwarza z trójki na dziesiętną, mnożąc przez 3**(10-l).

crashoz
źródło
2

Cjam, 31 bajtów

{{3bA0e[\}2*.{3*+"100102221"=}}

Wypróbuj online!

Chrom
źródło
2

J , 43 bajty

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

Z pewnością można dalej grać w golfa.

Wyjaśnienie:

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

Wypróbuj online!

Galen Iwanow
źródło
2

Pyth 26 25 24 bajtów

Zapisano 1 bajt dzięki @ErikTheOutgolfer

Zapisz inną bajt, zainspirowany @ JonathanAllan za odpowiedź

im@j3422 3id3Cm.[0Tjd3Q3

Dane wejściowe to lista 2 elementów [a,b]. Spróbuj go online tutaj , lub sprawdzić wszystkie przypadki testowe tutaj .

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
źródło
.Tmoże być C.
Erik the Outgolfer
1

Japt , 24 23 bajty

Sprawienie, by piłka rzuciła się na bieg Japt'a jako język miesiąca - w pełni oczekuję, że zostanę obeznany z tym!

Pobiera dane wejściowe w odwrotnej kolejności jako tablicę liczb całkowitych (tj [b,a].).

ms3 ùTA y_n3 g6883ì3Ãì3

Spróbuj

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
Kudłaty
źródło
0

Perl 5 -p , 102 bajtów

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

Wypróbuj online!

Xcali
źródło
0

Wolfram Language (Mathematica) , 75 72 60 bajtów

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

Wypróbuj online!

wersja bez gry w golfa:

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

Zarówno ai bsą konwertowane na liście dziesięciu trit parami, następnie wykorzystywane jako wskaźnik 2D w tabeli przeglądowej numerów {1, 0, 0, 1, 0, 2, 2, 2, 1}. Wynik jest ponownie interpretowany jako lista dziesięcioliniowa i konwertowany z powrotem do postaci całkowitej.

Tabela odnośników jest zakodowana jako IntegerDigits[6883,3], co jest krótkie, ponieważ przetwarzamy IntegerDigitssymbol.

rzymski
źródło