균형 잡힌 3 차 변환기


32

도전 아이디어에 대한 크레딧은 @AndrewPiliser로 이동하십시오. 샌드 박스 에서 그의 원래 제안 은 취소되었고 그가 몇 달 동안 활동하지 않았기 때문에 나는 그 도전을 받아 들였습니다.

균형 삼항 은 비표준 숫자 시스템입니다. 그래서 - 그것은 당신이 왼쪽으로 더 가서 숫자 3의 요인에 의해 가치가 증가하는 것을 원처럼100입니다9100128입니다.

그러나 0, 1 및 2의 값을 갖는 대신 숫자의 값은 -1, 0 및 1 입니다. (여전히 정수를 표현하기 위해 이것을 사용할 수 있습니다.)

이 문제의 경우, 숫자의 의미는 +1로 기록됩니다 +, -1로 기록 될 것입니다 -, 그리고 0단지입니다 0. 균형이 잡힌 삼항은 -숫자 앞에 기호를 사용하여 다른 숫자 시스템처럼 기호를 부정 하지 않습니다 . 예를 참조하십시오.

당신의 임무는 32 비트 십진 부호있는 정수를 입력으로 취하여 균형 삼항으로 변환하는 완전한 프로그램을 작성하는 것입니다. 어떤 종류의 기본 변환 함수도 허용되지 않습니다 (Mathematica에는 아마도 하나가 있습니다). 입력은 표준 입력, 명령 행 인수 등이 될 수 있습니다.

입력이 0이 아니라면 출력에는 0이 입력에 존재하지만 출력에는 표시되지 않을 0수 있습니다 0.

이것들은 균형 삼항에서 십진수로의 변환입니다. 다른 방법으로 변환해야합니다.

+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

아 잠깐, 나는 방금 수십에 대한 질문 이 있음을 알았습니다. 이것은 중복입니까?

샌드 박스에서 언급했듯이 표준 피닌 표현에 대한 도전에 더 가깝다고 생각합니다 . 그러나 아마도 복제본이 아닐 수도 있습니다.
Martin Ender

답변:


22

파이썬 2:58 자

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

끝에서 한 자리 씩 균형 잡힌 삼항을 생성합니다. 마지막 숫자는 , 또는 , 잔차 n%3로 표시 됩니다. 그런 다음 마지막 숫자를 제거하고 Python의 floor-divide를 사용하여 3으로 나눕니다 . 그런 다음 숫자가 0이 될 때까지 새로운 마지막 숫자를 재귀 적으로 진행합니다.-10+1n=(n+1)/3

빈 문자열이 아닌 입력 0에 특별한 경우가 필요 0합니다.


스펙은 이것을 허용하지 않지만 프로그램 대신 함수를 작성하고 빈 문자열을 0으로 출력 할 수 있다면 40 문자 솔루션이 가능합니다.

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

n*"."and함수 전용 경우 에 사용 하는 것이 좋습니다. 또한 print s or 0더 잘 작동합니다 : P
Nabb

@Nabb 잘 부탁드립니다 s or 0. 나는 시도 n*"."and했지만 언제 실패합니다 n<0.
xnor

@ MartinBüttner Pyth의 더 긴 대답은 최적이 아닌 알고리즘을 사용했기 때문입니다.
옵티 마이저

@Optimizer 글쎄, 분명히, 그래서 더 나은 알고리즘을 먼저 얻은 Python 답변을 상향 조정했습니다. : P
Martin Ender

6

CJam, 24 바이트

나는 이것을 독립적으로 생각해 냈고 이것이 아마도 이것을 처리하는 유일한 방법이라고 생각합니다.

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

알고리즘 적으로 xnor의 답변과 유사합니다.

여기에서 온라인으로 사용해보십시오

작동 방식 :

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)";

"양수이면 증가, 음수이면 감소"비트가 필요합니까? 왜 증가하지 않습니까?
isaacg

@isaacg 사용해보십시오;)
Optimizer

CJam 부서의 반올림이 다른가요?
isaacg

@isaacg-반올림-아니요. CJam 정수 나누기는 반올림하지 않습니다. It floors
Optimizer

그러나 바닥이 0 또는 -inf입니까?
isaacg

6

자바 스크립트 (E6) 68

팝업을 통한 I / O를 통한 요청에 따라 완전한 프로그램. 핵심은 R 함수, 49 바이트입니다.

다른 재귀 솔루션과 크게 다르지 않습니다. "0"의 특수한 경우를 피하기 위해 문자열과 숫자 사이의 자동 변환 활용

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

R 기능 만 사용하여 FireFox / FireBug 콘솔에서 테스트

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

산출

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

뭔가 빠졌습니까? 지점 무엇 d=(n%3+3)%3경우 d=n%3에 대해 동일한 값을 얻을 수는 d?
RLH

@RLH는 음수 값이 아닙니다 (JavaScript가 아님). -20 % 3 === -2 % 3 === -2. 대신 -20 mod 3은 1이어야하고, (-20 % 3 + 3) % 3는 실제로 1입니다
edc65

6

피스, 71 24 23

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

이것은 @xnor의 40 문자 재귀 함수를 기반으로 한 재귀 솔루션입니다. ymod 3 인덱스를 사용하여 마지막 숫자를 찾아서 입력의 baanced 삼항을 구성한 다음 나머지 숫자는 바닥 나누기를 사용하여 (n + 1) / 3의 균형 삼항과 동일하다는 사실을 사용합니다. 그런 다음 함수를 호출하여 결과를 리턴하거나 입력이 0 인 경우 0을 리턴합니다.

여기에서 시도하십시오.


온라인 Pyth 통역사가 있습니까?

게시물에 추가하겠습니다.
isaacg

연결이 끊어졌습니다. 나는 그것을 추천 온라인으로보십시오! , 이제 통역사가 필요할 때마다 사용할 것입니다. 그건 그렇고, 코드가 작동하지 않는 것 같습니다. 나에게 입력을 반환합니다.
Pavel

@Pavel 2 년 전 제가 쓴 당시에 효과가있었습니다. 현재 온라인 Pyth 인터프리터는 pyth.herokuapp.com입니다 . 위의 코드를 실행하려면 github.com/isaacg1/pyth 에서 인터프리터를 확인하십시오 .
isaacg

3

티카 - 157 154 146 128

골프 버전 :

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

가독성에 대한 들여 쓰기

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

용법:

f[414]

산출:

+--0+00

문자 수를 줄인 Martin Büttner에게 감사드립니다.


3

매스 매 티카, 54 자

xnor의 재귀와 유사

유니 코드 문자를 대체하는 데 사용됩니다 Floor, Part,!=

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

산출

f간결하게 저장하고 볼 수없는 경우 유니 코드없이 작성

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 바이트

/^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/!/-/

온라인으로 사용해보십시오!

설명

코드의 첫 번째 절반 (첫 번째 줄 이하)은 십진수를 단항으로 변환하고 " sed에서의 골프 팁 "에서 바로 나온 것 입니다. 그런 다음 한 번에 하나의 trit로 단항을 균형 잡힌 삼항으로 변환합니다. 이는 수동으로 예제를 작업하여 보여줍니다.

최종 출력하기 전에, 원 숫자는 -, 0+에 의해 표현되고 !, :그리고 +각각.

흥미로운 결과를 위해,로 시작 -48하여 단항으로 변환했습니다 -. 첫 번째 (가장 오른쪽) 트릿을 계산하려면 나머지 48 ÷ 3을 계산해야합니다. 111s를 3s 로 바꾸면됩니다 :

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

48 ÷ 3에는 나머지가 없으므로 1s가 남아 있지 않으며 첫 번째 trit가 :(0) 임을 알고 있으므로 대체합니다.

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

이제 우리는 "한 곳"을 가지고 나머지 3는 세 곳을 나타냅니다. 수학을 계속 작동 시키려면 3으로 나누어야합니다. 즉, 1s로 바꿔야합니다 .

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

수학을 다시 확인해 봅시다. 우리는 11111111111111113 자리에 16 (단항 )이 있고 1에 0 ( :)이 있습니다. 3✕16 + 1✕0 = 48입니다. 지금까지는 좋았습니다.

이제 다시 시작합니다. 교체 111로들 3의 :

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

이번에 우리의 나머지는입니다 1. 그래서 우리는 세 +자리에 넣고 나머지를 3s로 1바꿉니다 :

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

위생 검사 시간 : 우리는 111119 위에 5 (단항 ) +, 3 위에 1 ( ) , 1 위에 0 ( :)이 있습니다 : 9✕5 + 3✕1 + 1✕0 = 48. 훌륭합니다! 다시 111s를 3s 로 바꿉니다.

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

이번에는 나머지가 2 ( 11)입니다. 그것은 두 개의 삼지창 ( +!)을 차지합니다 . 십진 산술에서와 같이, 우리는 가장 오른쪽 숫자를 취하고 나머지는 왼쪽 열에 추가합니다. 우리의 시스템에서, 그것은 우리가 !아홉 자리에 놓고 또 다른 세 개를 왼쪽에 추가 한 다음, 모든을 3s로 바꾸어 127의 자리를 나타냅니다.

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

이제 3이 남지 않았으므로 나머지 단항 자릿수를 해당하는 트라이 트로 바꿀 수 있습니다. 두 ( 11)이다 +!:

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

실제 코드에서이 두 단계로 수행된다 s/1/+/y/1:/!0/바이트를 저장하려면. 두 번째 단계는 또한 :s를 0s로 바꾸므로 실제로는 다음과 같이합니다.

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

이제 음수가 있는지 확인합니다. 우리는 표시를 없애고 각 삼지창을 뒤집어 야합니다.

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

마지막으로 !s를 -s 로 바꿉니다.

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

그게 다야!


2

Stax , 17 바이트

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

실행 및 디버깅

지금까지 가장 짧은 대답이지만 일부 골프 언어로 쉽게 구타해야합니다. 알고리즘은 @xnor의 Python 답변과 동일합니다.

ASCII 상응 :

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

1

자바 스크립트 (108) (102) (ES6, 아니 재귀 호출)

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}

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}

@ edc65의 대답만큼 화려하지는 않습니다 ...이 문제를 더 줄이는 데 도움이 될 것입니다 ...


1

클로저, 242 바이트

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

이것이 가장 긴 Clojure 답변입니까?

언 골프 (댓글 포함) :

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

여기에 8 진수 프로그램 을 입력으로 십진 부호가있는 정수를 가져 와서 균형 삼항으로 변환 하는 완전한 프로그램입니다

 
: 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
 

테스트

 
? 414
+--0+00
 

프로그램이 처음으로 변환 할 숫자를 요구할 때 (필요한 경우). 그런 다음 단어를 호출 f하여 다음 줄과 같이 더 많은 숫자를 변환 할 수 있습니다.

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

산출

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

코드 설명

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

입력 처리 용 코드입니다. 코드의 핵심은 단어 안에 f있습니다. 멀리에서 골프 물론 나는 단어를 사용하는 것 >bt대신에 f. 다음은 f주석이 달린 ungolfed 버전입니다 .

 
: 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 ​​자

코드 골프에 대한 나의 첫 번째 시도. 나는 그 짧은 언어를 전혀 모른다. 그래서 여기 자바로 해결책이있다. 더 짧아 줄 조언을 부탁드립니다.

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

여기에서보십시오 : http://ideone.com/fxlBBb

편집하다

로 대체 BufferedReader되어 절 Scanner을 제거 할 수 throws있었지만 가져 오기 (+2 자)를 변경해야했습니다. 로 대체 Integer되었습니다 int. 존재하지 않는 경우 불행하게도,이 프로그램은 컴파일되지 않습니다 String[] h에서 main.


1
Scanner대신을 사용하여 몇 바이트를 절약 할 수 있습니다 BufferedReader. 또한, String[] h그리고 throws java.lang.Exception아마도 필요하지 않습니다, 당신은 사용하여 몇 바이트를 저장할 수있는 int대신 Integer.

0

자바 스크립트 (ES6), 51 바이트

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

문자를 반복합니다. 먼저 이전의 총 시간에 3을 곱한 다음 isNaN (character)이 true이면 문자열 (문자 + "1")을 숫자로 변환하고 추가하고, 그렇지 않으면 0입니다.




0

APL (NARS), 26 자, 52 바이트

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

테스트:

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

⊥을 사용하면 더 적을 수 있지만 금지되어 있습니다 ...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.