どこで区切れば合計が同じ数になる???

こんにちは!!

今日は以下のような仕様のコードを書いてみました。

仕様

数字の配列が複数与えられます。

各配列の要素をどこかで区切ることによって左右の合計は同じ数になります。

どこで区切れば左右の数の合計が同じ数になるか返すプログラムを作ります。

また、返す際は左側の数字をA,右側の数字をBの文字列にします。

例 input = [

[3, 7, 4, 5, 1],

[6, 9, 1, 8, 8],

[11, 2, 5, 2, 2]

]

output = [

%w(A A B B B),

%w(A A A B B),

%w(A B B B B)

]

こんなの日常的になくない?と思う方もいるかもしれませんが、温かい目で見守って下さると嬉しいです笑

コード

class ArrayNumbers

def initialize(arr_num)
@arr_num = arr_num
end

def separate
@arr_num.map do |row|
i = 1
while i <= row.size
if row[0...i].sum == row[i..-1].sum
break(("A" * i )+ ("B" * (row.size - i))).chars
end
i += 1
end
end
end
end

このようなコードになりました!

初めはmapを使わず、eachメソッドで一文字ずつ配列に入れていたのですが、それだとコードが長くなってしまうのでmapメソッドで最後に評価した値を配列に入れることにしました。

その際while式の戻り値はnilってことを知らなかったので配列の要素が全部nilになっているのを見たときはビックリしました笑

breakに引数を渡せばよかったんですね〜。

個人的には戻り値がもう少しスッキリした書き方があるかな〜と模索していたのですが結局見つかリませんでした泣

追記

@scivola さんからのアドバイスを元にリファクタリングをしてみました!!

class ArrayNumbers

def initialize(arr_num)
@arr_num = arr_num
end

def separate
@arr_num.map do |row|
1.upto(row.size) { |i|
if row[0...i].sum == row[i..-1].sum
break ["A"] * i + ["B"] * (row.size - i)
end
}
end
end
end

#使用例

input = [
[3, 7, 4, 5, 1],
[6, 9, 1, 8, 8],
[11, 2, 5, 2, 2]
]

p ArrayNumbers.new(input).separate
#=>["A", "A", "B", "B", "B"],
# ["A", "A", "A", "B", "B"],
# ["A", "B", "B", "B", "B"]

uptoメソッドは繰り返しとループカウンターを同時に使いたいときにうってつけのメソッドでした!!!

存在自体は知っていたものの活用できていませんでした〜

Array#*は配列を繰り返したい時に使うメソッドです。

これは知らなかった!!!!

勉強になりました!