[JS TESTS] Rewrite web demo tests using new test infrastructure
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
// MAIN_ARGS: [2]
|
||||
|
||||
/**
|
||||
* This example implements the famous "99 Bottles of Beer" program
|
||||
* See http://99-bottles-of-beer.net/
|
||||
*
|
||||
* The point is to print out a song with the following lyrics:
|
||||
*
|
||||
* The "99 bottles of beer" song
|
||||
*
|
||||
* 99 bottles of beer on the wall, 99 bottles of beer.
|
||||
* Take one down, pass it around, 98 bottles of beer on the wall.
|
||||
*
|
||||
* 98 bottles of beer on the wall, 98 bottles of beer.
|
||||
* Take one down, pass it around, 97 bottles of beer on the wall.
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* 2 bottles of beer on the wall, 2 bottles of beer.
|
||||
* Take one down, pass it around, 1 bottle of beer on the wall.
|
||||
*
|
||||
* 1 bottle of beer on the wall, 1 bottle of beer.
|
||||
* Take one down, pass it around, no more bottles of beer on the wall.
|
||||
*
|
||||
* No more bottles of beer on the wall, no more bottles of beer.
|
||||
* Go to the store and buy some more, 99 bottles of beer on the wall.
|
||||
*
|
||||
* Additionally, you can pass the desired initial number of bottles to use (rather than 99)
|
||||
* as a command-line argument
|
||||
*/
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
if (args.isEmpty()) {
|
||||
printBottles(99)
|
||||
}
|
||||
else {
|
||||
val bottles = args[0].toIntOrNull()
|
||||
if (bottles != null) {
|
||||
printBottles(bottles);
|
||||
}
|
||||
else {
|
||||
println("You have passed '${args[0]}' as a number of bottles, " +
|
||||
"but it is not a valid integral number")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun printBottles(bottleCount: Int) {
|
||||
if (bottleCount <= 0) {
|
||||
println("No bottles - no song")
|
||||
return
|
||||
}
|
||||
|
||||
println("The \"${bottlesOfBeer(bottleCount)}\" song\n")
|
||||
|
||||
var bottles = bottleCount
|
||||
while (bottles > 0) {
|
||||
val bottlesOfBeer = bottlesOfBeer(bottles)
|
||||
print("$bottlesOfBeer on the wall, $bottlesOfBeer.\nTake one down, pass it around, ")
|
||||
bottles--
|
||||
println("${bottlesOfBeer(bottles)} on the wall.\n")
|
||||
}
|
||||
println("No more bottles of beer on the wall, no more bottles of beer.\n" +
|
||||
"Go to the store and buy some more, ${bottlesOfBeer(bottleCount)} on the wall.")
|
||||
}
|
||||
|
||||
fun bottlesOfBeer(count: Int): String =
|
||||
when (count) {
|
||||
0 -> "no more bottles"
|
||||
1 -> "1 bottle"
|
||||
else -> "$count bottles"
|
||||
} + " of beer"
|
||||
|
||||
// From the std package
|
||||
// This is an extension property, i.e. a property that is defined for the
|
||||
// type Array<T>, but does not sit inside the class Array
|
||||
fun <T> Array<T>.isEmpty() = size == 0
|
||||
@@ -0,0 +1,10 @@
|
||||
The "2 bottles of beer" song
|
||||
|
||||
2 bottles of beer on the wall, 2 bottles of beer.
|
||||
Take one down, pass it around, 1 bottle of beer on the wall.
|
||||
|
||||
1 bottle of beer on the wall, 1 bottle of beer.
|
||||
Take one down, pass it around, no more bottles of beer on the wall.
|
||||
|
||||
No more bottles of beer on the wall, no more bottles of beer.
|
||||
Go to the store and buy some more, 2 bottles of beer on the wall.
|
||||
@@ -0,0 +1,142 @@
|
||||
// MAIN_ARGS: [over9000]
|
||||
|
||||
/**
|
||||
* This is an example of a Type-Safe Groovy-style Builder
|
||||
*
|
||||
* Builders are good for declaratively describing data in your code.
|
||||
* In this example we show how to describe an HTML page in Kotlin.
|
||||
*
|
||||
* See this page for details:
|
||||
* https://confluence.jetbrains.net/display/Kotlin/Type-safe+Groovy-style+builders
|
||||
*/
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val result =
|
||||
html {
|
||||
head {
|
||||
title { +"XML encoding with Kotlin" }
|
||||
}
|
||||
body {
|
||||
h1 { +"XML encoding with Kotlin" }
|
||||
p { +"this format can be used as an alternative markup to XML" }
|
||||
|
||||
// an element with attributes and text content
|
||||
a(href = "https://jetbrains.com/kotlin") { +"Kotlin" }
|
||||
|
||||
// mixed content
|
||||
p {
|
||||
+"This is some"
|
||||
b { +"mixed" }
|
||||
+"text. For more see the"
|
||||
a(href = "https://jetbrains.com/kotlin") { +"Kotlin" }
|
||||
+"project"
|
||||
}
|
||||
p { +"some text" }
|
||||
|
||||
// content generated from command-line arguments
|
||||
p {
|
||||
+"Command line arguments were:"
|
||||
ul {
|
||||
for (arg in args)
|
||||
li { +arg }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println(result)
|
||||
}
|
||||
|
||||
abstract class Element {
|
||||
abstract fun render(builder: StringBuilder, indent: String)
|
||||
|
||||
override fun toString(): String {
|
||||
val builder = StringBuilder()
|
||||
render(builder, "")
|
||||
return builder.toString()
|
||||
}
|
||||
}
|
||||
|
||||
class TextElement(val text: String) : Element() {
|
||||
override fun render(builder: StringBuilder, indent: String) {
|
||||
builder.append("$indent$text\n")
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Tag(val name: String) : Element() {
|
||||
val children = ArrayList<Element>()
|
||||
val attributes = HashMap<String, String>()
|
||||
|
||||
protected fun <T : Element> initTag(tag: T, init: T.() -> Unit): T {
|
||||
tag.init()
|
||||
children.add(tag)
|
||||
return tag
|
||||
}
|
||||
|
||||
override fun render(builder: StringBuilder, indent: String) {
|
||||
builder.append("$indent<$name${renderAttributes()}>\n")
|
||||
for (c in children) {
|
||||
c.render(builder, indent + " ")
|
||||
}
|
||||
builder.append("$indent</$name>\n")
|
||||
}
|
||||
|
||||
private fun renderAttributes(): String? {
|
||||
val builder = StringBuilder()
|
||||
for (a in attributes.keys) {
|
||||
builder.append(" $a=\"${attributes[a]}\"")
|
||||
}
|
||||
return builder.toString()
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TagWithText(name: String) : Tag(name) {
|
||||
operator fun String.unaryPlus() {
|
||||
children.add(TextElement(this))
|
||||
}
|
||||
}
|
||||
|
||||
class HTML() : TagWithText("html") {
|
||||
fun head(init: Head.() -> Unit) = initTag(Head(), init)
|
||||
|
||||
fun body(init: Body.() -> Unit) = initTag(Body(), init)
|
||||
}
|
||||
|
||||
class Head() : TagWithText("head") {
|
||||
fun title(init: Title.() -> Unit) = initTag(Title(), init)
|
||||
}
|
||||
|
||||
class Title() : TagWithText("title")
|
||||
|
||||
abstract class BodyTag(name: String) : TagWithText(name) {
|
||||
fun b(init: B.() -> Unit) = initTag(B(), init)
|
||||
fun p(init: P.() -> Unit) = initTag(P(), init)
|
||||
fun h1(init: H1.() -> Unit) = initTag(H1(), init)
|
||||
fun ul(init: UL.() -> Unit) = initTag(UL(), init)
|
||||
fun a(href: String, init: A.() -> Unit) {
|
||||
val a = initTag(A(), init)
|
||||
a.href = href
|
||||
}
|
||||
}
|
||||
|
||||
class Body() : BodyTag("body")
|
||||
class UL() : BodyTag("ul") {
|
||||
fun li(init: LI.() -> Unit) = initTag(LI(), init)
|
||||
}
|
||||
|
||||
class B() : BodyTag("b")
|
||||
class LI() : BodyTag("li")
|
||||
class P() : BodyTag("p")
|
||||
class H1() : BodyTag("h1")
|
||||
class A() : BodyTag("a") {
|
||||
public var href: String
|
||||
get() = attributes["href"]!!
|
||||
set(value) {
|
||||
attributes["href"] = value
|
||||
}
|
||||
}
|
||||
|
||||
fun html(init: HTML.() -> Unit): HTML {
|
||||
val html = HTML()
|
||||
html.init()
|
||||
return html
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
XML encoding with Kotlin
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
XML encoding with Kotlin
|
||||
</h1>
|
||||
<p>
|
||||
this format can be used as an alternative markup to XML
|
||||
</p>
|
||||
<a href="https://jetbrains.com/kotlin">
|
||||
Kotlin
|
||||
</a>
|
||||
<p>
|
||||
This is some
|
||||
<b>
|
||||
mixed
|
||||
</b>
|
||||
text. For more see the
|
||||
<a href="https://jetbrains.com/kotlin">
|
||||
Kotlin
|
||||
</a>
|
||||
project
|
||||
</p>
|
||||
<p>
|
||||
some text
|
||||
</p>
|
||||
<p>
|
||||
Command line arguments were:
|
||||
<ul>
|
||||
<li>
|
||||
over9000
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// MAIN_ARGS: [a,b,c]
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
for (arg in args)
|
||||
println(arg)
|
||||
|
||||
// or
|
||||
println()
|
||||
for (i in args.indices)
|
||||
println(args[i])
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
a
|
||||
b
|
||||
c
|
||||
|
||||
a
|
||||
b
|
||||
c
|
||||
@@ -0,0 +1,11 @@
|
||||
// MAIN_ARGS: [123]
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
for (arg in args)
|
||||
println(arg)
|
||||
|
||||
// or
|
||||
println()
|
||||
for (i in args.indices)
|
||||
println(args[i])
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
123
|
||||
|
||||
123
|
||||
@@ -0,0 +1,5 @@
|
||||
// MAIN_ARGS: [10,20]
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println(maxOf(args[0].toInt(), args[1].toInt()))
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
20
|
||||
@@ -0,0 +1,12 @@
|
||||
// MAIN_ARGS: []
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println(getStringLength("aaa"))
|
||||
println(getStringLength(1))
|
||||
}
|
||||
|
||||
fun getStringLength(obj: Any): Int? {
|
||||
if (obj is String)
|
||||
return obj.length // no cast to String is needed
|
||||
return null
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
3
|
||||
null
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
// MAIN_ARGS: [2]
|
||||
|
||||
/**
|
||||
* This is a straightforward implementation of The Game of Life
|
||||
* See http://en.wikipedia.org/wiki/Conway's_Game_of_Life
|
||||
*/
|
||||
|
||||
/*
|
||||
* A field where cells live. Effectively immutable
|
||||
*/
|
||||
class Field(
|
||||
val width: Int,
|
||||
val height: Int,
|
||||
// This function tells the constructor which cells are alive
|
||||
// if init(i, j) is true, the cell (i, j) is alive
|
||||
init: (Int, Int) -> Boolean
|
||||
) {
|
||||
private val live: Array<Array<Boolean>> = Array(height) { i -> Array(width) { j -> init(i, j) } }
|
||||
|
||||
private fun liveCount(i: Int, j: Int)
|
||||
= if (i in 0..height - 1 &&
|
||||
j in 0..width - 1 &&
|
||||
live[i][j]) 1
|
||||
else 0
|
||||
|
||||
// How many neighbors of (i, j) are alive?
|
||||
fun liveNeighbors(i: Int, j: Int) =
|
||||
liveCount(i - 1, j - 1) +
|
||||
liveCount(i - 1, j) +
|
||||
liveCount(i - 1, j + 1) +
|
||||
liveCount(i, j - 1) +
|
||||
liveCount(i, j + 1) +
|
||||
liveCount(i + 1, j - 1) +
|
||||
liveCount(i + 1, j) +
|
||||
liveCount(i + 1, j + 1)
|
||||
|
||||
// You can say field[i, j], and this function gets called
|
||||
operator fun get(i: Int, j: Int) = live[i][j]
|
||||
}
|
||||
|
||||
/**
|
||||
* This function takes the present state of the field
|
||||
* and return a new field representing the next moment of time
|
||||
*/
|
||||
fun next(field: Field): Field {
|
||||
return Field(field.width, field.height) { i, j ->
|
||||
val n = field.liveNeighbors(i, j)
|
||||
if (field[i, j])
|
||||
// (i, j) is alive
|
||||
n in 2..3 // It remains alive iff it has 2 or 3 neighbors
|
||||
else
|
||||
// (i, j) is dead
|
||||
n == 3 // A new cell is born if there are 3 neighbors alive
|
||||
}
|
||||
}
|
||||
|
||||
/** A few colony examples here */
|
||||
fun main(args: Array<String>) {
|
||||
// Simplistic demo
|
||||
printField("***", 3)
|
||||
// "Star burst"
|
||||
printField("""
|
||||
__*__
|
||||
_***_
|
||||
__*__
|
||||
""", 10)
|
||||
// Stable colony
|
||||
printField("""
|
||||
__*__
|
||||
_*_*_
|
||||
__*__
|
||||
""", 3)
|
||||
// Stable from the step 2
|
||||
printField("""
|
||||
__**__
|
||||
__**__
|
||||
__**__
|
||||
""", 3)
|
||||
// Oscillating colony
|
||||
printField("""
|
||||
__**__
|
||||
__**__
|
||||
__**__
|
||||
__**__
|
||||
""", 6)
|
||||
// A fancier oscillating colony
|
||||
printField("""
|
||||
---------------
|
||||
---***---***---
|
||||
---------------
|
||||
-*----*-*----*-
|
||||
-*----*-*----*-
|
||||
-*----*-*----*-
|
||||
---***---***---
|
||||
---------------
|
||||
---***---***---
|
||||
-*----*-*----*-
|
||||
-*----*-*----*-
|
||||
-*----*-*----*-
|
||||
---------------
|
||||
---***---***---
|
||||
---------------
|
||||
""", 10)
|
||||
}
|
||||
|
||||
// UTILITIES
|
||||
|
||||
fun printField(s: String, steps: Int) {
|
||||
var field = makeField(s)
|
||||
for (step in 1..steps) {
|
||||
println("Step: $step")
|
||||
for (i in 0..field.height - 1) {
|
||||
for (j in 0..field.width - 1) {
|
||||
print(if (field[i, j]) "*" else " ")
|
||||
}
|
||||
println("")
|
||||
}
|
||||
field = next(field)
|
||||
}
|
||||
}
|
||||
|
||||
fun makeField(s: String): Field {
|
||||
val lines: List<String> = s.split("\n")
|
||||
|
||||
val w = lines.maxOf { it.length }
|
||||
val data = Array(lines.size) { Array(w) { false } }
|
||||
|
||||
// workaround
|
||||
for (i in data.indices) {
|
||||
data[i] = Array(w) { false }
|
||||
for (j in data[i].indices)
|
||||
data[i][j] = false
|
||||
}
|
||||
|
||||
for (line in lines.indices) {
|
||||
for (x in lines[line].indices) {
|
||||
val c = lines[line][x]
|
||||
data[line][x] = c == '*'
|
||||
}
|
||||
}
|
||||
|
||||
return Field(w, lines.size) { i, j -> data[i][j] }
|
||||
}
|
||||
+324
@@ -0,0 +1,324 @@
|
||||
Step: 1
|
||||
***
|
||||
Step: 2
|
||||
*
|
||||
Step: 3
|
||||
|
||||
Step: 1
|
||||
|
||||
*
|
||||
***
|
||||
*
|
||||
|
||||
Step: 2
|
||||
|
||||
***
|
||||
* *
|
||||
***
|
||||
|
||||
Step: 3
|
||||
*
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
*
|
||||
Step: 4
|
||||
*
|
||||
***
|
||||
** **
|
||||
***
|
||||
*
|
||||
Step: 5
|
||||
***
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
***
|
||||
Step: 6
|
||||
***
|
||||
* * *
|
||||
*** **
|
||||
* * *
|
||||
***
|
||||
Step: 7
|
||||
***
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
***
|
||||
Step: 8
|
||||
**
|
||||
* * *
|
||||
*** **
|
||||
* * *
|
||||
**
|
||||
Step: 9
|
||||
***
|
||||
* * *
|
||||
* * *
|
||||
* * *
|
||||
***
|
||||
Step: 10
|
||||
***
|
||||
* *
|
||||
** * *
|
||||
* *
|
||||
***
|
||||
Step: 1
|
||||
|
||||
*
|
||||
* *
|
||||
*
|
||||
|
||||
Step: 2
|
||||
|
||||
*
|
||||
* *
|
||||
*
|
||||
|
||||
Step: 3
|
||||
|
||||
*
|
||||
* *
|
||||
*
|
||||
|
||||
Step: 1
|
||||
|
||||
**
|
||||
**
|
||||
**
|
||||
|
||||
Step: 2
|
||||
|
||||
**
|
||||
* *
|
||||
**
|
||||
|
||||
Step: 3
|
||||
|
||||
**
|
||||
* *
|
||||
**
|
||||
|
||||
Step: 1
|
||||
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
|
||||
Step: 2
|
||||
|
||||
**
|
||||
*
|
||||
*
|
||||
**
|
||||
|
||||
Step: 3
|
||||
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
|
||||
Step: 4
|
||||
|
||||
**
|
||||
*
|
||||
*
|
||||
**
|
||||
|
||||
Step: 5
|
||||
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
|
||||
Step: 6
|
||||
|
||||
**
|
||||
*
|
||||
*
|
||||
**
|
||||
|
||||
Step: 1
|
||||
|
||||
|
||||
*** ***
|
||||
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
*** ***
|
||||
|
||||
*** ***
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
|
||||
*** ***
|
||||
|
||||
|
||||
Step: 2
|
||||
|
||||
* *
|
||||
* *
|
||||
** **
|
||||
|
||||
*** ** ** ***
|
||||
* * * * * *
|
||||
** **
|
||||
|
||||
** **
|
||||
* * * * * *
|
||||
*** ** ** ***
|
||||
|
||||
** **
|
||||
* *
|
||||
* *
|
||||
|
||||
Step: 3
|
||||
|
||||
|
||||
** **
|
||||
** **
|
||||
* * * * * *
|
||||
*** ** ** ***
|
||||
* * * * * *
|
||||
*** ***
|
||||
|
||||
*** ***
|
||||
* * * * * *
|
||||
*** ** ** ***
|
||||
* * * * * *
|
||||
** **
|
||||
** **
|
||||
|
||||
|
||||
Step: 4
|
||||
|
||||
|
||||
*** ***
|
||||
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
*** ***
|
||||
|
||||
*** ***
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
|
||||
*** ***
|
||||
|
||||
|
||||
Step: 5
|
||||
|
||||
* *
|
||||
* *
|
||||
** **
|
||||
|
||||
*** ** ** ***
|
||||
* * * * * *
|
||||
** **
|
||||
|
||||
** **
|
||||
* * * * * *
|
||||
*** ** ** ***
|
||||
|
||||
** **
|
||||
* *
|
||||
* *
|
||||
|
||||
Step: 6
|
||||
|
||||
|
||||
** **
|
||||
** **
|
||||
* * * * * *
|
||||
*** ** ** ***
|
||||
* * * * * *
|
||||
*** ***
|
||||
|
||||
*** ***
|
||||
* * * * * *
|
||||
*** ** ** ***
|
||||
* * * * * *
|
||||
** **
|
||||
** **
|
||||
|
||||
|
||||
Step: 7
|
||||
|
||||
|
||||
*** ***
|
||||
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
*** ***
|
||||
|
||||
*** ***
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
|
||||
*** ***
|
||||
|
||||
|
||||
Step: 8
|
||||
|
||||
* *
|
||||
* *
|
||||
** **
|
||||
|
||||
*** ** ** ***
|
||||
* * * * * *
|
||||
** **
|
||||
|
||||
** **
|
||||
* * * * * *
|
||||
*** ** ** ***
|
||||
|
||||
** **
|
||||
* *
|
||||
* *
|
||||
|
||||
Step: 9
|
||||
|
||||
|
||||
** **
|
||||
** **
|
||||
* * * * * *
|
||||
*** ** ** ***
|
||||
* * * * * *
|
||||
*** ***
|
||||
|
||||
*** ***
|
||||
* * * * * *
|
||||
*** ** ** ***
|
||||
* * * * * *
|
||||
** **
|
||||
** **
|
||||
|
||||
|
||||
Step: 10
|
||||
|
||||
|
||||
*** ***
|
||||
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
*** ***
|
||||
|
||||
*** ***
|
||||
* * * *
|
||||
* * * *
|
||||
* * * *
|
||||
|
||||
*** ***
|
||||
|
||||
|
||||
+215
@@ -0,0 +1,215 @@
|
||||
// MAIN_ARGS: []
|
||||
|
||||
/**
|
||||
* Let's Walk Through a Maze.
|
||||
*
|
||||
* Imagine there is a maze whose walls are the big 'O' letters.
|
||||
* Now, I stand where a big 'I' stands and some cool prize lies
|
||||
* somewhere marked with a '$' sign. Like this:
|
||||
*
|
||||
* OOOOOOOOOOOOOOOOO
|
||||
* O O
|
||||
* O$ O O
|
||||
* OOOOO O
|
||||
* O O
|
||||
* O OOOOOOOOOOOOOO
|
||||
* O O I O
|
||||
* O O
|
||||
* OOOOOOOOOOOOOOOOO
|
||||
*
|
||||
* I want to get the prize, and this program helps me do so as soon
|
||||
* as I possibly can by finding a shortest path through the maze.
|
||||
*/
|
||||
|
||||
fun <E> MutableList<E>.offer(element: E) = this.add(element)
|
||||
fun <E> MutableList<E>.poll() = this.removeAt(0)
|
||||
|
||||
/**
|
||||
* This function looks for a path from max.start to maze.end through
|
||||
* free space (a path does not go through walls). One can move only
|
||||
* straightly up, down, left or right, no diagonal moves allowed.
|
||||
*/
|
||||
fun findPath(maze: Maze): List<Pair<Int, Int>>? {
|
||||
val previous = HashMap<Pair<Int, Int>, Pair<Int, Int>>()
|
||||
|
||||
val queue = ArrayDeque<Pair<Int, Int>>()
|
||||
val visited = HashSet<Pair<Int, Int>>()
|
||||
|
||||
queue.offer(maze.start)
|
||||
visited.add(maze.start)
|
||||
while (!queue.isEmpty()) {
|
||||
val cell = queue.poll()
|
||||
if (cell == maze.end) break
|
||||
|
||||
for (newCell in maze.neighbors(cell.first, cell.second)) {
|
||||
if (newCell in visited) continue
|
||||
previous[newCell] = cell
|
||||
queue.offer(newCell)
|
||||
visited.add(cell)
|
||||
}
|
||||
}
|
||||
|
||||
if (previous[maze.end] == null) return null
|
||||
|
||||
val path = ArrayList<Pair<Int, Int>>()
|
||||
var current = previous[maze.end]
|
||||
while (current != maze.start) {
|
||||
path.add(0, current!!)
|
||||
current = previous[current]
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
/**
|
||||
* Find neighbors of the (i, j) cell that are not walls
|
||||
*/
|
||||
fun Maze.neighbors(i: Int, j: Int): List<Pair<Int, Int>> {
|
||||
val result = ArrayList<Pair<Int, Int>>()
|
||||
addIfFree(i - 1, j, result)
|
||||
addIfFree(i, j - 1, result)
|
||||
addIfFree(i + 1, j, result)
|
||||
addIfFree(i, j + 1, result)
|
||||
return result
|
||||
}
|
||||
|
||||
fun Maze.addIfFree(i: Int, j: Int, result: MutableList<Pair<Int, Int>>) {
|
||||
if (i !in 0..height - 1) return
|
||||
if (j !in 0..width - 1) return
|
||||
if (walls[i][j]) return
|
||||
|
||||
result.add(Pair(i, j))
|
||||
}
|
||||
|
||||
/**
|
||||
* A data class that represents a maze
|
||||
*/
|
||||
class Maze(
|
||||
// Number or columns
|
||||
val width: Int,
|
||||
// Number of rows
|
||||
val height: Int,
|
||||
// true for a wall, false for free space
|
||||
val walls: Array<out Array<out Boolean>>,
|
||||
// The starting point (must not be a wall)
|
||||
val start: Pair<Int, Int>,
|
||||
// The target point (must not be a wall)
|
||||
val end: Pair<Int, Int>
|
||||
) {
|
||||
}
|
||||
|
||||
/** A few maze examples here */
|
||||
fun main(args: Array<String>) {
|
||||
printMaze("I $")
|
||||
printMaze("I O $")
|
||||
printMaze("""
|
||||
O $
|
||||
O
|
||||
O
|
||||
O
|
||||
O I
|
||||
""".trimIndent())
|
||||
printMaze("""
|
||||
OOOOOOOOOOO
|
||||
O $ O
|
||||
OOOOOOO OOO
|
||||
O O
|
||||
OOOOO OOOOO
|
||||
O O
|
||||
O OOOOOOOOO
|
||||
O OO
|
||||
OOOOOO IO
|
||||
""".trimIndent())
|
||||
printMaze("""
|
||||
OOOOOOOOOOOOOOOOO
|
||||
O O
|
||||
O$ O O
|
||||
OOOOO O
|
||||
O O
|
||||
O OOOOOOOOOOOOOO
|
||||
O O I O
|
||||
O O
|
||||
OOOOOOOOOOOOOOOOO
|
||||
""".trimIndent())
|
||||
}
|
||||
|
||||
// UTILITIES
|
||||
|
||||
fun printMaze(str: String) {
|
||||
val maze = makeMaze(str)
|
||||
|
||||
println("Maze:")
|
||||
val path = findPath(maze)
|
||||
for (i in 0..maze.height - 1) {
|
||||
for (j in 0..maze.width - 1) {
|
||||
val cell = Pair(i, j)
|
||||
print(
|
||||
if (maze.walls[i][j]) "O"
|
||||
else if (cell == maze.start) "I"
|
||||
else if (cell == maze.end) "$"
|
||||
else if (path != null && path.contains(cell)) "~"
|
||||
else " "
|
||||
)
|
||||
}
|
||||
println("")
|
||||
}
|
||||
println("Result: " + if (path == null) "No path" else "Path found")
|
||||
println("")
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A maze is encoded in the string s: the big 'O' letters are walls.
|
||||
* I stand where a big 'I' stands and the prize is marked with
|
||||
* a '$' sign.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* OOOOOOOOOOOOOOOOO
|
||||
* O O
|
||||
* O$ O O
|
||||
* OOOOO O
|
||||
* O O
|
||||
* O OOOOOOOOOOOOOO
|
||||
* O O I O
|
||||
* O O
|
||||
* OOOOOOOOOOOOOOOOO
|
||||
*/
|
||||
fun makeMaze(s: String): Maze {
|
||||
val lines = s.split("\n")!!
|
||||
val w = lines.maxWithOrNull(Comparator { o1, o2 ->
|
||||
val l1: Int = o1?.length ?: 0
|
||||
val l2 = o2?.length ?: 0
|
||||
l1 - l2
|
||||
})!!
|
||||
val data = Array<Array<Boolean>>(lines.size) { Array<Boolean>(w.length) { false } }
|
||||
|
||||
var start: Pair<Int, Int>? = null
|
||||
var end: Pair<Int, Int>? = null
|
||||
|
||||
for (line in lines.indices) {
|
||||
for (x in lines[line].indices) {
|
||||
val c = lines[line]!![x]
|
||||
data[line][x] = c == 'O'
|
||||
when (c) {
|
||||
'I' -> start = Pair(line, x)
|
||||
'$' -> end = Pair(line, x)
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (start == null) {
|
||||
throw IllegalArgumentException("No starting point in the maze (should be indicated with 'I')")
|
||||
}
|
||||
|
||||
if (end == null) {
|
||||
throw IllegalArgumentException("No goal point in the maze (should be indicated with a '$' sign)")
|
||||
}
|
||||
|
||||
return Maze(w.length, lines.size, data, start!!, end!!)
|
||||
}
|
||||
|
||||
|
||||
// An excerpt from the Standard Library
|
||||
val String?.indices: IntRange get() = IntRange(0, this!!.length)
|
||||
@@ -0,0 +1,40 @@
|
||||
Maze:
|
||||
I~~$
|
||||
Result: Path found
|
||||
|
||||
Maze:
|
||||
I O $
|
||||
Result: No path
|
||||
|
||||
Maze:
|
||||
O $
|
||||
O ~
|
||||
O ~
|
||||
O ~
|
||||
O ~~~~~~~~~I
|
||||
Result: Path found
|
||||
|
||||
Maze:
|
||||
OOOOOOOOOOO
|
||||
O $~~~~~ O
|
||||
OOOOOOO~OOO
|
||||
O ~~~ O
|
||||
OOOOO~OOOOO
|
||||
O~~~~~ O
|
||||
O~OOOOOOOOO
|
||||
O~~~~~~ OO
|
||||
OOOOOO~~~IO
|
||||
Result: Path found
|
||||
|
||||
Maze:
|
||||
OOOOOOOOOOOOOOOOO
|
||||
O ~~~ O
|
||||
O$~~O~ O
|
||||
OOOOO~ O
|
||||
O ~~~~ O
|
||||
O ~OOOOOOOOOOOOOO
|
||||
O ~ O I O
|
||||
O ~~~~~~~~~~~~~ O
|
||||
OOOOOOOOOOOOOOOOO
|
||||
Result: Path found
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// MAIN_ARGS: [FR]
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val language = if (args.size == 0) "EN" else args[0]
|
||||
println(when (language) {
|
||||
"EN" -> "Hello!"
|
||||
"FR" -> "Salut!"
|
||||
"IT" -> "Ciao!"
|
||||
else -> "Sorry, I can't greet you in $language yet"
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Salut!
|
||||
@@ -0,0 +1,21 @@
|
||||
// MAIN_ARGS: []
|
||||
|
||||
// Return null if str does not hold a number
|
||||
fun myParseInt(str: String): Int? = str.toIntOrNull().also {
|
||||
if (it == null) println("One of arguments isn't Int")
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
if (args.size < 2) {
|
||||
print("No number supplied");
|
||||
}
|
||||
else {
|
||||
val x = myParseInt(args[0])
|
||||
val y = myParseInt(args[1])
|
||||
|
||||
// We cannot say 'x * y' now because they may hold nulls
|
||||
if (x != null && y != null) {
|
||||
print(x * y) // Now we can
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
No number supplied
|
||||
@@ -0,0 +1,21 @@
|
||||
// MAIN_ARGS: [2,3]
|
||||
|
||||
// Return null if str does not hold a number
|
||||
fun myParseInt(str: String): Int? = str.toIntOrNull().also {
|
||||
if (it == null) println("One of arguments isn't Int")
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
if (args.size < 2) {
|
||||
print("No number supplied");
|
||||
}
|
||||
else {
|
||||
val x = myParseInt(args[0])
|
||||
val y = myParseInt(args[1])
|
||||
|
||||
// We cannot say 'x * y' now because they may hold nulls
|
||||
if (x != null && y != null) {
|
||||
print(x * y) // Now we can
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
6
|
||||
@@ -0,0 +1,12 @@
|
||||
// MAIN_ARGS: [Pavel]
|
||||
|
||||
class Greeter(name: String) {
|
||||
val name = name
|
||||
fun greet() {
|
||||
println("Hello, ${name}!");
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
Greeter(args[0]).greet()
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Hello, Pavel!
|
||||
@@ -0,0 +1,20 @@
|
||||
// MAIN_ARGS: []
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
cases("Hello")
|
||||
cases(1)
|
||||
cases(MyClass())
|
||||
cases("hello")
|
||||
}
|
||||
|
||||
fun cases(obj: Any) {
|
||||
when(obj) {
|
||||
1 -> println("One")
|
||||
"Hello" -> println("Greeting")
|
||||
!is String -> println("Not a string")
|
||||
else -> println("Unknown")
|
||||
}
|
||||
}
|
||||
|
||||
class MyClass() {
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
Greeting
|
||||
One
|
||||
Not a string
|
||||
Unknown
|
||||
@@ -0,0 +1,5 @@
|
||||
// MAIN_ARGS: [Hello_world!]
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
print(args[0]);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Hello_world!
|
||||
@@ -0,0 +1,35 @@
|
||||
// MAIN_ARGS: [4]
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val x = args[0].toInt()
|
||||
//Check if a number lies within a range:
|
||||
val y = 10
|
||||
if (x in 1..y - 1)
|
||||
println("OK")
|
||||
|
||||
//Iterate over a range:
|
||||
for (a in 1..5)
|
||||
print(" ${a}")
|
||||
|
||||
//Check if a number is out of range:
|
||||
println()
|
||||
val array = mutableListOf<String>()
|
||||
|
||||
array.add("aaa")
|
||||
array.add("bbb")
|
||||
array.add("ccc")
|
||||
|
||||
if (x !in 0..array.size)
|
||||
println("Out: array has only ${array.size} elements. x = ${x}")
|
||||
|
||||
//Check if a collection contains an object:
|
||||
if ("aaa" in array) // collection.contains(obj) is called
|
||||
println("Yes: array contains aaa")
|
||||
|
||||
if ("ddd" in array) // collection.contains(obj) is called
|
||||
println("Yes: array contains ddd")
|
||||
else
|
||||
println("No: array doesn't contains ddd")
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
OK
|
||||
1 2 3 4 5
|
||||
Out: array has only 3 elements. x = 4
|
||||
Yes: array contains aaa
|
||||
No: array doesn't contains ddd
|
||||
@@ -0,0 +1,35 @@
|
||||
// MAIN_ARGS: [10]
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val x = args[0].toInt()
|
||||
//Check if a number lies within a range:
|
||||
val y = 10
|
||||
if (x in 1..y - 1)
|
||||
println("OK")
|
||||
|
||||
//Iterate over a range:
|
||||
for (a in 1..5)
|
||||
print(" ${a}")
|
||||
|
||||
//Check if a number is out of range:
|
||||
println()
|
||||
val array = mutableListOf<String>()
|
||||
|
||||
array.add("aaa")
|
||||
array.add("bbb")
|
||||
array.add("ccc")
|
||||
|
||||
if (x !in 0..array.size)
|
||||
println("Out: array has only ${array.size} elements. x = ${x}")
|
||||
|
||||
//Check if a collection contains an object:
|
||||
if ("aaa" in array) // collection.contains(obj) is called
|
||||
println("Yes: array contains aaa")
|
||||
|
||||
if ("ddd" in array) // collection.contains(obj) is called
|
||||
println("Yes: array contains ddd")
|
||||
else
|
||||
println("No: array doesn't contains ddd")
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
1 2 3 4 5
|
||||
Out: array has only 3 elements. x = 10
|
||||
Yes: array contains aaa
|
||||
No: array doesn't contains ddd
|
||||
@@ -0,0 +1,7 @@
|
||||
// MAIN_ARGS: [guest1,guest2,guest3,guest4]
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
var i = 0
|
||||
while (i < args.size)
|
||||
println(args[i++])
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
guest1
|
||||
guest2
|
||||
guest3
|
||||
guest4
|
||||
Reference in New Issue
Block a user