The Challenge
Given a rational number, determine the smallest number which is a positive integer multiple of it. Eg.
Given: 1.25
x1: 1.25
x2: 2.5
x3: 3.75
x4: 5
Thus: Answer is 5
Clarifications
Inputs will be a rational number in the range of (0,100]
of which the Decimal Representation has no more than 4 digits after the point.
Output must be an integer that is the total after multiplication (5
in the example, rather than 4
).
I/O may be in any Standard Format, including as a Fraction type.
Be careful if using repeated addition with floats, as 0.3 + 0.3...
results in 2.9999...
.
Test Cases
1.25 -> 5
4.0 -> 4
0.3 -> 3
4.625 -> 37
3.1428 -> 7857
Rules
- Standard Loopholes Apply
- This is code-golf so fewest bytes wins!
- Have Fun!
26 Answers 26
Vyxal 2.4.1, 2 bytes
ƒh
A version downgrade improves my byte count somehow.
Well not somehow. 2.4.1 and earlier versions didn't use exact numbers/rationals under the hood, so there was still a "convert decimal to numerator and denominator" built-in (because I've always wanted some form of rationals).
This is a back port of the Factor answer which half ported my original answer.
Takes input as floats because, well, only float input was supported in 2.4.1.
Converts to numerator, denominator. Then gets the first item of that.
Vyxal >=2.6, 35 bitsv2 , 4.375 bytes
S\//h
Maths? No thank you!
Takes input as either a fraction object or a float. Both are interpreted as rational implicitly so it doesn't really matter.
Simply casts input to string (which'll be a fraction because vyxal 2 be like that), split on /
and get the first item.
-
\$\begingroup\$ Oh! Smart approach! \$\endgroup\$ATaco– ATaco2023年09月14日 23:16:25 +00:00Commented Sep 14, 2023 at 23:16
-
\$\begingroup\$ Funny thing is that I noticed the pattern after having written a math inspired answer and running test cases :p \$\endgroup\$2023年09月14日 23:17:46 +00:00Commented Sep 14, 2023 at 23:17
J, 4 bytes
1&*.
LCM with 1 to get the numerator of a fractional value.
J has a built-in to extract the numerator/denominator from a number too, but is longer to get just the numerator:
J, 6 bytes
0{2&x:
-
\$\begingroup\$ TIL about dyadic x: \$\endgroup\$Jonah– Jonah2023年09月15日 06:16:51 +00:00Commented Sep 15, 2023 at 6:16
Excel, 37 bytes
=0+TEXTBEFORE(TEXT(A1,"0/00000"),"/")
Input in cell A1
.
Factor, 9 bytes
numerator
Same idea as lyxal's Vyxal answer, just no need for string manipulation.
Less "cheaty," perhaps? This version takes floats as input instead of ratios:
Factor + math.floating-point
, 26 bytes
[ double>ratio numerator ]
And my original answer for posterity:
Factor, 34 bytes
[ 0 [ 1 + 2dup * ratio? ] loop * ]
0
push zero — this is our multiplier[ ... ratio? ] loop
do...
while top of stack is a ratio (a number like 5/5 promotes itself to integer automatically)1 +
increment the multiplier2dup *
multiply but keep the input and multiplier on the stack too*
at this point, the input and correct multiplier are on the stack so multiply them
-
\$\begingroup\$ I managed to backport your answer by downgrading my vyxal version :p \$\endgroup\$2023年09月14日 23:30:36 +00:00Commented Sep 14, 2023 at 23:30
Julia, 11 bytes
~x=lcm(x,1)
Takes rational number inputs. Julia also has the function rationalize
for converting floating point values.
Julia 0.6, 33 bytes
>(x,i=1)=isinteger(i*x)?i*x:x>i+1
Recursive approach which takes an iterator as its own optional argument. The >
operator is overloaded, since it has lower precedence than +
, which saves a set of parentheses. Spaces are required around ternary operators beginning in Julia 1.0.The function isinteger
is a good fit; last("$(i*x)")<'1'
would be another (longer) approach.
-
1\$\begingroup\$ Another fun one:
>(x,i=1)=try Int(i*x)catch;x>i+1end
\$\endgroup\$MarcMush– MarcMush2023年09月16日 21:41:44 +00:00Commented Sep 16, 2023 at 21:41
R, (削除) 39 (削除ここまで) 31 bytes
\(x,y=x*1:1e6)y[!(y+1e7)%%1][1]
Correctly handles difficult inputs that otherwise suffer from floating-point inaccuracies.
R, 25 bytes (non-competing)
\(x,y=x*1:1e6)y[!y%%1][1]
Original answer: fails due to floating-point inaccuracies for 3.1428
, and probably other difficult inputs.
Google Sheets, 31 bytes
=+split(text(A1,"#/#####"),"/")
Put the input in cell A1
and the formula in B1
.
Uses number formatting like the Excel answer to get a fraction, then takes advantage of an undocumented feature of the unary plus operator +
, i.e., uplus()
, to get the numerator.
Ruby, 26 bytes
->d{(1..).find{_1/d%1==0}}
Original: Ruby, 31 bytes
f=->d,x=1{d*x%1>0?f[d,x+1]:d*x}
The more obvious f=->d{d.to_r.numerator}
does not seem to work for 0.300.
Thanks Value Ink for the tips, but I think that it should be a separate answer.
-
\$\begingroup\$
->d{d.to_s.to_r.numerator}
does work and is shorter by 5 bytes, and taking input as a string will lead to the obvious solution you posited. In fact, since the rules explicitly say a fractional input is allowed,proc &:numerator
also works for the truly "cheaty" version. \$\endgroup\$Value Ink– Value Ink2023年09月15日 18:53:58 +00:00Commented Sep 15, 2023 at 18:53
Python, 20 bytes
lambda n:n.numerator
An unnamed function that accepts a Fraction
object and returns the integer.
-
1\$\begingroup\$ Floating point inaccuracy I think - it accepts a float and does not perform repeated addition. \$\endgroup\$Jonathan Allan– Jonathan Allan2023年09月23日 21:50:10 +00:00Commented Sep 23, 2023 at 21:50
-
\$\begingroup\$ @NickKennedy removed. \$\endgroup\$Jonathan Allan– Jonathan Allan2023年09月24日 23:12:34 +00:00Commented Sep 24, 2023 at 23:12
APL(Dyalog Unicode), (削除) (削除ここまで)3 bytes SBCS
∧∘1
LCM between input and 1. This is actually really similar to a problem in the APL Competition, 1:7 Let's Be Rational.
Pyth, 6 bytes
*fsI*Q
Takes input as a float.
*fsI*Q
f Find the first integer, starting at 1 and counting upward, such that
*Q The integer multiplied by the input
I Is unchanged when
s Cast to an integer
* Multiply the result (the denominator) by the input
Same length:
fsIcTQ
Finds the numerator directly using division.
-
\$\begingroup\$ Fails for 3.1428 \$\endgroup\$Nick Kennedy– Nick Kennedy2023年09月23日 19:34:01 +00:00Commented Sep 23, 2023 at 19:34
-
\$\begingroup\$ @NickKennedy My other answer,
fsIcTQ
, works for that input - do you know if it also has a counterexample? \$\endgroup\$izzyg– izzyg2023年09月24日 22:29:42 +00:00Commented Sep 24, 2023 at 22:29
Rust, (削除) 39 (削除ここまで) 38 bytes
-1 thanks to @corvus_192
|mut x|{let n=x;while x%1.>0.{x+=n};x}
Closure naively loops and increments x
by its intial value until it becomes a whole number.
-
1\$\begingroup\$ I think using
>
instead of!=
works. \$\endgroup\$corvus_192– corvus_1922023年09月16日 17:18:57 +00:00Commented Sep 16, 2023 at 17:18 -
\$\begingroup\$ @corvus_192 you're right, thanks. \$\endgroup\$code– code2023年09月16日 18:26:47 +00:00Commented Sep 16, 2023 at 18:26
Python 3, 53 bytes
Trivial solution (thanks to lyxal for the comment).
lambda n:Fraction(n).numerator
from fractions import*
Originally (65 bytes, returns a float
which can be converted to an int
while being the same value):
def x(n,i=1):
while not str(i*n).endswith('.0'):i+=1
return i*n
20 bytes from SuperStormer:
lambda n:n.numerator
-
\$\begingroup\$ 20 bytes:
lambda n:n.numerator
meta \$\endgroup\$SuperStormer– SuperStormer2023年09月15日 14:50:56 +00:00Commented Sep 15, 2023 at 14:50 -
\$\begingroup\$ The number is not explicitly passed as a Fraction (I assume it is an
int
), however, I guess I'll add that as an extra answer. \$\endgroup\$Rhaixer– Rhaixer2023年09月17日 09:27:05 +00:00Commented Sep 17, 2023 at 9:27
AWK, (削除) 35 (削除ここまで) 24 bytes
{while(1ドル*++a%1);1ドル*=a}1
(Several improvements by @Dominic van Essen to my original answer: -11 bytes)
Original answer: AWK, 35 bytes
{while(1ドル*++a>int(1ドル*a));print1ドル*a}
-
\$\begingroup\$ 24 bytes... \$\endgroup\$Dominic van Essen– Dominic van Essen2023年09月19日 21:39:13 +00:00Commented Sep 19, 2023 at 21:39
-
\$\begingroup\$ Fails for 3.1428 \$\endgroup\$Nick Kennedy– Nick Kennedy2023年09月23日 19:30:28 +00:00Commented Sep 23, 2023 at 19:30
Vyxal, 39 bitsv2 , 4.875 bytes
{D⌊≠|+
Posting as a separate answer because it doesn't use any fraction string cheese :p
Takes input as either a fraction or a float, as both are implicitly converted to rationals.
Explained
{D⌊≠|+
{ | # While
⌊≠ # The floor of the top of the stack doesn't equal the top of the stack
D # (triplicate before the check so there's a copy left over)
+ # Add the input to the top of the stack
💎
Created with the help of Luminespire.
Charcoal, 27 bytes
≔I−θ.ηF⊟⪪θ.F25F¬%ηIκ≧÷IκηIη
Try it online! Link is to verbose version of code. Explanation:
≔I−θ.η
Remove the decimal point from the input and cast it to integer.
F⊟⪪θ.
Loop over each decimal place.
F25F¬%ηIκ≧÷Iκη
Divide the integer by 2 and/or 5 if possible.
Iη
Output the resulting integer.
Retina, (削除) 95 (削除ここまで) 71 bytes
\.(\d+)$
1,ドル$.1*0
.*5,0
$.(*2*),0
.*[2468],0
$.(*5*),0
}`0,0
,
^0+|,0*
Try it online! Link includes test cases. Explanation:
\.(\d+)$
1,ドル$.1*0
On the first pass, delete the decimal point but keep track of how many digits there were after it. (It's golfier to repeat this stage but it has no effect on subsequent passes.)
(.*5),0
$.(*2*),0
Try doubling the number to create a trailing zero to match.
(.*[2468]),0
$.(*5*),0
Try multiplying the number by 5
to create a trailing zero to match.
0,0
,
Remove a pair of matching zeros.
}`
Repeat until there are no more trailing zeros to remove or the number ends in 1
, 3
, 7
or 9
.
^0+|,0*
Delete any leading zeros and any remaining working digits.
T-SQL, 51 bytes
DECLARE @2 real=4.625
DECLARE @ REAL=@2
WHILE @>floor(@)SET @+=@2
PRINT @
Swift 2.2, floating-point, 65 bytes
func f(x:Float,y:Float=1)->Float{return x*y%1==0 ?x*y:f(x,y:y+1)}
Back in Swift 2, %
was supported for floating-point types. I also can't figure out what Decimal
was called back then.
Swift 5.8 + Foundation, decimal, 109 bytes
func f(x:Decimal,y:Decimal=1)->Decimal{var z=x,w=x*y
NSDecimalRound(&z,&w,0,.up)
return w==z ?w:f(x:x,y:y+1)}
Rounding mode doesn't matter; I chose .up
because it's the shortest. The function signature of NSDecimalRound
makes more sense in Objective-C where you only work with NSDecimal*
and not the struct directly.
05AB1E, 8 bytes
∞.ΔI/DïQ
Try it online or verify all test cases.
Explanation:
∞ # Push an infinite positive list: [1,2,3,...]
.Δ # Pop and find the first integer that's truthy for:
I/ # Divide the current integer by the input-decimal
D # Duplicate the decimal
ï # Cast/floor its copy to an integer
Q # Check if both are the same value
# (after which the found integer is output implicitly as result)
-
1\$\begingroup\$ @NickKennedy Should be fixed, although it's plausible another test case might still fail due to floating point accuracy tbh. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2023年09月24日 11:39:48 +00:00Commented Sep 24, 2023 at 11:39
-
\$\begingroup\$ Is the 4-byte answer a joke? It obviously fails if input is given as a non-reduced fraction. \$\endgroup\$Dominic van Essen– Dominic van Essen2023年09月25日 08:47:09 +00:00Commented Sep 25, 2023 at 8:47
-
\$\begingroup\$ @DominicvanEssen I'd say requiring reduced fraction input is usually reasonable, but yeah it's not serious here \$\endgroup\$l4m2– l4m22023年09月25日 09:15:48 +00:00Commented Sep 25, 2023 at 9:15
Ruby, 16 bytes
Builtin solution posted as a separate answer from G B's answer per their suggestion. Takes a Rational
as input.
proc &:numerator
Ruby -n
, 18 bytes
The same idea but takes input from STDIN via -n
and prints the answer.
p$_.to_r.numerator
1*input
. \$\endgroup\$