Tidak Cukup Romawi Ternary

23

Diberikan bilangan bulat n ≥ 0, mengeluarkannya dalam notasi basis-3 non-posisional, menggunakan digit 139ABCDE…dan pemisah 1 karakter. Setiap digit adalah kekuatan 3 berturut-turut dan digit di sisi kiri separator dinegasikan, misalnya A931 | B → 81− (1 + 3 + 9 + 27) → 41 . Digit hanya dapat muncul sekali.

Dengan ketat, biarkan nilai digit menjadi:

  • nilainya jika digitnya adalah 1, 3 atau 9
  • 27 jika digitnya adalah A
  • 3 kali nilai digit tepat sebelum untuk B..Z

Output Anda harus memenuhi jumlah (nilai digit di sebelah kanan |) - jumlah (nilai digit di sebelah kiri |) == input .

Contohnya

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

Anda dapat menggunakan karakter non-spasi yang berbeda sebagai pemisah. Anda juga diizinkan untuk tidak memiliki pemisah, dalam hal ini digit terbesar memulai urutan positif. Anda tidak perlu menangani apa pun yang lebih besar dari 2 32 −1 ( PMIGDCBA9|RQNLH3).

Anda dapat menulis program atau fungsi lengkap, dan input dan output dapat disediakan di salah satu saluran yang biasa.

Ini , jadi semakin pendek jawaban Anda, semakin baik!

FrownyFrog
sumber
2
(Terkait tidak berarti duplikat, tenang)
Leaky Nun
8
Apakah saya satu-satunya yang tidak tahu apa yang ditanyakan di sini?
Shaggy
3
@Shaggy Ekspresikan input sebagai jumlah dari kekuatan 3 dan negatifnya. Letakkan sisi negatif a |dan sisi positif di sebelah kanan.
Martin Ender
2
@KevinCruijssen "tidak, pesanannya gratis." - OP
user202729
3
@ user202729 Ah, ketinggalan komentar itu. Terima kasih. Itulah yang terjadi ketika aturan ada di komentar alih-alih diedit ke dalam tantangan .. ( FrownyFrog , dapatkah Anda menambahkan aturan itu ke tantangan: apakah urutan di kedua sisi pembatas baik-baik saja?)
Kevin Cruijssen

Jawaban:

5

Java 10, 120 113 112 109 107 102 byte

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 byte dengan menggunakan bagian dari trik @Arnauld JavaScript (ES6) jawaban 's ,
mengubah i=0dan i++<1?49:i<3?51:i<4?57:i+61untuk i=4dan ++i>9?i+55:i>8?57:++i+43.
-6 byte terima kasih kepada @Arnauld secara langsung, dengan menyingkirkan i.

Urutan output: Tertinggi ke terendah, |-delimiter, terendah ke tertinggi.

Penjelasan:

Cobalah 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
Kevin Cruijssen
sumber
1
Saya pikir ini bekerja: 103 byte
Arnauld
@Arnauld Bagus! Dan -1 byte lebih banyak dengan meletakkan rdi loop body. Terima kasih!
Kevin Cruijssen
@Arnauld Karena penasaran, seperti apa brute-forcers yang telah Anda gunakan untuk dua angka ajaib terakhir ini (ketika Anda masih digunakan i, dan ketika Anda menggunakannya kembali c)?
Kevin Cruijssen
1
Saya sudah membuangnya ...: - / Tapi ini yang terakhir . (Sangat tidak efisien, tapi tidak apa-apa untuk nilai sekecil itu.)
Arnauld
(Juga, saya benar-benar harus menguji apakah p=1dan tidak termasuk *1dalam kode jika itu - meskipun tidak mengarah pada formula yang lebih baik dalam hal ini.)
Arnauld
5

Python 3 , 103 99 91 byte

4 byte berkat Lynn.

8 byte berkat ovs.

def f(n,s="|",b=0):c=('139'+chr(b+62)*b)[b];return n and f(-~n//3,[s,s+c,c+s][n%3],b+1)or s

Cobalah online!

Kredit ke xnor untuk logika.

Biarawati Bocor
sumber
5

JavaScript (ES6), 82 80 79 byte

Output dalam huruf kecil, yang semoga baik-baik saja.

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

Cobalah online!

Mirip dengan jawaban Nun Leaky "Master Ninja" dan juga berdasarkan jawaban xnor .

Konversi digit

Kita mulai dengan k = 4 . Meskipun k kurang dari 9 , kami menambahnya dua kali pada setiap iterasi dan mengurangi 5 . Setelah itu, kami menambahnya hanya sekali dan mengubahnya menjadi basis-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'
 ... | ...           | ...            | ...      | ...
Arnauld
sumber
4

Jelly , 26 byte

‘:3Ɗ⁹С‘%3ẹЀ0,2ị139D;ØA¤Y

Cobalah online!

Gunakan baris baru sebagai pemisah.

pengguna202729
sumber
26 byte
Leaky Nun
25 byte
Leaky Nun
2

Stax , 30 29 byte

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

Jalankan dan debug itu

Port of Stax saya menjawab dalam Balanced Ternary Converter .

Penjelasan

Gunakan versi yang belum dibongkar untuk menjelaskan.

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
Weijun Zhou
sumber
1

C # .NET, 103 byte

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 of Java 10 saya jawab . Jika port langsung (kecuali n->untuk n=>) akan mungkin terjadi, saya akan mengedit jawaban Java saya dengan polyglot ini. Sayangnya, c+=pada karakter atau memiliki c=49tidak mungkin dalam C #, maka ini jawaban porting longgar.

Cobalah online.

Kevin Cruijssen
sumber
1

Perl 5 -p , 71 69 byte

tidak menggunakan pemisah. Bagian negatif dan positif adalah dalam "urutan roman" (digit terbesar pertama)

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

Cobalah online!

Ton Hospel
sumber
1

Ruby , 87 84 82 byte

Disimpan 2 byte berkat @ benj2240.

->n,s=[?1,?3,?9,*?A..?Z],r=[""]*3{r[-m=n%3]+=s.shift
n=n/3+m/2
n>0?redo:r[1,2]*?|}

Cobalah online!

Pasang kembali Monica iamnotmaynard
sumber
Saya akan berbohong jika saya mengatakan saya benar-benar mengikuti kode ini, tetapi saya tahu Anda mencukur 2 byte dengan redotrik: Coba online!
benj2240
1

J , 129 byte

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
)

Cobalah online!

Terlalu panjang, terutama untuk program J ...

Penjelasan:

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  
)
Galen Ivanov
sumber
1

C, int: 138 123 byte, long: 152 131 byte

Saya telah membuat dua versi ini, karena batasan tantangan dari input maks yang berfungsi 0x100000000sepertinya sedikit aneh. Satu versi bekerja dengan bilangan bulat 32 bit (yang gagal batas karena alasan yang jelas), versi lain bekerja dengan 64 bit (yang jauh melampaui batas yang diberikan, dengan biaya 14 8 byte tambahan).

Versi 32 bit:

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

Versi 64 bit:

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

Ini identik kecuali bahwa ia menyatakan variabel integer menjadi long(yaitu 64 bit di linux).

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

Seperti yang Anda lihat, ini bekerja dengan layak rekursif: Jika sisanya adalah 1, karakter masing-masing ditambahkan ke string output setelah panggilan rekursif. Jika sisanya 2, output dilakukan sebelum pengulangan. Dalam hal ini, saya juga menambah nilainya satu per satu untuk menangani digit negatif dengan benar. Ini memiliki manfaat tambahan untuk mengubah sisanya menjadi nol, yang memungkinkan saya untuk digunakan value%3sebagai syarat untuk pasca-rekursi jika.

Hasil konversi ditempatkan ke buffer global. The g()wrapper memiliki tugas nol mengakhiri string yang dihasilkan benar, dan untuk me-reset resultpointer ke awal (yang juga bagaimana g()"kembali" hasilnya).

Uji longversi dengan kode ini:

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

Kemungkinan lebih lanjut, tetapi golf destruktif:

  • -4 bytes: jadikan fungsi ini satu-shot dengan menghapus pointer reset g().

  • -5 byte: memaksa pemanggil untuk melakukan pemutusan tali, kembali string tanpa penghentian dalam buffer, dan akhir string di result.

cmaster
sumber
1

Arang , 36 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Penjelasan:

Nθ

Masukkan nilainya.

F³⊞υ⟦⟧

Dorong tiga daftar kosong ke daftar kosong yang telah ditentukan.

F⁺139α«

Ulangi karakter 139dan alfabet huruf besar.

⊞§υθι

Cyclically mengindeks daftar daftar dengan nilai dan mendorong karakter saat ini ke sana.

≔÷⊕θ³θ»

Bagi nilai dengan 3 tetapi bulatkan dengan menambahkan 1 terlebih dahulu.

F²«×|ι

Ulangi dua kali. Kedua kalinya, cetak a |.

↑⊟υ

Setiap loop kami pop entri terakhir dari daftar; pertama kali ini memberi kita entri yang memiliki sisa 2(yang sesuai dengan digit terner seimbang -1), sedangkan kedua kali ini memberi kita entri yang sesuai dengan digit terner seimbang 1. Array yang dihasilkan biasanya akan mencetak secara vertikal, tetapi memutar arah cetak ke atas membatalkannya.

Neil
sumber
1

J , 69 64 58 byte

('931',~u:90-i.26){~0(>,&I.<)(29$3)((+1&|.-3&*)]-*)^:_@#:]

Cobalah online!

FrownyFrog
sumber
0

Perl 5 , 92 89 byte

Terinspirasi oleh jawaban java dan 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}

Cobalah online!

Dengan sedikit ruang putih:

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

PHP, 73 byte

for(;0|$n=&$argn;$n/=3)${$n++%3}.=_139[++$i]?:chr(61+$i);echo${2},_,${1};

port jawaban xnor , 53 byte

for(;0|$n=&$argn;$n/=3)$s="0+-"[$n++%3].$s;echo$s??0;

Jalankan sebagai pipa dengan -nratau coba online .

Titus
sumber