バランス三元コンバーター


32

チャレンジアイデアのクレジットは@AndrewPiliserに送られます。サンドボックス彼の最初の提案は放棄され、彼がここで数ヶ月活動していないので、私は挑戦を引き継ぎました。

バランス三元法は、非標準の数字システムです。そう-あなたは更に左に行くように、それは3倍値の桁の増加という点で、三元のようなもの100である9100128です。

ただし、0、1、および2の値を持つ代わりに、数字の値は-1、0、および1になります。(これを使用して、任意の整数を表現できます。)

この挑戦のために、数字の意味は、+1のように書くことになる+-1として書き込まれます-、と0だけです0。バランスの取れた3進法では-、数字の前にある記号を使用して、他の数字システムのように数字を無効にしません。例を参照してください。

あなたの仕事は、32ビットの10進数の符号付き整数を入力として受け取り、それを平衡3進数に変換する完全なプログラムを作成することです。どんな種類の組み込みベース変換関数も許可されていません(Mathematicaにはおそらく1つあります...)。入力は、標準入力、コマンドライン引数などになります。

入力にが0ある場合を除き、入力には先行ゼロが存在する場合がありますが、出力には存在しない場合があります0

これらは、バランスの取れた3進数から10進数への変換です。他の方法で変換する必要があります。

+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

ああ待って、私はちょうどバランスのとれた十数で質問があることに気づいた-これは重複ですか?

サンドボックスで述べたように、標準のphinary表現に関する課題に近いと思います。しかし、おそらくどちらかの複製ではありません。
マーティンエンダー14年

回答:


22

Python 2:58文字

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

最後から1桁ずつバランスの取れた3進数を生成します。最後の数字は残基によって与えられn%3ビーイング-10または+1。次に、最後の桁を削除し、Pythonのfloor-divideを使用して3で除算しn=(n+1)/3ます。次に、数字が0になるまで新しい最後の数字を再帰的に処理します。

空の文字列ではなく、入力0が与える特別なケースが必要です0


仕様ではこれが許可されていませんが、プログラムの代わりに関数を作成して0の空の文字列を出力できる場合、40文字の解決策が可能です。

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

n*"."and機能のみの場合に使用することをお勧めします。また、print s or 0より良い作品:P
ナブ14年

@Nabbに電話してくださいs or 0。試しましたn*"."andが、失敗すると失敗しn<0ます。
xnor 14年

@MartinBüttnerPythのより長い答えは、最適でないアルゴリズムの使用によるものでした。
オプティマイザー14年

@Optimizerまあ、もちろん、だからこそ、より良いアルゴリズムを最初に得たPythonの答えを支持しました。:P
マーティンエンダー14年

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 14年

@isaacg試してみてください;)
オプティマイザー14年

CJamの部門の丸めは異なりますか?
isaacg 14年

@isaacg-丸め-いいえ。CJam整数除算は丸められません。Itフロア
オプティマイザー14年

しかし、フロアはゼロまたは-infに向かっていますか?
isaacg 14年

6

JavaScript(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%3d
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インデックスを使用して最後の桁を見つけることにより、入力のバランスの取れた3進値を構築し、残りの桁が(n + 1)/ 3の平衡3進値に等しいという事実を使用します。次に、関数を呼び出して結果を返します。入力が0の場合は0を返します。

ここで試してみてください。


オンラインのPythインタープリターはありますか?

あります、投稿に追加します。
isaacg 14年

リンクが壊れています。私はreccomend オンラインそれをお試しください!、何かの通訳が必要なときはいつでもこれを使用します。ところで、あなたのコードは機能していないように見えます。私にとっては、単に入力を返すだけです。
パベル

@Pavel 2年前に書いたときに機能しました。現在のオンラインPythインタープリターはpyth.herokuapp.comです。上記のコードを実行する場合は、言語の完全なバージョン管理された履歴を持つgithub.com/isaacg1/pythからインタープリターをチェックアウトできます。
isaacg 16

3

Mathematicaの- 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

文字数を減らしてくれたMartinBüttnerに感謝します。


3

Mathematica、54文字

xnorの再帰に似ています

Unicodeのシンボルを置換するために使用されますFloorPart!=

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でのゴルフのヒント」から直接来ています。次に、単項式から平衡式3項式に一度に1トリットを変換します。これについては、例を手動で操作して説明します。

最終出力前に、三桁-0および+で表される!:および+それぞれ。

興味深い結果を得るために、-48単項に変換された(-そのまま)から始めます。最初の(右端の)トリットを計算するには、48÷3の残りを計算する必要があります。これを行うには、111sを3sに置き換えます。

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

48÷3には残りがないので、1sは残りません。最初のトリットが:(0の場合)であることがわかっているので、それを置き換えます。

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

これで「1つの場所」ができたので、残り3のが3の場所を表していることがわかります。数学を機能させるには、それらを3で割る、つまり1sで置き換える必要があります。

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

数学を再確認しましょう1111111111111111。3の位に16(単項)があり、ゼロ(:)があります。それは3✕16+1✕0= 48です。

もう一度始めましょう。111sを3sに置き換えます。

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

今回は残りがな1ので+、3桁に置き、残り3のsを1sに置き換えます。

-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)です。それには2つのトリット(+!)が必要です。つまり、キャリーがあります。10進算術のように、右端の数字を取得し、残りを左の列に追加します。私たちのシステムで!は、9の場所に置き、その左にさらに3を追加してから、すべての3sを1sに置き換えて27の場所を表します。

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

今は3が残っていないので、残りの単項数字を対応するトリットで置き換えることができます。2(11)は+!次のとおりです。

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

実際のコードでは、これは2つの段階で行われ、さs/1/+/y/1:/!0/バイトを保存するために、。2番目のステップも:sを0sに置き換えるため、実際には次のようになります。

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

次に、負の数があるかどうかを確認します。そのため、記号を取り除き、各トリットを反転する必要があります。

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

最後に、!sを-s に置き換えます。

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

それでおしまい!



1

JavaScript 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

Clojure、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の回答ですか?

Ungolfed(コメント付き):

(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文字

これは、入力として10進数の符号付き整数を取り、それを平衡3進数に変換する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(コメント付きの)改変されていないバージョンがあります:

 
: 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文字

コードゴルフの私の最初の試み。私はこれらの本当に短い言語のいずれも知らないので、Javaのソリューションを紹介します。さらに短縮するためのアドバイスをお願いします。

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られScannerthrows句を削除できましたが、インポートを変更する必要がありました(+2文字)。に置き換えられましIntegerint。ない場合は残念ながら、プログラムがコンパイルされませんString[] hではmain


1
Scanner代わりにを使用すると、数バイトを節約できる場合がありますBufferedReader。また、String[] hそしてthrows java.lang.Exceptionおそらく必要はありません、あなたが使用することによって、いくつかのより多くのバイトを救うかもしれないint代わりにInteger

0

JavaScript(ES6)、51バイト

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

文字をループします。最初に前の合計時間3を乗算し、isNaN(character)がtrueの場合、文字列(文字+ "1")を数値に変換して加算します。それ以外の場合はゼロです。




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.