Tekrarlanan bir ondalık sayıyı kesire dönüştürme


23

Bu sorunun sadece sonlanan ondalık sayıları için geçerli olması gerekmez - tekrarlanan ondalık sayılar da algoritma yoluyla kesirlere dönüştürülebilir.

Göreviniz, giriş olarak tekrarlanan bir ondalık sayı alan bir program yapmak ve ilgili ondalık sayıyı ve bu ondalık basamağı üreten paydayı (en düşük terimlerle) çıkarmaktır. 1'den büyük olan fraksiyonlar, benzeri olmayan fraksiyonlar olarak gösterilmelidir 9/5. Girişin pozitif olacağını varsayabilirsiniz.

Tekrarlanan ondalık bu formatta verilecektir:

5.3.87

İkinci nokta tekrarlandıktan sonraki her şeyle, şöyle:

5.3878787878787...

Programınız, eğik çizgiyle (veya düz metinler çıkarmazsanız, dilinizdeki eşdeğer formu) ayırarak pay ve paydayı temsil eden iki tamsayı çıkaracaktır:

889/165

Sonlanan ondalık sayıların, ikinci noktadan sonra hiçbir şey olmayacağını ve yinelenmeyen ondalık kısım içermeyen ondalık sayıların, iki nokta arasında hiçbir şey olmayacağını unutmayın.

Test durumları

Bu test durumları, gerekli tüm köşe kasalarını kapsar:

0..3 = 1/3
0.0.3 = 1/30
0.00.3 = 1/300
0.6875. = 11/16
1.8. = 9/5
2.. = 2/1
5..09 = 56/11
0.1.6 = 1/6
2..142857 = 15/7
0.01041.6 = 1/96
0.2.283950617 = 37/162
0.000000.1 = 1/9000000
0..9 = 1/1
0.0.9 = 1/10
0.24.9 = 1/4

İsterseniz, tamsayı kısmı olmayan kesirlerin ilk noktanın solunda hiçbir şeyin olmadığını varsayabilirsiniz. Bu isteğe bağlı test durumları ile test edebilirsiniz:

.25. = 1/4
.1.6 = 1/6
..09 = 1/11
.. = 0/1

1
Kesiri basitleştirmek gerekli midir? Yoksa basitleştirilmemiş bir biçimde (örneğin:) bırakmak makul 9/99mü?
Justin

3
(in lowest terms)yani, fraksiyon basitleştirilmelidir.
Joe Z.

2
13Bunun yerine çıktı almama izin verilir 13/1mi?
14'te mniip

4
Bu girişi 1.9999...ve çıkışı ele 2/1
aldığınızdan

3
@ThomasEding 1.9999.olduğunu 19999/10000almak için, 2/1size gereken 1..9bu değil mi?
Qwertiy

Yanıtlar:


8

Dyalog APL ( 75 73 69 68 karakter)

İşte bir başka ve beşinci girişim (muhtemelen benim sonuncum); Günü, 80 karakterden kısa bir kod parçası yazmaya ve kurallara tam olarak uymaya çalışarak geçirdim. Bu meydan okuma günümü kazandı!

Sonunda Dyalog APL ile çalışan (ancak çalıştırma işlevini kullanan çevrimiçi yorumlayıcı sayfasında değil) çalışan 75 karakterden oluşan bir APL satırı aldım.

(N,D)÷D∨N←(⍎'0',1↓I/⍨2=+\P)+(⍎'0',I/⍨2>+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I← '1.2.3'

Elbette biraz daha kısaltabilirim, ancak bir, iki veya üç alanın eksik olduğu özel durumlar. Kodum, ..giriş durumunu bile ele alabilir .

APL'nin okunmasının zor olduğunu biliyorum ve insanlar bir kodun gerçekte nasıl çalıştığını anlamaktan zevk aldıkları için, burada bazı açıklamalar var. Temel olarak, D değişkenindeki son paydayı ve N değişkenindeki son sayıcıyı hesaplarım.

APL sağdan sola ayrıştırılır.

  • İlk olarak, dize I ( I←) değişkeninde saklanır .
  • Daha sonra, bir noktanın nerede olduğunu belirten bir boole vektörüyle eşleştirilir ve bu vektöre P ( P←'.'=) adı verilir . Örneğin, '1.2.3' 0 1 0 1 0 ile eşlenecek.
  • Bu vektör 10 tabanındaki rakamlardır ( 10⊥); şimdi '1.2.3' 1010.
  • Ardından 1 bu sayıdan çıkarılır ( burada 1-⍨veya ile ¯1+, burada ikincisini seçtim). Şimdi '1.2.3' 1009.
  • Daha sonra bu sayı bir dizgeye ( ) dönüştürülür , iki başlangıç ​​basamağı kaldırılır ( 2↓), bu da 09'ı ilk '1.2.3' örneğimizden yapar; dize tersine çevrildi ( ).
  • Burada, özel bir durum olarak dizginin önüne ilk 0 karakteri ekliyorum; dört karakteri kullanmak beni üzüyor '0',ama ikinci ve üçüncüsü alanları boş olduğunda hata yapmaktan kaçındım. Dize, bir sayıya ( ) geri dönüştürülür ve bu, D'nin 0'a eşit olması nedeniyle, her iki son alanın boş olduğu durumlar dışında, payda olan D'de depolanır.
  • D←D+0=1 kodu kümesi D parçası şu anda boş ise ve artık D (elusyonu bölünmeden önce ancak) payda ihtiva eder.
  • Bu payda ( ×), ilk (⍎'0',I/⍨2>+\P)P dizgesinin içeriği ile tekrar P'den başlayan ikinci noktaya kadar çarpılır ( ) ( örneğime göre 0 1 0 1 0), ardışık sayıları toplayarak (0 1 1 2 yapar) 2 örneğime göre), hangi değerlerin 2'den küçük olduğunu kontrol edin (boolean vektörünü 1 1 1 0 0 yapın) ve I'de karşılık gelen karakterleri alın; (ilk iki alan boşsa) başka bir tuzağın önlenmesi için dizenin önüne bir 0 daha eklenir ve tamamı bir sayıya dönüştürülür.
  • Giriş dizisinin son kısmı önceki ürüne (⍎'0',1↓I/⍨2=+\P), P'yi tekrar alan, tekrar biriktirerek ekler, hangi değerlerin 2'ye eşit olduğunu kontrol eder (önceki açıklamaya bakın), karakterleri alır, ilk önce nokta olanı kaldırır. , önleyici bir ilk 0 karakteri ekler ve bir sayıya dönüştürür.
  • Bu toplamı izleyen ürün, N olan depoda depolanır.
  • Son olarak, GCD, D∨N ile hesaplanır ve her iki sayı da bu GCD'ye bölünür.

düzenleme: İşte 73 karakter için bir düzeltme:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←D+0=D←⍎'0',⌽2↓⍕¯1+10⊥P←'.'=I←

Bu hack fikri ilk önce kümülatif ilavenin 2'ye eşit değerlere sahip olduğu durumu hesaplamak, daha sonra bunları saklamak ve ilk vakayı elde etmek için bu bitsel maskeyi ters çevirmek; bu nedenle bir sonraki durumun hesaplanması daha az karaktere ihtiyaç duyar.

düzenleme: İşte 69 karakter için başka bir düzeltme:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽2↓⍕¯1+10⊥P←'.'=I←

Bu hack fikri, en karmaşık özel durumu değerlendirilecek diziye APL kodu olarak yerleştirmektir (dizgeden sayıya dönüşüm aşamasında).

düzenleme: İşte 68 karakter için başka bir düzeltme:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←⍎'1⌈0',⌽3↓⍕1-10⊥P←'.'=I←

Bu kesmek fikri değiştirmektir ekleyerek -1 değerine ameliyatla bu değere 1 substracting için 1 olarak o değer çıkarılarak daha sonra (eksi işareti olacaktır) başında daha fazla en geç bir karakteri kaldırın.

düzenleme: Kozmetik değişikliği:

(N,D)÷D∨N←(⍎'0',1↓P/I)+(⍎'0',I/⍨~P←2=+\P)×D←1⌈⍎'0',⌽3↓⍕1-10⊥P←'.'=I←

Boyutta gelişme yok, ancak değerlendirilecek kodun azami işlevini çıkarmak için daha memnun .


Bunu tryapl.org ile çalıştırmaya çalıştım ve şikayet etti INVALID TOKEN. Neden biliyor musun?
Peter Taylor

@Peter Taylor: Evet, benim mesajımda bile söyleniyor; Bunun nedeni, Dyalog sunucusu için güvenli olmayan ve çevrimiçi olarak devre dışı bırakılmış (güvenli mod) "execute" operatörünü kullanmam. Yüklü bir Dyalog APL sürümünde denemelisiniz.
Thomas Baruchel

Ah, ayıp. Arada bir PCG gönderimini test edebilmek için 60 € harcamam. Alternatif bir çevrimiçi APL test cihazı buldum, ancak kodunuzda Dyalog'a özgü bir şey var gibi görünüyor, çünkü rütbe hataları veya uzunluk hataları veriyor.
Peter Taylor

Peter Taylor; hayır ;-) Lütfen GNU APL ile kendi web sitemi kullan (hala deneysel ve resmi değil); ama uyumlu hale getirmek için iki karakter eklemek zorunda kaldım (etrafına parantez I): bu kalıcı bağlantıyı gör
Thomas Baruchel

15

Perl 6 (93 101 100 80 68 66 bayt)

$/=split ".",get;say ($0+($1+$2/(9 x$2.comb||1))/10**$1.comb).nude

Boyut, sadece başarısızlık yerine hiçbir şeyle başa çıkmak için artırıldı. Mouq kullanmayı önerdi $/, bu yüzden şimdi kullanılıyor ve kod 20 bayt daha kısa. Ayiko değiştirilmesi teklif /ile kodu daha kısa olacak şekilde (12 bayt). Daha sonra Mouq değiştirilmesi teklif charsile comb(sayısal bağlamda sayıda dönüşüm sonrası karakterlerin listesi karakter sayısı olduğu için, bunlar aynı olduğu durumda).

Örnek çıktı:

$ perl6 script.p6
5.3.87
889 165
$ perl6 script.p6
2.0.0
2 1
$ perl6 script.p6
0..3
1 3
$ perl6 script.p6
0.0.3
1 30
$ perl6 script.p6
0.0.0
0 1
$ perl6 script.p6
0.1.6
1 6
$ perl6 script.p6
0.01041.6
1 96
$ perl6 script.p6
0.2.283950617
37 162
$ perl6 script.p6
123.456.789
41111111 333000

Ne yazık ki, sıfır ile iki nokta arasında bir yer tutucu kullanmanın sorunsuz olduğu ortaya çıktı. 0..09döner 1/11, ancak 0.0.09döner 1/110.
Joe Z.

@JoeZ. Ah tamam. Hiçbir şey yazılmadığında, davayı işlemek için kodumu güncelleştirdim.
Konrad Borowski

Perl 6'yı bilmiyorum, ama 'abc' verildiğinde, programınızın c / 99 ... 9'u hesaplamak için tam olarak rasyonel aritmetik kullandığını, ancak yalnızca ab'yi hesaplamak için kayan nokta kullandığını tahmin etmede haklı mıyım? Bu durumda b birçok haneye sahipse yanlış cevap verecektir.
Omar

@ OmarAntolín-Camarena: Çok değil. Perl 6'da, değişkenler kayan nokta sayıları değil, varsayılan değerlerdir. Örneğin, 0.1 + 0.2 == 0.3Perl 6'da.
Konrad Borowski

2
80 karaktere $/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude
golf attı

6

J ( 85 90 89 karakter)

Saniyeden 5 karakterden daha kısa olan orijinal fonksiyonumda birkaç hata vardı: "n / 1" olarak tamsayılar çıkmadı ve bir düzineden fazla rakamdan oluşan rakamlara yanlış cevap verdi. İşte J'de, Eelvex'in bir karakteri kaydetme önerisini de içeren düzeltilmiş bir işlevi:

f=:3 :0
'a t'=.|:(".@('0','x',~]),10x^#);._1'.',y
(,'/'&,)&":/(,%+.)&1+/a%*/\1,0 1-~}.t
)

Bir dize alır ve bir dize döndürür. İşte örnek bir oturum:

   f '..'
0/1
   f '0.0.0'
0/1
   f '3..'
3/1
   f '..052631578947368421'
1/19
   f '0.2.283950617'
37/162
   f '.0.103092783505154639175257731958762886597938144329896907216494845360824742268041237113402061855670'
1/97

İlk iki test 0/13/1
senaryosunun

Tamsayıların çıkışını 5 karakter, mniip pahasına yaptım.
Omar

('0','x',~])Bir bayt kullanın ve kaydedin.
Eelvex

5

C, 171

Oldukça uzun. Daha da azaltılabilir. Hayır scanf, noktalar arasında herhangi bir sayı yoksa, gerçekten işleyemez. Hayır strtol. Sadece numara çırpma:

a,b,c,d,q;main(){while((q=getchar()-48)>-3)q<0?(d=b>0,b+=!b):d?(c=c*10+q,d*=10):(a=a*10+q,b*=10);for(a=a*--d+c,q=b*=d;q>1;a%q+b%q?--q:(a/=q,b/=q));printf("%d/%d\n",a,b);}

Ölçek:

rfc <<< "2..142857"
15/7

5

DC (tamamen genel değil, 76 karaktere kadar kısaltılmış)

Tamamen genel değil, ama lütfen bunu dünyadaki en eski şeylerden biriyle yaptığımı düşünün:

5.3.87 dsaX10r^d1-rla*sasbdscX10r^dlc*rlb*rlb*la+snsdlnld[dSarLa%d0<a]dsax+dldr/rlnr/f

Düzenleme: Çözümümü düzenlerim; daha genel değil, fakat biraz daha kısa:

sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f

Olarak kullan:

5.3.87 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
  • İlk alan gerekli değildir:

    .1.3 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
    

    tamam.

  • İkinci ve susuzluk alan en az bir basamak gerektirir


5

Javascript, 203

Çok uzun, ama yine de eğlenceli. Yeni satırlar, çünkü noktalı virgüller okunamıyor.

s=prompt(b=1).split(".")
P=Math.pow
a=s[0]
c=s[1]
d=P(10,l=c.length)
f=(P(10,s[2].length)-1)*P(10,l)||1
e=s[2]=+s[2]
a=d*a+b*c;b*=d
a=f*a+b*e;b*=f
function g(a,b){return b?g(b,a%b):a}g=g(a,b);a/g+"/"+b/g

Ben alıyorum 889/NaNben çalıştırdığınızda 5.3.87... Am bir şey yanlış yapıyor?
rafaelcastrocouto

Bilmiyorum ... Bu kodu yalnızca Safari konsoluna yapıştırırsam (Firefox veya Chrome da yapmalı), enter tuşuna basın ve "5.3.87" yazın, sadece "889/165"konsola giriyorum . Nasıl çalıştırıyorsun? @rafaelcastrocouto
tomsmeding

boşver ... Sanırım şu anda çalıştığı için yanlış bir şey yaptım ...
rafaelcastrocouto

1
b=1Parçayı içinde hareket ettirerek 1 karakter kaydedebilirsiniz prompt().
user2428118

1
f=(P(10,s[2].length)-1)*P(10,l),f=f?f:1=>f=(P(10,s[2].length)-1)*P(10,l)||1
f.ardelian

3

J (farklı yöntem)

Çok farklı bir metoda dayanan başka bir çözüm; bu sefer tamamen genel; sadece bir tamsayı gönderildiğinde 1-paydası eksik:

   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '.1.3'
2r15
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '.1.'
1r10
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '1..'
1
   ".((({.~(i.&1)),'+'"_,((":@(10&^)@#,'%~',])@}.@#~~:/\),'+%',((,~(##'9'"_),'%x:0'"_)@}.@#~2:=+/\@]))(=&'.')) '1..3'
4r3

3

GolfScript (67 karakter)

`{'.'/1$=.10\,?@-).!+0@+~}+3,/1$4$*]-1%~;*+*+].~{.@\%.}do;{/}+/'/'@

NB Bu boş tamsayı parçaları destekler.

Dize formunun ise 'n.p.q'o zaman değeridir n + p/E + q/(DE) = ((nD + p)E + q)/DEburada D = 10^(len p)ve E = 10^(len q) - 1, başka zaman len q = 0, bu durumda, E = 1(0 bölme önlemek için).

diseksiyon:

           # Stack: 'n.p.q'
`{         # Combined with the }+ below this pulls the value into the block
           # Stack: idx 'n.p.q'
    '.'/   # Stack: idx ['n' 'p' 'q']
    1$=    # Stack: idx str   (where str is the indexed element of ['n' 'p' 'q'])
    .10\,? # Stack: idx str 10^(len str)
    @-)    # Stack: str 10^(len str)-idx+1
           #   If idx = 0 we don't care about the top value on the stack
           #   If idx = 1 we compute D = 10^(len 'p')
           #   If idx = 2 we compute E' = 10^(len 'q') - 1
    .!+    # Handle the special case E'=0; note that D is never 0
    0@+~   # Stack: 10^(len str)-idx+1 eval('0'+str) (GolfScript doesn't treat 011 as octal)
}+         # See above
3,/        # Run the block for idx = 0, 1, 2
           # Stack: _ n D p E q
1$4$*      # Stack: _ n D p E q D*E
]-1%~;     # Stack: D*E q E p D n
*+*+       # Stack: D*E q+E*(p+D*n)
].~        # Stack: [denom' num'] denom' num'
{.@\%.}do; # Stack: [denom' num'] gcd
{/}+/      # Stack: denom num
'/'@       # Stack: num '/' denom

Her seferinde bir test girişinin her biriyle programın çalışmasını simüle eden çevrimiçi demo .


Denedim ve tüm kuralları takip ediyor gibi görünmüyor: "Sonlandırılan ondalık sayıların ikinci noktadan sonra hiçbir şeye sahip olmayacağına ve yinelenmeyen ondalık kısım içermeyen ondalık sayıların iki nokta arasında hiçbir şey olmayacağına dikkat edin." Kodunuzu girdi olmakla çalıştıramadım0.1.
Thomas Baruchel

-1. +300 puan aldığınızı fark ettikten sonra tekrar denedim. Adil değil, çünkü diğer çözümler sizin açıkça yapmadığınız tüm kuralları takip etmek için ellerinden geleni yaptı.
Thomas Baruchel

@ כאלוכאל, kurallara uymayı denemediğim iddiasına itiraz ediyorum. İsteğe bağlı test vakalarının pozisyonu, son bloğun tüm gerekli vakaları kapsadığını düşünmeme neden oldu; yanıldığım ortaya çıktı ve diğer kişilerin de aynı hatayı yapmasını önlemek için soruyu kısa bir süre sonra düzenleyeceğim. Daha önce işlenmemiş köşe kasalarını işlemek için kodumu güncelledim ve bunu göstermek için bir sınama bağlantım güncellendi.
Peter Taylor

bu iyi. Muhtemelen 300 puan hak ediyorsun. CodeGolf'a yeniyken, bu 300 puan benim için zor bir hedef oldu ve hala son tarihte kodumun kurallara tam olarak uyması için en kısa kod olduğunu düşündüğümde hala sahip olamadığım için hayal kırıklığına uğradım. Her neyse, tüm puanlarımı kazanmak için hayatım var. Saygılarımızla.
Thomas Baruchel

@ כאלוכאל: 500 puan başlatmak istedim (evet, ben böyle cömertim, daha az veremem) ödül ve sana o puanları verdim, ama sanırım zaten bir ödül başladı. Pekala, her neyse. Bu ödülün ne zaman biteceğini ve bu puanları kimlerin alacağını merak ediyorum.
Konrad Borowski

2

piton

Kitaplık yok - 156 karakter

_=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),
(10**len(c)-bool(c))*10**len(b);f=_(d,e);print'%i/%i'%(d/f,e/f)

Kullanımı fractions- 127 karakter

from fractions import*;a,b,c=raw_input().split('.');print Fraction(int(a+b+c)-bool(c)*int(a+b
),(10**len(c)-bool(c))*10**len(b))

fractionsVersiyon baskılar gibi şeyler "Kesir (7, 5)" yerine "7/5", değil mi?
Omar

Öyle değil; Bu arada, en iyi olanı çalıştırmıyorum. _=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b), ValueError: need more than 1 value to unpack
14'te

@ OmarAntolín-Camarena AFAIK, uygun olduğunda printkullanır , kullanmaz . Bu benim sonumdaki çıktı: puu.sh/7w64w.pngstrrepr
Oberon

@tomsmeding Her ikisi de bir satırda; Satır sonu, cevaba uyacak şekilde eklendi. _=lambda a,b:b and _(b,a%b)or a;a,b,c=raw_input().split('.');d,e=int(a+b+c)-bool(c)*int(a+b),(10**len(c)-bool(c))*10**len(b);f=_(d,e);print'%i/%i'%(d/f,e/f)hepsini bir satırda gitmeli.
Oberon

Doğru, @Oberon, muhtemelen benim bilgisayarımda olmadığımı ve kodu çalıştıramadığımı tahmin edebileceğiniz gibi.
Omar

2

Mathematica, 143

Her zamanki gibi, Mathematica, işi yapmak için birçok üst düzey işlev sunuyor, ancak onlara ayrıntılı isimler veriyor.

x=StringTake;c=ToExpression;p=s~StringPosition~".";{o,t}=First/@p;u=StringLength@s-t;d=t-o-1;Rationalize@(c@x[s,t-1]+c@x[s,-u]/((10^u)-1)/10^d)

Zamanım olduğunda daha sonra eklenecek örnek çıktı.


Bana tamsayıları n / 1 yerine n olarak çıkarıyor gibi geliyor. Bu doğru mu? (Benim
Omar

Ah, şimdi anlıyorum .... yorumlarda belirtilmiş. Her fraksiyon azaltılırsa Ne tuhaf gereklilik ... neden izin n/1azaltmayı n? Tamsayıları daha sonra dönüştürmek için fazladan ~ 50 bayt ekleyeceğim.
Jonathan Van Matre

Yaklaşımınız iyi. Benimki kullandığı FromDigitsiçin ben de göndermeye karar verdim.
DavidC,

2

Yakut - 112

x,y,z=gets.chop.split".";y||='0';z||='0';puts((y.to_i+Rational(z.to_i,10**z.length-1))/10**y.length+x.to_i).to_s

Bu benim ilk yakutla ilgili denemem, bu yüzden iyileştirmeler önermekten çekinmeyin.

$ ruby20 % <<< '5.3.87'
889/165
$ ruby20 % <<< '0..3'
1/3
$ ruby20 % <<< '0.0.3'
1/30
$ ruby20 % <<< '0.00.3'
1/300
$ ruby20 % <<< '0.6875.0'
11/16
$ ruby20 % <<< '1.8.0'
9/5
$ ruby20 % <<< '2..'
2/1
$ ruby20 % <<< '..'
0/1

".. 've" .1.2 "desteğinin kaldırılması, teknik özelliklere uymamanız anlamına geliyor, değil mi? (Onları da kaldırmayı tercih ederim.)
Omar

@ OmarAntolín-Camarena Belirli bir noktada, özellik söylüyor If you wish. Ben istemiyorum, bu yüzden 1. veya 3. basamak grubunu içermeyen kesirleri desteklemiyorum. Ancak, spesifikasyona uyan 2. basamak grubundan yoksun kesirleri destekliyorum.
saat

@minip, belirtimi yanlış okudunuz: "desteklemesini dilerseniz .. ve .1.2" yazmıyor, "diyorsa, dilerseniz, 0 .. ve 0.1.2 'nin her zaman olduğu gibi verildiğini varsayabilirsiniz. .. ve .1.2 ".
Omar

@ OmarAntolín-Camarena Noktası alındı. Düzenlenen.
saat

2

C, 164

Sıfırdan yapmama rağmen bu, Orion'un C çözümüne benziyor. Ancak bazı optimizasyonlarını çaldığını itiraf ediyorum. Çok kısa değil, ancak idare ediyor. = 1/4 ve 0.000000.1 = 1/9000000.

long a,b,c,d,e;main(){while((c=getchar()-48)>-3)c+2?a=a*10+c,b*=10:b?e=a,d=b:(b=1);
b>d?a-=e,b-=d:0;for(d=2;d<=a;)a%d+b%d?d++:(a/=d,b/=d);printf("%ld/%ld\n",a,b);}

2

Kitaplık kullanmadan iki python cevabı. İlk önce isteğe bağlı girişi birinciden önce bir rakam olmadan kullanır. ve 162 karakter

_=lambda a,b:b and _(b,a%b)or a;i,t,r=raw_input().split(".");b=r!="";d=(10**len(r)-b)*10**len(t);n=int((i+t+r)or 0)-b*int((i+t)or 0);f=_(d,n);print "%i/%i"%(n,d)

İkincisi, ilk haneden önce hiçbir şey işlemez, ancak gereken tüm girdileri doğru işlemez ve 150 karakterdir

_=lambda a,b:b and _(b,a%b)or a;i,t,r=raw_input().split(".");b=r!="";d=(10**len(r)-b)*10**len(t);n=int(i+t+r)-b*int(i+t);f=_(d,n);print "%i/%i"%(n,d)

2

Haskell

import Data.Ratio
f n=case s '.' n of
    [x,y,z]->(r x)%1+(r y)%(10^(length y))+(r z)%((10^t-1)*(10^(length y)))
        where
            r ""=0
            r n=read n
            t = if length z==0 then 9 else length z
s _ []=[[]]
s n (x:xs) | x==n = []:(s n xs)
           | otherwise = let (l:ls)=s n xs in (x:l):ls

Hey, bu kod golf, denemiyorsun bile!
saat

@mniip Ben kod golf de iyi değilim. En az tek karakterli değişken isimleri kullandım.
PyRulez

1
Dili veya kullanılan toplam karakter / bayt miktarını hiçbir zaman belirtmediniz.
Justin Fay

2
Girintilerde alan kazanmak, spanişlevleri uygulamak için kısa takma adlar eklemek, mümkün olduğunda alanı kaldırmak için {;} kullanın . import Data.Ratio v=span(/='.');w=tail;l=length;f n=(r x)%1+(r y)%p+(r z)%((10^t-1)*p)where{(x,b)=v n;(y,d)=v(w b);z=w d;p=10^(l y);r""=0;r n=read n;t=if null z then 9 else l z}- 178 karakter, 321 den aşağıya. NB True, eşanlamlı ,otherwisenull zlength z==0
bazzargh

2

JavaScript (ECMASCript 6) 180 175

G=(a,d)=>d?G(d,a%d):a;P=a=>+("1e"+a);L=a=>a.length;f=prompt().split(".");B=P(L(b=f[1]));D=P(L(b)+L(c=f[2]))-P(L(b))||1;alert((m=(f[0]+b||0)*D+B*(c||0))/(g=G(m,n=B*D))+"/"+n/g)

300 ödül için açık bir kazanan olmasa da ... bulabildiğim en kısa şey bu:

  • Önceki sürümden değişiklikler : mantığa hafif bir değişiklik ve Güç Pişlevinde değişiklik yaparak +("1e"+a)yerine Math.pow(10,a)birkaç karakter daha kaydetme ...

1

Mathematica 175

f@i_:=
If[IntegerQ[g=FromDigits[Map[IntegerDigits@ToExpression@#&,StringSplit[i,"."]/.""-> {}]
/.{a_,b_,c_}:> {{Sequence@@Join[a,b],c},Length@a}]],HoldForm[Evaluate@g]/HoldForm@1,g]

Rutinin çoğu girdilere masaj yapmaya gider. Tam sayıların ele alınması için yaklaşık 50 karakter kullanıldı.


Örnekler

f["7801.098.765"]

frac1

Daha fazla örnek:

TableForm[
 Partition[{#, f[#]} & /@ {"19..87", "19.3.87", "5.3.87", "0.0.3", "0..3", "0.2.283950617", 
"123.456.789", "6666.7777.8888", "2.0.0","0.0.0"}, 5], TableSpacing -> {5, 5}]

frac2


Normal olarak Mathematica'da nasıl başarılır?

FromDigitsgirişin belirli bir formda olması şartıyla, doğrudan tekrar eden bir ondalık ondalık sayıdan doğrudan bir fraksiyon elde edebilir. Tamsayılar tamsayılar olarak görüntülenir.

z={{{1, 9, {8, 7}}, 2}, {{1, 9, 3, {8, 7}}, 2}, {{5, 3, {8, 7}}, 1}, {{{3}}, -1}, {{{3}}, 0}, 
{{2, {2, 8, 3, 9, 5, 0, 6, 1, 7}}, 0}, {{1, 2, 3, 4, 5, 6, {7, 8, 9}}, 3}, 
{{6, 6, 6, 6, 7, 7, 7, 7, {8}}, 4}, {{2}, 1}, {{0}, 1}}

FromDigits/@z

z


Çıktınız yanlış formatta, çok hoş.
Omar

Garip bir şekilde, bu, Mathematica'daki kesirleri ifade etmek için varsayılan biçimdir. Bu formatı daha basit olana değiştirmek için birkaç karakter daha gerekir.
DavidC

1

J (96 karakter)

Eğik çizgi sembolünü ayırıcı olarak kullanmıyorum (ancak Mathematica’daki çözüm de zaten daha iyi olan bir grafiksel gösterimi kullandığı için değil); J dilde fraksiyon ile gösterilir rbunun yerine /:

   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '1..3'
4r3
   (((-.@]#[)((".@[%#@[(10x&^)@-{.@])+({.@](10x&^)@-#@[)*<:@{:@](".%<:@(10x&^)@#)@}.[)I.@])(=&'.')) '123.456.789'
41111111r333000

1

APL (tamamen genel değil)

Tamamen genel değil (dc için benim çözümüm gibi); Dyalog APL ile çalışır (ancak neden Dyalog APL'nin çevrimiçi sürümünde değil):

(R,F)÷(F←D×N)∨R←(⍎C)+D×(⍎I/⍨2>+\P)×N←10*¯1++/≠\P⊣D←¯1+10*⍴C←1↓I/⍨2=+\P←'.'=I← '123.456.789'

İlk alan isteğe bağlıdır, ancak diğer iki alan için en az bir basamak gerekir.


1

JavaScript (189)

i=prompt().split(".");a=i[0];b=i[1];c=i[2];B=b.length;p=Math.pow;n=a+b+c-(a+b);d=p(10,B+c.length)-p(10,B);f=1;while(f){f=0;for(i=2;i<=n;i++)if(n%i==0&&d%i==0){n/=i;d/=i;f=1}};alert(n+"/"+d)

Örnek:

Giriş:

5.3.87

Çıktı:

889/165

1

C (yazılı olarak 420 karakter; gereksiz boşluklar kaldırıldıktan sonra daha az)

Bunun 64 bit olduğunu varsaydığına dikkat edin long(örneğin 64 bit Linux); 0.2.28395061732-bit kullanan sistemlerde test durumu için başarısız olur long. Bu, yazım şeklini long longdeğiştirip printfformat dizgisini uygun şekilde değiştirerek bazı karakterlerin maliyetine göre düzeltilebilir .

#include <stdio.h>

long d[3], n[3], i;

int main(int c, char** v)
{
  while (c = *v[1]++)
    switch(c)
    {
    case '.':
      n[++i] = 1;
      break;
    default:
      d[i] = 10 * d[i] + c - '0';
      n[i] *= 10;
    }

  n[2] -= n[2] != 1;

  while (i--)
    d[2] += d[i] * n[i+1], n[i]*=n[i+1];

  i = d[2];
  *n = n[1];

  while (i)
    *d = i, i = *n%i, *n = *d;
  printf("%ld/%ld\n", d[2]/ *n, n[1]/ *n);
}

Güzel. Sen değiştirerek 1 karakterini tıraş edebilirsiniz '0'için 48.
Todd Lehman,

Bence switchifadeyi yeniden yazarak da birkaç tane daha kazanabilirsiniz if(c==46) n[++i]=1; else d[i]=10*d[i]+c-48,n[i]*=10;.
Todd Lehman,

-3

GTB , 81

`_:s;_,1,l?_)-S;_,"."
s;A;,1,S;_,".")-1
s;_,1+S;_,"."),l?_)-S;_,"."))→_
x?A;+_)►Frac

Örnek

?3.25.
            13/4

4
Bir derleyici bu dil için özgürce kullanılabilir hale gelinceye kadar, onu kullanan her cevabı reddedeceğim.
Gareth

1
Yukarıda bağlantı verilen sayfada bir derleyici var gibi görünüyor?
skibrianski

@skibrianski Bu yazıya meta
mniip 'te

2
@Gareth, sizin de oy kullanmanız için bir kaç Mathematica cevabı var. : P
Omar,

2
@ OmarAntolín-Camarena Mathematica için bir derleyici / tercüman var. GTB'de hiç yok. GTBBana inanmıyorsanız yukarıdaki bağlantıyı izleyin . Özel bir program için bazı sıkıştırılmış öğeler elde edersiniz, o zaman bu programı arar ve bir indirme sağladığını iddia eden sitenin uygun olmadığını söylersiniz. Peki nasıl derleriz?
Gareth
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.