LoginSignup
0
0

More than 1 year has passed since last update.

Rubyでダイヤル問題を解く

Last updated at Posted at 2022-09-23

問題

  • AからZまでの目盛りを持つダイヤルがあるとする。
  • このダイヤルは右に回すことも左に回すことも出来る。
  • ダイヤルは丸いのでAとZは隣り合わせだ。

ひとつの目盛りから別の目盛りまで、動かす必要のある最小の目盛り数を求めたい。

image.png

コード

XからBまでの距離を計算すると、移動距離は4であることが分かる。

B -> A -> Z -> Y -> X で4マス移動だ。

SCALES = ("A".."Z").to_a

current_dial = "X"
next_dial = "B"

current_dial_place = SCALES.index(current_dial) + 1
next_dial_place = SCALES.index(next_dial) + 1

formal_move_diff = (next_dial_place - current_dial_place).abs
reversed_move_diff = SCALES.size - formal_move_diff

minimum_diff = [formal_move_diff, reversed_move_diff].min # 4

解説

ダイアルの配列全体はこうだ。

SCALES = ("A".."Z").to_a
# => ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]

XからBまでの距離を求める時は、位置の差分を求めれば良い。
Bは2番目、Xは24番目に位置する。

next_dial_place = SCALES.to_a.index("B")+1 # => 2
current_dial_place = SCALES.to_a.index("X")+1 # => 24

配列内での2つの位置の距離は、片方の値から片方を引き算して絶対値を得れば良い。

formal_move_diff = (next_dial_place - current_dial_place).abs # 22

AからZの配列の中では、XとBは22個離れている。

だがこれはダイヤルなので逆順にも回すことが出来る。
逆順での距離は ダイヤルの全ての目盛りの数 - 正順での距離 で求められる。

(ここでは便宜的に片方を正順、もう片方を逆順と呼ぶ)

reversed_move_diff = SCALES.size - formal_move_diff # 4

正順と逆順、両者の小さい方が最小の目盛り数である。

minimum_diff = [formal_move_diff, reversed_move_diff].min

感想

逆順での計算が大変だと思ったが、意外に引き算だけで大丈夫だった。

別案

AからZまでの同じ配列を2個つなげて、AとZが隣り合わせの配列を作ろうかとも考えていた。
こちらのほうが良かったかもしれない。

# AからZまでの配列二個分を連結する
SCALES = ("A".."Z").to_a*2 

# XとBの位置を得る
# アルファベットは2セットなので合計4箇所が見つかる
places = SCALES.each_index.select { |i| ["X", "B"].include? SCALES[i] } # [1, 23, 27, 49]

# 最初のXから最初のBまでの距離
move1 = places[1] - places[0] # 22

# 最初のBから二個目のXまでの距離
move2 = places[2] - places[1] # 4

[move1, move2].min # 4

チャットメンバー募集

何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

Twitter

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0