Chuyển đổi cân bằng Ternary


32

Tín dụng cho ý tưởng thử thách đi đến @AndrewPiliser. Đề xuất ban đầu của anh ấy trong hộp cát đã bị bỏ rơi và vì anh ấy đã không hoạt động ở đây trong vài tháng, tôi đã vượt qua thử thách.

Ternary cân bằng là một hệ thống số không chuẩn. Nó giống như ternary ở chỗ các chữ số tăng về giá trị bởi một yếu tố của 3 như bạn đi xa hơn sang trái - vì vậy10091001là 28.

Tuy nhiên, thay vì có các giá trị 0, 1 và 2, các chữ số có các giá trị -1, 0 và 1 . (Bạn vẫn có thể sử dụng số này để thể hiện bất kỳ số nguyên nào.)

Đối với thử thách này, ý nghĩa chữ số +1sẽ được viết là +, -1sẽ được viết là -, và 0chỉ là 0. Chim nhạn cân bằng không sử dụng -ký hiệu phía trước các số để phủ định chúng giống như các hệ thống số khác làm - xem các ví dụ.

Nhiệm vụ của bạn là viết một chương trình hoàn chỉnh, lấy số nguyên có chữ ký thập phân 32 bit làm đầu vào và chuyển đổi nó thành ternary cân bằng. Không có chức năng chuyển đổi cơ sở tích hợp nào được cho phép (Mathicala có thể có một ...). Đầu vào có thể là đầu vào tiêu chuẩn, đối số dòng lệnh, v.v.

Các số 0 đứng đầu có thể có mặt trong đầu vào nhưng không có trong đầu ra, trừ khi đầu vào là 0, trong trường hợp đó cũng phải xuất ra 0.

Ví dụ

Đây là các chuyển đổi từ ternary cân bằng sang thập phân; bạn sẽ phải chuyển đổi theo cách khác.

+0- = 1*3^2 + 0*3^1 + -1*3^0 = 9 + 0 + -1 = 8
+-0+ = 1*3^3 + -1*3^2 + 0*3^1 + 1*3^0 = 27 + -9 + 0 + 1 = 19
-+++ = -1*3^3 + 1*3^2 + 1*3^1 + 1*3^0 = -27 + 9 + 3 + 1 = -14

Đợi đã, tôi vừa nhận thấy có một câu hỏi về hàng chục cân bằng - đây có phải là một bản sao không?

Như tôi đã đề cập trong hộp cát, tôi nghĩ rằng nó gần với thách thức hơn về các biểu diễn phinary tiêu chuẩn . Nhưng nó có lẽ không phải là một bản sao của một trong hai.
Martin Ender

Câu trả lời:


22

Python 2: 58 ký tự

n=input()
s=""
while n:s="0+-"[n%3]+s;n=-~n/3
print s or 0

Tạo ra chữ số ba chữ số cân bằng từ cuối. Chữ số cuối cùng được đưa ra bởi các dư lượng n%3con người -1, 0hoặc +1. Sau đó, chúng tôi xóa chữ số cuối cùng và chia cho 3 bằng cách chia tầng của Python n=(n+1)/3. Sau đó, chúng tôi tiến hành đệ quy với chữ số cuối cùng mới cho đến khi số là 0.

Một trường hợp đặc biệt là cần thiết cho đầu vào 0để cung cấp 0thay vì chuỗi trống.


Thông số kỹ thuật không cho phép điều này, nhưng nếu người ta có thể viết hàm thay vì chương trình và xuất chuỗi rỗng thành 0, thì có thể có giải pháp 40 char.

g=lambda n:n and g(-~n/3)+"0+-"[n%3]or""

Tốt hơn để sử dụng n*"."andtrong trường hợp chỉ có chức năng. Cũng print s or 0hoạt động tốt hơn: P
Nabb

@Nabb Gọi tốt s or 0. Tôi đã thử n*"."and, nhưng nó thất bại khi n<0.
xnor

@ MartinBüttner Câu trả lời dài hơn của Pyth chỉ là do sử dụng thuật toán không tối ưu.
Tối ưu hóa

@Optimizer Vâng, rõ ràng, và đó là lý do tại sao tôi đã đưa ra câu trả lời Python có thuật toán tốt hơn trước. : P
Martin Ender

6

CJam, 24 byte

Tôi đã nghĩ ra điều này một cách độc lập và tôi nghĩ rằng, đây có lẽ là cách duy nhất để xử lý việc này.

li{_3%"0+-"=\_g+3/}h;]W%

Về mặt thuật toán, nó tương tự như câu trả lời của xnor.

Dùng thử trực tuyến tại đây

Cách thức hoạt động :

li{               }h                 "Read input, convert to integer and run the code block"
                                     "until stack has 0 on top";
   _3%                               "Copy and get modulus 3";
      "0+-"=                         "Take the correct character based on the above modulus";
            \_g+                     "Swap, copy and take signum of the number and add"
                                     "that to it, incrementing the number if positive,"
                                     "decrementing otherwise";
                3/                   "Integer divide by 3 and continue until 0";
                    ;]               "Pop the residual 0 and wrap everything in array";
                      W%             "Reverse to get in binary format (right handed)";

Là bit "tăng nếu dương, giảm nếu âm" có cần thiết không? Tại sao không chỉ tăng?
isaacg

@isaacg Hãy dùng thử;)
Trình tối ưu hóa

Là làm tròn trên bộ phận của CJam khác nhau?
isaacg

@isaacg - Làm tròn - không. Phân chia số nguyên CJam không làm tròn. Tầng này
Trình tối ưu hóa

Nhưng sàn hướng về 0 hay -inf?
isaacg

6

JavaScript (E6) 68

Một chương trình hoàn chỉnh, theo yêu cầu, với I / O thông qua cửa sổ bật lên. Cốt lõi là hàm R, 49 byte.

Không quá khác biệt với các giải pháp đệ quy khác, tôi đoán vậy. Tận dụng chuyển đổi tự động giữa chuỗi và số để tránh trường hợp đặc biệt cho "0"

 alert((R=(n,d=(n%3+3)%3)=>n?R((n-d)/3+(d>1))+'0+-'[d]:'')(prompt()))

Kiểm tra trong bảng điều khiển FireFox / FireBug, chỉ sử dụng chức năng R

['0','8','19','-14','414'].map(x =>x +': '+R(x))

Đầu ra

["0: 0", "8: +0-", "19: +-0+", "-14: -+++", "414: +--0+00"]

Tui bỏ lỡ điều gì vậy? Điểm của d=(n%3+3)%3khi d=n%3mang lại cùng một giá trị cho d?
RLH

@RLH không dành cho các giá trị âm (không có trong JavaScript). -20% 3 === -2% 3 === -2. Thay vào đó, -20 mod 3 phải là 1 và (-20% 3 + 3)% 3 thực sự là 1
edc65

6

Bình thường, 71 24 23

L?+y/hb3@"0+-"%b3bk|yQ0

Đây là một giải pháp đệ quy, dựa trên hàm đệ quy 40 ký tự của @ xnor. yxây dựng ternary baated của đầu vào, bằng cách tìm chữ số cuối cùng sử dụng chỉ số mod 3, và sau đó sử dụng thực tế là phần còn lại của các chữ số bằng với ternary cân bằng cho (n + 1) / 3, sử dụng phép chia nổi. Sau đó, nó gọi hàm, trả về kết quả hoặc 0 nếu đầu vào là 0.

Hãy thử nó ở đây.


Có một thông dịch viên Pyth trực tuyến?

Có, tôi sẽ thêm nó vào bài viết.
isaacg

Liên kết của bạn bị hỏng. Tôi khuyên bạn nên thử trực tuyến! , mà bạn sẽ sử dụng từ bây giờ bất cứ khi nào bạn cần một thông dịch viên cho bất cứ điều gì. Nhân tiện, mã của bạn dường như không hoạt động, đối với tôi nó chỉ trả về đầu vào.
Pavel

@Pavel Nó hoạt động hai năm trước, khi tôi viết nó. Trình thông dịch Pyth trực tuyến hiện tại là pyth.herokuapp.com Nếu bạn muốn chạy đoạn mã trên, bạn có thể kiểm tra trình thông dịch từ sau đó từ github.com/isaacg1/pyth , có phiên bản hoàn chỉnh về lịch sử ngôn ngữ.
isaacg

3

Toán học - 157 154 146 128

Phiên bản chơi gôn:

f=(s="";n=#;i=Ceiling@Log[3,Abs@#]~Max~0;While[i>=0,s=s<>Which[n>=(1+3^i)/2,n-=3^i;"+",n>-(1+3^i)/2,"0",1>0,n+=3^i;"-"];i--];s)&

Và với sự thụt vào cho mức độ dễ đọc:

f = (s = ""; n = #; i = Ceiling@Log[3, Abs@#]~Max~0;
 While[i >= 0, 
  s = s<>Which[
   n >= (1 + 3^i)/2, n -= 3^i; "+",
   n > -(1 + 3^i)/2, "0", 
   1 > 0, n += 3^i; "-"
  ];
 i--];
s)&

Sử dụng:

f[414]

Đầu ra:

+--0+00

Rất cám ơn Martin Büttner trong việc giảm số lượng nhân vật.


3

Toán học, 54 ký tự

Tương tự như đệ quy của xnor

Ký tự Unicode được sử dụng để thay thế Floor, Part,!=

If[(t=⌊(#+1)/3⌋)≠0,#0@t,""]<>{"0","+","-"}〚#~Mod~3+1〛&

Đầu ra

Được lưu trữ fđể cho ngắn gọn và được viết mà không có unicode, bạn không thể xem

f=If[(t=Floor[(#+1)/3])!=0,#0@t,""]<>{"0","+","-"}[[#~Mod~3+1]]&
f /@ {8, 19, -14, 414} // Column

+0-
+-0+
-+++
+--0+00

3

GNU sed, 236 byte

/^0/bV
:
s/\b9/;8/
s/\b8/;7/
s/\b7/;6/
s/\b6/;5/
s/\b5/;4/
s/\b4/;3/
s/\b3/;2/
s/\b2/;1/
s/\b1/;0/
s/\b0//
/[^;-]/s/;/&&&&&&&&&&/g
t
y/;/1/
:V
s/111/3/g
s/3\b/3:/
s/311/33!/
s/31/3+/
y/3/1/
tV
s/1/+/
y/1:/!0/
/-/{s/-//
y/+!/!+/
}
y/!/-/

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

Giải trình

Nửa đầu của mã (trừ dòng đầu tiên) dịch thập phân sang unary và xuất phát trực tiếp từ " Mẹo chơi golf trong sed ". Sau đó, nó dịch unary sang ternary một trit tại một thời điểm, mà tôi sẽ chứng minh bằng cách làm một ví dụ bằng tay.

Trước khi kết quả cuối cùng, các chữ số ternary -, 0+được đại diện bởi !, :+, tương ứng.

Để có một kết quả thú vị, chúng tôi bắt đầu với -48, đã được chuyển đổi thành unary (với -nguyên vẹn). Để tính trit đầu tiên (phải nhất), chúng ta phải tính phần còn lại là 48 3. Chúng ta có thể làm điều này bằng cách thay thế 111s bằng 3s:

-111111111111111111111111111111111111111111111111 │ s/111/3/g
# => -3333333333333333

48 3 không có phần còn lại, vì vậy không 1còn tồn tại và chúng tôi biết điểm đầu tiên của chúng tôi là :(cho 0), vì vậy chúng tôi thay thế nó:

-3333333333333333 │ s/3\b/3:/
# => -3333333333333333:

Bây giờ chúng ta có "vị trí của chúng ta", vì vậy chúng ta biết các 3s còn lại đại diện cho vị trí thứ ba. Để giữ cho toán học hoạt động, chúng ta phải chia chúng cho 3, tức là thay thế chúng bằng 1s:

-3333333333333333: │ y/3/1/
# => -1111111111111111:

Hãy kiểm tra kỹ toán học của chúng tôi: Chúng tôi có 16 (đơn nguyên 1111111111111111) ở vị trí thứ ba và số 0 ( :) ở vị trí thứ nhất. Đó là 3 Khăn16 + 1 Khăn0 = 48. Cho đến nay rất tốt.

Bây giờ chúng ta bắt đầu lại. Thay 111s bằng 3s:

-1111111111111111: │ s/111/3/g
# => -333331:

Lần này phần còn lại của chúng tôi là 1, vì vậy chúng tôi đặt +vào vị trí thứ ba và thay thế các 3s còn lại bằng 1s:

-333331: │ s/31/3+/; y/3/1/
# => -11111+:

Thời gian kiểm tra trạng thái: Chúng tôi có 5 (đơn vị 11111) ở vị trí số 9, 1 ( +) ở vị trí số ba và 0 ( :) ở vị trí số: 9 Đ5 + 3 Đọ1 + 1 Đọ = 48. Tuyệt vời! Một lần nữa chúng ta thay 111s bằng 3s:

-11111+: │ s/111/3/g
# => -311+:

Lần này phần còn lại của chúng tôi là 2 ( 11). Điều đó chiếm hai trits ( +!), có nghĩa là chúng ta có một carry. Giống như trong số học thập phân có nghĩa là chúng ta lấy chữ số ngoài cùng bên phải và thêm phần còn lại vào cột bên trái. Trong hệ thống của chúng tôi, điều đó có nghĩa chúng ta đặt !ở nơi nines và thêm ba khác sang bên trái của nó, sau đó thay thế tất cả các 3s với 1s để đại diện cho nơi 27s:

-311+: │ s/311/33!/; y/3/1/
# => -11!+:

Bây giờ chúng tôi không còn 3 số nào nữa, vì vậy chúng tôi có thể thay thế bất kỳ chữ số đơn nguyên nào còn lại bằng các dấu tương ứng của chúng. Hai ( 11) là +!:

-11!+: │ s/11/+!/
# => -+!!+:

Trong mã thực tế, điều này được thực hiện theo hai bước s/1/+/y/1:/!0/để lưu byte. Bước thứ hai cũng thay thế :s bằng 0s, vì vậy nó thực sự làm điều này:

-11!+: │ s/1/+/; y/1:/+0/
# => -+!!+0

Bây giờ chúng tôi kiểm tra nếu chúng tôi có một số âm. Chúng tôi làm, vì vậy chúng tôi phải loại bỏ các dấu hiệu và sau đó đảo ngược từng trit:

-+!!+0 │ /-/ { s/-//; y/+!/!+/; }
# => !++!0

Cuối cùng, chúng ta thay !s bằng -s:

!++!0 │ y/!/-/
# => -++-0

Đó là nó!


2

Stax , 17 byte

ë1·âΓM¿├>Ö≥Er☺à┤3

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

Câu trả lời ngắn nhất cho đến nay, nhưng nên dễ dàng bị đánh bại bởi một số ngôn ngữ chơi golf. Thuật toán giống như câu trả lời Python của @ xnor.

Tương đương ASCII:

z{"0+-";3%@+,^3/~;wr

1

JavaScript 108 102 (ES6, không có cuộc gọi đệ quy)

t=a=>{v="";if(0==a)v="0";else for(a=(N=0>a)?-a:a;a;)v="0+-"[r=(a%3+3)%3]+v,2==r&&++a,a=a/3|0;return v}

Mục nhập gốc tại 108

t=a=>{v="";if(0==a)v="0";else for(a=(N=0>a)?-a:a;a;)v=(N?"0-+":"0+-")[r=a%3]+v,2==r&&++a,a/=3,a|=0;return v}

Không thú vị như câu trả lời của @ edc65 ... Tôi đánh giá cao bất kỳ trợ giúp nào làm giảm điều này hơn nữa ...


1

Clojure, 242 byte

#(clojure.string/join""(map{1"+"0"0"-1"-"}(loop[x(vec(map read-string(clojure.string/split(Integer/toString % 3)#"")))](let[y(.indexOf x 2)](if(< y 0)x(let[z(assoc x y -1)](recur(if(= y 0)(vec(cons 1 z))(assoc z(dec y)(inc(x(dec y))))))))))))

Đây có phải là câu trả lời Clojure dài nhất cho đến nay?

Ungolfed (có ý kiến):

(use '[clojure.string :only (split join)]);' (Stupid highlighter)
; Import functions

(defn ternary [n]
  (join ""
  ; Joins it all together
    (map {1 "+" 0 "0" -1 "-"}
    ; Converts 1 to +, 0 to 0, -1 to -
      (loop [x (vec (map read-string (split (Integer/toString n 3) #"")))]
      ; The above line converts a base 10 number into base 3,
      ; and splits the digits into a list (8 -> [2 2])
        (let [y (.indexOf x 2)]
        ; The first occurrence of 2 in the list, if there is no 2,
        ; the .indexOf function returns -1
          (if (< y 0) x
          ; Is there a 2? If not, then output the list to
          ; the map and join functions above.
            (let [z (assoc x y -1)]
            ; Converts where the 2 is to a -1 ([2 2] -> [-1 2])
              (recur
                (if (= y 0) (vec (cons 1 z))
                  ; If 2 is at the 0th place (e.g. [2 2]),
                  ; prepend a 1 (e.g. [-1 2] -> [1 -1 2])
                  (assoc z (dec y) (inc (x (dec y)))))))))))))
                  ; Else increment the previous index
                  ; (e.g. [1 -1 2] -> [1 0 -1])

1

8 , 179 171 167 ký tự

Đây là một chương trình hoàn chỉnh trong phần 8 , lấy một số nguyên có chữ số thập phân làm đầu vào và chuyển đổi nó thành ternary cân bằng

 
: f "" swap repeat dup 3 n:mod ["0","+","-"] swap caseof rot swap s:+ swap dup n:sgn n:+ 3 n:/mod nip while drop s:rev ;
"? " con:print 16 null con:accept >n
f cr . cr
 

Kiểm tra

 
? 414
+--0+00
 

Lần đầu tiên chương trình yêu cầu một số để chuyển đổi (theo yêu cầu). Sau đó, có thể gọi từ fđể chuyển đổi nhiều số hơn như trong dòng sau:

 
[ 8 , 19 , -14 , ] ( nip dup . space f . cr ) a:each drop 
 

Đầu ra

 
8 +0-
19 +-0+
-14 -+++
 

Giải thích mã

 
"? " con:print 16 null con:accept >n
 

Đây là mã để xử lý đầu vào. Cốt lõi của mã là bên trong từ f. Rời khỏi sân golf tôi sẽ sử dụng từ này >btthay vì f. Đây là phiên bản chưa được chỉnh sửa của f(có ý kiến):

 
: f \ n -- s
    ""   \ used for the first symbol concatenation
    swap \ put number on TOS to be used by loop
    repeat
        dup 
        3 n:mod      \ return the remainder of the division by 3
        [ "0" , "+" , "-" , ] 
        swap caseof  \ use remainder to take proper symbol
        rot          \ put previous symbol on TOS 
        swap         \ this is required because "" should come first
        s:+          \ concatenate symbols
        swap         \ put number on TOS 
        dup
        n:sgn n:+    \ add 1 if positive or add -1 if negative
        3 n:/mod nip \ put quotient only on TOS
    while drop
    s:rev            \ reverse the result on TOS
;
 

0

Java, 327 269 ​​ký tự

Lần thử đầu tiên của tôi trong môn đánh gôn. Tôi không biết bất kỳ ngôn ngữ thực sự ngắn nào, vì vậy đây là một giải pháp trong Java. Tôi đánh giá cao lời khuyên để tiếp tục rút ngắn nó.

import java.util.*;class a{public static void main(String[] h){int i=Integer.parseInt(new Scanner(System.in).nextLine());String r="";while(i!=0){if(i%3==2||i%3==-1){r="-"+r;}else if(i%3==1||i%3==-2){r="+"+r;}else{r="0"+r;}i=i<0?(i-1)/3:(i+1)/3;}System.out.println(r);}}

Dùng thử tại đây: http://ideone.com/fxlBBb

CHỈNH SỬA

Thay thế BufferedReaderbằng Scanner, cho phép tôi xóa throwsmệnh đề, nhưng phải thay đổi nhập (+2 ký tự). Thay thế Integerbởi int. Thật không may, chương trình sẽ không biên dịch nếu không có String[] htrong main.


1
Bạn có thể lưu một vài byte bằng cách sử dụng Scannerthay vì của bạn BufferedReader. Ngoài ra, String[] hthrows java.lang.Exceptioncó lẽ không cần thiết, và bạn có thể tiết kiệm thêm một vài byte bằng cách sử dụng intthay vì Integer.

0

JavaScript (ES6), 51 byte

v=>[...v].map(x=>t=3*t+((+x!=+x)?(x+1)-0:0),t=0)&&t

Lặp qua các ký tự. Đầu tiên nhân tổng số lần trước 3 lần, sau đó nếu isNaN (ký tự) là đúng, chuyển đổi chuỗi (ký tự + "1") thành một số và thêm nó, nếu không thì không.




0

APL (NARS), 26 ký tự, 52 byte

{+/(3*¯1+⍳≢⍵)ׯ2+⌽'-0+'⍳⍵}

kiểm tra:

  h←{+/(3*¯1+⍳≢⍵)ׯ2+⌽'-0+'⍳⍵}
  h '+0-'
8
  h '+-0+'
19
  h '-+++'
¯14
  h ,'-'
¯1
  h ,'0'
0
  h ,'+'
1

có thể nó sẽ ít hơn nếu được sử dụng nhưng nó bị cấm ...

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.