Code Signal -Arcade
코드시그널
아케이드 문제 관련 풀이들을 구글링하면서 찾아가는 일지를 하나씩하나씩 기록하고자 합니당.
주로 자바 위주로 풀이를 올릴예정이고,
추가로 공부하고 있는 파이썬이나 코틀린, GO, 자바스크립트 더 나아가 스위프트까지...
되는대로 가능한대로 구글링하고 정답맞추면 바로 패스!!
이런식으로 좋은 코드이든 말든 짜집기한 결과물들을 개인적 소장을 위해 기록합니다. ^^
참고 사이트들은 아래에 링크로 남겨둘터이니 자세하고 더욱 깊은 내용들은 링크로 들어가보세요!
File Naming
파일 이름 정하기
이 문제는 주어진 파일 명 리스트를 다시 정리해달라는 것입니다.
중복되는 파일명들을 정리해주고, 순차적으로 정리했을때, 중복되는 값은 (n)을 붙여가며 중복처리를 해달라는 문제입니다.
그런데 희한하게 한번해 리스트를 검사해서 중복값을 정리해주는 것이 아닙니다.
한 개씩 요소를 확인해주고 중복되면 (n)을 붙여주고, 이미 (n)을 붙여준 파일명이 또 발겨되면 숫자를 바꾸는 것이아니라 (n)을 또 붙여서 정리해주는 것입니다.
예시를 들어 설명하겠습니다. (저도 뭔말인지 한참 고생했던 기억이 있습니다.)
doc, doc, image, doc(1), doc 순으로 파일명이 있습니다.
먼저 첫번째 doc는 중복이 없으니 doc입니다.
두번째 요소 doc는 1번째 요소와 겹치니 (1)을 붙여줍니다.
image는 그대로.
doc(1) 이녀석 부터 문제입니다. doc(1)이 두번째에 있으니 doc(2)일 줄 알았지만, 그렇지 않고 doc(1)(1)로 설정합니다.
그리고 마지막 doc는 doc(2)로 명칭해줍니다.
즉 한 개씩 검사를 했을 때, 이전의 요소에 겹치는 것이 있다면, 중복값을 구분해주는 것입니다.
긴말 필요없이 코드를 보겠습니다.;;;
String[] fileNaming(String[] names) {
String[] check = Arrays.copyOf(names, names.length);
int n = 1;
for( int i = 1; i < names.length; i++){
for(int j = 0; j<i; j++ ){
if(names[i].equals(names[j]) == true ){
if(names[i] != check[i]){
names[i] = check[i]+"("+n+")";
n++;
j = -1;
continue;
}
n = 1;
names[i] += "("+n+")"; j = -1;
n++;
}
}
}
return names;
}
제 풀이는 반복문이 많아서 알고리즘의 복잡도가 꽤 높습니다;;
일단 코드를 보겠습니다.
먼저, names와 똑같은 배열을 생성해줍니다.
그리고
for( int i = 1; i < names.length; i++){
for(int j = 0; j<i; j++ ){
if(names[i].equals(names[j]) == true ){
if(names[i] != check[i]){
names[i] = check[i]+"("+n+")";
n++;
j = -1;
continue;
}
n = 1;
names[i] += "("+n+")"; j = -1;
n++;
}
}
이 부분을 보면, i는 names의 길이에 맞게 돌아가고, 안의 반복문은 j가 0부터 시작해서 i의 범위 안에서 돌아가게 해줍니다.
이후에, if문을 통해서 중복값이 발견되면, 작업을 해준다고 명령합니다.
if(names[i].equals(names[j]) == true ){
이 다음이 핵심인데요.
크게 두파트로 나눠집니다.
1.
if(names[i] != check[i]){
names[i] = check[i]+"("+n+")";
n++;
j = -1;
continue;
}
이 부분과
2.
n = 1;
names[i] += "("+n+")"; j = -1;
n++;
이 부분입니다.
대부분의 중복값은 2번 파트에 의해서 중복명칭을 붙여줍니다.
여기서 중요한 것은 1번 파트입니다.
좌측 사진을 보면, 원래 names의 명칭을 2번 파트로만 돌리면 아래
이와 같이 나오게 됩니다. 기대되는 결과 값이랑 다르죠?
문제가 여기였습니다.
제 기억에도.
즉, 5번째 요소가 (1)(1)(1) 이 붙어버리고 말아서 답은 doc(2) 되어야 하기 때문입니다.
그렇다면 이 부분을 어떻게 수정할지 고민을 많이 한 결과
1번 파트가 답이 되었습니다.
1번 파트를 다시볼까요.
if(names[i] != check[i]){
names[i] = check[i]+"("+n+")";
n++;
j = -1;
continue;
}
이 부분을 다시 이렇게 적어보면,
if(names[i] != check[i]){
System.out.print(i+": names= "+names[i]+" check= "+check[i]);
names[i] = check[i]+"("+n+")";
n++;
j = -1;
continue;
}
이렇게 출력이 됩니다. Test1 의 경우이죠.
이 출력을 보시면, names의 5번째 요소 doc는 이미 doc(1)로 변경된 것을 알 수 있습니다.
왜냐하면 2번 파트 때문입니다. 2번 파트까지 다 출력을 해보겠습니다.
위의 코드를 다시 이렇게 해보세요.
String[] fileNaming(String[] names) {
String[] check = Arrays.copyOf(names, names.length); //Arrays.copyOf(원본배열, 복사할 길이);
int n = 1;
System.out.println(Arrays.toString(check));
for( int i = 1; i < names.length; i++){
for(int j = 0; j<i; j++ ){
if(names[i].equals(names[j]) == true ){
if(names[i] != check[i]){
System.out.print(i+": names= "+names[i]+" check= "+check[i]);
names[i] = check[i]+"("+n+")";
n++;
j = -1;
continue;
}
n = 1;
System.out.println(i+": names= "+names[i]+" check= "+check[i]);
names[i] += "("+n+")"; j = -1;
n++;
}
}
}
return names;
}
출력 부분이 몇개 추가된거 말고는 차이는 없습니다.
이렇게 하면 콘솔에 출력 되는 것이 보이겠죠?
위와 같이 출력이 됩니다. i = 4일 때, 두번 출력이 됩니다. 뭘까요. 즉 다시 검사하는 원리입니다.
원본인 check를 만든이유가 여기있습니다.
2번 파트는 원래의 형태로 반복되는 부분에 (n)을 세면서 붙여줍니다. 그리고 다시 검사했을때 더이상 중복이 있으면 안되겠죠.
그런데, 마지막 출력, doc(1)와 doc의 차이가 발생하면 값이 변동되게 됩니다.
그래서 저렇게 가정문에 걸리면 파일명을 붙여주는 공식이 다릅니다.
1번 파트는
names[i] = check[i]+"("+n+")";
2번 파트는
names[i] += "("+n+")";
이렇게 다르죠.
1번 파트는 기존의 Check원본을 갔다가 씁니다.
2번 파트는 그렇지 않습니다.
이런식으로 차이가 있습니다.
후.... 저도 설명하면서 뭐라하는지 모르겠지만...
아무튼 반복적으로 검사를 하여 중복값을 명확하게 구분해주는 방법이라고 보시면 됩니다.;;;
별의미 없는 문제 같아요.
이제 엘리트 분들의 답안을 감상하자...
JAVA
Object fileNaming(String[] names) {
List<String> input = Arrays.asList(names);
List<String> result = new ArrayList<>();
for( String s : names ){
if(result.contains(s)){
int i = 1;
for(; result.contains(s+"("+i+")") ;i++){
}
s+="("+i+")";
}
result.add(s);
}
return result;
}
지금 생각해보니 리스트로 푸는게 더 좋아보입니다.. 후.. 저도 수듄이 그리 좋지 않을 때라 방법을 잘 몰랐나봐요
Python3
def fileNaming(names):
for i in range(len(names)):
if names[i] in names[:i]:
j=1
while names[i]+"("+str(j)+")" in names[:i]:
j+=1
names[i]+="("+str(j)+")"
return names
JS
const fileNaming = names => {
const used = {};
return names.map(name => {
let newName = name;
while (used[newName]) {
newName = `${name}(${used[name]++})`;
}
used[newName] = 1;
return newName;
});
};
공감 버튼♥ 눌러주시면 더욱 많은 포스팅을 올리는데 힘이 됩니다!
부탁드려요 돈드는거 아니잖아요~
'Algorithm > Java' 카테고리의 다른 글
#58_Code Signal Arcade >> Message From Binary Code (0) | 2020.07.15 |
---|---|
#56_Code Signal Arcade >> Digits Product (0) | 2020.07.12 |
#55_Code Signal Arcade >> Different Squares (0) | 2020.07.09 |