[Programmers / JAVA] Level 1 New ID Recommendation (72410)
[Programmers / JAVA] Level 1 New ID Recommendation (72410)
| Rank | Language Used |
|---|---|
| Level 1 | 🖼️ JAVA |
Neo, a new developer who joined Kakao, was assigned to the "Kakao Account Development Team" and put in charge of generating IDs for users signing up for Kakao services. Neo's first task was to develop a program that, when a newly signing-up user enters an ID that doesn't meet Kakao's ID rules, recommends a new ID that's similar to the entered ID but follows the rules. Below are the rules for a Kakao ID.
- The ID must be between 3 and 15 characters long.
- The ID may only use lowercase alphabet letters, digits, a hyphen (-), an underscore (_), and a period (.).
- However, a period (.) cannot be used at the beginning or end, and cannot be used consecutively.
Neo plans to check whether a new user's entered ID meets Kakao's ID rules through the following sequential 7-step process, and if it doesn't meet the rules, recommend a new ID that does.
Assuming the ID entered by the new user is new_id,
- Step 1 Replace all uppercase letters in new_id with their corresponding lowercase letters.
- Step 2 Remove all characters from new_id except lowercase alphabet letters, digits, a hyphen (-), an underscore (_), and a period (.).
- Step 3 Replace any sequence of two or more consecutive periods (.) in new_id with a single period (.).
- Step 4 If a period (.) is located at the beginning or end of new_id, remove it.
- Step 5 If new_id is an empty string, assign "a" to new_id.
- Step 6 If the length of new_id is 16 or more, remove all characters except the first 15 characters of new_id.
If, after removal, a period (.) ends up at the end of new_id, remove that trailing period (.) character as well. - Step 7 If the length of new_id is 2 or fewer, repeatedly append the last character of new_id to the end until the length of new_id becomes 3.
For example, if the value of new_id is ...!@BaT#*..y.abcdefghijklm, after going through the 7 steps above, new_id changes as follows.
-
Step 1 The uppercase letters 'B' and 'T' were changed to lowercase 'b' and 't'.
- ...!@BaT#*..y.abcdefghijklm → ...!@bat#*..y.abcdefghijklm
-
Step 2 The characters '!', '@', '#', '*' were removed.
- ...!@bat#*..y.abcdefghijklm → ...bat..y.abcdefghijklm
-
Step 3 '...' and '..' were changed to '.'.
- ...bat..y.abcdefghijklm → .bat.y.abcdefghijklm
-
Step 4 The '.' at the beginning of the ID was removed.
- .bat.y.abcdefghijklm → bat.y.abcdefghijklm
-
Step 5 Since the ID isn't an empty string, there's no change.
- bat.y.abcdefghijklm → bat.y.abcdefghijklm
-
Step 6 Since the length of the ID is 16 or more, everything except the first 15 characters was removed.
- bat.y.abcdefghijklm → bat.y.abcdefghi
-
Step 7 Since the length of the ID isn't 2 or fewer, there's no change.
- bat.y.abcdefghi → bat.y.abcdefghi
Therefore, when the new user's entered new_id is ...!@BaT#*..y.abcdefghijklm, the new ID recommended by Neo's program is bat.y.abcdefghi.
Given new_id, representing the ID entered by a new user, as a parameter, complete the solution function so that it returns the recommended ID after going through the 7-step process designed by Neo.
new_id is a string with a length between 1 and 1,000 inclusive.
new_id consists of uppercase alphabet letters, lowercase alphabet letters, digits, and special characters.
The special characters that can appear in new_id are limited to -_.~!@#$%^&*()=+[{]}:?,<>/.
| No | new_id | result |
|---|---|---|
| 1 | ...!@BaT#*..y.abcdefghijklm | bat.y.abcdefghi |
| 2 | z-+.^. | z-- |
| 3 | =.= | aaa |
| 4 | 123_.def | 123_.def |
| 5 | abcdefghijklmn.p | abcdefghijklmn |
Input/Output Example #1
Same as the problem's example.
Input/Output Example #2
The process by which new_id changes over the 7 steps is as follows.
Step 1 No change.
Step 2 z-+.^. → z-..
Step 3 z-.. → z-.
Step 4 z-. → z-
Step 5 No change.
Step 6 No change.
Step 7 z- → z--
Input/Output Example #3
The process by which new_id changes over the 7 steps is as follows.
Step 1 No change.
Step 2 =.= → .
Step 3 No change.
Step 4 . → new_id becomes an empty string.
Step 5 → a
Step 6 No change.
Step 7 a → aaa
Input/Output Example #4
Through steps 1 to 7, new_id ("123_.def") doesn't change. In other words, new_id already meets Kakao's ID rules from the start.
Input/Output Example #5
Step 1 No change.
Step 2 No change.
Step 3 No change.
Step 4 No change.
Step 5 No change.
Step 6 abcdefghijklmn.p → abcdefghijklmn. → abcdefghijklmn
Step 7 No change.
Since the problem lays out the logic that must be performed at each step, it seems appropriate to design this by separating each step into its own method.
Convert the input string to lowercase.
JAVA
private String step1(String new_id) { return new_id.toLowerCase(); }
Keep only certain characters and remove the rest. You could turn the string into a char[] and use a for loop to compare and remove characters, but using a regular expression makes this much easier and simpler to implement.
JAVA
private String step2(String new_id) { return new_id.replaceAll("[^a-z0-9-_.]", ""); }
- [^] - Inside [], ^ is used to mean negation (NOT)
- [a-z] - lowercase letters
- [0-9] - digits
replaceAll can use a regular expression. With the regex above, we can strip out every character that isn't a lowercase letter, digit, or one of the allowed special characters.
Change ... or .... into a single .. Let's implement this logic easily with a regex as well.
JAVA
private String step3(String new_id) { return new_id.replaceAll("\\.{2,}", "."); }
- .{2,} - two or more periods
Using replaceAll, change any string of two or more consecutive periods into a single period.
Remove a period if there's one at the beginning or end of the string.
JAVA
private String step4(String new_id) { return new_id.replaceAll("^[.]|[.]$", ""); }
- ^ - the beginning of the string. Outside of [], this isn't negation (NOT).
- $ - the end of the string
- | - OR operation
In other words, this is a regex that finds a period at the beginning of the string or a period at the end of the string. Let's use replaceAll to replace it with an empty string.
If the string is empty, assign a. Otherwise, leave it as-is.
JAVA
private String step5(String new_id) { return new_id.equals("") ? "a" : new_id; }
This is the same concept as a character-count limit. However, since truncating the character count could result in a period that was in the middle now ending up at the end, the condition includes reapplying step 4.
For example, the ID aaaaaaaaaaaaaa.a is 16 characters long, and once limited to 15 characters, a period would end up at the end.
JAVA
private String step6(String new_id) { return new_id.length() > 15 ? step4(new_id.substring(0, 15)) : new_id; }
If new_id is longer than 15 characters, use the substring method to cut it to the first 15 characters. Then just call the step4 method we implemented above.
Splitting up the methods by step like this makes them easier to reuse.
For example, for ab, keep appending the last character b until the string reaches 3 characters. The result would be abb.
JAVA
private String step7(String new_id) { int more = 3 - new_id.length(); // If at least one more character is needed if (more > 0) { char last = new_id.charAt(new_id.length() - 1); StringBuilder builder = new StringBuilder(); builder.append(new_id); builder.append(String.valueOf(last).repeat(more)); return builder.toString(); } // If not else { return new_id; } }
Calculate how many more characters are needed to reach 3 characters using more. Then get the last character using charAt.
Use the repeat method to repeat that character more times, then append it to new_id.
For string concatenation operations, I personally prefer to use StringBuilder. Using + works fine too and produces the same result, so use whichever you're comfortable with.
String Concatenation Operator (+) and StringBuilder
In JAVA, the String addition operator is convenient but relatively memory-intensive. Since String is an immutable object, each operation creates a new object and discards the old one.
Using StringBuilder concatenates strings the way we'd expect, requiring relatively fewer resources for the operation.
This was meant to address a problem from the past when JAVA's level of optimization and computer performance weren't great; of course, JAVA has since undergone a lot of optimization, and computer performance has improved thousands of times over, so you don't need to worry about this too much these days.
JAVA
/** * New ID Recommendation class * * @author RWB * @since 2021.12.07 Tue 00:47:16 */ class Solution { /** * Method that returns the answer * * @param new_id: [String] The new ID * * @return [String] The answer */ public String solution(String new_id) { String answer = step1(new_id); answer = step2(answer); answer = step3(answer); answer = step4(answer); answer = step5(answer); answer = step6(answer); answer = step7(answer); return answer; } /** * Method that returns the step 1 result * Replace all uppercase letters with lowercase * * @param new_id: [String] The new ID * * @return [String] The step 1 result */ private String step1(String new_id) { return new_id.toLowerCase(); } /** * Method that returns the step 2 result * Remove characters other than lowercase letters, digits, hyphen (-), underscore (_), and period (.) * * @param new_id: [String] The new ID * * @return [String] The step 2 result */ private String step2(String new_id) { return new_id.replaceAll("[^a-z0-9-_.]", ""); } /** * Method that returns the step 3 result * Replace two or more consecutive periods with a single period * * @param new_id: [String] The new ID * * @return [String] The step 3 result */ private String step3(String new_id) { return new_id.replaceAll("\\.{2,}", "."); } /** * Method that returns the step 4 result * Remove a period if it's at the very beginning or end * * @param new_id: [String] The new ID * * @return [String] The step 4 result */ private String step4(String new_id) { return new_id.replaceAll("^[.]|[.]$", ""); } /** * Method that returns the step 5 result * Assign a if the string is empty * * @param new_id: [String] The new ID * * @return [String] The step 5 result */ private String step5(String new_id) { return new_id.equals("") ? "a" : new_id; } /** * Method that returns the step 6 result * If 16 characters or more, truncate to 15 characters. If a period ends up at the end, remove it * * @param new_id: [String] The new ID * * @return [String] The step 6 result */ private String step6(String new_id) { return new_id.length() > 15 ? step4(new_id.substring(0, 15)) : new_id; } /** * Method that returns the step 7 result * If 2 characters or fewer, append the last character until the length becomes 3 * * @param new_id: [String] The new ID * * @return [String] The step 7 result */ private String step7(String new_id) { int more = 3 - new_id.length(); // If at least one more character is needed if (more > 0) { char last = new_id.charAt(new_id.length() - 1); StringBuilder builder = new StringBuilder(); builder.append(new_id); builder.append(String.valueOf(last).repeat(more)); return builder.toString(); } // If not else { return new_id; } } }
That's the full code.
If you have a basic understanding of regular expressions, this can be solved easily, but if not, you'll have to go through a somewhat tedious process.
