Adding fractions

14

2

Write a program or a function that takes two non-empty lists of the same length as input and does the following:

  • uses elements of first list to get numerators,
  • uses elements of the second list to get denominators,
  • displays resulting fractions after simplification (2/4=>1/2), separated by "+"s,
  • displays "=" and result of addition after last fraction.

Example:

Input

[1, 2, 3, 3, 6]
[2, 9, 3, 2, 4]

Output

1/2+2/9+1+3/2+3/2=85/18

About rules

  • elements of lists will be positive integers,
  • elements can be separated by spaces, eg: 1/2 + 2/9 + 1 + 3/2 + 3/2 = 85/18 is ok,
  • trailing newline is allowed,
  • lists can be taken in other formats than above, eg.: (1 2 3 3 6) or {1;2;3;3;6}, etc.,
  • 1 can be expressed as 1/1,
  • instead of printing you can return appropriate string,
  • you do not need to handle wrong input,
  • shortest code wins.

user65167

Posted 2017-05-19T10:45:01.773

Reputation:

What range of values does it have to support? – Brad Gilbert b2gills – 2017-05-19T12:26:48.120

@BradGilbertb2gills I would say at least -30 000 to 30 000, but then I don't know whether it would be extra problem for some languages. So maybe just standard integer range of your language of choice. – None – 2017-05-19T12:36:19.370

@PrzemysławP saying "standard integer range of your language of choice" is not a good idea, some languages have standard integer as booleans – Felipe Nardi Batista – 2017-05-19T12:37:39.080

Thank you! @BradGilbertb2gills Then at least -30 000 to 30 000. – None – 2017-05-19T12:40:18.133

Can we get fractions as [1, 2] [2, 9] [3, 3] ... instead? – Olivier Grégoire – 2017-05-19T12:42:19.527

@OlivierGrégoire No, sorry! – None – 2017-05-19T12:42:54.450

The standard integer range for Perl 6 is infinite, but the default range for denominators of Rationals is uint64.Range.max. So I was asking if I had to convert them all to FatRats instead. – Brad Gilbert b2gills – 2017-05-19T12:49:06.763

@BradGilbertb2gills Sorry if I caused confusion - my second comment applies: -30 000 to 30 000. – None – 2017-05-19T13:02:43.610

can i concatenate the both lists as [1, 2, 3, 3, 6, 2, 9, 3, 2, 4] ? – Felipe Nardi Batista – 2017-05-19T13:12:09.457

@FelipeNardiBatista The input should be taken as two lists. After that you can obviously concatenate them. – None – 2017-05-19T15:11:03.130

Are the inputs going to be positive? – Dennis – 2017-05-19T19:58:05.517

@Dennis Not always. – None – 2017-05-19T20:15:12.420

That should be reflected in the test cases. – Dennis – 2017-05-19T20:17:21.273

@Dennis You are right. I'll add one more test case. – None – 2017-05-19T20:21:03.263

Can we assume the lists will always have at least two elements each? – Scott Milner – 2017-05-19T20:55:38.327

@ScottMilner Yes. – None – 2017-05-19T20:56:39.450

@Dennis It looks like pretty much every solution assumed it's always positive integers so I think it's better to say that input should be only positive integer. Sorry for confusion:/ – None – 2017-05-19T21:12:07.903

@BradGilbertb2gills Sorry again, but seeing that many people assumed input should be positive integers I think it's better to say that minimal supported range would be 1-30 000. Again, sorry for confusion:/ – None – 2017-05-19T21:15:45.247

Answers

1

M, 12 11 bytes

÷µFj”+;”=;S

This is a dyadic link. Due to a bug, it doesn't work as a full program. F is also required due to a bug.

Try it online!

How it works

÷µFj”+;”=;S  Dyadic link. Left argument: N. Right argument: D

÷            Perform vectorized division, yielding an array of fractions (R).
 µ           Begin a new, monadic chain. Argument: R
  F          Flatten R. R is already flat, but j is buggy and has side effects.
   j”+       Join R, separating by '+'.
      ;”=    Append '='.
         ;S  Append the sum of R.

Dennis

Posted 2017-05-19T10:45:01.773

Reputation: 196 637

I like how more than a quarter of the program is to append the '='. :) – Computronium – 2017-07-19T10:19:22.163

7

Ruby 2.4, 54 53 characters

->n,d{a=n.zip(d).map{|n,d|n.to_r/d};a*?++"=#{a.sum}"}

Thanks to:

  • Value Ink for the Ruby 2.4 specific version (-3 characters)
  • Value Ink for optimizing the Rational initialization (-1 character)

Ruby, 58 57 56 characters

->n,d{t=0;n.zip(d).map{|n,d|t+=r=n.to_r/d;r}*?++"=#{t}"}

Sample run:

irb(main):001:0> puts ->n,d{t=0;n.zip(d).map{|n,d|t+=r=n.to_r/d;r}*?++"=#{t}"}[[1, 2, 3, 3, 6], [2, 9, 3, 2, 4]]
1/2+2/9+1/1+3/2+3/2=85/18

Try it online!

manatwork

Posted 2017-05-19T10:45:01.773

Reputation: 17 865

1a=n.zip(d).map{|f|(f*?/).to_r};a*?++"=#{a.sum}" in Ruby 2.4 saves you 3 bytes. – Value Ink – 2017-05-19T18:46:05.157

Thanks @ValueInk. I suspected that may be possible, just had no 2.4 neither locally nor on TIO. – manatwork – 2017-05-20T16:13:30.530

1Yeah, I installed 2.4 specifically so I could test out solutions with sum haha. Also I just remembered that .map{|i,j|i.to_r/j} is shorter by 1 byte – Value Ink – 2017-05-22T20:25:46.107

Doh. I tried various approaches through .to_f and division, but didn't thought to dividing Rational with Fixnum. Thanks again, @ValueInk. – manatwork – 2017-05-24T19:54:38.573

6

Mathematica, 33 bytes

Row@{Row[#/#2,"+"],"=",Tr[#/#2]}&

input

[{1, 2, 3, 3, 6}, {2, 9, 3, 2, 4}]

J42161217

Posted 2017-05-19T10:45:01.773

Reputation: 15 931

Isn't Row@@{#/#2,"+"} the same as Row[#/#2,"+"]? – feersum – 2017-05-19T13:57:39.363

yes! you are right! – J42161217 – 2017-05-19T14:04:31.777

1Fantastic! I didn't realize Row was so convenient for things like this :) – Greg Martin – 2017-05-19T18:08:53.300

3

Python 3, 104 bytes

9 bytes thanks to Felipe Nardi Batista.

from fractions import*
def f(*t):c=[Fraction(*t)for t in zip(*t)];print('+'.join(map(str,c)),'=',sum(c))

Try it online!

Leaky Nun

Posted 2017-05-19T10:45:01.773

Reputation: 45 011

golfed a bit – Felipe Nardi Batista – 2017-05-19T11:10:17.017

@FelipeNardiBatista muito. – Leaky Nun – 2017-05-19T11:11:09.577

change +'='+str(sum(c)) to ,'=',sum(c) – Felipe Nardi Batista – 2017-05-19T11:15:10.730

@FelipeNardiBatista Thanks, also I've used Python 3 here (based on personal preference). – Leaky Nun – 2017-05-19T11:18:27.237

You can save a lot of bytes by switching to Python 2 – ovs – 2017-05-19T14:22:08.813

At the cost of 5 bytes you can stay at python3: def f(*t):c=[*map(Fraction,*t)];print('+'.join(map(str,c)),'=',sum(c)) (93 bytes) – ovs – 2017-05-21T12:15:57.053

3

Perl 6,  77  73 bytes

{join('+',($/=[@^a Z/ @^b]).map:{.nude.join('/')})~"="~$/.sum.nude.join('/')}

Try it

{($/=[@^a Z/@^b])».nude».join('/').join('+')~'='~$/.sum.nude.join('/')}

Try it

Expanded:

{  # bare block lambda with two placeholder params 「@a」 and 「@b」

  (
    $/ = [              # store as an array in 「$/」 for later use

      @^a Z/ @^b        # zip divide the two inputs (declares them)

    ]

  )».nude\              # get list of NUmerators and DEnominators
  ».join('/')           # join the numerators and denominators with 「/」

  .join('+')            # join that list with 「+」

  ~
  '='                   # concat with 「=」
  ~

  $/.sum.nude.join('/') # get the result and represent as fraction
}

Brad Gilbert b2gills

Posted 2017-05-19T10:45:01.773

Reputation: 12 713

3

Clojure, 71 bytes

#(let[S(map / % %2)](apply str(concat(interpose '+ S)['=(apply + S)])))

Yay for built-in fractions!

NikoNyrh

Posted 2017-05-19T10:45:01.773

Reputation: 2 361

2

Mathematica, 61 bytes

t=#~ToString~InputForm&;Riffle[t/@#,"+"]<>"="<>t@Tr@#&[#/#2]&

alephalpha

Posted 2017-05-19T10:45:01.773

Reputation: 23 988

2

JavaScript (ES6), 111 bytes

Takes the lists in currying syntax (a)(b).

let f =

a=>b=>a.map((v,i)=>F(A=v,B=b[i],N=N*B+v*D,D*=B),N=0,D=1,F=(a,b)=>b?F(b,a%b):A/a+'/'+B/a).join`+`+'='+F(A=N,B=D)

console.log(f([1, 2, 3, 3, 6])([2, 9, 3, 2, 4]))

Arnauld

Posted 2017-05-19T10:45:01.773

Reputation: 111 334

2

Java, 225 bytes

int c(int a,int b){return b>0?c(b,a%b):a;}
(N,D)->{int n=0,d=1,i=0,g;String s="";for(;i<N.length;g=g(N[i],D[i]),N[i]/=g,D[i]/=g,s+=(i>0?"+":"")+N[i]+"/"+D[i],n=n*D[i]+N[i]*d,d*=D[i++],g=g(n,d),n/=g,d/=g);return s+"="+n+"/"+d;}

N and D are both int[], contextualized.

I reused Kevin Cruijssen's GCD function.

See it and test it online!

Olivier Grégoire

Posted 2017-05-19T10:45:01.773

Reputation: 10 647

2

Julia v0.4+, 66 53 bytes

-13 bytes thanks to Dennis

a^b=replace(join(a.//b,"+")"=$(sum(a.//b))","//","/")

Try it Online!

Alternately, if fractions can be displayed using // rather than /, the following works for 35 bytes:

a^b=join(a.//b,'+')"=$(sum(a.//b))"

Julian Wolf

Posted 2017-05-19T10:45:01.773

Reputation: 1 139

2

setlX, 103 bytes

f:=procedure(a,b){i:=1;l:=[];while(i<=#a){l:=l+[a[i]/b[i]];i+=1;}s:=join(l,"+");return s+"="+eval(s);};

Creates a function called f where your insert two lists.

ungolfed:

f := procedure (a,b) {
    i:=1;
    l:=[];
    while(i<=#a){
        l:=l+[a[i]/b[i]];
        i+=1;
    }
    s:=join(l,"+");
    return s+"="+eval(s);
};

with named variables and annotations:
setlX doesn't provide a comment feature so let's just pretend that we can comment with %

f := procedure(firstList,secondList) {
    count := 1;
    list := []; 
    while(count <= #firstList) {
        % calculate every fraction and save it as a list
        list := list + [firstList[count]/secondList[count]];
        count += 1;
    }
    % Seperate every list entry with a plus ([2/3,1] -> "2/3+1")
    str := join(list, "+");
    % eval executes the string above and thus calculates our sum
    return str + "=" + eval(str);
};

BlueWizard

Posted 2017-05-19T10:45:01.773

Reputation: 161

What if #firstList is different from #secondList? – RosLuP – 2017-05-21T19:05:12.630

you mean differnet size? The question states that first list is used by enumerator and wrong input can be ingored – BlueWizard – 2017-05-21T20:04:12.563

but other than that: if the second list is longer, the remaining entries will be ignored. If the list is shorter a runtime error will occur. – BlueWizard – 2017-05-21T20:05:19.500

1

05AB1E, 35 34 bytes

‚øvyy¿÷'/ý'+}¨'=¹.¿©¹÷²*O®‚D¿÷'/ýJ

Try it online!

Emigna

Posted 2017-05-19T10:45:01.773

Reputation: 50 798

1

Perl 6, 72 bytes 65 bytes

Native and automatic rationals should make this easy, but default stringification is still as decimal, so we have to .nude (numerator and denominator) which kills our score and makes the 1 ugly :(

my \n = 1,2,3,3,6; my \d = 2,9,3,2,4;
(n Z/d)».nude».join("/").join("+")~"="~([+] n Z/d).nude.join("/")

Update: Removed unneeded brackets, kill more space and use smarter map. Saves characters over Brad's solution at the cost of no not being a lambda sub.

Dean Serenevy

Posted 2017-05-19T10:45:01.773

Reputation: 111

Welcome to the site! Nice first answer! – programmer5000 – 2017-05-19T13:13:30.993

1

Jelly, 31 bytes

,:gj”/
ṙJ$ṖP×Sç⁸P¤,ç@"j”+$¥Ṛj”=

Try it online!

Leaky Nun

Posted 2017-05-19T10:45:01.773

Reputation: 45 011

1

F#, 244 241 239 bytes

let rec g a=function|0->abs a|b->g b (a%b)
let h a b=g a b|>fun x->a/x,b/x
let s,n,d=List.fold2(fun(s,n,d)N D->
 let(N,D),(n,d)=h N D,h(n*D+N*d)(d*D)
 s@[sprintf"%i/%i"N D],n,d)([],0,1)nom div
printf"%s=%i/%i"(System.String.Join("+",s))n d

Try it online!

Brunner

Posted 2017-05-19T10:45:01.773

Reputation: 331

1

PHP>=7.1, 190 Bytes

<?function f($x,$y){for($t=1+$x;$y%--$t||$x%$t;);return$x/$t."/".$y/$t;}[$n,$d]=$_GET;for($p=array_product($d);$x=$n[+$k];$e+=$x*$p/$y)$r[]=f($x,$y=$d[+$k++]);echo join("+",$r)."=".f($e,$p);

Online Version

+14 Bytes for replacement return$x/$t."/".$y/$t; with return$y/$t>1?$x/$t."/".$y/$t:$x/$t; to output n instead of n/1

Jörg Hülsermann

Posted 2017-05-19T10:45:01.773

Reputation: 13 026

1

setlX, 62 bytes

[a,b]|->join([x/y:[x,y]in a><b],"+")+"="++/[x/y:[x,y]in a><b];

ungolfed:

[a,b]|->                  define a function with parameters a and b
  join(                 
    [ x/y :               using set comprehension, make a list of fractions 
      [x,y] in a><b       from the lists zipped together
    ],
    "+"
  )                       join them with "+"
  + "="                   concat with an equals sign
  +                       concat with
  +/[x/y:[x,y]in a><b]    the sum of the list
;

interpreter session

corvus_192

Posted 2017-05-19T10:45:01.773

Reputation: 1 889

0

MATL, 32 bytes

/YQv'%i/%i+'wYD3L)61yUYQVwV47b&h

Try it online!

Explanation

Consider [1, 2, 3, 3, 6], [2, 9, 3, 2, 4] as input.

/         % Implicit inout. Divide element-wise
          % STACK: [0.5 0.222 1 1.5 1.5]
YQ        % Rational approximation (with default tolerance)
          % STACK: [1 2 1 3 3], [2 9 1 2 2]
v         % Conctenate all stack elements vertically
          % STACK: [1 2; 2 9; 1 2; 3 2; 3 2]
'%i/%i+'  % Push this string (sprintf format specifier)
          % STACK: [1 2; 2 9; 1 2; 3 2; 3 2], '%i/%i+'
wYD       % Swap, sprintf
          % STACK: '1/2+2/9+1/1+3/2+3/2+'
3L)       % Remove last entry
          % STACK: '1/2+2/9+1/1+3/2+3/2'
61        % Push 61 (ASCII for '=')
          % STACK: '1/2+2/9+1/1+3/2+3/2', 61
y         % Duplicate from below
          % STACK: '1/2+2/9+1/1+3/2+3/2', 61, '1/2+2/9+1/1+3/2+3/2'
U         % Evaluste string into a number
          % STACK: '1/2+2/9+1/1+3/2+3/2', 61, 4.722
YQ        % Rational approximation 
          % STACK: '1/2+2/9+1/1+3/2+3/2', 61, 85, 18
VwV       % Convert to string, swap, convert to string
          % STACK: '1/2+2/9+1/1+3/2+3/2', 61, '18', '85'
47        % Push 47 (ASCII for '/')
          % STACK: '1/2+2/9+1/1+3/2+3/2', 61, '18', '85', 47
b         % Bubble up in stack
          % STACK: '1/2+2/9+1/1+3/2+3/2', 61, '85', 47, '18'
&h        % Concatenate all stack elements horizontally. Implicitly display
          % STACK: '1/2+2/9+1/1+3/2+3/2=85/18'

Luis Mendo

Posted 2017-05-19T10:45:01.773

Reputation: 87 464

0

R, 109 bytes

f=MASS::fractions;a=attributes
g=function(n,d)paste(paste(a(f(n/d))$f,collapse='+'),a(f(sum(n/d)))$f,sep='=')

requires the MASS library (for its fractions class). the function g returns the required output as a string.

Try it online! (R-fiddle link)

Giuseppe

Posted 2017-05-19T10:45:01.773

Reputation: 21 077

0

TI-BASIC, 100 bytes

:L₁⁄L₂                                              //Creates a fraction from Lists 1 & 2, 7 bytes
:toString(Ans→Str1                                  //Create string from list, 7 bytes
:inString(Ans,",→A                                  //Look for commas, 9 bytes
:While A                                            //Begin while loop, 3 bytes
:Str1                                               //Store Str1 to Ans, 3 bytes
:sub(Ans,1,A-1)+"+"+sub(Ans,A+1,length(Ans)-A→Str1  //Replace "," with "+", 33 bytes
:inString(Ans,",→A                                  //Check for more commas, 9 bytes
:End                                                //End while loop, 2 bytes
:Str1                                               //Store Str1 to Ans, 3 bytes
:sub(Ans,2,length(Ans)-2                            //Remove opening and closing brackets, 13 bytes
:Ans+"="+toString(expr(Ans                          //Add "=" and answer, 11 bytes

Note the at the beginning, different from /. This makes the fractions hold their forms. It does work with negative fractions.

Sigh. TI-BASIC is horrible with strings. If all we had to do was print the fractions, and then their sum, the code would be:

TI-BASIC, 12 bytes

:L₁⁄L₂    //Create fractions from lists, 7 bytes
:Disp Ans //Display the above fractions, 3 bytes
:sum(Ans  //Display the answer, 2 bytes

That means that 88 bytes of my code is spent just formatting the answer! Hmph.

Scott Milner

Posted 2017-05-19T10:45:01.773

Reputation: 1 806

0

C, 171 bytes

Try Online

i;t;x;y;f(int s,int*a,int*b){x=*a;y=*b;while(++i<s)x=(y-b[i])?(x*b[i])+(a[i]*y):(x+a[i]),y=(y-b[i])?(b[i]*y):y;for(i=1;i<=(x<y?x:y);++i)t=(x%i==0&&y%i==00)?i:t;x/=t;y/=t;}

Khaled.K

Posted 2017-05-19T10:45:01.773

Reputation: 1 435

0

Axiom, 212 bytes

C==>concat;S==>String;g(a)==C[numerator(a)::S,"/",denom(a)::S];h(a:List PI,b:List PI):S==(r:="";s:=0/1;#a~=#b or #a=0=>"-1";for i in 1..#a repeat(v:=a.i/b.i;s:=s+v;r:=C[r,g(v),if i=#a then C("=",g(s))else"+"]);r)

test

(5) -> h([1,3,4,4,5,6], [2,9,5,5,6,7])
   (5)  "1/2+1/3+4/5+4/5+5/6+6/7=433/105"
                                                             Type: String
(6) -> h([1,3,4,4], [2,9,5,5,6,7])
   (6)  "-1"
                                                             Type: String

RosLuP

Posted 2017-05-19T10:45:01.773

Reputation: 3 036

0

Casio Basic, 161 Bytes

Dim(List 1)->A
for 1->I to A step 1
3*I-2->B
List 1[I]->C
List 2[I]->D
locate 1,B,C
locate 1,B+1,"/"
locate 1,B+2,D
C/D+E->E
next
locate 1,B+3,"="
locate 1,B+4,E

Explanation:

  • Number of input is saved in A
  • A iterations
  • B acts as a counter for correct displaying
  • I'th item of List 1 and 2 saved in C and D
  • Displaying of Variable C / Variable D
  • save C/D+E in E
  • After last number locate = and E

ADDB

Posted 2017-05-19T10:45:01.773

Reputation: 171

0

Haskell (Lambdabot), 94 91 86 bytes

t=tail.((\[n,_,d]->'+':n++'/':d).words.show=<<)
a#b|f<-zipWith(%)a b=t f++'=':t[sum f]

Try it online!

Thanks @Laikoni for -8 bytes!

Ungolfed

-- convert each fraction to a string (has format "n%d", replace '%' with '/' and prepend '+' ("+n/d"), keep the tail (dropping the leading '+')
t = tail.((\[n,_,d]->'+':n++'/':d).words.show=<<)
-- build a list of fractions
a # b = let f = zipWith(%) a b in
-- stringify that list, append "=" and the stringified sum of these fractions
  t f ++ "=" ++ t [sum f]

ბიმო

Posted 2017-05-19T10:45:01.773

Reputation: 15 345

Your missing a import Data.Ratio for % which is not in Prelude. – Laikoni – 2017-07-19T14:16:36.307

1You can save some bytes by replacing "?"++ with '?':. – Laikoni – 2017-07-19T14:21:43.510

Whoops, totally missed that.. Thanks! Yup, fixed. – ბიმო – 2017-07-19T14:25:34.127

1The shortening also works for "/"++d and "="++. – Laikoni – 2017-07-19T14:25:57.400

Yeah, I just noticed.. But only for "="++ :S – ბიმო – 2017-07-19T14:30:50.080

1Rearranging saves some more bytes: tail(f>>=t)++'=':(tail.t.sum)f – Laikoni – 2017-07-19T14:46:33.297

1

Putting tail and =<< into t saves some more: Try it online!

– Laikoni – 2017-07-19T14:55:48.697

Neat, I like how you did [sum f] to pull out the tail. Thanks a lot! – ბიმო – 2017-07-19T15:21:26.503

0

Google Sheets, 83 81 bytes

=ArrayFormula(JOIN("+",TRIM(TEXT(A:A/B:B,"?/???")))&"="&TEXT(sum(A:A/B:B),"?/???"

Saved 2 bytes thanks to Taylor Scott

Sheets will automatically add 2 closing parentheses to the end of the formula.

The two arrays are input as the entirety of columns A and B. Empty rows below the inputs will throws errors.

Engineer Toast

Posted 2017-05-19T10:45:01.773

Reputation: 5 769

you should be able to drop 2 bytes by dropping the terminal )) – Taylor Scott – 2017-09-05T16:17:32.503