Dengeli Üçlü Dönüştürücü


32

Mücadele fikri için krediler @AndrewPiliser'e gider. Kum havuzundaki orijinal teklifi terk edildi ve burada birkaç aydır aktif olmadığı için mücadeleyi ben devraldım.

Dengeli üçlü standart olmayan bir sayı sistemidir. Böylece - O sola ileri gidip olarak rakam 3 kat değer artıyor olduğu üçlü gibidir100olduğunu9ve100128 olduğunu.

Bununla birlikte, 0, 1 ve 2 değerlerine sahip olmak yerine , rakamlar -1, 0 ve 1 değerlerine sahiptir . (Herhangi bir tamsayıyı ifade etmek için bunu hala kullanabilirsiniz.)

Bu meydan okuma, basamaklı anlamı +1olarak yazılacaktır +, -1olarak yazılır -ve 0adildir 0. Dengeli üçlü, -sayıları önündeki simgeyi, diğer sayısal sistemler gibi onları olumsuzlamak için kullanmaz - örneklere bakın.

Göreviniz, girdi olarak 32 bitlik ondalık bir tamsayı alan ve onu dengeli üçlüye dönüştüren eksiksiz bir program yazmaktır. Herhangi bir türde yerleşik temel dönüştürme işlevine izin verilmez (Mathematica'da muhtemelen bir tane vardır ...). Giriş, standart giriş, komut satırı argümanları, vb. Üzerinde olabilir.

Önde gelen sıfırlar girişte bulunabilir, ancak girişte olmadıkça, girişte olmayabilir 0, bu durumda çıktı da olmalıdır 0.

Örnekler

Bunlar dengeli üçlüden ondalıkya dönüşümler; diğer yolla dönüştürmeniz gerekecek.

+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

Oh bekleyin, sadece dengeli düzine bir soru olduğunu fark ettim - bu bir kopyası mı?

Kum havuzunda belirttiğim gibi, standart kimlik beyanları konusundaki mücadeleye daha yakın olduğunu düşünüyorum . Ama bu muhtemelen ikisinin de kopyası değil.
Martin Ender

Yanıtlar:


22

Python 2: 58 karakter

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

Dengeli üçgenin sonundan başlayarak haneye kadar sayı oluşturur. Son basamak Tortu verilir n%3varlık -1, 0ya da +1. Son basamağı kaldırır ve Python'un kat bölmesini kullanarak 3'e böleriz n=(n+1)/3. Ardından, sayı 0 olana kadar tekrar tekrar yeni son rakamla ilerleriz.

Girişin boş dize yerine 0verilmesi için özel bir durum gerekir 0.


Teknik özellikler buna izin vermiyor, ancak eğer bir program yerine bir fonksiyon yazabilir ve boş dizgiyi 0 ile yazdırabilirseniz, 40 karakterlik bir çözüm mümkün olacaktır.

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

n*"."andYalnızca işlev durumunda kullanmak daha iyidir. Ayrıca print s or 0daha iyi çalışır: P
Nabb

@ Nabb İyi çağrı s or 0. Denedim n*"."andama ne zaman başarısız oluyor n<0.
xnor

@ MartinBüttner Pyth'un daha uzun cevabı sadece optimal olmayan bir algoritmanın kullanılmasıydı.
Doktor,

@Optimizer Açıkçası, bu yüzden daha iyi bir algoritma alan Python cevabını iptal ettim. : P
Martin Ender

6

CJam, 24 bayt

Bağımsız olarak bununla geldim ve bunun muhtemelen bununla başa çıkmanın tek yolu olduğunu düşünüyorum.

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

Algoritmik olarak, xnor'ın cevabına benzer.

Burada çevrimiçi deneyin

Nasıl çalışır :

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

"Pozitifse artış, negatifse azalma" biraz gerekli midir? neden sadece artış değil?
isaacg

@isaacg Deneyin;)
Optimizer

CJam'ın bölümündeki sonuç farklı mı?
isaacg

@isaacg - Yuvarlama - no. CJam tamsayı bölümü yuvarlak değil. Bu katlar
Doktor

Fakat sıfıra mı yoksa -inf'e mi?
isaacg

6

JavaScript (E6) 68

İstenildiği gibi, açılır pencereden I / O içeren eksiksiz bir program. Çekirdek R işlevidir, 49 bayttır.

Diğer özyinelemeli çözümlerden çok farklı değil sanırım. "0" için özel bir durumdan kaçınmak için dize ve sayı arasındaki otomatik dönüşümün avantajını kullanmak

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

ÖlçekSadece R işlevini kullanarak FireFox / FireBug konsolunda edin

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

Çıktı

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

Bir şey mi eksik? Ne d=(n%3+3)%3zaman d=n%3aynı değeri verir ne anlama geliyor d?
RLH,

@RLH negatif değerler için değil (JavaScript'te değil). -20% 3 === -2% 3 === -2. Bunun yerine -20 mod 3 1 olmalı ve (-20% 3 + 3)% 3 gerçekten 1
edc65 21

6

Pyth, 71 24 23

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

Bu, @ xnor'ın 40 karakter özyinelemeli işlevine dayanan özyinelemeli bir çözümdür. ymod 3 endeksini kullanarak son basamağı bularak girdinin dengeli üçlüsünü oluşturur ve daha sonra basamakların geri kalanının (n + 1) / 3 için katlanmış bölümü kullanarak dengeli üçlüye eşit olduğu gerçeğini kullanır. Ardından, işlevi döndürerek sonucu döndürür veya giriş 0 ise 0 olur.

Burada dene.


Çevrimiçi Pyth tercümanı var mı?

Var, ben yazıya ekleyeceğim.
isaacg

Bağlantınız koptu. Tavsiye ederim Çevrimiçi deneyin! Bundan sonra ne zaman bir tercümana ihtiyacınız olursa kullanacağınız. Bu arada, kodun çalışmıyor gibi görünüyor, benim için sadece girişi döndürdü.
Pavel,

@Pavel Yazdığımda iki yıl önce çalıştı. Geçerli çevrimiçi Pyth tercümanı pyth.herokuapp.com 'dir . Yukarıdaki kodu çalıştırmak istiyorsanız, tercümanı dilden kontrol edilmiş bir geçmişi olan github.com/isaacg1/pyth adresinden kontrol edebilirsiniz.
isaacg

3

Mathematica - 157 154 146 128

Golf versiyonu:

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

Ve okunaklılık için girinti ile:

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

Kullanımı:

f[414]

Çıktı:

+--0+00

Martin Büttner'e karakter sayısını azaltmakta çok teşekkür ederiz.


3

Mathematica, 54 karakter

Xnor's recursion ile benzer

Unicode semboller yerine kullanılır Floor, Part,!=

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

Çıktı

fKısalık olarak saklanır ve unicode incase olmadan yazılır.

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 bayt

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

Çevrimiçi deneyin!

açıklama

Kodun ilk yarısı (ilk satırdan az), ondalık basamağı tek kelimeye çevirir ve doğrudan “ Sed'de golf için ipuçları ” dan gelir . Sonra, her seferinde bir el ile bir örnek çalışarak göstereceğim, her seferinde dengeli üçlü bir triti çevirir.

Son çıkış önce, üçlü sayı -, 0ve +ile temsil edilir !, :ve +sırasıyla.

İlginç bir sonuç için, başlangıçtan sonra -48( -bozulmamış) birliğe dönüşen ile başlıyoruz . İlk (en sağdaki) paragrafı hesaplamak için, geri kalan 48 ÷ 3 değerini hesaplamamız gerekir. Bunu 111s'yi s ile değiştirerek yapabiliriz 3:

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

48 ÷ 3 ' 1ün geri kalanı yok, bu yüzden kalmadı ve ilk adımımızın :(0 için) olduğunu biliyoruz , o yüzden değiştiriyoruz:

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

Şimdi "kendi yerlerimiz" var, bu yüzden kalanların 3üçlü yeri temsil ettiğini biliyoruz . Matematiği çalışır halde tutmak için, onları 3'e bölmeliyiz, yani onları 1s ile değiştirin :

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

Matematiğimizi iki kez kontrol edelim: 1111111111111111Üçlü yerde 16 (unary ), ve yerde sıfır ( :) aldık . Bu 3✕16 + 1✕0 = 48'dir. Şimdiye kadar çok iyi.

Şimdi tekrar başlıyoruz. S'yi 111s ile değiştirin 3:

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

Bu sefer kalanımız şudur 1, bu yüzden +üçlüleri yerleştirip kalanları 3s ile değiştiririz 1:

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

Akıl sağlığı kontrol süresi: 11111Dokuzlar yerinde 5 (unary ) +, üçler yerinde 1 ( ) ve o yerde 0 ( :) var: 9✕5 + 3✕1 + 1✕0 = 48. Harika! Yine 111s'yi s ile değiştiriyoruz 3:

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

Bu sefer kalanımız 2 (11 ). Bu iki triti ( +!) alıyor, bu da bizim elimizde taşıdığımız anlamına geliyor. Ondalık aritmetikte olduğu gibi, en sağdaki basamağı alıyoruz ve gerisini sola sütuna ekliyoruz. Bizim sistemimizde bu !, dokuzuncu yere koyduğumuz ve soluna üç tane daha eklediğimiz, daha sonra 27'lerdeki yeri temsil etmek için tüm s'leri 3s ile değiştirelim 1:

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

Artık 3 tane kalmadı, bu yüzden kalan herhangi bir basamak hanesini karşılık gelen değerleriyle değiştirebiliriz. İki ( 11) +!:

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

Gerçek kodda bu iki adımda yapılır s/1/+/vey/1:/!0/ baytları kurtarmak için. İkinci adım aynı zamanda :s'yi s ile değiştirir 0, yani aslında bunu yapar:

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

Şimdi negatif bir sayımız olup olmadığını kontrol ediyoruz. Yapıyoruz, bu yüzden işaretten kurtulmalı ve her basamağı ters çevirmeliyiz:

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

Sonunda !s ile değiştiririz- :

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

Bu kadar!


2

Stax , 17 bayt

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

Koş ve hata ayıkla

Şimdiye kadarki en kısa cevap, ancak bazı golf dilleri tarafından kolayca yenilmelidir. Algoritma @ xnor'ın Python cevabı ile aynıdır.

ASCII eşdeğeri:

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

1

JavaScript 108 102 (ES6, tekrarlı arama yok)

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’deki orijinal giriş

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'in cevabı kadar süslü değil ... Bunu daha da azaltmak için herhangi bir yardımı takdir ediyorum ...


1

Clojure, 242 bayt

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

Bu, bugüne kadarki en uzun Clojure cevabı mı?

Ungolfed (yorumlarla):

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

İşte 8'inci tam bir programdır ve girdi olarak ondalık işaretli bir tamsayı alır ve onu dengeli üçlüye dönüştürür

 
: 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
 

Ölçek

 
? 414
+--0+00
 

Program ilk kez dönüştürülecek bir sayı ister (gerektiği gibi). Ardından, faşağıdaki satırdaki gibi daha fazla sayıyı dönüştürmek için sözcüğü çağırmak mümkündür :

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

Çıktı

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

Kod açıklaması

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

Bu giriş işlemenin kodudur. Kodun özü kelimenin içindedir f. Golf sahasından uzak >btyerine kelimeyi kullanırdım f. İşte bir ungolfed versiyonu f(yorumlarla):

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

İlk önce kod golfünü deniyorum. Bu kısa dillerden hiçbirini tanımıyorum, işte Java'da bir çözüm. Daha da kısaltmak için tavsiye ediyorum.

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

Burada deneyin: http://ideone.com/fxlBBb

DÜZENLE

Değiştirilen BufferedReadertarafından Scanner, beni uzaklaştırmak için izin throwsşartı, ama değişim ithalat (2 karakter) gerekiyordu. IntegerTarafından değiştirildi int. Yoksa yazık ki, programın derlemek olmaz String[] hiçinde main.


1
Bunun Scanneryerine bir kaç bayt kaydedebilirsiniz BufferedReader. Ayrıca,String[] h ve throws java.lang.Exceptionmuhtemelen gerekli değildir ve intyerine birkaç bayttan tasarruf edebilirsiniz Integer.

0

JavaScript (ES6), 51 bayt

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

Karakterler arasında dolaş. Önce önceki toplam çarpı 3 ile çarpın, sonra isNaN (karakter) true ise, dizgiyi (karakter + "1") bir sayıya dönüştürün ve ekleyin, aksi halde sıfır.




0

APL (NARS), 26 karakter, 52 bayt

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

Ölçek:

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

⊥ kullanılırsa daha az olabilir, ancak yasaktır ...

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.