Перетворити повторний десятковий дріб


23

Це питання не потрібно застосовувати лише до закінчення десяткових знаків - повторювані децималі також можуть бути перетворені у дроби через алгоритм.

Ваше завдання полягає в тому, щоб зробити програму, яка приймає повторний десятковий як вхідний, і вивести відповідний чисельник і знаменник (найнижчим рівнем), який виробляє це десяткове розширення. Дроби, що перевищують 1, повинні бути представлені як неправильні дроби 9/5. Можна припустити, що вхід буде позитивним.

Повторне десяткове число буде подано у такому форматі:

5.3.87

при цьому все повторюється після другої крапки:

5.3878787878787...

Ваша програма виведе два цілі числа, що представляють чисельник і знаменник, розділені косою рисою (або еквівалентною формою на вашій мові, якщо ви не виведете звичайний текст):

889/165

Зауважте, що після закінчення другої крапки після децималей нічого не буде, а децималі без десяткової частини, що не повторюється, не матимуть нічого між двома крапками.

Тестові справи

Ці тестові справи охоплюють усі необхідні кутові випадки:

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

За бажанням ви також можете припустити, що дроби без цілих частин не мають нічого зліва від першої крапки. Ви можете перевірити це за допомогою цих необов'язкових тестових випадків:

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

1
Чи потрібно спростити дріб? Або розумно залишати його в непростому вигляді (наприклад:) 9/99?
Джастін

3
(in lowest terms)тобто дріб повинен бути спрощений.
Джо З.

2
Чи дозволено мені виводити 13замість 13/1?
mniip

4
Не забудьте впоратись із цим входом 1.9999...та виходом2/1
Thomas Eding

3
@ThomasEding 1.9999.- 19999/10000щоб отримати 2/1потрібну 1..9, чи не так?
Qwertiy

Відповіді:


8

Діалог APL ( 75 73 69 68 символів)

Ось ще одна і п'ята спроба (швидше за все, моя остання); Я провів день, намагаючись написати якийсь фрагмент коду, менший за 80 символів, і цілком відповідав правилам. Цей виклик зробив мій день!

Нарешті я отримав рядок APL, що складається з 75 символів, працюючи з Dyalog APL (але не на сторінці онлайн-перекладача, оскільки використовую функцію Execute ), який є наступним:

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

Звичайно, я міг би зробити це трохи коротшим, але особливі випадки, коли одне, два чи три поля відсутні. Мій код може навіть обробляти ..регістр вводу.

Я знаю, що APL важко читати, і оскільки люди із задоволенням розуміють, як фрагмент коду насправді працює, ось кілька пояснень. В основному я обчислюю кінцевий знаменник у змінній D та кінцевий чисельник у змінній N.

APL розбирається справа наліво.

  • По-перше, рядок зберігається у змінній I ( I←).
  • Потім він відображається на вектор булевих знаків, що вказує, де знаходиться точка, і цей вектор називається P ( P←'.'=). Наприклад, "1.2.3" буде відображено в 0 1 0 1 0.
  • Цей вектор є цифрами в базі 10 ( 10⊥); зараз '1.2.3' - 1010.
  • Потім 1 віднімається від цього числа (або з, 1-⍨або з ¯1+, тут я вибрав друге). Зараз '1.2.3' - 1009.
  • Потім це число перетворюється у рядок ( ), дві початкові цифри видаляються ( 2↓), що складає 09 з нашого початкового прикладу '1.2.3'; рядок обернено ( ).
  • Тут, як особливий випадок, я додаю початковий символ 0 перед рядком; мені дуже сумно використовувати чотири символи, '0',але я це зробив, щоб уникнути помилки, коли друге і третє поля обоє порожні. Рядок перетворюється назад у число ( ) і зберігається в D, що є знаменником, за винятком випадків, коли обидва останні поля порожні, тому що в такому випадку D дорівнює 0.
  • D←D+0=Шматок коду безлічі D 1 , якщо вона в даний час нульовий, а тепер D містить знаменник (до НОД поділу однак).
  • Цей знаменник множиться ( ×) зі змістом початкового рядка I до другої крапки, з (⍎'0',I/⍨2>+\P)якої починається знову з P (у моєму прикладі 0 1 0 1 0), додає послідовні числа шляхом їх кумуляції (що складає 0 1 1 2 2 у моєму прикладі), перевірте, які значення менші за 2 (створення булевого вектора 1 1 1 0 0), і взяти відповідні символи в I; ще один 0 додається перед рядком для запобігання черговій пастці (якщо два початкових поля порожні) і ціле перетворюється в число.
  • Остання частина вхідного рядка додається до попереднього добутку з (⍎'0',1↓I/⍨2=+\P), який приймає P знову, додає, накопичуючи ще раз, перевіряє, які значення дорівнюють 2 (див. Попереднє пояснення), приймає characers, видаляє першу, яка є крапкою , додає попереджувальний початковий символ 0 і перетворюється на число.
  • Цей продукт із сумою зберігається в N, який є чисельником.
  • Нарешті, GCD обчислюється з D∨N, і обидва числа діляться цим GCD.

редагувати: Ось виправлення для 73 символів:

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

Ідея цього хака - обчислити спочатку випадок, коли сукупне додавання має значення, що дорівнюють 2, зберігаючи їх для подальшого та інвертуючи цю розрядну маску для отримання першого випадку; таким чином для обчислення наступного випадку потрібно менше символів.

редагувати: Ось чергове виправлення для 69 символів:

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

Ідея цього злому полягає в тому, щоб вбудувати найскладніший спеціальний випадок як код APL у рядку, який слід оцінювати (на етапі перетворення рядка в число).

редагувати: Ось чергове виправлення для 68 символів:

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

Ідея цього хаку полягає в заміні додавання -1 до значення для підняття 1 до цього значення операцією, що підкреслює це значення 1, а потім видалити пізніше на один символ більше (що буде знаком мінус).

редагувати: Косметичні зміни:

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

Не поліпшення розміру, але більш задоволене, щоб отримати максимальну функцію з коду, що оцінюється.


Я спробував запустити це з tryapl.org, і він скаржиться INVALID TOKEN. Ти знаєш чому?
Пітер Тейлор

@ Петер Тейлор: Так, це навіть сказано в моєму повідомленні; це тому, що я використовую оператор "Execute", який був би небезпечний для сервера Dyalog і був відключений в Інтернеті (безпечний режим). Ви повинні спробувати це на встановленій версії Dyalog APL.
Томас Баручель

Ах, сором. Я не збираюсь витрачати 60 €, щоб мати змогу перевірити випадкові подання PCG. Я знайшов альтернативний тестер APL в Інтернеті, але, схоже, у вашому коді є щось специфічне для Dyalog, оскільки воно дає помилки ранжування або помилки довжини.
Пітер Тейлор

@ Петер Тейлор; ні ;-) Будь ласка, використовуйте мій власний веб-сайт (досі експериментальний та не офіційний) з APL GNU; але мені довелося додати два символи, щоб зробити його сумісним (дужки навколо одного I): дивіться це постійну посилання
Thomas Baruchel

15

Perl 6 (93 101 100 80 68 66 байт)

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

Розмір був збільшений, щоб нічого не впоратися, а не просто вийти з ладу. Mouq запропонував використовувати $/, тому він зараз використовується, а код на 20 байт коротший. Айко запропонував замінити /на , тому код ще коротший (на 12 байт). Тоді Mouq запропонував замінити charsна comb(у числовому контексті вони однакові, оскільки список символів після перетворення в число - це число символів).

Вибірка зразка:

$ 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

На жаль, виявляється, що використовувати нуль як заповнювач між двома крапками - це безрезультатно. 0..09повертається 1/11, але 0.0.09повертається 1/110.
Джо З.

@JoeZ. О, добре. Я оновив свій код для обробки випадку, коли нічого не вводиться.
Конрад Боровський

Я не знаю Perl 6, але чи правильно я гадаю, що в даному "abc" ваша програма використовує точну раціональну арифметику для обчислення c / 99 ... 9, але використовує лише плаваючу крапку для обчислення ab? У тому випадку, якщо b має багато цифр, вона дасть неправильну відповідь.
Омар

@ OmarAntolín-Camarena: Не зовсім. У Perl 6 раціональні значень за замовчуванням, а не числа з плаваючою комою. Наприклад, 0.1 + 0.2 == 0.3у Perl 6.
Конрад Боровський

2
Гольфували до 80 годин: $/=split ".",get;say join "/",($0+($1+$2/(9 x chars $2 or 1))/10**$1.chars).nude:)
Mouq

6

J ( 85 90 89 символів)

Моя оригінальна функція, яка була на 5 символів коротшою за другу, мала пару помилок: вона не виводила цілих чисел як "n / 1", і вона давала неправильну відповідь на числа, що мають більше десятка або близько цифр. Ось виправлена ​​функція в J, яка також включає пропозицію Eelvex щодо збереження символу:

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

Він отримує рядок і повертає рядок. Ось зразок сеансу:

   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

Ви повинні зафіксувати свою функцію для виведення 0/1та отримання 3/1перших двох тестових випадків. Дивіться цей коментар
mniip

Я виправив вихід на цілі числа вартістю 5 знаків, @mniip.
Омар

Використовуйте ('0','x',~])та зберігайте байт.
Ельвенкс

5

С, 171

Досить довго. Можливо, ще більше зменшити. Ні scanf, що насправді не вдається впоратися з цим, якщо між точками немає чисел. Ні strtol. Сумління простого числа:

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

Тест:

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

5

DC (не повністю загальний, скорочено до 76 символів)

Не зовсім загальне, але, будь ласка, врахуйте, що я зробив це з однією з найстаріших речей у світі:

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

Редагувати: я редагую своє рішення; це не більш загально, але трохи коротше:

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

Використовуйте його як:

5.3.87 sadsbX10r^sclaX10r^dd1-dsdlblc**rla*+dsnrld*dsd[dSarLa%d0<a]dsax+dldr/rlnr/f
  • Перше поле не потрібно:

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

    гаразд.

  • Друге поле і спрага потребують хоча б однієї цифри


5

Javascript, 203

Шлях занадто довгий, але все-таки веселий. Нові рядки, бо крапки з комою не читаються.

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

Я отримую, 889/NaNколи бігаю 5.3.87... Чи я щось роблю не так?
rafaelcastrocouto

Я не знаю ... Якщо я просто вставте цей код у консоль Safari (Firefox або Chrome теж повинен зробити), натисніть клавішу Enter і введіть "5.3.87", я просто потрапляю "889/165"в консоль. Як ти це працюєш? @rafaelcastrocouto
tomsmeding

не маю на увазі ... Я думаю, я щось зробив не так, оскільки зараз працює ...
rafaelcastrocouto

1
Ви можете зберегти 1 символ, перемістивши b=1частину всередину 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 (інший метод)

Ще одне рішення, засноване на зовсім іншому методі; цього разу цілком загальне; при відсутності цілого числа є лише 1-знаменник:

   ".((({.~(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 символів)

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

Примітка. Це підтримує порожні цілі частини.

Якщо рядок має вигляд 'n.p.q'то значення , n + p/E + q/(DE) = ((nD + p)E + q)/DEде D = 10^(len p)і E = 10^(len q) - 1, за винятком того, коли len q = 0, в цьому випадкуE = 1 (щоб уникнути поділу на 0).

Розсічення:

           # 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

Демонстрація в Інтернеті, яка імітує запуск програми з кожного тестового вводу, по одному.


Я спробував це, і, схоже, не дотримуються всіх правил: "Зверніть увагу, що після закінчення другої крапки після закінчення десяткових знаків нічого не буде, а децималі без десяткової частини, що не повторюється, не матимуть нічого між двома крапками." Я не міг змусити ваш код працювати з тим, що вводиться0.1.
Thomas Baruchel

-1. Я повторив його ще раз, помітивши, що ви отримали +300 балів. Це не справедливо, адже інші рішення зробили все можливе, щоб дотримуватися всіх правил, яких ви, очевидно, ще не зробили.
Томас Баручель

@ ברוכאל, я заперечую проти вашого твердження, що я не намагався дотримуватися правил. Позиція факультативних тестових випадків збила мене з думки, що заключний блок охоплює всі необхідні випадки; виявляється, що я помилився, і незабаром я відредагую питання, щоб уникнути інших помилок. Зараз я оновив свій код, щоб обробляти раніше не оброблені кутові справи, і оновив своє посилання на тест, щоб продемонструвати це.
Пітер Тейлор

все добре. Ви, мабуть, заслуговуєте 300 балів. Будучи новим у CodeGolf, ці 300 очок були для мене складною ціллю, і я все ще розчарований, що не отримав їх, поки я все ще думаю, що в граничний час мій код був найкоротшим, щоб він повністю відповідав правилам. У всякому разі, я все життя за виграш очок. З повагою
Томас Баручель

@ ברוכאל: Я хотів започаткувати 500 балів (так, я щедрий, як це, не те, що я можу дати менше) виграш, і я дам тобі очки, але, мабуть, вже почався щедрот. Ну, що б там не було. Мені цікаво, коли ця виграш закінчиться, і хто отримає ці очки.
Конрад Боровський

2

Пітон

Немає бібліотек - 156 символів

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

Використання fractions- 127 символів

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

У fractionsверсії друкує такі речі , як «фракції (7, 5)» замість «7/5», чи не так?
Омар

Це не так; Я, до речі, не став працювати першим. _=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, printвикористовує, strколи доступно, ні repr. Це вихід на мій кінець: puu.sh/7w64w.png
Оберон

@tomsmeding Обидва знаходяться в одній лінії; було додано перерву рядка, щоб вони вписалися у відповідь. _=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)повинні йти всі в один рядок.
Оберон

Так, @Oberon, як ви, напевно, можете здогадатися, я не був за своїм комп’ютером і не міг запустити код.
Омар

2

Математика, 143

Як завжди, Mathematica пропонує безліч функцій високого рівня, щоб виконувати цю роботу, але дає їм багатослівні імена.

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)

Вибірка зразка буде додана пізніше, коли я встигну.


Мені здається, ніби це виводить цілі числа як n, а не n / 1. Це так? (У моєму рішенні така ж помилка ... :()
Омар

Ах, зараз я бачу .... зазначено в коментарях. Яка дивна вимога ... якщо кожна інша частка зменшується, чому б не дозволити n/1її зменшити n? Я додаю додаткові ~ 50 байт, щоб пізніше перетворити цілі числа.
Джонатан Ван Матре

Ваш підхід прекрасний. Моя використовує, FromDigitsтому я вирішив також розмістити його.
DavidC

2

Рубін - 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

Це мій перший експеримент з рубіном, тому сміливо пропонуйте вдосконалення.

$ 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

Видалення підтримки ".." та ".1.2" означає, що ви не дотримуєтесь специфікацій, правда? (Я б також віддав перевагу їх видаленню.)
Омар

@ OmarAntolín-Camarena На цей конкретний момент, специфікація каже If you wish. Я не бажаю, тому я не підтримую дроби без 1-ї чи 3-ї групи цифр. Я, однак, підтримую дроби, яким не вистачає 2-ї групи цифр, що відповідає специфікації.
mniip

@minip, ви неправильно прочитали специфікацію: вона не говорить "якщо ви хочете, ви можете підтримати .. і .1.2", вона говорить, "якщо ви хочете, ви можете вважати, що 0 .. і 0.1.2 завжди даються як .. і .1.2 ".
Омар

@ OmarAntolín-Camarena Point прийнято. Відредаговано.
mniip

2

С, 164

Це схоже на рішення C Оріона, навіть якщо я робив це з нуля. Признаюсь, проте вкрав ряд його оптимізацій. Він не набагато коротший, але справляється .25. = 1/4 і 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

Два відповіді python, не використовуючи бібліотек. Перший обробляє додатковий вхід без цифри перед першим. і становить 162 символів

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

Друга не обробляє нічого перед першою цифрою, але правильно обробляє всі необхідні входи і становить 150 символів

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

Хаскелл

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

Гей, це код-гольф, ви навіть не намагаєтеся!
mniip

@mniip Я не дуже добре гольф коду. Принаймні, я використовував одноіменні імена змінних.
PyRulez

1
Ви ніколи не вказували мову та загальну кількість використаних символів / байтів.
Джастін Фей

2
Використовуйте {;} для економії місця на відступів, spanдля реалізації s, додавання коротких псевдонімів для функцій, видалення місця, де це можливо. 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 символів, що зменшується на 321. NB Trueє синонімом otherwise, null zцеlength 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 баунтів ... це найкоротший, який я можу придумати:

  • Зміни в порівнянні з попередньою версією: незначна зміна логіки та зміни Pфункції живлення , змінюючи її, +("1e"+a)замість того, Math.pow(10,a)щоб заощадити ще кілька символів ...

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]

Більшість рутинних робіт йде на масаж вводу. Приблизно 50 символів пішло на обробку цілих чисел.


Приклади

f["7801.098.765"]

frac1

Більше прикладів:

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


Як це можна було б виконати в Mathematica

FromDigitsможе отримати дробу безпосередньо з повторюваного десяткового числа, що повторюється, за умови, що вхід має певну форму. Цілі числа відображаються як цілі числа.

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


Ваш вихід у неправильному форматі, це занадто сильно.
Омар

Як не дивно, це формат за замовчуванням для вираження дробів у Mathematica. Щоб змінити цей формат на більш простий, знадобиться ще кілька символів.
DavidC

1

J (96 символів)

Я не використовую символ косої риси як роздільник (але рішення в Mathematica не має, оскільки він використовує графічне зображення, яке все одно краще); на мові J частка rзамість цього відображається як /:

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

1

APL (не повністю загальний)

Не повністю загальне (як моє рішення для постійного струму); працює з Dyalog APL (але не в онлайн-версії Dyalog APL, не знаю, чому):

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

Перше поле необов’язкове, але для обох інших полів потрібно принаймні одна цифра.


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)

Приклад:

Вхід:

5.3.87

Вихід:

889/165

1

C (420 символів, як написано; менше після видалення зайвого пробілу)

Зауважте, що це передбачає 64-розрядні long(наприклад, 64-бітний Linux); він не вийде для тестового випадку 0.2.283950617в системах, що використовують 32-бітні long. Це можна виправити ціною деяких символів, змінивши тип на long longта відповідно змінивши printfрядок формату.

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

Приємно. Ви можете поголити 1 символ, змінивши '0'на 48.
Тодд Леман

Я думаю, ви також можете врятувати ще кілька, переписавши switchзаяву як if(c==46) n[++i]=1; else d[i]=10*d[i]+c-48,n[i]*=10;.
Тодд Леман

-3

GTB , 81

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

Приклад

?3.25.
            13/4

4
До тих пір, поки компілятор не стане вільно доступним для цієї мови, я оскаржую кожну відповідь, якою він користується.
Гарет

1
Здається, на вказаній сторінці пов’язаний компілятор?
скибрянський

@skibrianski Перегляньте цю публікацію на мета
mniip

2
@Gareth, є кілька відповідей Mathematica для вас теж : P
Омар

2
@ OmarAntolín-Camarena Є компілятор / перекладач для Mathematica. GTB не має жодної. Перейдіть за GTBпосиланням вище, якщо ви мені не вірите. Ви отримаєте кілька стислих речей для власної програми, після чого будете шукати цю програму і виявите, що сайт, який претендує на завантаження, говорить, що вона недоступна. То як ми це складемо?
Гарет
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.