Nie całkiem rzymskie trójki


23

Biorąc pod uwagę liczbę całkowitą n ≥ 0, wypisz ją w niepozycjonowanej notacji bazowej 3, używając cyfr 139ABCDE…i separatora 1-znakowego. Każda cyfra jest kolejną potęgą 3, a cyfry po lewej stronie separatora są negowane, np. A931 | B → 81− (1 + 3 + 9 + 27) → 41 . Cyfra może pojawić się tylko raz.

Rygorystycznie, niech wartość cyfry będzie:

  • jego wartość, jeżeli cyfra to 1, 3 lub 9
  • 27 jeśli cyfra to A
  • 3-krotność wartości cyfry tuż przed nią dla BZ

Twój wynik powinien spełniać sumę (wartość cyfr po prawej stronie |) - suma (wartość cyfr po lewej stronie |) == input .

Przykłady

input     output
----------------
0         |
1         |1
7         3|91
730       |D1
9999      FEDC|GA9

Możesz użyć innego znaku spacji jako separatora. Możesz również nie mieć separatora, w którym to przypadku największa cyfra rozpoczyna sekwencję dodatnią. Nie potrzeba do obsługi niczego większy niż 2 32 -1 ( PMIGDCBA9|RQNLH3).

Możesz napisać pełny program lub funkcję, a dane wejściowe i wyjściowe mogą być dostarczane na zwykłych kanałach.

To jest , więc im krótsza odpowiedź, tym lepiej!


2
(spokrewniony nie oznacza duplikatu, uspokój się)
Leaky Nun

8
Czy jestem jedynym, który nie ma pojęcia, o co tu pyta?
Shaggy

3
@Shaggy Wyrazić dane wejściowe jako sumę potęg 3 i ich negatywów. Umieść negatywy po lewej stronie |a pozytywy po prawej stronie.
Martin Ender

2
@KevinCruijssen „nie, zamówienie jest bezpłatne”. - OP
użytkownik202729

3
@ user202729 Ah, przegapiłem ten komentarz. Dzięki. Tak się dzieje, gdy reguły są w komentarzach, a nie edytowane w wyzwaniu. ( FrownyFrog , czy mógłbyś dodać tę regułę do wyzwania: każda kolejność po obu stronach separatora jest w porządku?)
Kevin Cruijssen

Odpowiedzi:


5

Java 10, 120 113 112 109 107 102 bajtów

n->{var r="|";for(char c=49;n++>0;c=(char)(c+=c>64?1:c*4%22%9),n/=3)r=n%3<1?c+r:n%3>1?r+c:r;return r;}

-3 bajty przy użyciu części sztuczki odpowiedzi JavaScript (ES6) @Arnauld ,
zmianai=0ii++<1?49:i<3?51:i<4?57:i+61nai=4i++i>9?i+55:i>8?57:++i+43.
-6 bajtów dzięki @Arnauld bezpośrednio, pozbywając sięi.

Kolejność produkcji: od najwyższej do najniższej, |-delimiter, od najniższej do najwyższej.

Wyjaśnienie:

Wypróbuj online.

n->{              // Method with integer parameter and String return-type
  var r="|";      //  Result-String, starting at the delimiter "|"
  for(char c=49;  //  Character, starting at '1'
      n++>0       //  Loop as long as `n` is larger than 0
                  //  Increasing it by 1 with `n++` at the start of every iteration
      ;           //    After every iteration:
       c=(char)(  //     Change character `c` to:
          c+=c>64?//      If the current `c` is an uppercase letter:
              1   //       Simpy go to the next letter using `c+1`
             :    //      Else:
              c*4%22%9),
                  //       Change '1' to '3', '3' to '9', or '9' to 'A' 
       n/=3)      //     Integer-divide `n` by 3
     r=           //     Change the result to:
       n%3<1?     //      If `n` modulo-3 is 0:
        c+r       //       Prepend the character to the result
       :n%3>1?    //      Else-if `n` modulo-3 is 2:
        r+c       //       Append the character to the result
       :          //      Else:
        r;        //       Leave `r` unchanged
   return r;}     //  Return the result-String

1
Myślę, że to działa: 103 bajty
Arnauld

@Arnauld Nice one! I -1 więcej bajtu poprzez umieszczenie rw ciele pętli. Dzięki!
Kevin Cruijssen

@Arnauld Z ciekawości, jak wyglądają brutalni napastnicy, jak używałeś tych dwóch ostatnich magicznych liczb (kiedy nadal używasz ii kiedy ponownie używasz c)?
Kevin Cruijssen

1
Już to wyrzuciłem ...: - / Ale tutaj jest ostatni . (Bardzo nieefektywne, ale przy tak małych wartościach jest to w porządku).
Arnauld

(Poza tym naprawdę powinienem sprawdzić, czy p=1nie zawiera *1kodu, jeśli tak jest - nawet jeśli nie prowadzi to do lepszej formuły w tym przypadku.)
Arnauld


5

JavaScript (ES6), 82 80 79 bajtów

Dane wyjściowe pisane są małymi literami, co powinno mieć nadzieję.

f=(n,s=(k=4,'|'),c=++k>8?k.toString(36):++k-5)=>n?f(++n/3|0,[c+s,s,s+c][n%3]):s

Wypróbuj online!

Podobna do odpowiedzi Nieczystej „Mistrzyni Ninja” Dziurawej a także na podstawie odpowiedzi Xnora .

Konwersja cyfr

Zaczynamy od k = 4 . Podczas gdy k jest mniejsze niż 9 , zwiększamy go dwukrotnie przy każdej iteracji i odejmujemy 5 . Następnie zwiększamy go tylko raz i przekształcamy w base-36.

  k  | ++k > 8       | k.toString(36) | ++k - 5  | result
-----+---------------+----------------+----------+--------
  4  | k=5  -> false |                | k=6 -> 1 | 1
  6  | k=7  -> false |                | k=8 -> 3 | 3
  8  | k=9  -> true  | '9'            |          | '9'
  9  | k=10 -> true  | 'a'            |          | 'a'
  10 | k=11 -> true  | 'b'            |          | 'b'
 ... | ...           | ...            | ...      | ...



2

Stax , 30 29 bajtów

£└≤☻╘pÿ╖╡A[ô%æτ⌐}►ºôßHl4⌡π%^ 

Uruchom i debuguj

Port mojej odpowiedzi Stax w Balanced Ternary Converter .

Wyjaśnienie

Używa rozpakowanej wersji do wyjaśnienia.

139$VA+cz{;3%+,^3/~;wY1|I@'|ay2|I@L
139$VA+c                               "139AB...Z", make a copy
        z                              Empty array to store the digits
          {         w                  Do the following until 0.
           ;3%+                           Append `b%3` to the digits
                                          Originally, `b` is the input
              ,^3/                        `b=(b+1)/3`
                  ~;                       Make a copy of `b` which is used as the condition for the loop

                     Y                 Save array of digits in `y` for later use
                      1|I              Find index of 1's
                         @             Find the characters in "139AB...Z" corresponding to those indices
                          '|           A bar
                            ay2|I@     Do the same for 2's
                                  L    Join the two strings and the bar and implicit output

1

C # .NET, 103 bajty

n=>{var r="|";for(var c='1';n++>0;c=(char)(c>64?c+1:c+c*4%22%9),n/=3)r=n%3<1?c+r:n%3>1?r+c:r;return r;}

Port mojej odpowiedzi Java 10 . Gdyby możliwy był bezpośredni port (z wyjątkiem n->do n=>), edytowałbym swoją odpowiedź Java za pomocą tego poliglota. Niestety, c+=w przypadku postaci lub posiadanie c=49nie jest możliwe w C #, stąd ta luźna przeniesiona odpowiedź.

Wypróbuj online.


1

Perl 5 -p , 71 69 bajtów

nie używa separatora. Części ujemne i dodatnie są w „kolejności rzymskiej” (pierwsza cyfra na początku)

#!/usr/bin/perl -p
$n=$_}{s/@{[$n++%3]}\K/]/,$n/=3,y/?-]/>-]/for($_=21)x31;y/>?@12/139/d

Wypróbuj online!



1

J , 129 bajtów

f=:3 :0
a=.'139',u:65+i.26
s=.'|'while.y>0 do.if.1=c=.3|y do.s=.s,{.a end.y=.<.y%3
if.c=2 do.s=.s,~{.a 
y=.1+y end.a=.}.a end.s
)

Wypróbuj online!

Zbyt długi, szczególnie w przypadku programu J ...

Wyjaśnienie:

f =: 3 : 0
   a =. '139',u:65+i.26   NB. a list '139ABC...Z'
   s =. '|'               NB. initialize the list for the result  
   while. y>0 do.         NB. while the number is greater than 0
      c =. 3|y            NB. find the remainder (the number modulo 3)
      y =. <.y%3          NB. divide the number by 3 
      if. c = 1 do.       NB. if the remainder equals 1
         s =. s,{.a       NB. Append the current power of 3 to the result
      end.
      if. c = 2 do.       NB. if the remainder equals 2 
         s =. s,~{.a      NB. prepends the result with the current power of 3
         y =. 1+y         NB. and increase the number with 1
      end.
      a =. }.a            NB. next power of 3 
   end.
   s                      NB. return the result  
)

1

C, int: 138 123 bajtów long: 152 131 bajtów

Stworzyłem dwie wersje tego, ponieważ limit wyzwań dla maksymalnego działania 0x100000000wydawał się nieco dziwny. Jedna wersja działa z 32-bitowymi liczbami całkowitymi (która z oczywistych powodów nie spełnia limitu), druga wersja działa z 64 bitami (co znacznie wykracza poza podany limit, kosztem 14 8 dodatkowych bajtów).

Wersja 32-bitowa:

char b[22],*r=b;f(v,l)char*l;{v%3>1?*r++=*l,v++:0;v&&f(v/3,l+1);v%3?*r++=*l:0;}g(v){f(v,"139ABCDEFGHIJKLMNOPQR");*r=0;r=b;}

Wersja 64-bitowa:

char b[22],*r=b;f(long v,char*l){v%3>1?*r++=*l,v++:0;v&&f(v/3,l+1);v%3?*r++=*l:0;}g(long v){f(v,"139ABCDEFGHIJKLMNOPQR");*r=0;r=b;}

Jest to identyczne, z tą różnicą, że deklaruje zmienną całkowitą long (która ma 64 bity w Linux).

Wersja bez golfa long:

char buffer[22],*result=buffer;
f(long value,char*letter){
    if(value%3>1){
        *result++=*letter,value++;
    }
    if(value){
        f(value/3,letter+1);
    }
    if(value%3){
        *result++=*letter;
    }
}
g(long value){
    f(value,"139ABCDEFGHIJKLMNOPQR");
    *result=0;
    result=buffer;
}

Jak widać, działa to przez rekurencyjne przyzwoite: Jeśli reszta to 1, odpowiedni znak jest dołączany do ciągu wyjściowego po wywołaniu rekurencyjnym. Jeśli reszta to 2, dane wyjściowe są wykonywane przed powtórzeniem. W tym przypadku zwiększam również wartość o jeden, aby poprawnie obsługiwać cyfrę ujemną. Daje to dodatkową korzyść polegającą na zmianie reszty na zero, co pozwala mi korzystaćvalue%3 jako warunku dla rekursji po rekursji if.

Wynik konwersji jest umieszczany w buforze globalnym. Zadaniem g()otoki jest prawidłowe zakończenie wynikowego łańcucha i zresetowanie resultwskaźnika do jego początku (tak też jestg() „zwraca” wynik).

Przetestuj longwersję za pomocą tego kodu:

#include <stdio.h>

char b[22],*r=b;f(long v,char*l){v%3>1?*r++=*l,v++:0;v&&f(v/3,l+1);v%3?*r++=*l:0;}g(long v){f(v,"139ABCDEFGHIJKLMNOPQR");*r=0;r=b;}

void printConversion(long value) {
    g(value);
    printf("%ld: %s\n", value, r);
}

int main() {
    for(long i = 0; i <= 40; i++) {
        printConversion(i);
    }
    printConversion(0x7fffffff);
    printConversion(0xffffffffu);
    printConversion(0x100000000);
}

Możliwe dalsze, ale destrukcyjne golfa:

  • -4 bajty: zmień funkcję na jedną, usuwając wskaźnik resetujący g().

  • -5 bajtów: zmusza program wywołujący do zakończenia łańcucha, zwracając ciąg bez zakończenia w buffer, a koniec łańcucha w result.


1

Węgiel drzewny , 36 bajtów

NθF³⊞υ⟦⟧F⁺139α«⊞§υθι≔÷⊕θ³θ»F²«×|ι↑⊟υ

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

Nθ

Wprowadź wartość.

F³⊞υ⟦⟧

Wciśnij trzy puste listy do predefiniowanej pustej listy.

F⁺139α«

Pętla znaków 139i alfabetu.

⊞§υθι

Cyklicznie indeksuj listę list wartością i wypychaj do niej bieżący znak.

≔÷⊕θ³θ»

Podzielić wartość przez 3, ale zaokrąglić, dodając najpierw 1.

F²«×|ι

Pętla dwa razy. Za drugim razem wydrukuj a |.

↑⊟υ

W każdej pętli wstawiamy ostatni wpis z listy; po raz pierwszy daje nam to wpisy, które miały resztę 2(co odpowiada zrównoważonej cyfrze trójskładnikowej -1), podczas gdy po raz drugi daje nam wpisy odpowiadające zrównoważonej cyfrze trójskładnikowej 1. Powstały układ normalnie drukowałby pionowo, ale obrócenie kierunku drukowania w górę anuluje to.



0

Perl 5 , 92 89 bajtów

Zainspirowany odpowiedziami Java i Python.

sub n{($n,$r,$c,@a)=(@_,'|',1,3,9,'A'..'Z');$n?n(int++$n/3,($c.$r,$r,$r.$c)[$n%3],@a):$r}

Wypróbuj online!

Z białą przestrzenią:

sub n {
  ($n, $r, $c, @_) = (@_, "|", 1, 3, 9, 'A' .. 'Z');
  $n ? n( int++$n/3, ($c.$r, $r, $r.$c)[$n%3], @_)
     : $r
}

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.