11
\$\begingroup\$

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

\$\endgroup\$
8
  • 2
    \$\begingroup\$ Surely a fraction type trivialises the question? \$\endgroup\$
    – Neil
    Sep 14, 2023 at 22:56
  • \$\begingroup\$ @Neil If you've got a trivial solution, I implore you to submit it. Also worth noting many, even modern languages, don't have fractional types. \$\endgroup\$
    – ATaco
    Sep 14, 2023 at 23:01
  • 5
    \$\begingroup\$ Essentially, this is just finding the numerator of the fraction form of a decimal \$\endgroup\$
    – lyxal
    Sep 14, 2023 at 23:26
  • 2
    \$\begingroup\$ "determine the smallest number which is a positive integer multiple of it." -> "determine the smallest positive integer which is a positive integer multiple of it."? To me the first sounds like we can just output 1*input. \$\endgroup\$ Sep 15, 2023 at 12:09
  • 2
    \$\begingroup\$ @DominicvanEssen Inaccuracies due to floating-point errors are disallowed. Answers that fail on this point should clarify explicitly, and attempt to provide an answer that does not. I'll add this as a test case. \$\endgroup\$
    – ATaco
    Sep 19, 2023 at 22:44

26 Answers 26

6
\$\begingroup\$

Vyxal 2.4.1, 2 bytes

ƒh

Try it Online!

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

Try it Online!

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.

\$\endgroup\$
2
  • \$\begingroup\$ Oh! Smart approach! \$\endgroup\$
    – ATaco
    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\$
    – lyxal
    Sep 14, 2023 at 23:17
5
\$\begingroup\$

J, 4 bytes

1&*.

Attempt This Online!

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:

Attempt This Online!

\$\endgroup\$
1
  • \$\begingroup\$ TIL about dyadic x: \$\endgroup\$
    – Jonah
    Sep 15, 2023 at 6:16
5
\$\begingroup\$

Excel, 37 bytes

=0+TEXTBEFORE(TEXT(A1,"0/00000"),"/")

Input in cell A1.

\$\endgroup\$
4
\$\begingroup\$

Factor, 9 bytes

numerator

Attempt This Online!

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 ]

Attempt This Online!

And my original answer for posterity:


Factor, 34 bytes

[ 0 [ 1 + 2dup * ratio? ] loop * ]

Attempt This Online!

  • 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 multiplier
  • 2dup * 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
\$\endgroup\$
1
  • \$\begingroup\$ I managed to backport your answer by downgrading my vyxal version :p \$\endgroup\$
    – lyxal
    Sep 14, 2023 at 23:30
4
\$\begingroup\$

Julia, 11 bytes

~x=lcm(x,1)

Attempt This Online!

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

Try it online!

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.

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

R, 39 31 bytes

\(x,y=x*1:1e6)y[!(y+1e7)%%1][1]

Attempt This Online!

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]

Attempt This Online!

Original answer: fails due to floating-point inaccuracies for 3.1428, and probably other difficult inputs.

\$\endgroup\$
3
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

Ruby, 26 bytes

->d{(1..).find{_1/d%1==0}}

Attempt This Online!

Original: Ruby, 31 bytes

f=->d,x=1{d*x%1>0?f[d,x+1]:d*x}

Attempt This Online!

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.

\$\endgroup\$
1
  • \$\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
    Sep 15, 2023 at 18:53
2
\$\begingroup\$

PARI/GP, 25 bytes

n->numerator(bestappr(n))

Attempt This Online!

\$\endgroup\$
2
\$\begingroup\$

Perl 5 -p, 26 bytes

($\=$_*++$i)=~/\./&&redo}{

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Maxima, 17 bytes

Try it online!

f(n):=num(rat(n))
\$\endgroup\$
2
\$\begingroup\$

APL(Dyalog Unicode), 3 bytes SBCS

∧∘1

Try it on APLgolf!

LCM between input and 1. This is actually really similar to a problem in the APL Competition, 1:7 Let's Be Rational.

\$\endgroup\$
2
\$\begingroup\$

Pyth, 6 bytes

*fsI*Q

Takes input as a float.

Try it online!

*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.

\$\endgroup\$
2
  • \$\begingroup\$ Fails for 3.1428 \$\endgroup\$ 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\$
    – isaacg
    Sep 24, 2023 at 22:29
2
\$\begingroup\$

Rust, 39 38 bytes

-1 thanks to @corvus_192

|mut x|{let n=x;while x%1.>0.{x+=n};x}

Try it online!

Closure naively loops and increments x by its intial value until it becomes a whole number.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ I think using > instead of != works. \$\endgroup\$
    – corvus_192
    Sep 16, 2023 at 17:18
  • \$\begingroup\$ @corvus_192 you're right, thanks. \$\endgroup\$
    – code
    Sep 16, 2023 at 18:26
2
\$\begingroup\$

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
\$\endgroup\$
2
  • \$\begingroup\$ 20 bytes: lambda n:n.numerator meta \$\endgroup\$ 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\$ Sep 17, 2023 at 9:27
2
\$\begingroup\$

Nekomata, 1 byte

Attempt This Online!

= 'numerator' = 'Get the numerator of a number'

\$\endgroup\$
2
\$\begingroup\$

AWK, 35 24 bytes

{while($1*++a%1);$1*=a}1

Try it online!

(Several improvements by @Dominic van Essen to my original answer: -11 bytes)


Original answer: AWK, 35 bytes

{while($1*++a>int($1*a));print$1*a}

Try it online!

\$\endgroup\$
2
2
\$\begingroup\$

Python, 20 bytes

lambda n:n.numerator

An unnamed function that accepts a Fraction object and returns the integer.

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Floating point inaccuracy I think - it accepts a float and does not perform repeated addition. \$\endgroup\$ Sep 23, 2023 at 21:50
  • \$\begingroup\$ @NickKennedy removed. \$\endgroup\$ Sep 24, 2023 at 23:12
1
\$\begingroup\$

Vyxal, 39 bitsv2, 4.875 bytes

{D⌊≠|+

Try it Online!

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.

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

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.

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

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.

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

T-SQL, 51 bytes

DECLARE @2 real=4.625

DECLARE @ REAL=@2
WHILE @>floor(@)SET @+=@2
PRINT @
\$\endgroup\$
1
\$\begingroup\$

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.

Try it on SwiftFiddle!

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.

Try it on SwiftFiddle!

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

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)
\$\endgroup\$
1
  • 1
    \$\begingroup\$ @NickKennedy Should be fixed, although it's plausible another test case might still fail due to floating point accuracy tbh. \$\endgroup\$ Sep 24, 2023 at 11:39
0
\$\begingroup\$

JavaScript (V8), 31 bytes

f=(n,m=n)=>(m+1e9)%1?f(n,m+n):m

Try it online!

Take float

JavaScript (V8), 4 bytes

x=>x

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Is the 4-byte answer a joke? It obviously fails if input is given as a non-reduced fraction. \$\endgroup\$ 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
    Sep 25, 2023 at 9:15
0
\$\begingroup\$

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

Attempt This Online!

Ruby -n, 18 bytes

The same idea but takes input from STDIN via -n and prints the answer.

p$_.to_r.numerator

Attempt This Online!

\$\endgroup\$

Your Answer

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

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