Загружаем каталог…
Загружаем каталог…
오늘의 할일 코드카타 정리 세션 정리 코드카타 정리 1. 옹알이 (2) 문제 설명 머쓱이는 태어난 지 11개월 된 조카를 돌보고 있습니다. 조카는 아직 "aya", "ye", "woo", "ma" 네 가지 발음과 네 가지 발음을 조합해서 만들 수 있는 발음밖에 하지 못하고 연속해서 같은 발음을 하는 것을 어려워합니다. 문자열 배열 babbling이 매개변수로 주어질 때, 머쓱이의 조카가 발음할 수 있는 단어의 개수를 return하도록 solution 함수를 완성해주세요. #include <string> #include <vector> using namespace std; int solution(vector<string> babbling) { int answer = 0; for (int i = 0; i < babbling.size(); i++) { string word = babbling[i]; int pos = 0; // 현재 읽고 있는 글자의 위치 int prev_sound = 0; // 방금 낸 소리를 기억할 변수 (0: 없음, 1: aya, 2: ye, 3: woo, 4: ma) bool is_valid = true; // 이 단어를 발음할 수 있는지 체크 // 단어 끝까지 계속 글자를 확인 while (pos < word.length()) { // 현재 위치에서 3글자를 잘랐을 때 aya고 방금 낸 소리가 aya(1)가 아니면 if (word.substr(pos, 3) == "aya" && prev_sound != 1) { prev_sound = 1; // 방금 낸 소리를 "aya"로 업데이트 pos += 3; // 3글자를 읽었으니 위치를 3칸 앞으로 이동 } // 현재 위치에서 2글자를 잘랐을 때 ye고, 방금 낸 소리가 ye(2)가 아니면 else if (word.substr(pos, 2) == "ye" && prev_sound != 2) { prev_sound = 2; pos += 2; } // 현재 위치에서 3글자를 잘랐을 때 woo고 방금 낸 소리가 woo(3)가 아니면 else if (word.substr(pos, 3) == "woo" && prev_sound != 3) { prev_sound = 3; pos += 3; } // 현재 위치에서 2글자를 잘랐을 때 ma고 방금 낸 소리가 ma(4)가 아니면 else if (word.substr(pos, 2) == "ma" && prev_sound != 4) { prev_sound = 4; pos += 2; } // 네 가지 소리 중 아무것도 아니거나, 연속된 소리라서 발음할 수 없는 경우 else { is_valid = false; // 불합격 처리 break; } } // 단어를 끝까지 읽고 불합격 판정을 받지 않았다면 if (is_valid) { answer++; } } return answer; } AI가 작성한 코드 #include <string> #include <vector> using namespace std; int solution(vector<string> babbling) { int answer = 0; // 1. 하드코딩된 if-else를 없애고, 발음 사전을 정적 배열로 분리합니다. const string sounds[4] = {"aya", "ye", "woo", "ma"}; // 2. 값 복사를 방지하기 위해 const string& (상수 참조)로 단어를 읽어옵니다. for (const string& word : babbling) { int pos = 0; int prev_sound = -1; bool is_valid = true; while (pos < word.length()) { bool matched = false; // 3. 4개의 발음 사전을 돌며 현재 글자와 일치하는지 확인합니다. for (int i = 0; i < 4; i++) { // substr 대신 compare 함수를 사용하여 메모리 할당 없이 글자를 비교합니다. if (word.compare(pos, sounds[i].length(), sounds[i]) == 0) { if (prev_sound == i) { // 연속 발음 체크 is_valid = false; break; } prev_sound = i; pos += sounds[i].length(); matched = true; break; // 일치하는 발음을 찾았으니 사전 검색을 멈춥니다. } } // 4. 사전에 있는 4가지 발음 중 어떤 것과도 일치하지 않거나, 연속 발음으로 판정된 경우 if (!matched || !is_valid) { is_valid = false; break; } } // 끝까지 무사히 파싱(Parsing)을 마쳤다면 정답 처리합니다. if (is_valid) { answer++; } } return answer; } substr 소멸과 compare 도입 (Zero-Allocation): 이전 코드의 word.substr()은 호출될 때마다 힙(Heap) 메모리에 새로운 문자열 덩어리를 잘라서 계속 생성합니다. 만약 몬스터 AI나 전투 시스템이 매 프레임마다 이런 문자열 자르기를 수행한다면 심각한 메모리 파편화와 프레임 드랍이 발생합니다. 반면 word.compare(시작점, 길이, 비교할단어)는 원본 문자열을 건드리지 않고 '눈으로만' 빠르게 비교하고 넘어가므로 메모리 할당(동적 할당) 비용이 '0'입니다. const string& 참조자 사용: for (string word : babbling) 처럼 쓰면 배열 안의 단어를 매번 새로운 변수에 통째로 '복사'해서 가져옵니다. 뒤에 &(참조자)를 붙이면 복사하지 않고 원본 데이터의 주소만 슬쩍 들여다보기 때문에, 데이터가 클수록 속도 차이가 엄청나게 벌어집니다. 데이터와 로직의 분리 (Data-Driven Design): 이전에는 if (.. == "aya"), else if (.. == "ye") 처럼 로직 안에 데이터가 섞여 있어, 나중에 옹알이 종류가 10개로 늘어나면 코드 길이도 10배로 길어집니다. 이 코드는 sounds라는 배열로 데이터를 분리해 두었기 때문에, 옹알이 종류가 100개로 늘어나도 안쪽 for문의 조건만 i < 100으로 바뀔 뿐 전체 로직은 단 한 줄도 길어지지 않습니다. 2. 숫자 짝꿍 문제 설명 두 정수 X, Y의 임의의 자리에서 공통으로 나타나는 정수 k(0 ≤ k ≤ 9)들을 이용하여 만들 수 있는 가장 큰 정수를 두 수의 짝꿍이라 합니다(단, 공통으로 나타나는 정수 중 서로 짝지을 수 있는 숫자만 사용합니다). X, Y의 짝꿍이 존재하지 않으면, 짝꿍은 -1입니다. X, Y의 짝꿍이 0으로만 구성되어 있다면, 짝꿍은 0입니다. 예를 들어, X = 3403이고 Y = 13203이라면, X와 Y의 짝꿍은 X와 Y에서 공통으로 나타나는 3, 0, 3으로 만들 수 있는 가장 큰 정수인 330입니다. 다른 예시로 X = 5525이고 Y = 1255이면 X와 Y의 짝꿍은 X와 Y에서 공통으로 나타나는 2, 5, 5로 만들 수 있는 가장 큰 정수인 552입니다(X에는 5가 3개, Y에는 5가 2개 나타나므로 남는 5 한 개는 짝 지을 수 없습니다.) 두 정수 X, Y가 주어졌을 때, X, Y의 짝꿍을 return하는 solution 함수를 완성해주세요. #include <string> #include <vector> #include <algorithm> using namespace std; string solution(string X, string Y) { string answer = ""; // 0부터 9까지 숫자가 몇 번 나왔는지 countX, countY 2개(모두 0으로 초기화) int countX[10] = {0}; int countY[10] = {0}; // X 문자열을 돌면서 각 숫자가 몇 개 있는지 체크 for (int i = 0; i < X.length(); i++) { // '3'에서 '0'을 빼면 실제 숫자 3 (아스키코드 원리) int num = X[i] - '0'; countX[num]++; } // Y 문자열도 똑같이 체크 for (int i = 0; i < Y.length(); i++) { int num = Y[i] - '0'; countY[num]++; } // 가장 큰 수를 만들어야 하니까 제일 큰 숫자인 9부터 0까지 거꾸로 for (int i = 9; i >= 0; i--) { int common_count = min(countX[i], countY[i]); // 공통으로 가진 개수만큼 숫자를 이어 붙이기 for (int j = 0; j < common_count; j++) { answer += to_string(i); } } // 예외 처리: 짝꿍이 하나도 없어서 문자열 비면 "-1" if (answer == "") { return "-1"; } // 예외 처리: 짝꿍을 만들었는데 0으로만 시작한다면 그냥 "0"으로 바꾸기 if (answer[0] == '0') { return "0"; } return answer; } AI가 작성한 코드 #include <string> #include <vector> #include <algorithm> // min 함수 사용 using namespace std; string solution(string X, string Y) { int countX[10] = {0}; int countY[10] = {0}; // 1. 인덱스(i) 변수 없이 범위 기반 for문으로 문자열을 직접 순회합니다. for (char c : X) countX[c - '0']++; for (char c : Y) countY[c - '0']++; string answer = ""; // 2. 가장 큰 숫자(9)부터 0까지 확인하며 문자열을 조립합니다. for (int i = 9; i >= 0; i--) { int common_count = min(countX[i], countY[i]); if (common_count > 0) { // 3. 반복문 안의 += 연산과 to_string()을 완전히 제거하고, // append 함수를 통해 '필요한 개수만큼 단번에' 메모리에 복사해 넣습니다. answer.append(common_count, i + '0'); } } // 4. empty() 함수를 사용하여 빈 문자열인지 더 직관적으로 확인합니다. if (answer.empty()) return "-1"; if (answer[0] == '0') return "0"; return answer; } to_string과 += 연산의 소멸 (Zero Overhead) 이전 코드의 answer += to_string(i)는 겉보기엔 간단하지만, 내부적으로는 끔찍한 연산 폭탄입니다. 매번 숫자를 문자로 바꾸기 위해 새로운 임시 문자열(객체)을 생성하고, 그걸 다시 정답 문자열 뒤에 이어 붙이기 위해 힙(Heap) 메모리를 헐었다가 다시 짓는 과정을 300만 번 반복할 수도 있습니다. 반면 answer.append(개수, 문자)를 사용하면, 컴퓨터가 "아! 숫자 9를 10만 개 한 번에 붙이라는 거구나!" 하고 필요한 메모리 공간을 딱 한 번만 확보한 뒤 블록 단위로 초고속 복사를 수행합니다. char와 아스키코드를 이용한 직접 치환 (i + '0') to_string(3) 같은 무거운 변환 함수를 쓸 필요가 없습니다. 컴퓨터에게 3 + '0'(아스키코드 48)을 계산하라고 하면 즉시 아스키코드 51번, 즉 문자 '3'이 튀어나옵니다. 숫자를 문자로 바꾸는 가장 로우레벨(Low-level)이면서 가장 빠른 방법입니다. Unreal Engine 멀티플레이어 게임 개발 : 3회차 정리 챕터 2-1 : Remote Procedure Call 기초 RPC : 호출하는 PC와 실행하는 PC가 달라도 되게끔 해주는 통신 기법 -> 게임에 큰 영향을 끼치지 않는 일시적인 효과들에 사용(사운드, 파티클 등) 함수를 실행할 때 내부적으로 동작하는 방식에 따라 Call과 Invoke로 구분 1. Call 특징: 정적인(Static) 의미 결정 시점: 프로그램이 빌드되는 컴파일 타임에 어떤 함수가 실행될지, 호출하는 곳과 실행하는 곳이 이미 명확하게 정해져 있음. 작동 방식: 대상 함수를 직접적으로(Direct) 호출하고 실행 예시: 일반적인 전역 함수나 클래스의 멤버 함수 호출이 여기에 해당 2. Invoke 특징: 동적인(Dynamic) 의미 결정 시점: 프로그램이 실행 중인 런타임 상황에 따라 어떤 함수가 실행될지, 호출하는 곳과 실제로 실행되는 곳이 어디인지 결정 작동 방식: 대리자나 네트워크를 거쳐 간접적으로(Indirect) 함수를 호출하고 실행 예시: 함수 포인터, 동적 바인딩, 그리고 RPC가 대표적인 Invoke 방식 멀티플레이 프로그래밍에서 클라이언트가 서버의 함수를 실행하거나, 서버가 클라이언트의 함수를 실행하도록 명령할 때 "RPC를 Invoke 한다"고 표현 RPC는 코드를 작성하는 시점(컴파일 타임)에 바로 내 컴퓨터에서 실행될지 확정되는 것이 아니라, 게임이 돌아가는 도중(런타임)에 네트워크 상태와 NetRole, NetMode에 따라 실행될 타겟(서버 혹은 특정 클라이언트)이 동적으로 결정되어 간접적으로 실행되기 때문 Actor Ownership PlayerController가 Local PlayerController와 같다면, Client-Owned Actor 예: 내 플레이어 캐릭터 PlayerController가 Local PlayerController와 다르다면, Owned by different client 예: 내 화면에 보이는 친구의 플레이어 캐릭터 서버에서 스폰되었지만 SetOwner() 함수 호출이 없으면, Server-Owned Actor 예: 보물상자 액터 Unowned Actor == Server-Owned Actor 라고 생각해도 됨 NetMulticast, Server, Client 키워드 UFUNCTION() 매크로와 함께 사용하는 해당 원격 PC에서 RPC를 실행시켜 달라는 요청 실제로 실행될지는 표를 통해 판단 NetMulticast : 서버를 포함한 모든 클라이언트에서 해당 RPC 실행 요청 Server : 서버에서 해당 RPC 실행 요청 Client : 클라이언트에서 해당 RPC 실행 요청
То, что RADAR обнаружил и классифицировал для этой возможности. Это опубликованный источником текст, а не подтверждение, что предложение ещё действует.
TIL(67). 오늘의 할일 코드카타 정리 세션 정리 코드카타 정리 1. 옹알이 (2) 문제 설명 머쓱이는 태어난 지 11개월 된 조카를 돌보고 있습니다. 조카는 아직 "aya", "ye", "woo", "ma" 네 가지 발음과 네 가지 발음을 조합해서 만들 수 있는 발음밖에 하지 못하고 연속해서 같은 발음을 하는 것을 어려워합니다. 문자열 배열 babbling이 매개변수로 주어질 때, 머쓱이의 조카가 발음할 수 있는 단어의 개수를 return하도록 solution 함수를 완성해주세요. #include #include using namespace std; int solution(vector babbling) { int answer = 0; for (int i = 0; i #include using…
Открыть источник