diff --git a/6. Zigzag Conversion/6. Zigzag Conversion.md b/6. Zigzag Conversion/6. Zigzag Conversion.md new file mode 100644 index 0000000..e255379 --- /dev/null +++ b/6. Zigzag Conversion/6. Zigzag Conversion.md @@ -0,0 +1,90 @@ +# 6. Zigzag Conversion +## STEP1 +- 何も見ずに解いてみる +- 言われたことをやる。numRows が 1 の時は先に処理しておくとよさそう。 +- 最終行をよりよく書く方法があるかわからない。 +```python +class Solution: + def convert(self, s: str, numRows: int) -> str: + if numRows == 1: + return s + + row_to_letters = [[] for _ in range(numRows)] + direction = 1 # 1: going down, -1: going up + row_index = 0 + for letter in s: + row_to_letters[row_index].append(letter) + if row_index == 0 and direction == -1: + direction = 1 + elif row_index == numRows - 1 and direction == 1: + direction = -1 + row_index += direction + return "".join("".join(row) for row in row_to_letters) +``` +- 行の位置は計算できる。こちらの方がわかりやすいと思う人もいそう。 +```python +class Solution: + def convert(self, s: str, numRows: int) -> str: + if numRows == 1: + return s + + row_to_letters = [[] for _ in range(numRows)] + num_letters_in_cycle = 2 * numRows - 2 + for i, letter in enumerate(s): + position_in_cycle = i % num_letters_in_cycle + if position_in_cycle < numRows: + row_index = position_in_cycle + else: + row_index = num_letters_in_cycle - position_in_cycle + row_to_letters[row_index].append(letter) + return "".join("".join(row) for row in row_to_letters) +``` + +## STEP2 +### プルリクやドキュメントを参照 +- https://github.com/olsen-blue/Arai60/pull/61/files + - 進む方向をフラグで管理する書き方もある。たしかに、STEP1で書いた direction は方向だけと読まれる可能性あり。step はありかも。 +- https://github.com/olsen-blue/Arai60/pull/61/files#r2040670667 + - itertools.batched を使った面白解法。 + - https://docs.python.org/3/library/itertools.html#itertools.batched +- https://github.com/olsen-blue/Arai60/pull/61/files#r2042314581 + - 以下の二つは同じ + `"".join("".join(row_chars) for row_chars in rows)` + `"".join(c for row_chars in rows for c in row_chars)` + - for の順番にあまり納得がいかない。 + - https://docs.python.org/3/reference/expressions.html#generator-expressions をみると以下のよう。 + +generator_expression ::= "(" expression comp_for ")" +comp_for ::= ["async"] "for" target_list "in" or_test [comp_iter] +comp_iter ::= comp_for | comp_if + +当てはめると +(1) c (2) for (3) row_chars (4) in (5) rows (6) for c in row_chars +(1) expression (2)"for" (3) target_list (4) "in" (5) or_test (6) comp_iter +のように読まれるので前の for が外側の for になる。全て追えていないがおそらく expression には comp_iter は含まれないため、逆の解釈はできない。 + +- https://github.com/hayashi-ay/leetcode/pull/71/files + - 4th の方向管理はシンプルでいいですね。 + - row_index を先に進めてから、方向の反転をすればよい。 + +## STEP3 +### 3回ミスなく書く +```python +class Solution: + def convert(self, s: str, numRows: int) -> str: + if numRows == 1: + return s + + row_to_letters = [[] for _ in range(numRows)] + row_index = 0 + direction = 1 + for letter in s: + row_to_letters[row_index].append(letter) + row_index += direction + if row_index == 0 or row_index == numRows - 1: + direction *= -1 + return "".join(c for row in row_to_letters for c in row) +``` +練習として書いていて思ったが、Generator Comprehension の nest は書きにくいし読みにくい。 + +3分,2分,2分で3回Accept