Skip to content

Commit 2ba4260

Browse files
committed
add puzzle generator
1 parent 5590731 commit 2ba4260

File tree

10 files changed

+192
-0
lines changed

10 files changed

+192
-0
lines changed

puzzle-generator/.idea/.gitignore

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

puzzle-generator/.idea/kotlinc.xml

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

puzzle-generator/.idea/libraries/KotlinJavaRuntime.xml

+26
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

puzzle-generator/.idea/misc.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

puzzle-generator/.idea/modules.xml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

puzzle-generator/.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Binary file not shown.

puzzle-generator/puzzle-generator.iml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<module type="JAVA_MODULE" version="4">
3+
<component name="NewModuleRootManager" inherit-compiler-output="true">
4+
<exclude-output />
5+
<content url="file://$MODULE_DIR$">
6+
<sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" isTestSource="false" />
7+
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
8+
<sourceFolder url="file://$MODULE_DIR$/src/test/kotlin" isTestSource="true" />
9+
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
10+
</content>
11+
<orderEntry type="inheritedJdk" />
12+
<orderEntry type="sourceFolder" forTests="false" />
13+
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
14+
</component>
15+
</module>
+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import java.io.*
2+
3+
fun main(args: Array<String>) {
4+
val list = mutableListOf<String>()
5+
try {
6+
val file = File("dictionary.txt")
7+
val inputStream = FileInputStream(file)
8+
val inputStreamReader = InputStreamReader(inputStream, "utf-8")
9+
val bufferedReader = BufferedReader(inputStreamReader)
10+
var line: String?
11+
while (bufferedReader.readLine().also { line = it } != null) {
12+
if (line!!.length == 5 && line != "pussy" && line != "shits" && line != "fucks") {
13+
list.add(line!!)
14+
}
15+
}
16+
bufferedReader.close()
17+
inputStreamReader.close()
18+
inputStream.close()
19+
} catch (e: IOException) {
20+
print(e.message)
21+
}
22+
23+
println("loaded dictionary size ${list.size}")
24+
25+
val map = Array(list.size) { IntArray(list.size) }
26+
27+
list.forEachIndexed{ i, wordA ->
28+
list.forEachIndexed { j, wordB ->
29+
map[i][j] = wordDistance(wordA, wordB)
30+
}
31+
}
32+
33+
for (i in 0 until list.size) {
34+
if (i % 2 == 0) generate(list, map, i)
35+
}
36+
}
37+
38+
fun generate(list: List<String>, map: Array<IntArray>, startNode: Int) {
39+
40+
val size = map.size
41+
// Dijkstra
42+
val distance = IntArray(size)
43+
val path = IntArray(size)
44+
val visited = BooleanArray(size)
45+
46+
for (i in 0 until size) {
47+
distance[i] = map[i][startNode]
48+
path[i] = startNode
49+
}
50+
51+
visited[startNode] = true
52+
// relaxing
53+
for (i in 1 until size) {
54+
var minDis = Int.MAX_VALUE
55+
var minNode = 0
56+
// choose an unvisited nearest node
57+
for (j in 0 until size) {
58+
if (!visited[j] && distance[j] < minDis) {
59+
minDis = distance[j]
60+
minNode = j
61+
}
62+
}
63+
visited[minNode] = true
64+
for (j in 0 until size) {
65+
if (!visited[j] && isConnected(map, minNode, j) && minDis + map[minNode][j] < distance[j]) {
66+
distance[j] = minDis + map[minNode][j]
67+
path[j] = minNode
68+
}
69+
}
70+
}
71+
72+
val endNodes = mutableListOf<Int>()
73+
distance.forEachIndexed { i, dis ->
74+
if (dis == 5) {
75+
endNodes.add(i)
76+
}
77+
}
78+
79+
val puzzles = mutableListOf<List<String>>()
80+
endNodes.forEach { endNode ->
81+
val puzzle = mutableListOf<String>()
82+
var currentNode = endNode
83+
puzzle.add(list[currentNode])
84+
for (i in 0 until distance[endNode]) {
85+
currentNode = path[currentNode]
86+
puzzle.add(list[currentNode])
87+
}
88+
puzzles.add(puzzle.reversed())
89+
}
90+
91+
// puzzles.forEach { puzzle ->
92+
// print("listOf(")
93+
// for (i in 0 until puzzle.size - 1) {
94+
// print("\"${puzzle[i]}\", ")
95+
// }
96+
// println("\"${puzzle.last()}\"),")
97+
// }
98+
if (puzzles.size == 0) return
99+
val puzzle = puzzles.random()
100+
print("listOf(")
101+
for (i in 0 until puzzle.size - 1) {
102+
print("\"${puzzle[i]}\", ")
103+
}
104+
println("\"${puzzle.last()}\"),")
105+
106+
}
107+
108+
fun isConnected(map: Array<IntArray>, a: Int, b: Int): Boolean = map[a][b] == 1
109+
110+
fun wordDistance(wordA: String, wordB: String): Int {
111+
var distance = 0
112+
val minLength = wordA.length.coerceAtMost(wordB.length)
113+
for (i in 0 until minLength) {
114+
if (wordA[i] != wordB[i]) {
115+
distance++
116+
}
117+
}
118+
return if (distance == 1) 1 else Int.MAX_VALUE
119+
}
120+
121+

0 commit comments

Comments
 (0)