From 2464b686954771ea530b75f129d0cfe4f966b4a6 Mon Sep 17 00:00:00 2001 From: kazukiii Date: Tue, 18 Jun 2024 14:39:42 -0700 Subject: [PATCH 1/2] =?UTF-8?q?step1,=20step2,=20step3=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arai60/unique-email-addresses/README.md | 33 +++++++++++++++++++++++ arai60/unique-email-addresses/step1.py | 9 +++++++ arai60/unique-email-addresses/step2.py | 20 ++++++++++++++ arai60/unique-email-addresses/step2_re.py | 10 +++++++ arai60/unique-email-addresses/step3.py | 19 +++++++++++++ 5 files changed, 91 insertions(+) create mode 100644 arai60/unique-email-addresses/README.md create mode 100644 arai60/unique-email-addresses/step1.py create mode 100644 arai60/unique-email-addresses/step2.py create mode 100644 arai60/unique-email-addresses/step2_re.py create mode 100644 arai60/unique-email-addresses/step3.py diff --git a/arai60/unique-email-addresses/README.md b/arai60/unique-email-addresses/README.md new file mode 100644 index 0000000..92ef87c --- /dev/null +++ b/arai60/unique-email-addresses/README.md @@ -0,0 +1,33 @@ +## 考察 +- 初見の問題 +- 方針 + - 文字列操作してHashSetに追加すればよさそう + - C++にはたしかsplitがなかったはずなので、Pythonでやる + - 文字列操作の代わりに正規表現でも出来そう + - ソラでは書ける自信がない(書けるようになっておいた方がいい?) + - 後ほど、調べながらやる + - time: O(nm), space: O(nm) + - n: emails.length, m: max_i(emails[i].length) +- あとは実装 + +## Step1 +- splitとreplaceを使った +- time: O(nm), space: O(nm) + +## Step2 +- まずは正規表現でもやってみる -> `step2_re.py` +- 他の人のPRを検索 + - splitしてからreplaceした方が効率が良い + - Ref. https://github.com/Mike0121/LeetCode/pull/31#discussion_r1642845600 + - 各emailに対する処理は関数化した方がわかりやすいかも + - Ref. https://github.com/SuperHotDogCat/coding-interview/pull/30/files#r1641769186 + - 正規表現について + - Ref. https://github.com/fhiyo/leetcode/pull/17#discussion_r1629618002 + +- 上記を元に各操作を関数化して組み合わせる書き方に修正した +- local_nameとdomain_nameの組み合わせをtupleで表現した + +## Step3 +- 1回目: 2m19s +- 2回目: 2m15s +- 3回目: 2m02s diff --git a/arai60/unique-email-addresses/step1.py b/arai60/unique-email-addresses/step1.py new file mode 100644 index 0000000..755a3c9 --- /dev/null +++ b/arai60/unique-email-addresses/step1.py @@ -0,0 +1,9 @@ +class Solution: + def numUniqueEmails(self, emails: List[str]) -> int: + unique_emails = set() + for email in emails: + local_name, domain_name = email.split('@') + formatted_local_name = local_name.replace('.', '').split('+')[0] + unique_emails.add(formatted_local_name + '@' + domain_name) + + return len(unique_emails) diff --git a/arai60/unique-email-addresses/step2.py b/arai60/unique-email-addresses/step2.py new file mode 100644 index 0000000..01d34cb --- /dev/null +++ b/arai60/unique-email-addresses/step2.py @@ -0,0 +1,20 @@ +class Solution: + def numUniqueEmails(self, emails: List[str]) -> int: + unique_emails = set() + for email in emails: + local_name, domain_name = email.split('@') + unique_emails.add(( + self.clean_local_name(local_name), + domain_name, + )) + + return len(unique_emails) + + def clean_local_name(self, local_name): + return self.remove_all_dots(self.remove_after_plus(local_name)) + + def remove_all_dots(self, text): + return text.replace('.', '') + + def remove_after_plus(self, text): + return text.split('+')[0] diff --git a/arai60/unique-email-addresses/step2_re.py b/arai60/unique-email-addresses/step2_re.py new file mode 100644 index 0000000..668147d --- /dev/null +++ b/arai60/unique-email-addresses/step2_re.py @@ -0,0 +1,10 @@ +class Solution: + def numUniqueEmails(self, emails: List[str]) -> int: + unique_emails = set() + for email in emails: + local_name, domain_name = email.split('@') + local_name = re.sub(r'\+.*', '', local_name) + local_name = re.sub(r'\.', '', local_name) + unique_emails.add(local_name + '@' + domain_name) + + return len(unique_emails) diff --git a/arai60/unique-email-addresses/step3.py b/arai60/unique-email-addresses/step3.py new file mode 100644 index 0000000..c94d89c --- /dev/null +++ b/arai60/unique-email-addresses/step3.py @@ -0,0 +1,19 @@ +class Solution: + def numUniqueEmails(self, emails: List[str]) -> int: + unique_emails = set() + for email in emails: + local_name, domain_name = email.split('@') + unique_emails.add(( + self.clean_local_name(local_name), + domain_name, + )) + return len(unique_emails) + + def clean_local_name(self, local_name): + return self.remove_all_dots(self.remove_after_plus(local_name)) + + def remove_all_dots(self, text): + return text.replace('.', '') + + def remove_after_plus(self, text): + return text.split('+')[0] From 2c0e6fded231f5461127dd553d12220e109e513c Mon Sep 17 00:00:00 2001 From: kazukiii Date: Wed, 19 Jun 2024 13:38:06 -0700 Subject: [PATCH 2/2] =?UTF-8?q?step4=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- arai60/unique-email-addresses/README.md | 7 +++++++ arai60/unique-email-addresses/step4.py | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 arai60/unique-email-addresses/step4.py diff --git a/arai60/unique-email-addresses/README.md b/arai60/unique-email-addresses/README.md index 92ef87c..ec50d44 100644 --- a/arai60/unique-email-addresses/README.md +++ b/arai60/unique-email-addresses/README.md @@ -31,3 +31,10 @@ - 1回目: 2m19s - 2回目: 2m15s - 3回目: 2m02s + +## Step4 +- レビューを元に修正 +- privateメソッド相当のものには先頭に _ を付与 +- メソッド名の見直し + - `claen_local_name` -> `_normalize_local_name` + - `remove_after_plus` -> `_remove_plus_and_after` diff --git a/arai60/unique-email-addresses/step4.py b/arai60/unique-email-addresses/step4.py new file mode 100644 index 0000000..060fbb2 --- /dev/null +++ b/arai60/unique-email-addresses/step4.py @@ -0,0 +1,19 @@ +class Solution: + def numUniqueEmails(self, emails: List[str]) -> int: + unique_emails = set() + for email in emails: + local_name, domain_name = email.split('@') + unique_emails.add(( + self._normalize_local_name(local_name), + domain_name, + )) + return len(unique_emails) + + def _normalize_local_name(self, local_name): + return self._remove_all_dots(self._remove_plus_and_after(local_name)) + + def _remove_all_dots(self, text): + return text.replace('.', '') + + def _remove_plus_and_after(self, text): + return text.split('+')[0]