ルビー3.0の出現-日06 -習慣習慣


ルビー3.0はちょうどリリースされたので、我々は実験に時間がかかると、すべての楽しい新機能がそこにあるかを参照してください年の陽気な時間です.
この一連の投稿では、Ruby 2.7と3.0の機能をいくつか紹介しますsolve Advent of Code problems . ソリューション自体は、機能の新しい使用を示すために最も効率的であることを意味していません.
これらのポストの各々が次第に長く、より関与するように、私は個々の日までにこれらを壊しています.
そう言ってしまおうじゃないか
次号

Day 06 - 第01部-カスタム税関
日6は別のかなり簡単なものだった.パート1のために、我々は特に新しい何も使用していません.私たちのタスクは、“はい”回答を見つけるために、“はい”は、文字で示されているそれらをカウントすることです.レコードは空白行で区切られますが、改行で区切られた各レコードに1つ以上の応答があります.
abcx
abcy
abcz
この場合には6 ユニークな答えは3人から.abcxyz . 問題の最初の部分はこれに集中しますので、解決策を見てみましょう.
puts File
  .read(ARGV[0])
  .split(/\n\n/)
  .map { _1.gsub(/\W/, '').chars.uniq.size }
  .sum
gsub 空白で
我々が見る最初の新しい線はmap 機能
.map { _1.gsub(/\W/, '').chars.uniq.size }
\W 任意の空白、改行、またはスペースを表します.
abcx
abcy
abcz
...これを:
abcxabcyabcz
uniq 登場人物
このソリューションの次の部分はchars , 私が信じているのは2.6で導入され、文字列を個々の文字に分割するためです.
'abcxabcyabcz'.chars
# => ["a", "b", "c", "x", "a", "b", "c", "y", "a", "b", "c", "z"]
この後、我々はどのように多くのユニークなyesの答えを知っているuniq は非常に有用です.
'abcxabcyabcz'.chars.uniq
# => ["a", "b", "c", "x", "y", "z"]
...それから、残っているすべては、彼らのどれくらいがあったかについて調べることですsize :
'abcxabcyabcz'.chars.uniq.size
# => 6
sum 仕上げる
それから最後の部分は、私たちができるすべてのレポートからのすべてのはい答えの合計を得ることですsum :
.map { _1.gsub(/\W/, '').chars.uniq.size }
.sum
...そして、我々の問題の最初の部分が行われます.

日06 -パート02 -これは徹底的です
番目の部分は物事を少し難しくします:それはもはや誰もが質問にyesと答えたが、誰もが持っている.それは、答えられたすべての人のために我々が答えている答えを見つける必要があるすべての人を意味しますintersection .
解決策を見てみましょう.
def answer_intersection(answers) =
  answers
    .lines
    .map { _1.chomp.chars }
    .reduce(&:intersection)
    .size

puts File
  .read(ARGV[0])
  .split(/\n\n/)
  .map { answer_intersection(_1) }
  .sum
chomp the chars我々が交差する答えにしたい最初のことは、我々が使うことができる形式に線をきれいにすることです.通常、1つだけ考えるchars がうまく動作するだろうが、それは今、決定的なyesとしてカウントごとに1つの答えに改行があることを意味しますchomp それは私たちのカウントをスローしないように終了します.
reduce クイックレッスン
今、これは多くのものを行う信じられないほど簡潔なラインです.分からない人にreduce これは旅行ですので、どのように動作するかについての簡単なレッスンから始めましょう.
追加は、最も簡単なリファレンス、および前にsum 私たちはこれをしました.
[1, 2, 3].reduce(0, :+)
# => 6
...この関数は、より明示的な形式を使用する場合に拡張されます.
[1, 2, 3].reduce(0) { |sum, v| sum + v }
# => 6
reduce よく呼ばれるfoldLeft 他の言語では、初期値から始まる左に値を折り畳みます.この場合、0 .
なぜ0 ? それはあなたが戻って同じ番号を取得する任意の数に追加する場合、それはあなたが戻って得る番号がない場合は、サムのための素敵なデフォルトですので0 それは私にとって全く理にかなっているようだ.
ブロック関数についてsum and v . sum アキュムレータと呼ばれることが多いa ) やメモm ) チュートリアルによって異なります.sum , この場合は、0 与えられるreduce(0) . v は反復子、またはコレクション内のすべての値です.
この特定のコードは次のようになります.
[1, 2, 3].reduce(0) { |sum, v| sum + v }
# => 6
...効果的な表現を得たなら、
0 + 1 + 2 + 3
# => 6
の価値観を簡単に見てみましょうreduce . そうですね.sum が最後の反復の結果であり、それを流れる値は以下のようになります.
[1, 2, 3].reduce(0) { |sum, v|
  p(sum: sum, v: v)
  sum + v
}

# {:sum=>0, :v=>1}
# {:sum=>1, :v=>2}
# {:sum=>3, :v=>3}
# => 6
最初の反復では、新しい合計が1 ( 0 + 1 ), 二番目3 ( 1 + 2 ), そして最後になる6 ( 3 + 3 ) これが最終結果です.私たちが親を使うならば、それはあまりにもこのように見えます
(((0 + 1) + 2) + 3)
あなたがより詳細な説明を望むならばreduce チェックアウトしてくださいReducing Enumerable もっと学ぶ.

それでintersection では?
そのコードを見てみましょうreduce then:
.reduce(&:intersection)
初期値はありません.これは、コレクションの最初の項目を減らすことを意味します.
record = [
  ['a', 'b', 'c', 'x'],
  ['a', 'b', 'c', 'y'],
  ['a', 'b', 'c', 'z']
]
If reduce 散在する++ それは同じですintersect . 考慮:
a, b, c = record
a.intersection(b).intersection(c)
# => ["a", "b", "c"]
我々が使用できる許可& これは同じことですが、可能な限り読みやすい方法を好みます.

それはsize 物事の
今、我々はすべての交差点の答えを誰もが私たちはどのようにそれらの多くを得ることができると言うsize , そして、私たちの主な機能ではsum それらのすべての最終的な答えを得るために.

日06ラップ
それは6日目にラップすることについて、我々はこれらの問題の各々を通して働き続けて、次の数日と数週間にわたって彼らの解決と方法論を調査し続けるでしょう.
場合は、元のソリューションのすべてをチェックアウトするthe Github repo 完全にコメントソリューションです.
次号