Không phải Ternary La Mã


23

Cho một số nguyên n ≥ 0, xuất nó trong ký hiệu cơ sở 3 không vị trí, sử dụng các chữ số 139ABCDE…và dấu phân cách 1 ký tự. Mỗi chữ số là một lũy thừa 3 và các chữ số ở phía bên trái của dải phân cách bị phủ định, ví dụ A931 | B → 81− (1 + 3 + 9 + 27) → 41 . Một chữ số có thể chỉ xuất hiện một lần.

Một cách nghiêm ngặt, hãy để giá trị của một chữ số là:

  • giá trị của nó nếu chữ số là 1, 3 hoặc 9
  • 27 nếu chữ số là A
  • 3 lần giá trị của chữ số ngay trước nó cho B..Z

Đầu ra của bạn phải thỏa mãn tổng (giá trị của các chữ số ở bên phải |) - sum (giá trị của các chữ số ở bên trái |) == đầu vào .

Ví dụ

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

Bạn có thể sử dụng một ký tự không phải không gian khác làm dấu phân cách. Bạn cũng được phép không có dấu phân cách, trong trường hợp đó, chữ số lớn nhất bắt đầu chuỗi dương. Bạn không cần xử lý bất cứ thứ gì lớn hơn 2 32 1 ( PMIGDCBA9|RQNLH3).

Bạn có thể viết một chương trình hoặc chức năng đầy đủ, đầu vào và đầu ra có thể được cung cấp trên bất kỳ kênh thông thường nào.

Đây là , vì vậy câu trả lời của bạn càng ngắn càng tốt!


2
(liên quan không có nghĩa là trùng lặp, bình tĩnh)
Leaky Nun

8
Tôi có phải là người duy nhất không có manh mối gì đang được hỏi ở đây không?
Xù xì

3
@Shaggy Thể hiện đầu vào dưới dạng tổng lũy ​​thừa của 3 và phủ định của chúng. Đặt các phủ định bên trái của a |và các tích cực ở bên phải của nó.
Martin Ender

2
@KevinCruijssen "không, đơn hàng miễn phí." - OP
dùng202729

3
@ user202729 À, bỏ lỡ bình luận đó. Cảm ơn. Đó là điều xảy ra khi các quy tắc được đưa ra trong các bình luận thay vì được chỉnh sửa thành thử thách .. ( FrownyFrog , bạn có thể thêm quy tắc đó vào thử thách: một trong hai bên của dấu phân cách đều ổn không?)
Kevin Cruijssen 28/03/18

Câu trả lời:


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 bằng cách sử dụng một phần của trick của @Arnauld JavaScript (ES6) câu trả lời 's ,
thay đổi i=0i++<1?49:i<3?51:i<4?57:i+61để i=4++i>9?i+55:i>8?57:++i+43.
-6 byte nhờ trực tiếp @Arnauld , bằng cách loại bỏ i.

Thứ tự đầu ra: Cao nhất đến thấp nhất |, thấp nhất, thấp nhất đến cao nhất.

Giải trình:

Hãy thử trực tuyến.

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
Tôi nghĩ rằng điều này hoạt động: 103 byte
Arnauld

@Arnauld Đẹp một! Và -1 byte hơn bằng cách đặt rtrong thân vòng lặp. Cảm ơn!
Kevin Cruijssen

@Arnauld Vì tò mò, những người mắc bệnh ung thư trông như thế nào mà bạn đã sử dụng cho hai con số ma thuật cuối cùng này (khi bạn vẫn còn sử dụng ivà khi bạn sử dụng lại c)?
Kevin Cruijssen

1
Tôi đã vứt nó đi ...: - / Nhưng đây là cái cuối cùng . (Rất không hiệu quả, nhưng điều đó ổn đối với các giá trị nhỏ như vậy.)
Arnauld

(Ngoài ra, tôi thực sự nên kiểm tra xem có p=1và không bao gồm *1trong mã nếu có - mặc dù nó không dẫn đến một công thức tốt hơn trong trường hợp đó.)
Arnauld


5

JavaScript (ES6), 82 80 79 byte

Đầu ra bằng chữ thường, hy vọng sẽ ổn.

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

Hãy thử trực tuyến!

Tương tự như câu trả lời của Leaky "Ninja Master" Nun và cũng dựa trên câu trả lời của xnor .

Chuyển đổi chữ số

Chúng tôi bắt đầu với k = 4 . Trong khi k nhỏ hơn 9 , chúng tôi tăng nó hai lần ở mỗi lần lặp và trừ 5 . Sau đó, chúng tôi chỉ tăng nó một lần và chuyển đổi nó thành cơ sở 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 byte

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

Chạy và gỡ lỗi nó

Cổng câu trả lời Stax của tôi trong Chuyển đổi cân bằng Ternary .

Giải trình

Sử dụng phiên bản giải nén để giải thích.

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

Cổng câu trả lời Java 10 của tôi . Nếu một cổng trực tiếp (trừ n->để n=>) đã có thể, tôi sẽ đã chỉnh sửa câu trả lời của tôi với Java nhiều thứ tiếng này. Tuy nhiên, thật không may, c+=trên các ký tự hoặc c=49không có trong C #, do đó câu trả lời được chuyển lỏng lẻo này.

Hãy thử trực tuyến.


1

Perl 5 -p , 71 69 byte

không sử dụng dải phân cách. Phần âm và dương nằm trong "thứ tự La Mã" (chữ số lớn nhất trước)

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

Hãy thử trực tuyến!



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
)

Hãy thử trực tuyến!

Quá dài, đặc biệt là cho một chương trình J ...

Giải trình:

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 byte , long: 152 131 byte

Tôi đã tạo ra hai phiên bản này, vì giới hạn của các thách thức về đầu vào tối đa hoạt động 0x100000000có vẻ hơi kỳ quặc. Một phiên bản hoạt động với số nguyên 32 bit (không đạt giới hạn vì lý do rõ ràng), phiên bản còn lại hoạt động với 64 bit (vượt quá giới hạn đã cho, với chi phí là 14 8 byte thêm).

Phiên bản 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;}

Phiên bản 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;}

Điều này giống hệt nhau ngoại trừ việc nó khai báo biến số nguyên là long(64 bit trên linux).

longPhiên bản chưa được chỉnh sửa:

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

Như bạn có thể thấy, điều này hoạt động bằng cách đệ quy khá: Nếu phần còn lại là 1, ký tự tương ứng được nối vào chuỗi đầu ra sau lệnh gọi đệ quy. Nếu phần còn lại là 2, đầu ra được thực hiện trước khi đệ quy. Trong trường hợp này, tôi cũng tăng giá trị lên một để xử lý chữ số âm một cách chính xác. Điều này có thêm lợi ích của việc thay đổi phần còn lại thành không, cho phép tôi sử dụng value%3làm điều kiện cho đệ quy sau.

Kết quả của việc chuyển đổi được đặt vào bộ đệm toàn cầu. Trình g()bao bọc có công việc không kết thúc chuỗi kết quả một cách chính xác và để đặt lại resultcon trỏ về điểm bắt đầu của nó (đó cũng là cách g()"trả về" kết quả).

Kiểm tra longphiên bản với mã này:

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

Có thể xa hơn, nhưng chơi golf phá hoại:

  • -4 byte: làm cho hàm thành một lần bằng cách xóa thiết lập lại con trỏ trong g().

  • -5 byte: buộc người gọi thực hiện chấm dứt chuỗi, trả về chuỗi mà không kết thúc buffervà kết thúc chuỗi trong result.


1

Than , 36 byte

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

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Giải trình:

Nθ

Nhập giá trị.

F³⊞υ⟦⟧

Đẩy ba danh sách trống vào danh sách trống được xác định trước.

F⁺139α«

Lặp qua các ký tự 139và bảng chữ cái viết hoa.

⊞§υθι

Lập chỉ mục theo chu kỳ danh sách các danh sách với giá trị và đẩy ký tự hiện tại đến nó.

≔÷⊕θ³θ»

Chia giá trị cho 3 nhưng làm tròn nó bằng cách thêm 1 trước.

F²«×|ι

Lặp lại hai lần. Lần thứ hai, in a |.

↑⊟υ

Mỗi vòng lặp chúng tôi bật mục cuối cùng từ danh sách; lần đầu tiên điều này cung cấp cho chúng ta các mục có phần còn lại 2(tương ứng với một chữ số ternary cân bằng -1), trong khi lần thứ hai này cho chúng ta các mục tương ứng với một chữ số ternary cân bằng của 1. Mảng kết quả thường sẽ in theo chiều dọc, nhưng xoay hướng in lên trên sẽ hủy bỏ.



0

Perl 5 , 92 89 byte

Lấy cảm hứng từ các câu trả lời java và 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}

Hãy thử trực tuyến!

Với một số khoảng trắng:

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.