diff --git a/779. K-th Symbol in Grammar/779. K-th Symbol in Grammar.md b/779. K-th Symbol in Grammar/779. K-th Symbol in Grammar.md new file mode 100644 index 0000000..36f6e85 --- /dev/null +++ b/779. K-th Symbol in Grammar/779. K-th Symbol in Grammar.md @@ -0,0 +1,97 @@ +# 779. K-th Symbol in Grammar +## STEP1 +- 何も見ずに解いてみる +- 行数を一つずつ減らしていく。ある行において、文字列の前半にいたら index をそのままに行数を -1 して良い。文字列の後半にいたら、index から文字列の半分の長さを引き、0と1を反転させた回数を +1 し行数を -1 する。 +- 他の問題より不正な入力が入りやすいと思ったので、チェックしたい。 +- 書いている段階では明確に整理できていなかったので、読み返すとコードが読みにくい。 + +```python +class Solution: + def kthGrammar(self, n: int, k: int) -> int: + n -= 1 + k -= 1 + + if n == 0: + if k != 0: + raise ValueError("invalid input") + return 0 + + num_symbols = 2 ** n + count = 0 + while num_symbols >= 2: + if not 0 <= k < num_symbols: + raise ValueError("invalid input") + num_symbols //= 2 + if k >= num_symbols: + count += 1 + k -= num_symbols + if count % 2 == 0: + return 0 + else: + return 1 +``` + +## STEP2 +### プルリクやドキュメントを参照 +- https://github.com/olsen-blue/Arai60/pull/47/files#diff-da439603310f08640b8dab0ec6cfc15251b5669e04e4effc5795dbe1f506a8daR43 + - k の偶奇での場合分けは気が付かなかった。局所的な関係性で考えるパターン。 + - k % 2 で場合分けするならば、(k+1) // 2 について k // 2 で良い場合は使い分けたい気がする。下記のように if 文の外に置くのであれば当然 (k+1) // 2 でないといけない。 + +```python +class Solution: + def kthGrammar(self, n: int, k: int) -> int: + if n == 0: + return 0 + + previous_symbol = self.kthGrammar(n - 1, (k + 1) // 2) + if k % 2 == 0: + return 1 - previous_symbol + else: + return previous_symbol +``` +- https://github.com/olsen-blue/Arai60/pull/47/files#diff-da439603310f08640b8dab0ec6cfc15251b5669e04e4effc5795dbe1f506a8daR65 + - よくみると n ではなく k に注目しても良いことがわかる +- https://github.com/fuga-98/arai60/pull/46/files + - k のビットを考える方法。これは綺麗だけど思いつきにくい。 + - https://docs.python.org/3/library/stdtypes.html#int.bit_count +```python +class Solution: + def kthGrammar(self, n: int, k: int) -> int: + return (k - 1).bit_count() % 2 +``` + +- 色々な実装パターンがあるが以下が一番理解しやすいと感じた。 +```python +class Solution: + def kthGrammar(self, n: int, k: int) -> int: + if n < 0: + raise ValueError("n must be positive.") + if not 1 <= k <= 2 ** (n - 1): + raise ValueError("k is out of range") + + result = 0 + while k > 1: + if k % 2 == 0: + result = 1 - result + k = (k + 1) // 2 + return result +``` +## STEP3 +### 3回ミスなく書く +```python +class Solution: + def kthGrammar(self, n: int, k: int) -> int: + if n < 0: + raise ValueError("n must be positive") + if not 1<= k <= 2 ** (n - 1): + raise ValueError("k is out of range") + + result = 0 + while k > 1: + if k % 2 == 0: + result = 1 - result + k = (k + 1) // 2 + return result +``` + +3分,2分,2分で3回Accept