-
Notifications
You must be signed in to change notification settings - Fork 60
[사다리미션] 강민혁 제출합니다. #56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| # 사다리 - 함수형 프로그래밍 | ||
|
|
||
| ## 네이버 사다리 게임 분석 | ||
| 1. 인원수를 입력한다. | ||
| 2. 인원수 만큼 이름과 당첨 항목을 입력한다. | ||
| 3. 사다리를 그린다. | ||
| 4. 사다리결과를 반환한다. | ||
|
|
||
| ## 1단계 - 요구사항 | ||
| - 사다리는 4x4 사이즈로 유지된다. | ||
| - 사다리 중간점은 중첩될 수 없다. | ||
|
|
||
| ## 1단계 구현 방법 고민 | ||
| 1단계 같은경우 4x4 사이즈의 고정된 값을 가진 사다리를 만든다. | ||
|
|
||
| 사다리 전체의 정보를 가진 Ladder 객체는 내부에 가로줄 하나 하나의 정보를 담도록 해준다. | ||
| 그렇다면 4x4의 경우 width가 4인 가로줄을 총 4개를 가지게 된다. | ||
|
|
||
| 그리고 각각의 가로줄은 Line으로 정의한다. Line은 내부에 사이사이에 연결점을 체크한다. | ||
|
|
||
| 예를 들어, 4를 기준으로 생각 했을 때, 출발하는 사람들은 총 4명, 4명이라면 줄을 나누는 경우 3가지가 될 것이다. | ||
|
|
||
| 그렇기 때문에 width - 1을 기준으로 내부에 boolean 리스트를 가진다 | ||
|
|
||
| boolean 리스트는 바로 0번째가 true인 경우 - 뒤에 오는 두번째, 즉 2번 유저와 3번 유저의 사이에 오는 사다리는 true가 될 수 없다. | ||
|
|
||
| connect를 랜덤으로 만드는 과정은 다음과 같은 과정을 따르게 된다. | ||
| - for문을 통한 반복으로 List<Boolean>에 값 작성 | ||
| - i가 0번째 라면, random generate를 통해 값을 추출하고 정해진 값에 따라 true, false를 넣는다. | ||
| - 그 이후 부터는 random generate를 하기 전에, 바로 앞 boolean 값이 true라면 반드시 false가 오고 | ||
| - false라면 random generate이후 로직을 진행한다. | ||
|
|
||
| ## 2단계 - 요구사항 | ||
| - 사다리는 크기를 입력받아 생성이 가능하다. | ||
|
|
||
| ## 2단계 구현 방법 고민 | ||
| - 2단계는 InputView를 통해 width와 height를 입력받게되면 쉽게 풀린다고 생각했습니다. | ||
|
|
||
| ## 3단계 - 요구사항 | ||
| - 사다리의 시작지점과 도착지점을 출력한다. | ||
|
|
||
| ## 3단계 구현 방법 고민 | ||
| - 일단 사다리를 가지는 사다리게임 객체를 생성 | ||
| - 사다리 게임의 진행 순서는 다음과 같이 해결해야됨. | ||
|
|
||
| 1. 사다리게임의 width는 곧 사다리 게임 참여자의 숫자와 같음 | ||
| 2. 사다리게임이 실행되면 0번째 인덱스 부터시작 | ||
| 3. 0번째 인덱스는 좌측으로 갈수 없음 우측에 길이있는지 검사 | ||
| 4. 길이 없다면 그대로 유지후 다음 과정 수행 | ||
| 5. 우측에 길이 있다면 현재 position + 1 | ||
| 6. 좌측에 길이 있는 경우 position - 1 | ||
| 7. 이 반복문을 height만큼 완료하고 완료된 값을 map에 저장 | ||
| 8. map은 startindex - finalindex로 구성됨 | ||
| 9. 결과를 OutputView에서 print해줌 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| import controller.LadderController; | ||
|
|
||
| public class LadderMain { | ||
|
|
||
| public static void main(String[] args) { | ||
| final LadderController ladderController = new LadderController(); | ||
|
|
||
| ladderController.run(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| package controller; | ||
|
|
||
| import domain.*; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import ui.InputView; | ||
| import ui.OutputView; | ||
| import util.InputParser; | ||
|
|
||
| public class LadderController { | ||
|
|
||
| public void run() { | ||
| final Players players = inputPlayers(); | ||
| final Rewards rewards = inputRewards(); | ||
| final int height = InputView.inputLadderHeight(); | ||
| final BooleanGenerator randomBooleanGenerator = new RandomBooleanGenerator(); | ||
|
|
||
| final LadderGame game = createLadderGame(players, rewards, height, randomBooleanGenerator); | ||
| final LadderResult results = game.run(players, rewards); | ||
|
|
||
| printResults(players, rewards, game, results); | ||
| } | ||
|
|
||
| private Players inputPlayers() { | ||
| final String playersString = InputView.inputPlayers(); | ||
| return InputParser.parsePlayers(playersString); | ||
| } | ||
|
|
||
| private Rewards inputRewards() { | ||
| final String rewardString = InputView.inputReward(); | ||
| return InputParser.parseRewards(rewardString); | ||
| } | ||
|
|
||
| private LadderGame createLadderGame(final Players players, final Rewards rewards, final int height, final BooleanGenerator booleanGenerator) { | ||
| final int width = players.size(); | ||
| final List<Line> lines = createLines(width, height, booleanGenerator); | ||
|
|
||
| final Ladder ladder = Ladder.of(lines); | ||
|
|
||
| return new LadderGame(ladder, rewards); | ||
| } | ||
|
|
||
| private List<Line> createLines(final int width, final int height, final BooleanGenerator booleanGenerator) { | ||
| List<Line> lines = new ArrayList<>(); | ||
|
|
||
| for (int i = 0; i < height; i++) { | ||
| lines.add(new Line(width, booleanGenerator)); | ||
| } | ||
|
|
||
| return lines; | ||
| } | ||
|
|
||
| private void printResults(final Players players, final Rewards rewards, final LadderGame game, final LadderResult results) { | ||
| OutputView.printGameResult(players, game.getLadder(), rewards); | ||
| OutputView.printResults(results); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package domain; | ||
|
|
||
| @FunctionalInterface | ||
| public interface BooleanGenerator { | ||
|
|
||
| boolean nextBoolean(); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| package domain; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public class Ladder { | ||
|
|
||
| private final List<Line> lines; | ||
|
|
||
| private Ladder(final List<Line> lines) { | ||
| validateLines(lines); | ||
|
|
||
| this.lines = lines; | ||
| } | ||
|
|
||
| private void validateLines(final List<Line> lines) { | ||
| validateEmpty(lines); | ||
| validateWidth(lines); | ||
| validateHeight(lines); | ||
| } | ||
|
|
||
| public static Ladder of(final List<Line> lines) { | ||
| return new Ladder(lines); | ||
| } | ||
|
|
||
| public List<Line> lines() { | ||
| return lines; | ||
| } | ||
|
|
||
| public int width() { | ||
| return lines().get(0).size() + 1; | ||
| } | ||
|
|
||
| private static void validateEmpty(final List<Line> lines) { | ||
| if (lines.isEmpty()) { | ||
| throw new RuntimeException("빈 라인은 들어올 수 없습니다."); | ||
| } | ||
| } | ||
|
|
||
| private void validateWidth(List<Line> lines) { | ||
| int firstLineWidth = lines.get(0).size(); | ||
|
|
||
| if (firstLineWidth < 1) { | ||
| throw new RuntimeException("사다리 폭은 최소 2 이상이어야 합니다."); | ||
| } | ||
|
|
||
| for (Line line : lines) { | ||
| if (line.size() != firstLineWidth) { | ||
| throw new RuntimeException("모든 라인의 폭이 동일해야 합니다."); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void validateHeight(List<Line> lines) { | ||
| if (lines.isEmpty()) { | ||
| throw new RuntimeException("사다리 높이는 최소 1 이상이어야 합니다."); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package domain; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
|
|
||
| public class LadderGame { | ||
|
|
||
| private final Ladder ladder; | ||
|
|
||
| public LadderGame(final Ladder ladder, final Rewards rewards) { | ||
| validateLadderGame(ladder, rewards); | ||
| this.ladder = ladder; | ||
| } | ||
|
|
||
| public LadderResult run(Players players, Rewards rewards) { | ||
| Map<Integer, Integer> results = new HashMap<>(); | ||
|
|
||
| int width = ladder.width(); | ||
|
|
||
| for (int startPosition = 0; startPosition < width; startPosition++) { | ||
| int finalPosition = runSinglePath(startPosition); | ||
| results.put(startPosition, finalPosition); | ||
| } | ||
|
|
||
| return new LadderResult(results, players, rewards); | ||
| } | ||
|
|
||
| public Ladder getLadder() { | ||
| return ladder; | ||
| } | ||
|
|
||
| private int runSinglePath(final int startPosition) { | ||
| int currentPosition = startPosition; | ||
|
|
||
| for (Line line : ladder.lines()) { | ||
| currentPosition = movePosition(currentPosition, line); | ||
| } | ||
|
|
||
| return currentPosition; | ||
| } | ||
|
|
||
| private boolean canMoveRight(final int position, final Line line) { | ||
| return position >= 0 && position < line.size() && line.isConnected(position); | ||
| } | ||
|
|
||
| private boolean canMoveLeft(final int position, final Line line) { | ||
| return position > 0 && position <= line.size() && line.isConnected(position - 1); | ||
| } | ||
|
|
||
| private int movePosition(final int currentPosition, final Line line) { | ||
| if (canMoveRight(currentPosition, line)) { | ||
| return currentPosition + 1; | ||
| } | ||
|
|
||
| if (canMoveLeft(currentPosition, line)) { | ||
| return currentPosition - 1; | ||
| } | ||
|
|
||
| return currentPosition; | ||
| } | ||
|
|
||
| private void validateLadderGame(final Ladder ladder, final Rewards rewards) { | ||
| if (ladder.width() != rewards.size()) { | ||
| throw new RuntimeException("사용자 수와 리워드 수는 동일해야 합니다."); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| package domain; | ||
|
|
||
| import java.util.Map; | ||
|
|
||
| public record LadderResult(Map<Integer, Integer> results, Players players, Rewards rewards) { | ||
|
|
||
| public String getReward(final String targetPlayerInput) { | ||
| final Player player = new Player(targetPlayerInput); | ||
| final int playerIndex = players.findPlayerIndexByName(player); | ||
|
|
||
| final int resultIndex = getResult(playerIndex); | ||
|
|
||
| return rewards.getReward(resultIndex); | ||
| } | ||
|
|
||
| public int getResult(int index) { | ||
| if (results.get(index) == null) { | ||
| throw new RuntimeException("값이 존재하지 않습니다."); | ||
| } | ||
| return results.get(index); | ||
| } | ||
|
|
||
| @Override | ||
| public Map<Integer, Integer> results() { | ||
| return results; | ||
| } | ||
|
|
||
| @Override | ||
| public Players players() { | ||
| return players; | ||
| } | ||
|
|
||
| @Override | ||
| public Rewards rewards() { | ||
| return rewards; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| package domain; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| public class Line { | ||
|
|
||
| private final List<Boolean> connects; | ||
|
|
||
| public Line(final int width, final BooleanGenerator booleanGenerator) { | ||
| this.connects = new ArrayList<>(); | ||
|
|
||
| for (int i = 0; i < width - 1; i++) { | ||
| final boolean canConnect = !isPreviousConnected(); | ||
| final boolean connectStatus = canConnect && booleanGenerator.nextBoolean(); | ||
| connects.add(connectStatus); | ||
| } | ||
| } | ||
|
|
||
| public Line(final List<Boolean> connects) { | ||
| validateConnects(connects); | ||
| this.connects = connects; | ||
| } | ||
|
|
||
| private boolean isPreviousConnected() { | ||
| if (connects.isEmpty()) { | ||
| return false; | ||
| } | ||
|
|
||
| return connects.get(connects.size() - 1); | ||
| } | ||
|
|
||
| public boolean isConnected(final int index) { | ||
| return connects.get(index); | ||
| } | ||
|
|
||
| public int size() { | ||
| return connects.size(); | ||
| } | ||
|
|
||
| private void validateConnects(List<Boolean> connections) { | ||
| for (int i = 0; i < connections.size() - 1; i++) { | ||
| if (connections.get(i) && connections.get(i + 1)) { | ||
| throw new RuntimeException("연속된 연결은 허용되지 않습니다."); | ||
| } | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package domain; | ||
|
|
||
| public record Player(String name) { | ||
|
|
||
| public Player { | ||
| validateName(name); | ||
| } | ||
|
|
||
| private void validateName(final String name) { | ||
| if (name.length() > 5) { | ||
| throw new RuntimeException("이름은 5글자를 초과할 수 없습니다."); | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ladder 생성자를 만들고 검증을 진행해주셨군요! 정적 팩토리메서드에서도 생성자를 사용하도록 잘 변경해주셨네요!
하지만 지금은 생성자와 정적 팩토리메서드의 용도가 같아보여요.
넗이, 높이, 커넥션제너레이터 등을 파라미터로 받는 generate, initialize 등의 정적 팩토리메서드로 바꿔보면 어떨까요?
의도해서 말씀드린 방향은 이거였어요!