유전 알고리즘은 진화와 같은 방식으로 후보 해 집단을 개선합니다. 적합한 부모를 고르고, 결합하고, 무작위 돌연변이를 더합니다. 여기서 후보는 비트 문자열이고 적합도는 1의 개수입니다 (OneMax 문제).
테스트할 수 있도록 모든 무작위 선택이 주어집니다. N개의 문자열 (N은 짝수)로 N개의 자식을 쌍으로 만듭니다. 쌍 k = 0, 1, …, N/2 - 1에 대해:
- 선택: parent1은 토너먼트
tournaments[2k]의 승자이고 parent2는tournaments[2k + 1]의 승자입니다. 토너먼트[i, j]는population[i]와population[j]중 1이 더 많은 쪽이 이기며, 같으면population[i]가 이깁니다. - 교차 (c =
crossover_points[k]): 자식 2k = parent1[0:c] + parent2[c:], 자식 2k + 1 = parent2[0:c] + parent1[c:].
그다음 각 돌연변이 [child, position]를 순서대로 적용해 그 자식의 그 비트를 뒤집습니다.
ga_generation(population, tournaments, crossover_points, mutations)를 구현하세요.
입력
population: 길이가 L로 같은 N개의 비트 문자열.
tournaments: 집단 인덱스의 N개 쌍.
crossover_points: N/2개의 절단점. 각각 1 이상 L - 1 이하.
mutations: [child, position] 쌍 (비어 있을 수 있음).
출력
N개의 자식을 순서대로 반환합니다.
제약 조건
2 ≤ N ≤ 200 (N은 짝수), 2 ≤ L ≤ 64
0 ≤ 돌연변이 수 ≤ 1,000
예시
입력:
mutations = [
[0, 0]
]
population = ["0000", "1111", "1100", "0011"]
tournaments = [
[0, 1],
[2, 3],
[1, 2],
[0, 3]
]
crossover_points = [2, 1]
예상 출력:
["0100", "1111", "1011", "0111"]
설명
쌍 0: "1111"이 "0000"을 이기고, "1100"과 "0011"은 동점이므로 앞의 것이 이깁니다. 2비트 뒤에서 자르면 "1100"과 "1111". 쌍 1: 부모는 "1111"과 "0011", 1비트 뒤에서 자르면 "1011"과 "0111". 마지막으로 자식 0의 비트 0을 뒤집어 "0100".
입력:
mutations = []
population = ["10", "01"]
tournaments = [
[0, 1],
[1, 0]
]
crossover_points = [1]
예상 출력:
["11", "00"]
설명
두 문자열 모두 1이 하나이므로 각 토너먼트는 첫 번째 인덱스가 이깁니다: parent1 = "10", parent2 = "01". 1비트 뒤에서 자르면 "11"과 "00".
참고 자료
-
예시 1 미실행입력:
mutations = [ [0, 0] ] population = ["0000", "1111", "1100", "0011"] tournaments = [ [0, 1], [2, 3], [1, 2], [0, 3] ] crossover_points = [2, 1]예상 출력:["0100", "1111", "1011", "0111"]내 출력 -
예시 2 미실행입력:
mutations = [] population = ["10", "01"] tournaments = [ [0, 1], [1, 0] ] crossover_points = [1]예상 출력:["11", "00"]내 출력
제출 시 4개의 숨겨진 테스트도 실행됩니다.
온라인 C++ 컴파일러 및 디버거
서버 모드 GDB에서 중단점, 변수 확인과 단계별 실행으로 C++를 디버깅하세요.
C/C++ 배우고 연습하기
실행 가능한 레슨으로 구성된 학습 경로를 따라가고 코딩 챌린지로 실력을 확인하세요.
💻 이 C++ 온라인 실행기 소개
CodeUtility C++ Executor는 브라우저에서 바로 C++ 코드를 작성하고 실행할 수 있게 해줍니다 - 설치나 컴파일러 설정이 전혀 필요 없습니다. 안전한 샌드박스에서 동작하며, C++11, C++14, C++17부터 최신 버전까지 실제 C++ 표준을 지원합니다.
이 도구는 클라우드에서 실제 C++ 컴파일러로 코드를 컴파일하고 실행하므로, 버전 간에 정확하고 일관된 동작을 보장합니다. 변수, 함수, 반복문, 조건문, 객체지향 프로그래밍 같은 핵심 C++ 개념을 자유롭게 실험해 보세요.
인터뷰 대비, 최신 C++ 기능 학습, 알고리즘 로직 검증 등 어떤 목적이든, CodeUtility C++ Executor는 어떤 기기에서든 즉시 코드를 실행할 수 있는 간단하면서도 강력한 환경을 제공합니다.
하나의 실행기에서 다중 파일 편집기, 격리된 실행 터미널, 런타임별 라이브러리, 영구 작업 공간, 공유 및 실시간 협업을 이용하세요.
이 실행기는 어떻게 사용하나요?
런타임을 선택하고 파일을 열거나 만든 다음 코드를 작성하고 실행을 선택하세요. 출력은 터미널에 표시되며, 로그인한 사용자는 작업 공간에 파일을 보관하고 라이브러리를 설치하며 공유를 통해 협업할 수 있습니다.
- 버전을 선택하고 현재 파일을 편집하거나 작업 공간의 다른 파일을 여세요.
- 코드를 실행하고 요청 시 터미널에 입력한 다음 저장된 실행 기록을 확인하세요.
- 작업에 둘 이상의 코드 조각이 필요하면 라이브러리, 작업 공간 도구, 공유 및 채팅을 사용하세요.
💡 위에서 바로 시도해볼 수 있는 C++ 기본기와 예제
1. 변수와 상수 선언
C++에서는 각 변수의 타입을 선언해야 합니다. 초기화 후 변경할 수 없는 읽기 전용 값을 정의하려면 const를 사용하세요.
int age = 30;
double pi = 3.14159;
char grade = 'A';
std::string name = "Alice";
bool isActive = true;
// 상수
const int MAX_USERS = 100;
const std::string COMPANY = "CodeUtility";
// const 값을 변경하려 하면 컴파일 타임 오류가 발생합니다
// MAX_USERS = 200; // ❌ 오류
2. 조건문 (if / switch)
분기에는 if, else if, else를 사용합니다. 여러 값 분기에는 switch를 사용합니다.
int x = 2;
if (x == 1) {
std::cout << "하나\n";
} else if (x == 2) {
std::cout << "둘\n";
} else {
std::cout << "기타\n";
}
// switch-case
switch (x) {
case 1:
std::cout << "하나\n";
break;
case 2:
std::cout << "둘\n";
break;
default:
std::cout << "기타\n";
}
3. 반복문
for, while, do-while로 코드 블록을 반복하세요.
for (int i = 0; i < 3; i++) {
std::cout << i << "\n";
}
int n = 3;
while (n > 0) {
std::cout << n << "\n";
n--;
}
4. 배열
배열은 같은 타입의 여러 요소를 저장합니다.
int numbers[3] = {10, 20, 30};
std::cout << numbers[1] << "\n";
5. 배열/벡터 다루기
동적 배열에는 std::vector를 사용하세요.
#include <vector>
std::vector nums = {1, 2, 3};
nums.push_back(4);
nums.pop_back();
for (int n : nums) {
std::cout << n << " ";
}
6. 콘솔 입력/출력
std::cin은 입력, std::cout은 출력에 사용합니다.
std::string name;
std::cout << "이름을 입력하세요: ";
std::cin >> name;
std::cout << "안녕하세요, " << name << "\n";
7. 함수
함수는 재사용 가능한 로직을 묶습니다. 매개변수와 반환 타입을 사용하세요.
int add(int a, int b) {
return a + b;
}
std::cout << add(3, 4);
8. 맵
std::map은 딕셔너리처럼 키-값 쌍을 저장합니다.
#include <map>
std::map ages;
ages["Alice"] = 30;
std::cout << ages["Alice"];
9. 예외 처리
try와 catch로 런타임 오류를 처리하세요.
try {
throw std::runtime_error("오류가 발생했습니다");
} catch (const std::exception& e) {
std::cout << e.what();
}
10. 파일 입출력
fstream으로 파일을 읽고 쓸 수 있습니다.
#include <fstream>
std::ofstream out("file.txt");
out << "안녕 파일";
out.close();
std::ifstream in("file.txt");
std::string line;
getline(in, line);
std::cout << line;
in.close();
11. 문자열 다루기
C++ 문자열은 length(), substr(), find() 같은 메서드를 제공합니다.
std::string text = "Hello World";
std::cout << text.length();
std::cout << text.substr(0, 5);
std::cout << text.find("World");
12. 클래스와 객체
C++는 클래스를 사용한 객체지향 프로그래밍을 지원합니다.
class Person {
public:
std::string name;
Person(std::string n) : name(n) {}
void greet() { std::cout << "안녕하세요, 저는 " << name; }
};
Person p("Alice");
p.greet();
13. 포인터
포인터는 다른 변수의 메모리 주소를 저장합니다. 주소를 얻으려면 &를,
역참조(그 주소의 값을 접근)하려면 *를 사용합니다.
int x = 10;
int* ptr = &x;
std::cout << "x의 값: " << x << "\n";
std::cout << "x의 주소: " << ptr << "\n";
std::cout << "포인터로 읽은 값: " << *ptr << "\n";
// 포인터를 통해 x 수정
*ptr = 20;
std::cout << "변경된 x: " << x << "\n";
🐞 %{language} 코드를 온라인으로 디버깅하는 방법
온라인 %{language} 디버거로 컴파일러나 IDE를 설치하지 않고 런타임 및 논리 오류를 찾으세요. 서버 모드는 디버그 심볼로 컴파일하고 GDB에서 프로그램을 실행합니다.
- 줄 번호 옆에 중단점을 설정합니다.
- Debug를 선택해 컴파일하고 첫 중단점에서 멈춥니다.
- 현재 줄, 호출 스택과 변수를 확인합니다.
- Continue, Step Over, Step Into, Step Out으로 실행을 제어합니다.
- 종료하려면 Stop을 선택합니다.
재현 가능한 작은 예제로 시작하고 예상 밖의 동작 직전에 중단점을 설정하세요.