Chuyển đổi một số thập phân lặp lại thành một phân số


23

Câu hỏi này không cần áp dụng cho việc chỉ chấm dứt số thập phân - lặp lại số thập phân cũng có thể được chuyển đổi thành phân số thông qua thuật toán.

Nhiệm vụ của bạn là tạo một chương trình lấy số thập phân lặp lại làm đầu vào và xuất ra tử số và mẫu số tương ứng (theo thuật ngữ thấp nhất) tạo ra sự mở rộng thập phân đó. Phân số lớn hơn 1 nên được biểu diễn dưới dạng phân số không chính xác như thế nào 9/5. Bạn có thể cho rằng đầu vào sẽ tích cực.

Số thập phân lặp lại sẽ được đưa ra trong định dạng này:

5.3.87

với tất cả mọi thứ sau khi dấu chấm thứ hai lặp lại, như thế này:

5.3878787878787...

Chương trình của bạn sẽ xuất hai số nguyên biểu thị tử số và mẫu số, được phân tách bằng dấu gạch chéo (hoặc dạng tương đương trong ngôn ngữ của bạn nếu bạn không xuất văn bản thuần túy):

889/165

Lưu ý rằng việc kết thúc số thập phân sẽ không có gì sau dấu chấm thứ hai và số thập phân không có phần thập phân không lặp lại sẽ không có gì giữa hai dấu chấm.

Các trường hợp thử nghiệm

Các trường hợp kiểm tra này bao gồm tất cả các trường hợp góc yêu cầu:

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

Nếu bạn muốn, bạn cũng có thể giả sử rằng các phân số không có phần nguyên không có gì ở bên trái của dấu chấm đầu tiên. Bạn có thể kiểm tra điều đó với các trường hợp kiểm tra tùy chọn sau:

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

1
Có cần thiết để đơn giản hóa các phần? Hoặc có hợp lý không khi để nó ở dạng không xác định (ví dụ 9/99:)?
Justin

3
(in lowest terms)tức là phần phải được đơn giản hóa.
Joe Z.

2
Tôi có được phép xuất ra 13thay vì 13/1không?
mniip

4
Hãy chắc chắn xử lý đầu vào 1.9999...và đầu ra này2/1
Thomas Eding

3
@ThomasEding 1.9999.19999/10000, để có được 2/1bạn cần 1..9, phải không?
Qwertiy

Câu trả lời:


8

Thuốc nhuộm APL ( 75 73 69 68 ký tự)

Đây là một nỗ lực khác và thứ năm (rất có thể là lần cuối cùng của tôi); Tôi đã dành cả ngày để cố gắng viết một số đoạn mã ngắn hơn 80 ký tự và hoàn toàn phù hợp với các quy tắc. Thử thách này đã làm cho ngày của tôi!

Cuối cùng tôi đã có một dòng APL gồm 75 ký tự, hoạt động với Dyalog APL (nhưng không phải trên trang phiên dịch trực tuyến vì sử dụng chức năng thực thi ), đây là một trong những ký tự sau:

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

Tất nhiên tôi có thể làm cho nó ngắn hơn một chút, nhưng trường hợp đặc biệt thiếu một, hai hoặc ba trường. Mã của tôi thậm chí có thể xử lý các ..trường hợp đầu vào.

Tôi biết rằng APL rất khó đọc và vì mọi người thích hiểu cách một đoạn mã thực sự hoạt động, đây là một số lời giải thích. Về cơ bản, tôi tính mẫu số cuối cùng trong biến D và tử số cuối cùng trong biến N.

APL được phân tích cú pháp từ phải sang trái.

  • Đầu tiên, chuỗi được lưu trữ trong biến I (I← ).
  • Sau đó, nó được ánh xạ tới một vectơ booleans cho biết vị trí của một dấu chấm và vectơ này được gọi là P (P←'.'= ). Ví dụ: '1.2.3' sẽ được ánh xạ thành 0 1 0 1 0.
  • Vectơ này là chữ số trong cơ sở 10 (10⊥ ); bây giờ '1.2.3' là 1010.
  • Sau đó, 1 được trừ từ số này (có thể có 1-⍨hoặc bằng¯1+ , ở đây tôi đã chọn số thứ hai). Bây giờ '1.2.3' là 1009.
  • Sau đó, số này được chuyển đổi thành một chuỗi ( ), hai chữ số ban đầu được loại bỏ ( 2↓), làm cho 09 từ ví dụ '1.2.3' ban đầu của chúng tôi; chuỗi được đảo ngược ( ).
  • Ở đây, như một trường hợp đặc biệt, tôi thêm một ký tự 0 ban đầu ở phía trước chuỗi; nó làm tôi buồn khi sử dụng bốn ký tự '0',nhưng tôi đã làm điều đó để tránh lỗi khi các trường thứ hai và thứ ba đều trống. Chuỗi được chuyển đổi trở lại thành một số ( ) và nó được lưu trữ trong D, đây là mẫu số trừ khi cả hai trường cuối cùng đều trống, vì trong trường hợp đó D bằng 0.
  • Các D←D+0= đoạn mã bộ D tới 1 nếu nó hiện là null, và bây giờ D chứa mẫu số (trước khi phân chia GCD tuy nhiên).
  • Mẫu số này được nhân ( ×) với nội dung của chuỗi ban đầu I cho đến dấu chấm thứ hai (⍎'0',I/⍨2>+\P)bắt đầu từ P một lần nữa (0 1 0 1 0 trong ví dụ của tôi), thêm các số liên tiếp bằng cách cộng chúng (tạo thành 0 1 1 2 2 trong ví dụ của tôi), kiểm tra giá trị nào nhỏ hơn 2 (tạo vectơ boolean 1 1 1 0 0) và lấy các ký tự tương ứng trong I; một số 0 khác được thêm vào trước chuỗi để ngăn bẫy khác (nếu hai trường ban đầu trống) và toàn bộ được chuyển đổi thành một số.
  • Phần cuối cùng của chuỗi đầu vào được thêm vào sản phẩm trước đó (⍎'0',1↓I/⍨2=+\P), với P một lần nữa, thêm bằng cách tích lũy lại, kiểm tra giá trị nào bằng 2 (xem phần giải thích trước), lấy các ký tự, loại bỏ giá trị đầu tiên là dấu chấm , thêm một ký tự 0 ban đầu ngăn chặn và chuyển đổi thành một số.
  • Sản phẩm này theo sau với một tổng được lưu trữ trong N là tử số.
  • Cuối cùng, GCD được tính bằng D∨N và cả hai số được chia cho GCD này.

chỉnh sửa: Đây là một sửa chữa cho 73 ký tự:

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

Ý tưởng của vụ hack này là điện toán trước tiên trong trường hợp bổ sung tích lũy có giá trị bằng 2, lưu trữ chúng sau này và đảo ngược mặt nạ bitwise này để lấy trường hợp đầu tiên; do đó tính toán trường hợp tiếp theo cần ít ký tự hơn.

chỉnh sửa: Đây là một sửa chữa khác cho 69 ký tự:

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

Ý tưởng của vụ hack này là nhúng trường hợp đặc biệt phức tạp nhất là mã APL trong chuỗi cần đánh giá (ở giai đoạn chuyển đổi chuỗi sang số).

chỉnh sửa: Đây là một sửa chữa khác cho 68 ký tự:

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

Ý tưởng của vụ hack này là thay thế thêm -1 vào giá trị để trừ 1 vào giá trị đó bằng cách trừ giá trị đó thành 1 sau đó xóa thêm một ký tự nữa ở đầu (sẽ là dấu trừ).

chỉnh sửa: Thay đổi mỹ phẩm:

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

Không cải thiện kích thước, nhưng hài lòng hơn để lấy hàm tối đa ra khỏi mã được đánh giá.


Tôi đã cố chạy cái này với tryapl.org và nó phàn nàn INVALID TOKEN. Bạn có biết tại sao?
Peter Taylor

@Peter Taylor: Vâng, nó thậm chí còn được nói trong tin nhắn của tôi; điều này là do tôi sử dụng toán tử "thực thi" sẽ không an toàn cho máy chủ của Dyalog và đã bị vô hiệu hóa trực tuyến (chế độ an toàn). Bạn phải thử nó trên phiên bản cài đặt của Dyalog APL.
Thomas Baruchel

A, xấu hổ quá. Tôi sẽ không chi 60 € để có thể kiểm tra trình PCG không thường xuyên. Tôi đã tìm thấy một trình kiểm tra APL trực tuyến thay thế, nhưng dường như có một thứ gì đó đặc trưng cho Dyalog trong mã của bạn vì nó đưa ra lỗi xếp hạng hoặc lỗi độ dài.
Peter Taylor

@Peter Taylor; không ;-) Xin vui lòng, sử dụng trang web của riêng tôi (vẫn còn thử nghiệm và chưa chính thức) với GNU APL; nhưng tôi đã phải thêm hai ký tự để làm cho nó tương thích (dấu ngoặc đơn quanh một I): xem permalink
Thomas Baruchel

15

Perl 6 (93 101 100 80 68 66 byte)

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

Kích thước được tăng lên để xử lý không có gì, thay vì chỉ thất bại. Mouq đề xuất sử dụng $/, vì vậy nó hiện đang được sử dụng và mã ngắn hơn 20 byte. Ayiko đề xuất thay thế /bằng , vì vậy mã thậm chí còn ngắn hơn (12 byte). Sau đó, Mouq đề xuất thay thế charsbằng comb(trong ngữ cảnh số, chúng giống hệt nhau, vì danh sách các ký tự sau khi chuyển đổi thành số là số ký tự).

Đầu ra mẫu:

$ 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

Thật không may, hóa ra việc sử dụng số 0 làm trình giữ chỗ giữa hai dấu chấm là không nên. 0..09trả lại 1/11, nhưng 0.0.09trả lại 1/110.
Joe Z.

@JoeZ. Ồ được thôi. Tôi đã cập nhật mã của mình để xử lý trường hợp khi không có gì được gõ.
Konrad Borowski

Tôi không biết Perl 6, nhưng tôi có đúng không khi đoán rằng 'abc', chương trình của bạn sử dụng số học hợp lý chính xác để tính c / 99 ... 9, nhưng chỉ sử dụng dấu phẩy động để tính ab? Trong trường hợp đó nếu b có nhiều chữ số thì nó sẽ trả lời sai.
Omar

@ OmarAntolín-Camarena: Không hoàn toàn. Trong Perl 6, các tỷ lệ hợp lý là mặc định, không phải là số dấu phẩy động. Ví dụ: 0.1 + 0.2 == 0.3trong Perl 6.
Konrad Borowski

2
$/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude
Chơi gôn

6

J ( 85 90 89 ký tự)

Hàm ban đầu của tôi, ngắn hơn 5 ký tự, có một vài lỗi: nó không xuất ra số nguyên là "n / 1" và nó đã trả lời sai về các số có hơn một chục chữ số. Đây là một chức năng được sửa trong J cũng kết hợp đề xuất của Eelvex để lưu một ký tự:

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

Nó nhận được một chuỗi và trả về một chuỗi. Đây là một phiên mẫu:

   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

Bạn nên sửa chức năng của mình thành đầu ra 0/1và trong 3/1hai trường hợp thử nghiệm đầu tiên, Xem bình luận này
mniip

Tôi đã sửa lỗi đầu ra cho số nguyên với chi phí là 5 ký tự, @mniip.
Omar

Sử dụng ('0','x',~])và lưu một byte.
Eelvex

5

C, 171

Khá dài. Có thể được giảm thêm. Không scanf, thực sự không thể xử lý nó nếu không có bất kỳ số nào giữa các dấu chấm. Không strtol. Chỉ cần bấm số giòn:

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

Kiểm tra:

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

5

DC (không hoàn toàn chung chung, rút ​​ngắn xuống còn 76 ký tự)

Không hoàn toàn chung chung, nhưng xin vui lòng, xem xét tôi đã làm điều đó với một trong những điều lâu đời nhất trên thế giới:

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

Chỉnh sửa: Tôi chỉnh sửa giải pháp của tôi; nó không chung chung hơn, nhưng ngắn hơn một chút:

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

Sử dụng nó như:

5.3.87 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
  • Trường đầu tiên không bắt buộc:

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

    không sao

  • Trường thứ hai và khát cần ít nhất một chữ số


5

Javascript, 203

Con đường quá dài, nhưng vẫn vui. Dòng mới vì dấu chấm phẩy là không thể đọc được.

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

Tôi nhận được 889/NaNkhi tôi chạy 5.3.87... Tôi đang làm gì đó sai?
rafaelcastrocouto 17/03/2016

Tôi không biết ... Nếu tôi chỉ dán mã này vào bảng điều khiển Safari (Firefox hoặc Chrome cũng vậy), nhấn enter và gõ "5.3.87", tôi chỉ cần "889/165"vào bảng điều khiển. Làm thế nào bạn đang chạy nó? @rafaelcastrocouto
tomsmeding 17/03/2016


1
Bạn có thể lưu 1 ký tự bằng cách di chuyển b=1phần bên trong 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 (phương pháp khác nhau)

Một giải pháp khác dựa trên một phương pháp rất khác nhau; lần này là hoàn toàn chung chung; chỉ thiếu là mẫu số 1 khi số nguyên được gửi:

   ".((({.~(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 ký tự)

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

NB Điều này hỗ trợ các phần nguyên trống.

Nếu chuỗi có dạng 'n.p.q'thì giá trị nằm n + p/E + q/(DE) = ((nD + p)E + q)/DEở đâu D = 10^(len p)E = 10^(len q) - 1, trừ khi len q = 0, trong trường hợp đó E = 1(để tránh chia cho 0).

Mổ xẻ

           # 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

Bản demo trực tuyến mô phỏng chạy chương trình với từng đầu vào kiểm tra, mỗi lần một.


Tôi đã thử nó và dường như nó không tuân theo tất cả các quy tắc: "Lưu ý rằng việc chấm dứt số thập phân sẽ không có gì sau dấu chấm thứ hai và số thập phân không có phần thập phân không lặp lại sẽ không có gì giữa hai dấu chấm." Tôi không thể làm cho mã của bạn hoạt động với đầu vào0.1.
Thomas Baruchel

-1. Tôi đã thử lại lần khác sau khi nhận thấy bạn có +300 điểm. Thật không công bằng, bởi vì các giải pháp khác đã cố gắng hết sức để tuân theo tất cả các quy tắc, điều mà rõ ràng là bạn chưa làm.
Thomas Baruchel

@ Tôi nói, tôi phản đối khẳng định của bạn rằng tôi đã không cố gắng tuân theo các quy tắc. Vị trí của các trường hợp kiểm tra tùy chọn làm tôi bối rối khi nghĩ rằng khối cuối cùng bao gồm tất cả các trường hợp cần thiết; Hóa ra tôi đã sai và tôi sẽ sớm sửa câu hỏi để tránh những người khác mắc lỗi tương tự. Bây giờ tôi đã cập nhật mã của mình để xử lý các trường hợp góc chưa được xử lý trước đó và cập nhật liên kết của tôi để kiểm tra để chứng minh điều đó.
Peter Taylor

vậy là được rồi. Bạn có thể xứng đáng với 300 điểm. Là người mới đối với CodeGolf, 300 điểm này là một mục tiêu đầy thách thức đối với tôi và tôi vẫn thất vọng vì không có được chúng trong khi tôi vẫn nghĩ rằng vào thời hạn cuối cùng, mã của tôi là ngắn nhất để hoàn toàn phù hợp với các quy tắc. Dù sao, tôi có cả cuộc đời để giành điểm. Trân trọng.
Thomas Baruchel

@ בבכאלכאלכאל: Tôi muốn bắt đầu 500 điểm (vâng, tôi hào phóng như thế, không phải là tôi có thể cho ít tiền hơn), và cho bạn những điểm đó, nhưng tôi đoán đã bắt đầu có tiền thưởng. Sao cũng được. Tôi tự hỏi khi nào tiền thưởng này sẽ kết thúc, và ai sẽ nhận được những điểm đó.
Konrad Borowski

2

Con trăn

Không có thư viện - 156 ký tự

_=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)

Sử dụng fractions- 127 ký tự

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

Các fractionsphiên bản in những câu như "Phân số (7, 5)" thay vì "7/5", đúng không?
Omar

Nó không; Nhân tiện, tôi không làm việc tốt nhất. _=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
tomsmeding

@ OmarAntolín-Camarena AFAIK, printsử dụng strkhi có sẵn, không repr. Đây là kết quả đầu ra của tôi: puu.sh/7w64w.png
Oberon

@tomsmeding Cả hai đều trên một dòng; ngắt dòng đã được thêm vào để làm cho chúng phù hợp với câu trả lời. _=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)nên đi tất cả trong một dòng.
Oberon

Ồ đúng rồi, @Oberon, như bạn có thể đoán là tôi không ở máy tính của mình và không thể chạy mã.
Omar

2

Toán học, 143

Như thường lệ, Mathematica cung cấp nhiều hàm cấp cao để thực hiện công việc, nhưng cung cấp cho chúng các tên dài dòng.

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)

Đầu ra mẫu sẽ được thêm vào sau khi tôi có thời gian.


Theo tôi thì điều này xuất ra số nguyên là n, thay vì n / 1. Có đúng không? (Giải pháp của tôi có cùng một lỗi ... :()
Omar

Ah, bây giờ tôi thấy .... được chỉ định trong các ý kiến. Thật là một yêu cầu kỳ quặc ... nếu mọi phân số khác đều giảm, tại sao không cho phép n/1giảm xuống n? Tôi sẽ thêm ~ 50 byte để chuyển đổi số nguyên sau này.
Jonathan Van Matre

Cách tiếp cận của bạn là tốt. Của tôi sử dụng FromDigitsvì vậy tôi quyết định đăng nó quá.
DavidC

2

Hồng ngọc - 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

Đây là thử nghiệm đầu tiên của tôi với ruby, vì vậy hãy đề xuất cải tiến.

$ 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

Xóa hỗ trợ ".. 'và" .1.2 "có nghĩa là bạn không theo dõi thông số kỹ thuật, phải không? (Tôi cũng muốn xóa chúng.)
Omar

@ OmarAntolín-Camarena Về điểm đó, thông số kỹ thuật nói , If you wish. Tôi không muốn, vì vậy tôi không hỗ trợ phân số mà không có nhóm chữ số 1 hoặc 3. Tuy nhiên, tôi đang hỗ trợ các phân số thiếu nhóm chữ số thứ 2, phù hợp với thông số kỹ thuật.
mniip

@minip, bạn đã đọc sai thông số: nó không nói "nếu bạn muốn bạn có thể hỗ trợ .. và .1.2", nó nói, "nếu bạn muốn, bạn có thể giả sử rằng 0 .. và 0.1.2 luôn được đưa ra là .. và .1.2 ".
Omar

@ OmarAntolín-Camarena Điểm lấy. Đã chỉnh sửa.
mniip

2

C, 164

Điều này tương tự như giải pháp C của orion, mặc dù tôi đã làm nó từ đầu. Tôi thú nhận tuy nhiên ăn cắp một số tối ưu hóa của anh ấy. Nó không ngắn hơn nhiều, nhưng nó xử lý 0,25. = 1/4 và 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

Hai câu trả lời python không sử dụng thư viện. Đầu tiên xử lý đầu vào tùy chọn mà không có một chữ số trước đầu tiên. và là 162 ký tự

_=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)

Thứ hai không xử lý gì trước chữ số đầu tiên nhưng xử lý chính xác tất cả các đầu vào cần thiết và là 150 ký tự

_=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

Này, đây là môn đánh gôn, bạn thậm chí không thử!
mniip

@mniip Mình chơi golf không giỏi. Atleast tôi đã sử dụng tên biến nhân vật duy nhất.
PyRulez

1
Bạn không bao giờ chỉ định ngôn ngữ hoặc tổng số ký tự / byte được sử dụng.
Justin Fay

2
Sử dụng {;} để tiết kiệm không gian trên các vết lõm, span để thực hiện s, thêm các bí danh ngắn cho các hàm, xóa khoảng trống nếu có thể. 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 ký tự, giảm từ 321. NB Truelà từ đồng nghĩa với otherwise, null 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)

Mặc dù nó không phải là một người chiến thắng rõ ràng cho 300 tiền thưởng ... đây là lần ngắn nhất tôi có thể đưa ra:

  • Thay đổi từ phiên bản trước: một số thay đổi nhỏ đối với logic và thay đổi Pchức năng Power bằng cách thay đổi nó thành +("1e"+a)thay vì Math.pow(10,a)lưu lại một vài ký tự ...

1

Toán học 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]

Hầu hết các thói quen đi đến mát xa đầu vào. Khoảng 50 ký tự đã đi đến xử lý số nguyên.


Ví dụ

f["7801.098.765"]

frac1

Ví dụ khác:

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


Làm thế nào nó thường được hoàn thành trong Mathematica

FromDigitscó thể có được một phần trực tiếp từ số thập phân lặp lại định kỳ, miễn là đầu vào có dạng cụ thể. Số nguyên được hiển thị dưới dạng số nguyên.

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


Đầu ra của bạn ở định dạng sai, nó quá đẹp.
Omar

Kỳ lạ thay, đây là định dạng mặc định để thể hiện phân số trong Mathicala. Sẽ cần thêm một vài ký tự để thay đổi định dạng này thành định dạng đơn giản hơn.
DavidC

1

J (96 ký tự)

Tôi không sử dụng biểu tượng dấu gạch chéo làm dấu phân cách (nhưng giải pháp trong Mathicala không phải vì nó sử dụng biểu diễn đồ họa dù sao cũng tốt hơn); trong ngôn ngữ J, phân số được hiển thị rthay vào đó là /:

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

1

APL (không hoàn toàn chung)

Không hoàn toàn chung chung (như giải pháp của tôi cho dc); hoạt động với Dyalog APL (nhưng không phải trên phiên bản trực tuyến của Dyalog APL, không biết tại sao):

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

Trường đầu tiên là tùy chọn, nhưng ít nhất một chữ số được yêu cầu cho cả hai trường khác.


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)

Thí dụ:

Đầu vào:

5.3.87

Đầu ra:

889/165

1

C (420 ký tự như đã viết; ít hơn sau khi xóa khoảng trắng không cần thiết)

Lưu ý rằng điều này giả sử 64 bit long(ví dụ Linux 64 bit); nó sẽ thất bại cho trường hợp thử nghiệm 0.2.283950617trên các hệ thống sử dụng 32 bit long. Điều này có thể được sửa chữa bằng chi phí của một số ký tự bằng cách thay đổi loại thành long longvà thay đổi printfchuỗi định dạng cho phù hợp.

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

Tốt đẹp. Bạn có thể cạo đi 1 ký tự bằng cách thay đổi '0'thành 48.
Todd Lehman

Tôi nghĩ rằng bạn cũng có thể tiết kiệm một vài chi tiết bằng cách viết lại switchtuyên bố như 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

Thí dụ

?3.25.
            13/4

4
Cho đến khi một trình biên dịch được cung cấp miễn phí cho ngôn ngữ này, tôi sẽ tải xuống mọi câu trả lời sử dụng nó.
Gareth

1
Dường như có một trình biên dịch trên trang được liên kết ở trên?
skibrianski


2
@Gareth, có một vài câu trả lời Mathicala để bạn downvote, quá. : P
Omar

2
@ OmarAntolín-Camarena Có một trình biên dịch / trình thông dịch cho Mathicala. GTB không có. Theo GTBliên kết ở trên nếu bạn không tin tôi. Bạn sẽ nhận được một số nội dung nén cho một chương trình độc quyền, sau đó bạn sẽ tìm kiếm chương trình đó và thấy rằng trang web tuyên bố cung cấp bản tải xuống cho biết nó không khả dụng. Vậy làm thế nào để chúng tôi biên dịch nó?
Gareth
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.