-
Notifications
You must be signed in to change notification settings - Fork 0
929. unique email addresses #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| { | ||
| "files.associations": { | ||
| "string": "cpp", | ||
| "string_view": "cpp" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| # step1 | ||
| 愚直に@の手前までは"."を無視して"+"が出現したら後は入れないとし、@発見後はそのままコピーし構築する方法。 | ||
|
|
||
| 他にあるとしたら正規表現とか? | ||
| ```cpp | ||
| #include <set> | ||
| #include <vector> | ||
|
|
||
| class Solution { | ||
| public: | ||
| int numUniqueEmails(std::vector<std::string>& emails) { | ||
| std::set<std::string> result; | ||
| for (const auto& email : emails) { | ||
| std::string normalized_email; | ||
|
|
||
| auto it = email.begin(); | ||
| bool findplus = false; | ||
| while (*it != '@') { | ||
| if (findplus) { | ||
| ++it; | ||
| continue; | ||
| } | ||
| if (*it == '.') { | ||
| ++it; | ||
| continue; | ||
| } | ||
| if (*it == '+') { | ||
| findplus = true; | ||
| ++it; | ||
| continue; | ||
| } | ||
| normalized_email.push_back(*it); | ||
| ++it; | ||
| } | ||
|
|
||
| while (it != email.end()) { | ||
| normalized_email.push_back(*it); | ||
| ++it; | ||
| } | ||
| result.insert(std::move(normalized_email)); | ||
| } | ||
| return result.size(); | ||
| } | ||
| }; | ||
| ``` | ||
|
|
||
| # step2 | ||
| STLの文字列の機能を使った実装 | ||
| ```cpp | ||
| #include <algorithm> | ||
| #include <set> | ||
| #include <vector> | ||
|
|
||
| class Solution { | ||
| public: | ||
| int numUniqueEmails(std::vector<std::string>& emails) { | ||
| std::set<std::string> seen; | ||
| for (const auto& email : emails) { | ||
| seen.insert(std::move(normalize_email(email))); | ||
| } | ||
| return seen.size(); | ||
| } | ||
| private: | ||
| std::string normalize_email(const std::string& email) { | ||
| auto at_position = email.find('@'); | ||
| auto local = email.substr(0, at_position); | ||
| auto at_domain = email.substr(at_position); | ||
| if (auto plus_position = local.find('+'); plus_position != std::string::npos) { | ||
| local.resize(plus_position); | ||
| } | ||
| // C++20以降ではstd::erase(local, '.');でも可 | ||
| local.erase(std::remove(local.begin(), local.end(), '.'), local.end()); | ||
| return local + at_domain; | ||
| } | ||
| }; | ||
|
|
||
| ``` | ||
| あるいはをやや不自然な感じもするがrangesを使った実装 | ||
| ```cpp | ||
| #include <ranges> | ||
| #include <set> | ||
| #include <vector> | ||
|
|
||
| class Solution { | ||
| public: | ||
| int numUniqueEmails(std::vector<std::string>& emails) { | ||
| std::set<std::string> seen; | ||
| for (const auto& email : emails) { | ||
| auto name_ranges = email | std::views::split('@'); | ||
| auto it = name_ranges.begin(); | ||
| auto local_range = *it; | ||
| auto domain_range = *(++it); | ||
| auto filtered_local_range = local_range | std::views::take_while([](const auto c) { return c != '+'; }) | | ||
| std::views::filter([](const auto c) { return c != '.'; }); | ||
| std::string processed_email = std::ranges::to<std::string>(filtered_local_range); | ||
| processed_email += '@'; | ||
| processed_email += std::ranges::to<std::string>(domain_range); | ||
| seen.insert(std::move(processed_email)); | ||
| } | ||
| return seen.size(); | ||
| } | ||
| }; | ||
|
|
||
| ``` | ||
|
|
||
| ## 他の人のPRを読む | ||
| - https://github.com/shintaroyoshida20/leetcode/tree/feature/hash-map/unique-email-addresses | ||
| ちゃんと入力が正しいことをチェックすると大変そう。RFCは気になったときに目を通したい… | ||
| 異常系も考慮するなら、ユーザーの入力のバリデーションの場面なら例外を投げてやり直させる/データ処理の場面なら不適データは無視する、といった形にする気がする。 | ||
| - 整理できていなかったが、Pythonではstr1+=cとしたときに元の文字列の再構築が起きるためループで順次足すのはまずいが、C++では問題ない。https://github.com/Ryotaro25/leetcode_first60/pull/15/files#r1641792391 | ||
| >C++ は、文字列は mutable なので特に問題はないです。Java、Python は immutable です。 | ||
| ちなみに、こういうのはよく知らない言語を触るときに一番初めに確認することの一つです。 | ||
|
|
||
|
|
||
| # step3 | ||
| ```cpp | ||
| #include <set> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| class Solution { | ||
| public: | ||
| int numUniqueEmails(const std::vector<std::string>& emails) { | ||
| std::set<std::string> seen; | ||
| for (const auto& email : emails) { | ||
| seen.insert(std::move(normalized_email(email))); | ||
| } | ||
| return seen.size(); | ||
| } | ||
| private: | ||
| std::string normalized_email(const std::string& email) { | ||
| auto at_position = email.find('@'); | ||
| auto local = email.substr(0, at_position); | ||
| auto at_domain = email.substr(at_position); | ||
| if (auto plus_position = local.find('+'); plus_position != std::string::npos) { | ||
| local.resize(plus_position); | ||
| } | ||
| std::erase(local, '.'); | ||
| return local + at_domain; | ||
| } | ||
| }; | ||
|
Comment on lines
+130
to
+141
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ここを関数に切り出すのは賛成です。
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. コメントありがとうございます。IDEの補助がないとつらいときに補助的にファイルを作っていたのですがレビューワーから見るとわかりにくいですね。紛らわしくならないように気を付けます |
||
| ``` | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| #include <algorithm> | ||
| #include <set> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| class Solution { | ||
| public: | ||
| int numUniqueEmails(std::vector<std::string>& emails) { | ||
| std::set<std::string> seen; | ||
| for (const auto& email : emails) { | ||
| seen.insert(normalize_email(email)); | ||
| } | ||
| return seen.size(); | ||
| } | ||
|
|
||
| private: | ||
| std::string normalize_email(const std::string& email) { | ||
| auto at_position = email.find('@'); | ||
| auto local = email.substr(0, at_position); | ||
| auto at_domain = email.substr(at_position); | ||
| if (auto plus_position = local.find('+'); plus_position != std::string::npos) { | ||
| local.resize(plus_position); | ||
| } | ||
| local.erase(std::remove(local.begin(), local.end(), '.'), local.end()); | ||
|
|
||
| return local + at_domain; | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #include <ranges> | ||
| #include <set> | ||
| #include <vector> | ||
|
|
||
| class Solution { | ||
| public: | ||
| int numUniqueEmails(std::vector<std::string>& emails) { | ||
| std::set<std::string> seen; | ||
| for (const auto& email : emails) { | ||
| auto name_ranges = email | std::views::split('@'); | ||
| auto it = name_ranges.begin(); | ||
| auto local_range = *it; | ||
| auto domain_range = *(++it); | ||
| auto filtered_local_range = local_range | std::views::take_while([](const auto c) { return c != '+'; }) | | ||
| std::views::filter([](const auto c) { return c != '.'; }); | ||
| std::string processed_email = std::ranges::to<std::string>(filtered_local_range); | ||
| processed_email += '@'; | ||
| processed_email += std::ranges::to<std::string>(domain_range); | ||
| seen.insert(processed_email); | ||
| } | ||
| return seen.size(); | ||
| } | ||
| }; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 後学のため、問題文+例+制約を読んでから、どのように道筋を立てたか教えて頂けないでしょうか?
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Apo-Matchbox
といった思考プロセスだったかと思います。 まとめると、
この問題の場合一次元的で図にするほどでもないですが、グラフやグリッド(二次元座標)、場合分けや状態遷移があるとき、問題文が複雑…などは図を書くのは大変有効です。 制約は問題文の状況をspecifyする要素ですが、実際の面接試験などでは面接官とコミュニケーションをして把握するものらしいですし、実際の業務でもどのような入力がありうるか?どれくらいの処理時間で終わらせないといけないか?どいういったインターフェースにするか?というのは所与の要素というより適宜考えてデザインしていかないといけないものかと思います。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @maeken4 問題の主旨と解答、他の方法を考えたりとしてますが、解法が出てこないですね。
少しずつ、知識と選択肢と出来る事を増やしていくシンプルな事でしか解決しないですね。 |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
比較目的で正規化する場合は Canonicalize と言うようです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
コメントありがとうございます。確かに「データを正規化する」とった文脈とは意味合いが違いますね。