Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ dependencies {
testImplementation platform('org.assertj:assertj-bom:3.25.1')
testImplementation('org.junit.jupiter:junit-jupiter')
testImplementation('org.assertj:assertj-core')
implementation 'org.slf4j:slf4j-api:2.0.9'
implementation 'org.slf4j:slf4j-simple:2.0.9'
testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
}

test {
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import model.Ladder;
import utils.ExceptionHandler;
import view.LadderView;

public class Application {
public static void main(String[] args) {
try {
Ladder ladder = Ladder.of(4, 4);
LadderView.printLadder(ladder);
} catch (Exception e) {
ExceptionHandler.handleException(e);
}
}
}
17 changes: 17 additions & 0 deletions src/main/java/model/Ladder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package model;

public class Ladder {
private final Lines lines;

public Ladder(Lines lines) {
this.lines = lines;
}

public static Ladder of(int width, int height) {
return new Ladder(LadderGenerator.generate(width, height));
}

public Lines getLines() {
return lines;
}
}
7 changes: 7 additions & 0 deletions src/main/java/model/LadderGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package model;

public class LadderGenerator {
public static Lines generate(int width, int height) {
return LineGenerator.generate(width, height);
}
}
31 changes: 31 additions & 0 deletions src/main/java/model/LadderValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package model;

import java.util.*;
import java.util.stream.*;

public class LadderValidator {
private static final Random RANDOM = new Random();

public static void validate(List<Line> lines, int width) {
IntStream.rangeClosed(0, width)
.forEach(i -> validateColumn(lines, i, width));
}

private static void validateColumn(List<Line> lines, int col, int width) {
boolean emptyColumn = lines.stream().noneMatch(line -> hasBridgeAt(line, col, width));
if (emptyColumn) {
connect(lines.get(RANDOM.nextInt(lines.size())), col, width);
}
}

private static boolean hasBridgeAt(Line line, int col, int width) {
if (col == 0) return line.hasBridgeAt(col);
if (col == width) return line.hasBridgeAt(col - 1);
return line.hasBridgeAt(col - 1) || line.hasBridgeAt(col);
}

private static void connect(Line line, int col, int width) {
if (col == width) line.setBridgeAt(col - 1);
else line.setBridgeAt(col);
}
}
23 changes: 23 additions & 0 deletions src/main/java/model/Line.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package model;

import java.util.*;

public class Line {
private final List<Boolean> points;

public Line(List<Boolean> points) {
this.points = points;
}

public List<Boolean> getPoints() {
return points;
}

public boolean hasBridgeAt(int index) {
return points.get(index);
}

public void setBridgeAt(int index) {
points.set(index, true);
}
}
26 changes: 26 additions & 0 deletions src/main/java/model/LineGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package model;

import java.util.*;

public class LineGenerator {
public static Lines generate(int width, int height) {
List<Set<Integer>> reserved = ReservedPositionGenerator.generate(width - 1, height);
List<Line> lines = new ArrayList<>();

for (int row = 0; row < height; row++) {
Line previous = getPreviousLine(lines, row);
Line line = SingleLineGenerator.generate(width - 1, reserved.get(row), previous);
lines.add(line);
}

LadderValidator.validate(lines, width - 1);
return new Lines(lines);
}

private static Line getPreviousLine(List<Line> lines, int row) {
if (row == 0) {
return null;
}
return lines.get(row - 1);
}
}
15 changes: 15 additions & 0 deletions src/main/java/model/Lines.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package model;

import java.util.List;

public class Lines {
private final List<Line> lines;

public Lines(List<Line> lines) {
this.lines = lines;
}

public List<Line> getLines() {
return lines;
}
}
19 changes: 19 additions & 0 deletions src/main/java/model/ReservedPositionGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package model;

import java.util.*;
import java.util.stream.*;

public class ReservedPositionGenerator {
private static final Random RANDOM = new Random();

public static List<Set<Integer>> generate(int width, int height) {
List<Set<Integer>> reserved = IntStream.range(0, height)
.mapToObj(i -> new HashSet<Integer>())
.collect(Collectors.toList());

IntStream.range(0, width)
.forEach(i -> reserved.get(RANDOM.nextInt(height)).add(i));

return reserved;
}
}
47 changes: 47 additions & 0 deletions src/main/java/model/SingleLineGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package model;

import java.util.*;
import java.util.stream.*;

public class SingleLineGenerator {
private static final Random RANDOM = new Random();

public static Line generate(int width, Set<Integer> reserved, Line prev) {
List<Boolean> points = new ArrayList<>(Collections.nCopies(width, false));

reserved.forEach(i -> {
if (isNotOverlap(points, prev, i)) {
points.set(i, true);
}
});

IntStream.range(0, width).forEach(i -> {
if (!points.get(i) && isNotOverlap(points, prev, i)) {
points.set(i, RANDOM.nextBoolean());
}
});

ensureOneBridge(points, prev);
return new Line(points);
}

private static boolean isNotOverlap(List<Boolean> points, Line prev, int i) {
if (prev != null && prev.hasBridgeAt(i)) return false;
if (i > 0 && points.get(i - 1)) return false;
return true;
}

private static void ensureOneBridge(List<Boolean> points, Line prev) {
if (points.contains(true)) return;

IntStream.range(0, points.size())
.filter(i -> canSetBridge(points, prev, i))
.findFirst()
.ifPresent(i -> points.set(i, true));
}

private static boolean canSetBridge(List<Boolean> points, Line prev, int index) {
return (prev == null || !prev.hasBridgeAt(index))
&& (index == 0 || !points.get(index - 1));
}
}
12 changes: 12 additions & 0 deletions src/main/java/utils/ExceptionHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package utils;

import org.slf4j.*;

public class ExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(ExceptionHandler.class);

public static void handleException(Exception e) {
System.err.println("시스템 오류 : " + e.getMessage());
logger.error("시스템 오류 : ", e);
}
}
31 changes: 31 additions & 0 deletions src/main/java/view/LadderView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package view;

import model.*;

public class LadderView {
private static final String BRIDGE = "-----|";
private static final String SPACE = " |";
private static final String BAR = "|";

public static void printLadder(Ladder ladder) {
printLines(ladder.getLines());
}

private static void printLines(Lines lines) {
lines.getLines().forEach(LadderView::printLine);
}

private static void printLine(Line line) {
System.out.print(BAR);
line.getPoints().forEach(LadderView::printPoint);
System.out.println();
}

private static void printPoint(Boolean point) {
if (point) {
System.out.print(BRIDGE);
return;
}
System.out.print(SPACE);
}
}