Today's Codekata
// a_len은 배열 a의 길이입니다.
// b_len은 배열 b의 길이입니다.
int solution(int a[], size_t a_len, int b[], size_t b_len) {
int answer = 0;
for (int i = 0; i < a_len; i++) {
answer += a[i] * b[i];
}
return answer;
}
길이가 같은 두 1차원 정수 배열 a, b가 매개변수로 주어집니다. a와 b의 내적을 return 하도록 solution 함수를 완성해주세요.
int solution(int left, int right) {
int answer = 0;
for (int i = left; i <= right; i++) {
int count = 0;
for (int j = 1; j <= i; j++) {
if (i % j == 0) {
count++;
}
}
if (count % 2 == 0) {
answer += i;
} else {
answer -= i;
}
}
return answer;
}
두 정수 left와 right가 매개변수로 주어집니다. left부터 right까지의 모든 수들 중에서, 약수의 개수가 짝수인 수는 더하고, 약수의 개수가 홀수인 수는 뺀 수를 return 하도록 solution 함수를 완성해주세요.
-- 카테고리별 상품 개수 구하기
SELECT SUBSTR(PRODUCT_CODE, 1, 2) AS CATEGORY,
COUNT(*) AS PRODUCTS
FROM PRODUCT
GROUP BY 1
-- 고양이와 개는 몇마리 있을까?
SELECT ANIMAL_TYPE,
COUNT(*) count
FROM ANIMAL_INS
WHERE ANIMAL_TYPE = 'DOG' OR ANIMAL_TYPE = 'CAT'
GROUP BY 1
ORDER BY 1
간단한 반복문이지만 문제를 어떻게 풀지 생각하는 과정이 정말 중요하다는 걸 느꼈다. 내가 직접 짠 코드가 원하는 결과를 출력할 때 뿌듯함을 느낀다.
Today I Learned
오늘은 함께 공부하고 있는 팀원이 제안해준 차량 관리 시스템을 연습삼아 만들어봤다.
Main
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
VehicleManager vehicleManager = new VehicleManager();
while (true) {
System.out.println("\n=== 차량 관리 시스템 ===");
System.out.println("1. 차량 추가");
System.out.println("2. 전체 차량 목록 보기");
System.out.println("3. 특정 차량 검색 (모델명)");
System.out.println("4. 모든 차량 시동 걸기");
System.out.println("0. 종료");
System.out.println("======================");
System.out.print("메뉴 선택: ");
int choice;
try {
choice = sc.nextInt();
sc.nextLine();
} catch (InputMismatchException e) {
System.out.println("숫자만 입력해주세요!");
sc.nextLine();
continue;
}
switch (choice) {
case 1:
System.out.print("추가할 차량 타입을 선택하세요 (1: 자동차, 2: 오토바이): ");
int selectedCarType = sc.nextInt();
sc.nextLine();
if (selectedCarType == 1) {
System.out.print("제조사: ");
String brand = sc.nextLine();
System.out.print("모델명: ");
String model = sc.nextLine();
System.out.print("색상: ");
String color = sc.nextLine();
System.out.print("연식: ");
int year = sc.nextInt();
System.out.print("문의 개수: ");
int numDoors = sc.nextInt();
Car car = new Car(brand, model, color, year, numDoors);
vehicleManager.addVehicle(car);
System.out.printf("'%s %s' 차량이 추가되었습니다.\n", brand, model);
} else if (selectedCarType == 2) {
System.out.print("제조사: ");
String brand = sc.nextLine();
System.out.print("모델명: ");
String model = sc.nextLine();
System.out.print("색상: ");
String color = sc.nextLine();
System.out.print("연식: ");
int year = sc.nextInt();
sc.nextLine();
System.out.print("사이드카가 있습니까? (Y/N): ");
String sidecar = sc.nextLine();
boolean hasSidecar = sidecar.equalsIgnoreCase("Y");
Motorcycle motorcycle = new Motorcycle(brand, model, color, year, hasSidecar);
vehicleManager.addVehicle(motorcycle);
System.out.println("'" + brand + model + "' 차량이 추가되었습니다.");
} else {
System.out.println("잘못된 차량 타입입니다. 1 또는 2를 입력해주세요.");
continue;
}
continue;
case 2:
System.out.println("--- 전체 차량 목록 ---");
vehicleManager.listAllVehicles();
System.out.println("---------------------");
continue;
case 3:
System.out.print("검색할 차량의 모델을 입력하세요: ");
String modelName = sc.nextLine();
vehicleManager.findVehicleByModel(modelName);
continue;
case 4:
vehicleManager.startAllEngines();
continue;
case 0:
System.out.println("프로그램을 종료합니다.");
break;
}
}
}
}
VehicleManager
public class VehicleManager {
private final List vehicles = new ArrayList<>();
public void addVehicle(Vehicle vehicle) {
vehicles.add(vehicle);
}
public void listAllVehicles() {
if (vehicles.isEmpty()) {
System.out.println("등록된 차량이 없습니다.");
}
for (Vehicle vehicle : vehicles) {
vehicle.displayInfo();
}
}
public void findVehicleByModel(String model) {
boolean found = false;
for (Vehicle vehicle : vehicles) {
if (vehicle.getModel().equalsIgnoreCase(model)) {
vehicle.displayInfo();
found = true;
}
}
if (!found) {
System.out.println("해당 모델의 차량을 찾을 수 없습니다.");
}
}
public void startAllEngines() {
for (Vehicle vehicle : vehicles) {
vehicle.startEngine();
}
}
}
Vehicle
public abstract class Vehicle {
private final String brand;
private final String model;
private final String color;
private final int year;
Vehicle(String brand, String model, String color, int year) {
this.brand = brand;
this.model = model;
this.color = color;
this.year = year;
}
public String getBrand() {
return brand;
}
public String getModel() {
return model;
}
public String getColor() {
return color;
}
public int getYear() {
return year;
}
public void startEngine() {
System.out.println(getModel() + "의 시동을 겁니다.");
}
public abstract void displayInfo();
}
Car
public class Car extends Vehicle {
private final int numDoors;
Car(String brand, String model, String color, int year, int numDoors) {
super(brand, model, color, year);
this.numDoors = numDoors;
}
public int getNumDoors() {
return numDoors;
}
@Override
public void displayInfo() {
System.out.printf("[자동차] %s %s (%d), 색상:%s, 문 개수: %d\n",
getBrand(), getModel(), getYear(), getColor(), getNumDoors());
}
}
MotorCycle
public class Motorcycle extends Vehicle {
private final boolean hasSidecar;
Motorcycle(String brand, String model, String color, int year, boolean hasSidecar) {
super(brand, model, color, year);
this.hasSidecar = hasSidecar;
}
public boolean isHasSidecar() {
return hasSidecar;
}
@Override
public void displayInfo() {
String sidecarStatus = hasSidecar ? "있음" : "없음";
System.out.printf("[오토바이] %s %s (%d), 색상:%s, 사이드카: %s\n",
getBrand(), getModel(), getYear(), getColor(), sidecarStatus);
}
}
Vehicle 클래스는 자동차와 오토바이의 공통 필드인 브랜드, 모델명, 색상, 연식 등을 포함하고, startEngine() 같은 공통 메서드도 정의해서 중복을 줄였다. displayInfo() 메서드를 추상 메서드로 정의해서 자동차와 오토바이에 맞게 오버라이딩해서 사용했다. 객체지향의 다형성을 활용한 부분이다. 그리고 상속을 통해 코드 재사용성과 유지보수성을 높였다. Truck같은 다른 차량 종류가 추가되더라도 쉽게 확장이 가능하다. 입력이 여러 번 있을 경우 nextInt()로 정수를 입력 받은 후 바로바로 버퍼를 비워서 잘못된 입력을 방지했다.
String sidecarStatus;
if (hasSidecar) {
sidecarStatus = "있음";
} else {
sidecarStatus = "없음";
}
그리고 이 부분을 삼항연산자를 활용해서 아주 간결하게 만들어 볼 수 있었다.
String sidecarStatus = hasSidecar ? "있음" : "없음";
6줄 짜리 코드가 1줄이 되는 마법을 경험했다. 삼항연산자는 '조건 ? 참일 때 값 : 거짓일 때 값' 형식으로 쓰이는 매우 간결한 조건문이다. 위 코드를 예를 들면 boolean 변수인 hasSidecar가 true면 "있음"을 false면 "없음"을 반환하게 되는 것이다.
마치며
오늘 연습 프로젝트를 통해 객체지향의 핵심적인 개념을 체험할 수 있는 의미있는 시간이었다. 추상 클래스와 상속 구조를 짜보면서 중복 제거와 재사용의 중요성을 배울 수 있었고, 입력 버퍼와 관련된 문제를 해결하려고 sc.nextLine()을 적절히 활용해본 것도 실무랑 연결된 중요한 깨달음이었다. 마지막으로 삼항연산자로 리팩토링해보면서 가독성과 간결함을 확보하는 좋은 방법도 알게 되었다. 역시 이론도 이론이지만 직접 코드를 치면서 배우는 것이 가장 많은 것 같다. 내일 일정이 많지만 매일매일 주어진 시간 안에서 최선을 다해야겠다.