Dmytro Filipenko
Dmytro Filipenko

Reputation: 941

Convert centimetres to feet and inches

I'm trying to write a function which converts cm to feet and inches

cmToFtIn(30) === {"feet": 1, "inches": 0}
cmToFtIn(29) === {"feet": 0, "inches": 11}

What I've done already is this complicated function

const cmToFeetMultiplier = multiply(1/30.5)
const ftToInMultiplier = multiply(12)
const floor = (num) => Math.floor(num)
const round = (num) => Math.round(num)
const cmToFtIn = pipe(
   cmToFeetMultiplier,
   juxt([identity, floor]),
   juxt([identity, pipe(apply(subtract), ftToInMultiplier, round)]),
   flatten,
   cond([
     [pipe(nth(2), equals(12)), (d) => ({feet: d[1] + 1, inches: 0})],
     [always(true), (d) => ({feet: d[1], inches: d[2]})],
   ])
  )

Maybe someone has some advice as to how to simplify it?

Playground

Upvotes: 3

Views: 2389

Answers (3)

Scott Sauyet
Scott Sauyet

Reputation: 50787

Unless this is an exercise to learn Ramda, I would suggest that Ramda is not the right tool for this job. I'm one of the authors of Ramda, and a big fan, but it's a tool designed to help make an FP style more palatable in JS, not a general-purpose utility library.

The issue is that this function can be written quite simply in vanilla JS:

const cmToInFt = (cm, inches = Math .round (cm / 2.54)) => ({
  feet: Math .floor (inches / 12),
  inches: inches % 12
})

const myHeight = cmToInFt (185)

console .log (myHeight)

Or, if you don't like default parameters, it might be:

const cmToInFt = (cm) => {
  const inches = Math .round (cm / 2.54)
  return {
    feet: Math .floor (inches / 12), 
    inches: inches % 12
  }
}

Ramda can add little to that. Obviously, as your approach and customcommander's answer show, you can use Ramda functions to help, and a little dose of compose is often useful. But this (which is very similar to the answer from Aadit M Shah, structured slightly differently) is already clean and readable. I see little that will make it easier to work with.

Upvotes: 2

customcommander
customcommander

Reputation: 18901

When you google "cm to inch":

enter image description here

and "cm to foot":

enter image description here

We can then build a inch and foot functions:

const inch = flip(divide)(2.54);
const foot = flip(divide)(30.48);

inch(30); //=> 11.811023622047244
foot(30); //=> 0.984251968503937

If you need to return an object {inch, foot} from a value in cm you can without Ramda:

const cmToFtIn = cm => ({inch: inch(cm), foot: foot(cm)});

cmToFtIn(30);
//=> {"foot": 0.984251968503937, "inch": 11.811023622047244}

With Ramda:

const cmToFtIn = applySpec({inch, foot});

cmToFtIn(30);
//=> {"foot": 0.984251968503937, "inch": 11.811023622047244}

Personally I'd recommend that you do not return rounded values directly from inch and foot functions. You can apply a second pass to round them where you need to do so. Two options:

Apply Math.round on your {inch, foot} object:

map(Math.round, cmToFtIn(30));
//=> {"foot": 1, "inch": 12}

Or compose Math.round and inch/foot functions:

const cmToFtIn = applySpec({
  inch: compose(Math.round, inch),
  foot: compose(Math.round, foot)
});

cmToFtIn(30);
//=> {"foot": 1, "inch": 12}

Upvotes: 2

Aadit M Shah
Aadit M Shah

Reputation: 74204

There are 2.54 centimeters in an inch. Hence, we have the equation.

const cmToInches = cm => cm / 2.54;

There are 12 inches in a foot. Hence, we have the equation.

const inchesToFtIn = inches => ({
  feet: Math.floor(inches / 12),
  inches: inches % 12,
});

Now, to convert centimeters to feet and inches we just compose these two functions.

const cmToInches = cm => cm / 2.54;

const inchesToFtIn = inches => ({
  feet: Math.floor(inches / 12),
  inches: inches % 12,
});

const cmToFtIn = cm => inchesToFtIn(cmToInches(cm));

console.log(cmToFtIn(30.48)); // 1 foot
console.log(cmToFtIn(27.94)); // 11 inches

If you need to round the inches then that's a small change.

const cmToInches = cm => cm / 2.54;

const inchesToFtIn = inches => ({
  feet: Math.floor(inches / 12),
  inches: inches % 12,
});

const cmToFtIn = cm => inchesToFtIn(Math.round(cmToInches(cm)));

console.log(cmToFtIn(30)); // 1 foot
console.log(cmToFtIn(29)); // 11 inches

Hope that helps.

Upvotes: 1

Related Questions