Skip to content

31. Next Permutation#2

Open
usatie wants to merge 3 commits into
review-basefrom
31/next_permutation
Open

31. Next Permutation#2
usatie wants to merge 3 commits into
review-basefrom
31/next_permutation

Conversation

@usatie

@usatie usatie commented Jan 30, 2025

Copy link
Copy Markdown
Owner

問題 : https://leetcode.com/problems/next-permutation/
言語 : C++
step3をやる際に、念の為ローカルでテストができるようにmain.cppとMakefileも用意しています。


#define T(...) \
({ \
std::cout << #__VA_ARGS__ " -> "; \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

可変引数マクロですね。確かに、そのまま文字列化するならば、こうするしかないですが、逆に変数を引数に与えると
{i, j, k} -> [1,2,3]
と表示されるはずで、これは意図通りなのか、あくまでも、並んでいる数字がみたいのかは考えどころでしょう。
std::initializer_list でもいいですし、可変引数テンプレートでもよいでしょう。

({;;}) は、GCC 拡張だったかと思います。
また、返り値が最後の式の評価になるので、最後の行で cout << endl; すると嵌ります。
https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html

単に {;;} とするのも手ですが、{;;}; と展開されるので、

if () T(); else {}

で事故りそうです。

ラムダの呼び出しに変えるのは一つです。[&]{std::cout << "";}()
古典的な do{}while(0) を使う手もあります。

テスト目的なのでよいという考えもありますが、結構嵌りそうなコードと感じました。

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.

今回は以前使ったことがあったStringizing operator (#)をあまり考えることなく使ってしまいましたが、std::initializer_listという手もあるのですね。
https://learn.microsoft.com/en-us/cpp/preprocessor/stringizing-operator-hash?view=msvc-170
https://en.cppreference.com/w/cpp/preprocessor/replace#.23_and_.23.23_operators
https://en.cppreference.com/w/cpp/utility/initializer_list

返り値が最後の式の評価になってしまうとは知りませんでした。単純にT(){;;};と展開されてしまうのがいやだなーと思っていたのですが、それ以外にも問題があるのですね。複数行マクロの引き出しが増えて、とても勉強になりました。

  • {;;}
  • ラムダ呼び出し
  • do {} while (0)

4. adjacent_findとupper_boundが今回の例にはピッタリ
5. reverse(begin, pivot)としておけば最初に降順ペアが見つからなかった場合にも
正しく動作するのでearly returnしなくても一箇所にまとめられる。
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

https://en.cppreference.com/w/cpp/algorithm/next_permutation
一応こちらに参考実装がございます。

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.

なるほどこんなものが標準ライブラリで提供されていたんですね。

以下のように使えるとchatgptに教えてもらってなるほど、確かにこれがあると使いやすいなと理解できました。

std::vector<int> v = {1, 2, 3};

// まずは v を昇順にソートしておく(これが「最初の順列」)
std::sort(v.begin(), v.end());

// 辞書順ですべての順列を列挙
do {
    // v を使った処理
    // (ここで順列 v を出力したり、何かしらのチェックを行う)
} while (std::next_permutation(v.begin(), v.end()));

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.

以下の二つについても使ったことがなかったので、参考実装を見て勉強になりました。

std::make_reverse_iterator
http://en.cppreference.com/w/cpp/iterator/make_reverse_iterator

std::is_sorted_until
http://en.cppreference.com/w/cpp/algorithm/is_sorted_until

Comment thread Arai60/08. Next Permutation/main.cpp Outdated
@@ -0,0 +1,31 @@
#include "step3.cpp"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

.cpp を include していると、違和感を感じます。実務では、ヘッダーファイルを作成し、それを include し、リンカーでリンクすると思います。仮に .cpp ファイルを include するとしても、かなり特殊なケースだと思いますので、なぜ .cpp を直接 include するか、コメントで説明を付け加えると思います。

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.

ありがとうございます。確かにそうですね。ちょっと面倒だと思ってしまったのですが各ステップのファイルをheaderファイルにして、次回からincludeもそこでやろうと思います。
しかも今気づいたのですが、コミット前にclang-formatでフォーマットをかけてしまった際にinclude順が変わってしまっていて、このままだとコンパイルが通りませんでした。


int tail = nums.size() - 1;
int i, j;
// 1. Find the first ASC pair nums[i] and nums[i+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.

略語は読むにあたり、やや認知負荷が高く感じます。単語はできる限りフルスペルで書いたほうが良いと思います。

NAME = a.out
SRC = main.cpp
CXX = g++
CXXFLAGS = -Wall -Wextra -Werror -std=c++11

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ローカルの実行環境はLeetCodeに合わせるのはどうでしょうか?

clang 19 using the latest C++ 23 standard, and libstdc++ provided by GCC 14.

https://support.leetcode.com/hc/en-us/articles/360011833974-What-are-the-environments-for-the-programming-languages

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.

ありがとうございます。なるほどそういう手がありましたか・・・!やってみます!

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.

自分はローカルの環境構築をdevenv.shで行っているのですが、1時間ほどこの設定にするために時間を溶かしてしまってそれでもまだできなさそうなので、一旦諦めます><

@usatie usatie mentioned this pull request Jan 31, 2025
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.

4 participants