12
\$\begingroup\$

In-between fractions

The challenge:

You will need to create code that takes atleast 3 inputs; 2 integers and "a fraction representation" - whichever type suits your language for representing the fraction increments) ie. If you choose string the input would be "1/4" or you could choose 2 extra integer inputs or a tuple or w/e.

Input can be anywhere reasonable (STDIN, function arguments, from a file, etc.), and so can output (STDOUT, function return value, to a file, etc.)

Rules:

  1. The input "fraction" will always be a valid fraction, less than 1; example "1/4"
  2. The second input integer will always have a higher value than the first integer. I.E the first input integer will always have a lower value than the second.
  3. The input integers can be negative.
  4. Outputted fractions should be reduced as much as possible (simplified)

The code will need to output every "fraction step" between the 2 numbers in increments of the input fraction.

The code should be a program or function as stated here

Example 1:

Input: -2,3,"1/2"

Output:

 -2
 -3/2 
 -1 
 -1/2 
  0 
  1/2 
  1 
  3/2  
  2 
  5/2 
  3

Example 2:

Input: 1,2,"2/3"

Output:

1
5/3
2

or

1
4/3
2

Note: Counting can start from either direction (thank you @Mego)

This is , so the shortest answer in bytes wins.

\$\endgroup\$
11
  • \$\begingroup\$ Could the fraction be taken as 2 integer inputs, making 4 total inputs? \$\endgroup\$
    – user45941
    Apr 15, 2016 at 7:40
  • \$\begingroup\$ I think ill keep the restraint of maximum of 3 inputs - I would like to see the code for 4 inputs aswell \$\endgroup\$ Apr 15, 2016 at 7:42
  • \$\begingroup\$ In that case, what about having a list/tuple/array/some other iterable type containing two integers for the third input? That's not fundamentally different than 4 integer inputs. You should also clarify that the fraction will not be equal to 0. \$\endgroup\$
    – user45941
    Apr 15, 2016 at 7:44
  • \$\begingroup\$ @Mego After thinking it through, I can't see why it shouldn't be allowed Changed to "code that takes atleast 3 inputs" \$\endgroup\$ Apr 15, 2016 at 7:48
  • 1
    \$\begingroup\$ @beaker as long as the output is correct and the input comes from atleast 2 integers, the rest is up to you :) - i've kept the input part pretty openended, to see different answers \$\endgroup\$ Apr 18, 2016 at 19:25

13 Answers 13

11
\$\begingroup\$

Mathematica, 16 bytes

Range@##⋃{#2}&

An unnamed function that takes two integers and a rational number and returns a list of numbers, e.g.:

Range@##⋃{#2}&[-2, 3, 1/2]
(* {-2, -(3/2), -1, -(1/2), 0, 1/2, 1, 3/2, 2, 5/2, 3} *)

Mathematica's Range does exactly what the challenge asks, except that it omits the upper bound if the difference between lower and upper bound isn't exactly a multiple of the step size. Therefore we take the Union (using ) with the list containing only the upper bound which ensures that it appears exactly once. Note that Union will sort the result but we want it sorted anyway, since the step size is always positive. Also since we're working with rationals, they're automatically reduced as much as possible.

\$\endgroup\$
10
\$\begingroup\$

T-SQL 2012+, 831 535 477 270 246 240 219 bytes

Please note this is a one liner - sql doesn't have build in function to reduce the fraction. May not be the best language for this type of question. It is human readable(kind of - compared to some of the other languages).

DECLARE @f INT=-5,@t INT=3,@n INT=3,@ INT=8;

WITH C as(SELECT
top((@t*@-@f*@)/@n+1)ROW_NUMBER()OVER(ORDER BY @)M
FROM sys.messages)SELECT(SELECT
IIF(V%@=0,LEFT(V/@,9),CONCAT(V/MAX(M),'/',ABS(@)/MAX(M)))FROM c
WHERE V%M=0AND @%M=0)FROM(SELECT
@f*@+@n*~-M V FROM c)k

Try it online

\$\endgroup\$
5
  • \$\begingroup\$ Isn't the language called T-SQL, and not "Sqlserver"? \$\endgroup\$ Apr 15, 2016 at 12:15
  • 1
    \$\begingroup\$ @DavidConrad the language is TSQL, but there are different versions of sqlserver and the TSQL for this will work for sqlserver 2012 because of the keyword IIF. Which would use the keyword CASE in older versions. Added your suggestion \$\endgroup\$ Apr 15, 2016 at 12:19
  • \$\begingroup\$ Good Job. You can save a few by changing either @n or @d to plain @. Your CTE query for N could be N AS(SELECT N FROM(VALUES(1),(1),(1),(1),(1),(1),(1),(1),(1),(1))M(N)) or N AS(SELECT 1N FROM sys.all_views). Given that there is almost guaranteed to be a few hundred in this view, you could reduce the cross joins as well. ISNULL is shorter than COALESCE and should work \$\endgroup\$
    – MickyT
    Apr 18, 2016 at 19:32
  • \$\begingroup\$ @MickyT thanks to your suggestions and a few of my own, I managed to reduce the length by 296 bytes, \$\endgroup\$ Apr 19, 2016 at 8:13
  • \$\begingroup\$ Great work there \$\endgroup\$
    – MickyT
    Apr 19, 2016 at 8:17
6
\$\begingroup\$

Python 2, 81 bytes

from fractions import*
a,b,c=map(Fraction,input())
while a<b:print a;a+=c
print b

Try it online

\$\endgroup\$
5
\$\begingroup\$

Octave, 34 30 bytes

@(a,b,c)rats(union([a:c:b],b))

Now takes the fraction as a numeric expression rather than separate numerator and denominator.

Sample on ideone

\$\endgroup\$
6
  • 1
    \$\begingroup\$ So why can't you use @(a,b,c)rats(union([a:c:b],b))? \$\endgroup\$
    – Luis Mendo
    Apr 15, 2016 at 17:32
  • \$\begingroup\$ @LuisMendo I can if mathematical expressions are acceptable inputs (the effective result of 1/2 as a numeric rather than string input), but that's not the way I interpreted "a fraction representation". If the OP agrees, I'll be glad to shave off 4 bytes. \$\endgroup\$
    – beaker
    Apr 15, 2016 at 17:38
  • \$\begingroup\$ Oh, I see. Well, I'm using that in my Matlab answer. So does the Mathematica answer apparently, unless "rational number" is a specific data type \$\endgroup\$
    – Luis Mendo
    Apr 15, 2016 at 17:42
  • \$\begingroup\$ @beaker i did actually respond \$\endgroup\$ Apr 19, 2016 at 17:07
  • \$\begingroup\$ @VisualBean Code already updated. \$\endgroup\$
    – beaker
    Apr 19, 2016 at 17:10
5
\$\begingroup\$

Haskell, 31 26 bytes

f a b c=min[b]$a:f(a+c)b c

Lazy evaluation FTW! Demo:

*Main> import Data.Ratio
*Main Data.Ratio> f (-2) 3 (1%2)
[(-2) % 1,(-3) % 2,(-1) % 1,(-1) % 2,0 % 1,1 % 2,1 % 1,3 % 2,2 % 1,5 % 2,3 % 1]
*Main Data.Ratio> f 1 2 (2%3)
[1 % 1,5 % 3,2 % 1]

(I was initially tempted by Haskell’s [a,a+c..b] notation, but it has some quirks that necessitate something like f a b c|l<-[a,a+c..b-c/2]=l++[b|last l<b] for 41 bytes or f a b c=[x|x<-[a,a+c..],x<b]++[b] for 33.)

\$\endgroup\$
3
  • \$\begingroup\$ I like your solution! However I think you need to include import Data.Ratio in your byte count too, I think you cannot use f without that, right? \$\endgroup\$
    – flawr
    Apr 15, 2016 at 10:34
  • 2
    \$\begingroup\$ @flawr: nice edge case: you don't need Data.Ratio for f itself, because it's polymorphic for all numeric types. However, when you want to call it with values of type Ratio, then you need the import. The challenge only requires to "create code that ...", not to use it. I think it's fine without the import. \$\endgroup\$
    – nimi
    Apr 15, 2016 at 15:37
  • 1
    \$\begingroup\$ More precisely, you only need the import for the % operator to create the test fractions 1 % 2 and 2 % 3. I’m not cheating here: you can really put those 26 bytes in a file by themselves, run the interpreter on that module, and have the interaction I displayed. (You could even avoid typing import Data.Ratio in the demo interaction, if you instead spell % as Data.Ratio.%.) \$\endgroup\$ Apr 15, 2016 at 16:20
5
\$\begingroup\$

MATL, 16 15 bytes

3$:3Gvu9X10ZGZD

This may fail for very large denominators. I hope output format is acceptable.

Try it online!

3$:    % take three inputs and generate range
3G     % push third input again
v      % vertically concatenate. Gives vertical array as output 
u      % get unique elements (i.e. remove the last one if it is repeated)
9X1    % predefined literal 'rat'
0ZG    % set rational format
ZD     % display using that format
\$\endgroup\$
5
\$\begingroup\$

Ruby, 32 54 48 bytes

->a,b,c{(a..b).step(c){|x|p x%1>0?x:x.to_i};p b}

This solution is based on Mego's Python answer and assumes that c will always be a Rational, Ruby's fraction format. Try it online!

Edit: Fixed a bug where integers weren't presented like integers. -6 bytes thanks to Not That Charles and MegaTom.

The functions are called in this way:

> f=->a,b,c{(a..b).step(c){|x|p x%1>0?x:x.to_i};p b}
> f[1,4,Rational(2,3)]
1
(5/3)
(7/3)
3
(11/3)
4
\$\endgroup\$
6
  • \$\begingroup\$ (3/1) should not be simply 3? \$\endgroup\$
    – edc65
    Apr 15, 2016 at 9:24
  • \$\begingroup\$ The simplest Rational form of 3 in Ruby is (3/1) \$\endgroup\$
    – Sherlock9
    Apr 15, 2016 at 9:34
  • \$\begingroup\$ .step(b,c).map should reduce the byte count here \$\endgroup\$ Apr 18, 2016 at 20:57
  • \$\begingroup\$ (a==a.to_i) can be a%1==0 for -4 bytes. \$\endgroup\$
    – MegaTom
    Jun 22, 2019 at 5:31
  • \$\begingroup\$ -2,3,1/2r (example 1) prints the last 3 twice. \$\endgroup\$
    – Value Ink
    Jul 8, 2019 at 19:45
3
\$\begingroup\$

Julia, 14 bytes

f(a,b,c)=a:c:b

This is similar to the Mathematica answer, except that Julia's ranges are already in the desired format, so it is even shorter. Also returns a collection of numbers. Example output:

11-element StepRange{Rational{Int64},Rational{Int64}}:
 -3//1,-5//2,-2//1,-3//2,-1//1,-1//2,0//1,1//2,1//1,3//2,2//1

Note that the integers are displayed with 1 in the denominator, and a double-slash is used for fractions. To get the output exactly as defined in the question requires some more code:

f(a,b,c)=map(x->println(x.num,x.den<2?"":"/$(x.den)"),a:c:b)
\$\endgroup\$
3
\$\begingroup\$

Matlab with Symbolic Toolbox / Octave with SymPy, 27 bytes

Thanks to @sanchises for pointing out an error, now corrected

@(a,b,c)sym(union(a:c:b,b))

This is an anonymous function. To call it, assign it to a variable or use ans.

Example:

>> @(a,b,c)sym(union(a:c:b,b))
ans = 
    @(a,b,c)sym(union(a:c:b,b))
>> ans(-2,3,1/2)
ans =
[ -2, -3/2, -1, -1/2, 0, 1/2, 1, 3/2, 2, 5/2, 3]
\$\endgroup\$
4
  • \$\begingroup\$ This does not conform to the spec, since the upper bound is not always included (try example 2). \$\endgroup\$
    – Sanchises
    May 9, 2016 at 11:44
  • \$\begingroup\$ @sanchises Thanks! Corrected now \$\endgroup\$
    – Luis Mendo
    May 9, 2016 at 13:52
  • \$\begingroup\$ And also, I think for c you can use, I quote, whichever type suits your language for representing the fraction increments [...] or w/e. I think it's pretty clear that symbolic is a logical and allowed (@VisualBean might want to confirm this) choice. The result of the colon operator is then 'upgraded' to a symbolic array, which means you can get rid of the sym() call altogether. \$\endgroup\$
    – Sanchises
    May 9, 2016 at 13:57
  • \$\begingroup\$ @sanchises Thanks, I've asked for clarification \$\endgroup\$
    – Luis Mendo
    May 9, 2016 at 14:10
2
\$\begingroup\$

Javascript, 108 90 86  81 bytes

(a,b,n,d)=>{var s="";for(a=a*d;a<b*d;a+=n)s+=(a%d?a+"/"+d:a/d)+" ";s+=b;return s}

An anonymous function. After assignment to a named variable with white space:

var f=(a,b,n,d)=>
{ var s="";
  for(a=a*d; a<b*d; a+=n)
    s+= (a%d ? a + "/" + d : a/d) + " ";
  s+=b;
  return s
}

Test examples:

console.log(f(1,2,1,8)); //writes:
1 9/8 10/8 11/8 12/8 13/8 14/8 15/8 2

console.log(f(-3,3,4,7)); // writes:
-3 -17/7 -13/7 -9/7 -5/7 -1/7 3/7 1 11/7 15/7 19/7 3 

An imperative approach using javascript, no recursion, library or functional programming.

\$\endgroup\$
1
\$\begingroup\$

Smalltalk – 89 bytes

For once Smalltalk is almost competitive!

Number extend[p:e q:i[|h|self to:e by:i do:[:x|h:=x. x printNl].h=e ifFalse:[e printNl]]]

Call like this:

> 2 p:5 q:1/2
2
5/2
3
7/2
4
9/2
5

> 1 p:2 q:2/3
1
5/3
2
\$\endgroup\$
1
\$\begingroup\$

R - 71 bytes

Assumes you have already installed the MASS package

f=function(x,y,z)MASS::fractions(union(seq(x,y,eval(parse(text=z))),y))

> f(1, 2, '1/3')
[1]   1 4/3 5/3   2
> f(2, 5, '1/2')
[1]   2 5/2   3 7/2   4 9/2   5
\$\endgroup\$
1
\$\begingroup\$

Pyret, 56 bytes

{(b,e,n,d):link(e,map(_ / d,range(b * d, e * d))).sort()}

Takes in beginning (b), end (e), numerator (n), and denominator (d). Creates a range of integers, divides those through and appends the end to the list (by linking and then sorting).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.