Skip to content

514 paint fence#30

Open
tarinaihitori wants to merge 3 commits intomainfrom
514-paint-fence
Open

514 paint fence#30
tarinaihitori wants to merge 3 commits intomainfrom
514-paint-fence

Conversation

@tarinaihitori
Copy link
Copy Markdown
Owner

元の問題(有料)
https://leetcode.com/problems/paint-fence/description/

https://www.lintcode.com/problem/514/

Description
There is a fence with n posts, each post can be painted with one of the k colors.
You have to paint all the posts such that no more than two adjacent fence posts have the same color.
Return the total number of ways you can paint the fence.

n and k are non-negative integers.


小田さんのコメントで、自分で実装できるならキャッシュなどのライブラリを使ってもよいとあるので、
こういうのは自分で実装できるようにならないといけないんだろうなというところで、自分でキャッシュを実装してみる。
まずデコレータをどう作るのかから手間取った。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

デコレーターは要は高階関数ということですね。

return ways_to_paint[n]
```

結局1つ前と同じ色で塗るか、違う色で塗るかの違いなので、配列ではなく
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

私は、これが分類として一番素直だと感じます。人によるでしょうが。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maximum Product Subarrayの話( https://discord.com/channels/1084280443945353267/1196498607977799853/1358753010670637149 の周辺)を見ていたときも思ったのですが、odaさんは再帰で引き継ぐ最小の条件を特によく考えているような印象があります。(私個人の感覚としては、より純粋数学に近いイメージです。メモリを保持して塗り替えていく・埋めていくというよりは、ある式に従って引き継ぎながら計算をするというような。もちろん、最小の引き継ぎ対象が結果的に配列になるケースもありますが。)

return count_ways(n)
```

あと、この関数が2回呼ばれたときどうなるのかついて、
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あっていると思います。以下の認識です。

同一インスタンス&num_ways呼び出し:
→ 毎回index_to_waysが初期化されるため前回のメモ化データは保持されない

同一インスタンス&count_ways呼び出し:
→ メモ化がが保持される

異なるインスタンス:
→ メモ化されたデータは共有されない

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます!

return k
if index == 2:
return k * k
index_to_ways[index] = (k-1) * (count_ways(index -1) + count_ways(index - 2))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

k-1
index -1
index - 2

- の前後の空白有無がバラバラなので統一した方がいいと思います。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この辺の意識抜けていました。気を付けます。

cache = LRU_Cache(maxsize)
def wrap(*args, **kwargs):
result = cache.get(args)
if result is not None:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

今回の場合は問題ないんですが、結果がNoneになる場合はこの判定が使えないので、一般の場合ではargs in cacheに相当する条件で判定したいですね。(ただ、このcacheがdictではないので、そのための実装が必要になってしまうのと、普通はキャッシュする関数は値を返すことがほとんどだとは思いますが)



def _lru_cache_wrapper(func, maxsize):
cache = LRU_Cache(maxsize)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このmaxsizeとcapacityの語は統一してもいいかなという気がしました。


def lru_cache(maxsize=1):
def decorating_function(func):
nonlocal maxsize
Copy link
Copy Markdown

@sasanquaneuf sasanquaneuf Apr 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nonlocalがあると若干身構えるなあと思って改善を考えていたのですが、この場合maxsizeのチェックと代入をシンプルに関数定義の上に出すのがよいですか?
こちらでやった方がよい理由はなにかあるでしょうか。

class LRU_Cache:
def __init__(self, capacity):
self.capacity = capacity
self.size = 0
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

size == len(self.cache)だと思うので、sizeは保持しないほうがすっきりするかもしれません。

next_node.prev = node
self.size += 1
self.cache[key] = node
if self.size > self.capacity:
Copy link
Copy Markdown

@sasanquaneuf sasanquaneuf Apr 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

今回は動的にcapacityが変わることはないと思いますが、なんとなくwhile self.size > self.capacity:のほうが良いかなと思いました。

return ways_to_paint[n]
```

結局1つ前と同じ色で塗るか、違う色で塗るかの違いなので、配列ではなく
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maximum Product Subarrayの話( https://discord.com/channels/1084280443945353267/1196498607977799853/1358753010670637149 の周辺)を見ていたときも思ったのですが、odaさんは再帰で引き継ぐ最小の条件を特によく考えているような印象があります。(私個人の感覚としては、より純粋数学に近いイメージです。メモリを保持して塗り替えていく・埋めていくというよりは、ある式に従って引き継ぎながら計算をするというような。もちろん、最小の引き継ぎ対象が結果的に配列になるケースもありますが。)

class Solution:
@lru_cache(maxsize=None)
def num_ways(self, n: int, k: int) -> int:
if n == 0 or k ==0:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

==0 の間にスペースを空けることをお勧めいたします。


2nd
1を読みやすくする。
cacheして少し効率化した。とはいえrangeの中に3などのハードコードされた値があるのが気持ち的にいやだなあ。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

認識されていたら申し訳ないのですが、cacheとlru_cacheは別物です

https://docs.python.org/ja/3.13/library/functools.html

ways_to_paint_different_color = (ways_to_paint_same_color + ways_to_paint_different_color) * (k -1)
ways_to_paint_same_color = temp
return ways_to_paint_different_color + ways_to_paint_same_color

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

自分はこの解答が好みでした。
直近の2つの状態だけもっていればよいので、dpといえど配列で管理していく必要はないのですよね。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

私はdpテーブルでやってしまっていましたが、自然言語で表現すると、2変数なのがしっくりときますね。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants