Java - 구구단 만들기 (2 ~ 9단)

Photo by Gayatri Malhotra on Unsplash

시작하기

구구단 만들기는 개발자로 취업하기 이전 Java 학원을 다닐 때 배웠던 문제입니다. 갑자기 지금 실력으로는 어떻게 코드를 만들 수 있을지 궁금해서 작성한 글이니 심심풀이로 봐주시면 좋겠습니다.

요구사항

  • 2 ~ 9까지 곱셈하여 출력한다.
  • 곱셈은 1 ~ 9까지 수를 제한한다.

샘플 코드 - 간단한 버전

public class MultiplicationTable {
    public static void main(String[] args) {
        int minNumber = 2;
        int maxNumber = 9;

        int startMultiplyValue = 1;
        int endMultiplyValue = 9;

        for (int number = minNumber; number <= maxNumber; number++) {
            for (int multiplyValue = startMultiplyValue; multiplyValue <= endMultiplyValue; multiplyValue++) {
                System.out.println(String.format("%d X %d = %d", number, multiplyValue, number * multiplyValue));
            }
            System.out.println();
        }
    }
}

샘플 코드 - 테스트 포함

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

class MultiplicationTableTest {

    private class MultiplicationTable {
        private static final int MIN_NUMBER = 2;
        private static final int MAX_NUMBER = 9;

        private final List<Multiplication> multiplications;

        public MultiplicationTable() {
            multiplications = IntStream.rangeClosed(MIN_NUMBER, MAX_NUMBER)
                    .mapToObj(Multiplication::new)
                    .collect(Collectors.toList());
        }

        public List<List<String>> getResult() {
            return multiplications.stream()
                    .map(multiplication -> multiplication.getResult())
                    .collect(Collectors.toList());
        }
    }

    private class Multiplication {
        private static final int MIN_NUMBER = 2;
        private static final int MAX_NUMBER = 9;

        private static final int MIN_MULTIPLE_VALUE = 1;
        private static final int MAX_MULTIPLE_VALUE = 9;

        private final int number;

        public Multiplication(final int number) {
            if (MIN_NUMBER > number) {
                throw new IllegalArgumentException(MIN_MULTIPLE_VALUE + "보다 작은 값을 사용할 수 없습니다.");
            }

            if (MAX_NUMBER < number) {
                throw new IllegalArgumentException(MAX_MULTIPLE_VALUE + "보다 큰 값을 사용할 수 없습니다.");
            }

            this.number = number;
        }

        public int multiply(final int value) {
            if (MIN_MULTIPLE_VALUE > value) {
                throw new IllegalArgumentException(MIN_MULTIPLE_VALUE + "보다 작은 값을 곱할 수 없습니다.");
            }

            if (MAX_MULTIPLE_VALUE < value) {
                throw new IllegalArgumentException(MAX_MULTIPLE_VALUE + "보다 큰 값을 곱할 수 없습니다.");
            }

            return number * value;
        }

        public List<String> getResult() {
            return IntStream.rangeClosed(MIN_MULTIPLE_VALUE, MAX_MULTIPLE_VALUE)
                    .mapToObj((value) -> String.format("%d * %d = %d", number, value, multiply(value)))
                    .collect(Collectors.toList());
        }
    }

    @Test
    void createTable() {
        assertThat(new MultiplicationTable().getResult()).hasSize(8);
    }

    @Test
    void getResult() {
        assertThat(new Multiplication(2).getResult()).containsExactly(
                "2 * 1 = 2",
                "2 * 2 = 4",
                "2 * 3 = 6",
                "2 * 4 = 8",
                "2 * 5 = 10",
                "2 * 6 = 12",
                "2 * 7 = 14",
                "2 * 8 = 16",
                "2 * 9 = 18"
        );
    }

    @ParameterizedTest
    @CsvSource({"2", "3", "4", "5", "6", "7", "8", "9"})
    void create(int number) {
        new Multiplication(number);
    }

    @ParameterizedTest
    @CsvSource({"1", "10"})
    void create_throw(int number) {
        assertThatThrownBy(() -> new Multiplication(number));
    }

    @ParameterizedTest
    @CsvSource({"2", "3", "4", "5", "6", "7", "8", "9"})
    void multiply_1(int value) {
        int multiplyValue = 1;
        int expectedValue = value * multiplyValue;
        assertThat(new Multiplication(expectedValue).multiply(multiplyValue)).isEqualTo(expectedValue);
    }

    @ParameterizedTest
    @CsvSource({"2", "3", "4", "5", "6", "7", "8", "9"})
    void multiply_9(int value) {
        int multiplyValue = 9;
        int expectedValue = value * multiplyValue;
        assertThat(new Multiplication(value).multiply(multiplyValue)).isEqualTo(expectedValue);
    }

    @ParameterizedTest
    @CsvSource({"0", "10"})
    void multiply_throwException(int multiplyValue) {
        assertThatThrownBy(() -> new Multiplication(1).multiply(multiplyValue));
    }
}

정리하기

예상한 시간보다 오랜 시간이 걸려 구구단 코드를 만들 수 있었습니다. 테스트 코드를 포함하지 않고 작성하는 것은 쉽게 작성할 수 있었지만 테스트를 포함하여 구구단을 만드는 코드는 생각보다 어려웠습니다. 미쳐 생각지 못한 테스트가 있기도 하고 지금 작성한 내용도 간단하게 작성하려고 하다 보니 일부 테스트는 제외하고 작성하였습니다. 다음에는 가볍지 않은 마음으로 구구단을 다시 만들어봐야 될 것 같습니다.

반응형

댓글

Designed by JB FACTORY