x、y座標使ったプログラミング問題を解いて思ったこと

メモがてらの投稿です。

よく、プログラミング問題を解く時に、x、y座標を使って解くやつありますよね。
以下みたいな感じで、あーだこーだするやつです。（雑

```
# #を囲うにはいくつの柵が必要？みたいな問題だとして

# 横の数と縦の数が宣言されて
6 4

# １列ずつ値がくる
####..
..#.#.
#.#.#.
.##..#

```

最初、x、y座標使ってなんなん、どうやって求めるんや、、意味不...と思ってましたが、
ちょっとずつ紐解けてきました。

今回は、自分なりにx、y座標の求め方やそれを使った応用などをまとめました。
まだまだ自分も学習中なので、よりよい方法などございましたらコメントいただけると幸いです！

なお、今回はrubyを使って記述しています。

# x、y座標の求め方

結論、配列を二重にし、ループ処理を使います。
こんな感じ。

```
fields = [
  ['#', '#', '#', '#', '.', '.'],
  ['.', '.', '#', '.', '#', '.'],
  ['#', '.', '#', '.', '#', '.'],
  ['.', '#', '#', '.', '.', '#'],
]

fields.each_with_index do |field, y|
  field.each_with_index do |f, x|
  end
end 
```

こうすることで、ループを使い添字を取得できます。

処理を説明していくと、
まず1回目のループ処理でfields内の各配列の添字を取得できます。

```
fields.each_with_index do |field, y|
```

![スクリーンショット 2021-07-17 13.02.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697823/49bdc20e-6501-482c-706c-87ab352fb414.png)
これがいわゆるy軸の値です。

次に、各配列をさらにループします。
同様にこちらも、添字を取得できます。

```
field.each_with_index do |f, x|
```
![スクリーンショット 2021-07-17 13.10.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697823/6c0ea42e-28b4-d443-2c54-ab581aec2026.png)
これがx軸の値です。

これらを使って、#のx、y座標を取得するならば
こんな感じかと思います。

```
hash_places = []

fields = [
  ['#', '#', '#', '#', '.', '.'],
  ['.', '.', '#', '.', '#', '.'],
  ['#', '.', '#', '.', '#', '.'],
  ['.', '#', '#', '.', '.', '#'],
]

fields.each_with_index do |field, y|
  field.each_with_index do |a, x|
    hash_places << { x: x, y: y} if a == '#'
  end
end
  
# hash_placesの中身
{:x=>1, :y=>0}
{:x=>2, :y=>0}
{:x=>3, :y=>0}
{:x=>2, :y=>1}
{:x=>4, :y=>1}
{:x=>0, :y=>2}
{:x=>2, :y=>2}
{:x=>4, :y=>2}
{:x=>1, :y=>3}
{:x=>2, :y=>3}
{:x=>5, :y=>3}
```
x、y座標の値のリストができました。


# 隣接関係を調べる
取得した値を使用して、上下左右に同じ値があるか、調べることができます。
方法は+1 -1を使用するだけです。

```
# 左の値を確認したいならば、x軸 - 1
# 右ならば、x軸 + 1
# 上ならば、y軸 - 1
# 下ならば、y軸 + 1
```

これを使って、先程のhash_placesから上下左右に#があるか調べてみると、
こんな感じになります。（ちょっと汚いコードですいません。。）

```
def is_neighbors(place, fields)
  top = place[:y] - 1 == -1 ? 'NONE' : { x: place[:x], y: place[:y] - 1 }
  is_top = top != 'NONE' && (fields[top[:y]][top[:x]] == fields[place[:y]][place[:x]])

  right = place[:x] + 1 == fields[0].length ? 'NONE' : { x: place[:x] + 1, y: place[:y] }
  is_right = right != 'NONE' && (fields[right[:y]][right[:x]] == fields[place[:y]][place[:x]])

  bottom = place[:y] + 1 == fields.length ? 'NONE' : { x: place[:x], y: place[:y] + 1 }
  is_bottom = bottom != 'NONE' && (fields[bottom[:y]][bottom[:x]] == fields[place[:y]][place[:x]])

  left = place[:x] - 1 == -1 ? 'NONE' : { x: place[:x] - 1, y: place[:y] }
  is_left = left != 'NONE' && (fields[left[:y]][left[:x]] == fields[place[:y]][place[:x]])

  answer = {
    is_top: is_top,
    is_right: is_right,
    is_bottom: is_bottom,
    is_left: is_left,
  }
end

hash_places.each_with_index do |place, i|
  puts "#{i + 1}番目: #{is_neighbors(place, fields)}"
end
# 戻り値
1番目: {:is_top=>false, :is_right=>true, :is_bottom=>false, :is_left=>false}
2番目: {:is_top=>false, :is_right=>true, :is_bottom=>false, :is_left=>true}
3番目: {:is_top=>false, :is_right=>true, :is_bottom=>true, :is_left=>true}
4番目: {:is_top=>false, :is_right=>false, :is_bottom=>false, :is_left=>true}
5番目: {:is_top=>true, :is_right=>false, :is_bottom=>true, :is_left=>false}
6番目: {:is_top=>false, :is_right=>false, :is_bottom=>true, :is_left=>false}
7番目: {:is_top=>false, :is_right=>false, :is_bottom=>false, :is_left=>false}
8番目: {:is_top=>true, :is_right=>false, :is_bottom=>true, :is_left=>false}
9番目: {:is_top=>true, :is_right=>false, :is_bottom=>false, :is_left=>false}
10番目: {:is_top=>false, :is_right=>true, :is_bottom=>false, :is_left=>false}
11番目: {:is_top=>true, :is_right=>false, :is_bottom=>false, :is_left=>true}
12番目: {:is_top=>false, :is_right=>false, :is_bottom=>false, :is_left=>false}
```

各値を上下左右で計算しています。
一番外側にいた場合は、隣の値がないので、
その時はNONEを返しています。

![スクリーンショット 2021-07-17 15.08.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697823/bd87a32a-13a7-3b89-1e3f-0dd3a27b2768.png)


左と上は、-1になることはないので、それを条件分岐に使用しています。
右と下は、要素の長さを超えることはないので、それを条件分岐に使用しています。

# 参考

[each_with_indexの使い方](https://qiita.com/tsuchinoko_run/items/5cef7dd9d8baf48ffde7)