問題です。

開始時点の x , y 座標と移動の歩数 N が与えられる。
以下の図のように時計回りに渦を巻くように移動を N 歩行った後の x , y 座標は?
マスの座標系は下方向が y 座標の正の向き、右方向が x 座標の正の向きとする。

引用元:https://paiza.jp/works/mondai/a_rank_level_up_problems/a_rank_snake_move_step4

どうしょうか? どのようなコードを書けばいいのでしょうか?

Nを上、Sを下、Wを左、Eを右とすると移動はESWWNNEEESSSWWWWNNNNEEEEと続いていきます。連続する移動が繰り返すたびにだんだん増えていきます。

これはX方向とY方向をわけて考えればいいのでしょうか?

X方向だと

+1,(+1が1回)
0,(0が1回)
-1-1,(-1が2回)
0,0,(0が2回)
+1,+1,+1,(+1が3回)
0,0,0,(0が3回)
-1,-1,-1,-1,(-1が4回)
0,0,0,0,(0が4回)
+1,+1,+1,+1,+1(+1が5回)
0,0,0,0,0,(0が5回)

と続いていきます。これをXn = (nで表せる関数)で表わすことができればいいのですが、うまい方法が思いつきません。
結局、ああでもない、こうでもないと2時間くらい考えてもえがわからず回答を見ることにしました。

模範解答

模範解答をみると、移動の方向の規則性について以下のように解説しています。

移動の方向は、ESWN ESWN… と続いていく。
移動方向は全部で4種類だが、移動回数は同じではない。
ただ移動のマス数には規則性がある。それが11 22 33 44 … と続いていく。
そこで1回目の移動かどうかを管理するフラグを使えば実装可能とのことです。

n回移動した場合の座標を出力する関数は以下のようになります。引数はstartXが最初のX座標、startYが最初のY座標、nが移動回数です。

うーん、これを思いつけというのは厳しいな。プログラマーであればすぐに気がつくのかもしれませんが、鳩レベルの脳みそしか持っていない管理人にとっては難しいです。

別解を考える

渦巻き状の処理であれば以前、このようなものを作ったことがあることを思い出しました。

ただ渦巻きの方向が違います。問題では中心から広がっていくように移動していくのですが、これは周囲から中心に向かって移動しています。どんなコードを書いていたのか見てみましたが、これは渦巻きの範囲が狭いから使える方法です。問題では移動の回数は100回を超えることはないということなので以下のようなコードで移動先の座標を求めることはできます。

及第点?それとも落第?

右に曲がることができる場合は右折する、できない場合は直進すればよいという規則性に気がつけば一応、これでよいはずです。

n に100よりも少し大きな数をいれても結果はすぐに出力されます。しかしnがもっと大きな数だとどうでしょうか? 模範解答では1000万を超える数をいれても結果はすぐに出力されますが、このコードでは1万くらいまでならちょっと待たされるくらいで済みますが、2万だと相当待たされます。

points.Any()を繰り返しているわけですから時間がかかるのは当然といえば当然です。

速度を改善する

そこで二次元配列を使うのはどうでしょうか? 配列を使う以上、アクセス違反が起きないように気をつける必要がありますが、以下のコードであれば上記のコードよりは処理が速いです。

どっちが速い?

模範解答と2番目に自作したメソッドで実行時間を計測します(最初の自作メソッドは論外!)。

n は 4000 * 10000 です。結果は3倍強の差になりました。どちらも2秒以内なのでまあいいかなとも思いますが、模範解答には敵いませんでした。