-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
105 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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,65 @@ | ||
package graphs.lee | ||
|
||
// TODO: implement without mutable board | ||
class Lee(width: Int, height: Int, os: Iterable[Point]) { | ||
import Lee._ | ||
private val board: Array[Array[Int]] = Array.fill(height, width)(EMPTY) | ||
putObstacles(os) | ||
|
||
def get(x: Int, y: Int): Int = board(y)(x) | ||
def set(x: Int, y: Int, value: Int): Unit = board(y)(x) = value | ||
def get(pt: Point): Int = get(pt.x, pt.y) | ||
def set(pt: Point, value: Int): Unit = set(pt.x, pt.y, value) | ||
def isOnBoard(p: Point) = p.y >= 0 && p.y < height && p.x >= 0 && p.x < width | ||
def isUnvisited(p: Point) = get(p) == EMPTY | ||
val deltas = Set((-1, 0), (0, -1), (1, 0), (0, 1)) | ||
def neighbours(p: Point) = deltas.map { case (dx, dy) => p.move(dx, dy) }.filter(isOnBoard) | ||
def neighboursUnvisited(p: Point) = neighbours(p).filter(isUnvisited) | ||
def neighboursByValue(p: Point, v: Int) = neighbours(p).filter(p => get(p) == v) | ||
def putObstacles(os: Iterable[Point]) = os.foreach(p => set(p, OBSTACLE)) | ||
def trace(src: Point, dst: Point): Option[Iterable[Point]] = { | ||
|
||
def flood(cur: Set[Point], curVal: Int): Option[Unit] = | ||
if (cur.isEmpty) None | ||
else { | ||
cur.foreach(p => set(p, curVal)) | ||
if (cur.contains(dst)) Some(()) // finalized | ||
else { // next step | ||
val next = cur.flatMap(neighboursUnvisited) | ||
flood(next, curVal + 1) | ||
} | ||
} | ||
|
||
def reconstruct(cur: Point, path: List[Point]): Iterable[Point] = get(cur) match { | ||
case START => path | ||
case v => | ||
val prev = neighboursByValue(cur, v - 1).head | ||
reconstruct(prev, prev :: path) | ||
} | ||
|
||
flood(Set(src), 1).map(_ => reconstruct(dst, List(dst))) | ||
} | ||
|
||
def fmtBoard(path0: Iterable[Point] = Iterable.empty) = { | ||
val path = path0.toSet | ||
def fmtCell(p: Point) = get(p) match { | ||
case OBSTACLE => colorize(" XX", Console.BLUE) | ||
case v => | ||
val valueF = "%3d".formatted(v) | ||
if (path.contains(p)) colorize(valueF, Console.RED) | ||
else valueF | ||
} | ||
board.indices | ||
.map(y => board(y).indices.map(x => Point(x, y)).map(fmtCell).mkString) | ||
.mkString("\n") | ||
} | ||
override def toString: String = fmtBoard() | ||
} | ||
|
||
private object Lee { | ||
val EMPTY = 0 | ||
val START = 1 | ||
val OBSTACLE = -10 | ||
|
||
def colorize(value: String, color: String) = color.concat(value).concat(Console.RESET) | ||
} |
This file contains 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,31 @@ | ||
package graphs.lee | ||
|
||
object LeeApp extends App { | ||
|
||
val src = Point(0, 0) | ||
val dst = Point(19, 0) | ||
val obstacles = Set( | ||
(5, 14), | ||
(5, 13), | ||
(5, 12), | ||
(5, 11), | ||
(5, 10), | ||
(5, 9), | ||
(5, 8), | ||
(10, 0), | ||
(10, 1), | ||
(10, 2), | ||
(10, 3), | ||
(10, 4), | ||
(10, 5), | ||
(10, 6), | ||
(10, 7), | ||
(10, 8) | ||
).map { case (x, y) => Point(x, y) } | ||
val lee = new Lee(20, 15, obstacles) | ||
val trace = lee.trace(src, dst) | ||
System.out.println(trace) | ||
System.out.println() | ||
trace.foreach(path => System.out.println(lee.fmtBoard(path))) | ||
|
||
} |
This file contains 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,9 @@ | ||
package graphs.lee | ||
|
||
case class Point (x: Int, y: Int) { | ||
|
||
override def toString: String = "[%d,%d]".formatted(x, y) | ||
|
||
def move(dx: Int, dy: Int): Point = Point(x + dx, y + dy) | ||
|
||
} |