こんにちは、ナナオです。
前回に引き続き競プロを実施していきたいと思います。
今回の問題は以下です。
移動が可能かの判定・幅のある移動 | レベルアップ問題集 | プログラミング学習サイト【paizaラーニング】
実装
コアとなるロジックはあまり変わらないのですが、途中で壁があったり壁を超えたりする場合はそれを超える手前の座標を出力したうえでStopと出力しなければいけないようです。
ちょっと大変でしたが実装しました。
package main
import "fmt"
func main(){
var h, w, sy, sx, n int
fmt.Scan(&h, &w, &sy, &sx, &n)
s := make([]string, h)
for i := 0; i < h; i++ {
fmt.Scan(&s[i])
}
dir := []string{"N", "E", "S", "W"}
c := 120 // 現在の向き
for i := 0; i < n; i++ {
var d string
var l int
fmt.Scan(&d, &l)
lr := 1
if d == "L" {
lr = -1
}
move := l * lr // 移動量
// X軸上に壁があるかどうか判定
checkWallX := func(y, fromX, toX, lr int) bool {
i := fromX
for {
i += lr
if i == toX {
fmt.Println(y, toX)
return true
}
if i >= w || i < 0 || s[sy][i] == '#' {
fmt.Println(y, i - lr)
fmt.Println("Stop")
return false
}
}
}
// Y軸上に壁があるかどうか判定
checkWallY := func(x, fromY, toY, lr int) bool {
i := fromY
for {
i += lr
if i == toY {
fmt.Println(toY, x)
return true
}
if i >= h || i < 0 || s[i][sx] == '#' {
fmt.Println(i - lr, x)
fmt.Println("Stop")
return false
}
}
}
// チェック結果を格納
result := true
switch dir[c%4] {
case "N":
result = checkWallX(sy, sx, sx + move, lr)
sx += move
case "S":
result = checkWallX(sy, sx, sx - move, -lr)
sx -= move
case "E":
result = checkWallY(sx, sy, sy + move, lr)
sy += move
case "W":
result = checkWallY(sx, sy, sy - move, -lr)
sy -= move
}
c += lr
if !result {
return
}
}
}
ポイントはcheckWall関数です。
ただX軸とY軸それぞれで用意している分、ちょっと長くなってしまいました。。
このロジックだと冗長なので、短くします。
解説を見て気づきましたが、移動はl変数に基づいて一つずつ行えばいいですね。
元の座標はly, lxで保持しています。
package main
import "fmt"
func main(){
var h, w, sy, sx, n int
fmt.Scan(&h, &w, &sy, &sx, &n)
s := make([]string, h)
for i := 0; i < h; i++ {
fmt.Scan(&s[i])
}
dir := []string{"N", "E", "S", "W"}
c := 120 // 現在の向き
for i := 0; i < n; i++ {
var d string
var l int
fmt.Scan(&d, &l)
lr := 1
if d == "L" {
lr = -1
}
for j := 0; j < l; j++ {
ly, lx := sy, sx
switch dir[c%4] {
case "N": sx += lr
case "S": sx -= lr
case "E": sy += lr
case "W": sy -= lr
}
if sy >= h || sx >= w || sy < 0 || sx < 0 || s[sy][sx] == '#' {
fmt.Println(ly, lx)
fmt.Println("Stop")
return
}
}
c += lr
fmt.Println(sy, sx)
}
}
だいぶスマートになりました👍