## DEV Community 👩‍💻👨‍💻 is a community of 921,001 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

# Daily Challenge #24 - Shortest Step

Today's challenge comes from user bdowds on CodeWars.

Given a number, return the shortest amount of steps it would take from 1 to land exactly on that number.

A step is defined as:

• Adding 1 to the number: num += 1
• Doubling the number: num *= 2

You will always start from the number 1 and you will have to return the shortest count of steps it would take to land exactly on that number.

Examples:

num == 3 would return 2 steps:

1 -- +1 --> 2: 1 step
2 -- +1 --> 3: 2 steps

2 steps

num == 12 would return 4 steps:

1 -- +1 --> 2: 1 step
2 -- +1 --> 3: 2 steps
3 -- x2 --> 6: 3 steps
6 -- x2 --> 12: 4 steps

4 steps

Math problems and string problems often require different approaches, so they'll test different areas of your critical thinking ability.

Good luck, happy coding!

Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge for a future post? Email yo+challenge@dev.to with your suggestions!

## Top comments (16) Hao • Edited on

If you convert the number to binary, the steps are exactly

(`number of 1s` - 1) * 2 + `number of 0s`

``````2  -> "10"   -> (1 - 1) * 2 + 1 = 1 step
7  -> "111"  -> (3 - 1) * 2 + 0 = 4 steps
12 -> "1100" -> (2 - 1) * 2 + 2 = 4 steps
``````

This way we don’t need loops or recursion.

``````String.prototype.count = function(char){
return this.split(char).length - 1;
}

function countSteps(n) {
let binary = n.toString(2);
return (binary.count('1') - 1) * 2 + binary.count('0');
}
`````` Massimo Artizzu

I was about to submit something like that, so have my applause instead 👏🎉

A little more thinking on the problem can really simplify the solution!

(On a side note, I wouldn't extend a native prototype, but that's out of context now 😅) Hao

That was my original version, then I thought writing two functions might confuse people so I changed it into this. It's just for the sake of demonstration and better readability.🤗But you were right, it is a bad habit to extend a native prototype. Corey Alexander

Wow this is brilliant! Nice job! SavagePixie • Edited on

There is probably a better way that doesn't use loops, but these are my initial thoughts:

(using JavaScript)

``````function countSteps(n) {
let steps = 0
while (n > 1) {
n % 2 == 0 ? n /= 2 : n--
steps++
}
return steps
}
`````` Andreas Jakof

That was my idea as well. SavagePixie • Edited on

Well, I imagine that there are other ways to solve it. I came to it when I realised that it wasn't a coding problem as much as a maths problem. There are two key things that we know:

• For natural numbers, doubling a number always makes it bigger than adding one (except when the number is 1, then it doesn't matter). So adding one is only needed to reach numbers with odd divisors
• The number that we need to reach

Therefore, since we know the number that we need to reach, it is a lot quicker to work backwards (from the number we need to reach) than to make guesses from number 1. Starting from the end, every time we get to an odd number we subtract 1 (the backward of adding one) and every time we get to an even number we divide by 2 (the backward of multiplying by two).
Since we are dividing by 2 every time we can, that'll ensure that we're always taking as few steps as possible.
Since the amount of steps is the same whether we go `1->n` or `n->1`, working backwards will give us the same result. Avalander

Here's some recursion. I think it will work, but I'm not sure since I'm on my phone, I'll test it when I get home.

``````const steps = (n, acc = 0) =>
n === 1
? acc
: n % 2 === 0
? steps(n / 2, acc + 1)
: steps(n - 1, acc + 1)
`````` Corey Alexander

I wrote two versions of this. The first one I wrote was an exhaustive search. Then I read some answers here and wanted to write up the solution @savagepixie had and compared them. They matched on all the numbers I tested on (up to 200 in the test case).
At first I wasn't convinced that the 'simpler' solution of counting down was gonna work, but I was definitely wrong! It performs way better than my exhaustive search and seems to be just as accurate

``````pub fn shortest_step_exhaustive_recurse(num: u64) -> Option<u64> {
fn recursive_helper(cur: u64, goal: u64) -> Option<u64> {
if cur == goal {
Some(0)
} else if cur > goal {
None
} else {
[cur + 1, cur * 2]
.iter()
.filter_map(|next_try| recursive_helper(*next_try, goal))
.map(|attempt| attempt + 1)
.min()
}
}

recursive_helper(1, num)
}

pub fn shortest_step_count_down(num: u64) -> Option<u64> {
if num == 0 {
None
} else if num == 1 {
Some(0)
} else if num % 2 == 0 {
Some(1 + shortest_step_count_down(num / 2)?)
} else {
Some(1 + shortest_step_count_down(num - 1)?)
}
}

#[cfg(test)]
mod tests {
use crate::*;

#[test]
fn all_algos_work_for_three() {
assert_eq!(shortest_step_exhaustive_recurse(3), Some(2));
assert_eq!(shortest_step_count_down(3), Some(2));
}

#[test]
fn all_algos_work_for_twelve() {
assert_eq!(shortest_step_exhaustive_recurse(12), Some(4));
assert_eq!(shortest_step_count_down(12), Some(4));
}

#[test]
fn all_algos_match_up_to_200() {
for i in 0..200 {
assert_eq!(
shortest_step_count_down(i),
shortest_step_exhaustive_recurse(i),
"Algos don't match for {}",
i
);
}
}
}

`````` Alvaro Montoro • Edited on

Elixir

``````defmodule Challenge do
def shortest_step(n) when n <= 1 do
0
end

def shortest_step(n) do
if rem(n,2) == 0 do
1 + shortest_step(div(n, 2))
else
1 + shortest_step(n-1)
end
end
end
``````

First time doing anything on Elixir. It was fun :) Oleksii Filonenko • Edited on

Elixir:

``````defmodule ShortestStep do
import Integer

@spec steps(non_neg_integer) :: non_neg_integer
def steps(start) when start > 0, do: do_steps(start)

@spec do_steps(non_neg_integer) :: non_neg_integer
defp do_steps(1), do: 0
defp do_steps(current) when is_odd(current), do: do_steps(current - 1) + 1
defp do_steps(current), do: do_steps(div(current, 2)) + 1
end
``````

Recursive thinking is fun :) willsmart • Edited on

JS using a bit of bitwise math

``````
// Wow,.. fancy :|
step = n => (n&~1) >> ((~n)&1)    // note that they're ~'s, not -'s

// Count how many times we need to iterate step until it hits 0
countSteps = n => {
if (n<=0 || Math.floor(n)!==n) throw new Error(`countSteps only accepts positive integers, \${n} was passed`);

let count =0;
while (n=step(n)) count++;
return count;
}
``````

(couple of edits to make it cleaner) peter279k

Here is the simple solution with Python:

``````def shortest_steps_to_num(num):
steps = 0
if num == 1:
return steps

while num != 1:
if num % 2 == 0:
num /= 2
num = int(num)
else:
num -= 1

steps += 1

return steps
`````` Udi • Edited on

Ruby:

``````number = 12

def step(n, step)
return step if n == 1

n = n % 2 == 0 ? n / 2 : n -= 1
step(n, step + 1)
end

puts step(number, 0)
``````

:)

### 🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.