その他

【CodeWars 7kyu】Reverserを解く

その他
この記事は約4分で読めます。
reverse(12345)
// 54321

のように、numberが入ったらreverse値を返す関数を作ろう、という問題。ただし、

You should do this without converting the inputted number into a string.(入力された数値を文字列に変換せずに行う必要があります。)

とあるので、このtestにpassさせつつ、実装する必要があります。

Training on Reverser
Codewars is where developers achieve code mastery through challenge. Train on kata in the dojo and reach your highest potential.

筆者の回答

function reverse(n, c = 0) {
  c = c * 10 + n % 10;
  n = Math.floor(n / 10);
  return (n ? reverse(n, c) : c);
}
// reverse(1234);
// -> 4321

1回目cは、0 * 10 + 4(4は1234を10で割ったあまり) -> 4

その後、Math.floor(n/10)で、整数を維持したまま、桁数を減らす(1234 -> 123)

2回目cは、4 * 10 + 3(3は123を10で割ったあまり) -> 43

その後、Math.floor(n/10)で、整数を維持したまま、桁数を減らす(123 -> 12)

3回目cは、43 * 10 + 2(2は12を10で割ったあまり) -> 432

その後、Math.floor(n/10)で、整数を維持したまま、桁数を減らす(12 -> 1)

4回目cは、432 * 10 + 1(2は12を10で割ったあまり) -> 4321

その後、Math.floor(n/10)で、整数を維持したまま、桁数を減らす(1 -> 0)

5回目cは、4321 * 10 + 0(0は1を10で割ったあまり) -> 4321

その後、Math.floor(n/10)で、整数を維持したまま、桁数を減らす(0 -> 0)

JavaScriptで、0はfalse扱いなので、ここで再帰関数が終了して、

return (n ? reverse(n, c) : c); で、4321が返るようにしてます。再帰関数をわざわざ使う必要はないのですが、せっかくなので使用しました。ベストプラクティスは、whileで回していました。

その他の回答

アンサーの中でも「なにこれ?」となったのが、この回答でした。

const reverse = n => +([] + n).split([]+[]).reverse().join([]+[]);

⓪最初の+演算子は、数値変換するために使われるものです。

①([] + n)ですが

//コンソールログ
n=11
// 11
console.log([]+n === 11);
// false
console.log([]+n === '11');
// true

このように、([] とか "" + 数値) === 数字) となります。今回なら、n=4321であれば

([] + 4321)
// '4321'

となります。

②split([]+[])ですが

//コンソールログ
console.log('123'.split([]));
// ['1', '2', '3']

となります。ここのsplit([])は、split(”)と同義なのですが、split(”)で指定してしまうと、

You should do this without converting the inputted number into a string.(入力された数値を文字列に変換せずに行う必要があります。)

こちらのtestに引っ掛かるため、裏技みたいな形で上手く抜けれるんだなぁーと感心しました。

ただ、split([]+[])と2回[]を書く必要があるかな?と思ったのですが、知見がある方、是非ここの理由を伺いたいです。

この+([]+[+[]])みたいな可読性の無い処理に対する説明がありましたので、興味のある方は一読してみたら面白いと思います。

Forbidden - Stack Exchange