こんにちは、ナナオです。
前回に引き続き競プロを実施していきたいと思います。
今回の問題は以下です。
座標系での規則的な移動 | レベルアップ問題集 | プログラミング学習サイト【paizaラーニング】
実装
最初は以下のように実装しました。
package main
import "fmt"
func main(){
var x, y, n int
fmt.Scan(&x, &y, &n)
// stepは偶数の時に増える
// 方角が変わるのはc数だけ移動したとき
step := 0
c := 0
d := "E"
for i := 0; i < n; i++ {
if i % 2 == 0 {
step++
}
// cの数だけ移動していた場合、現在の方角を変える
if i == c {
switch d {
case "E":
d = "S"
case "W":
d = "N"
case "N":
d = "E"
case "S":
d = "W"
}
}
switch d {
case "E":
x++
case "W":
x--
case "N":
y++
case "S":
y--
}
}
fmt.Println(x, y)
}
ですが、これだとcに何を入れればいいのかわからず断念してしまいました。
cに何を入れるべきか、それは今の方向に対して何回進んでいるか入れればいいとAIから助言をもらって実装を修正しました。
package main
import "fmt"
func main(){
var x, y, n int
fmt.Scan(&x, &y, &n)
// stepは偶数の時に増える
// 方角が変わるのはc数だけ移動したとき
step := 1
count := 0 // 今の方向に進んだ歩数
turnCount := 0 // 同じ距離で曲がった回数
d := "E"
for i := 0; i < n; i++ {
switch d {
case "E":
x++
case "W":
x--
case "N":
y--
case "S":
y++
}
// countの数だけ移動していた場合、現在の方角を変える
count++
if step == count {
count = 0
switch d {
case "E":
d = "S"
case "W":
d = "N"
case "N":
d = "E"
case "S":
d = "W"
}
turnCount++
// 2回曲がるごとに、次に進む距離を1増やす
if turnCount == 2 {
step++
turnCount = 0
}
}
}
fmt.Println(x, y)
}
修正したら動きました。
もっとスマートにはできそうです。
ということで解答例のコードを参考に修正しました。
package main
import "fmt"
func main(){
var x, y, n int
fmt.Scan(&x, &y, &n)
// stepは偶数の時に増える
// 方角が変わるのはc数だけ移動したとき
dir := []string{"N","E","S","W"}
step := 1
count := 1 // 今の方向に進む歩数
first := true // 曲がったのが一回目か二回目かのフラグ
d := 1 // 方向管理
for i := 0; i < n; i++ {
switch dir[d%4] {
case "E":
x++
case "W":
x--
case "N":
y--
case "S":
y++
}
count--
if first && count == 0 {
// 曲がるのが一回目のとき
count = step
first = false
d++
} else if count == 0 {
// 曲がるのが二回目のとき
step++
count = step
first = true
d++
}
}
fmt.Println(x, y)
}
かなりコードがすっきりしました。
👍