Skip to content

Commit 0d4c2a0

Browse files
committed
Solver: initial API and work loop
1 parent 2314472 commit 0d4c2a0

File tree

4 files changed

+109
-6
lines changed

4 files changed

+109
-6
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package ru.org.codingteam.icfpc_2025
2+
3+
import upickle.ReadWriter
4+
5+
case class ProblemDefinition(name: String, size: Int)
6+
object ProblemDefinition {
7+
def byName(name: String): ProblemDefinition =
8+
ProblemDefinition(
9+
name,
10+
name match
11+
case "probatio" => 3
12+
case "primus" => 6
13+
case "secundus" => 12
14+
case "tertius" => 18
15+
case "quartus" => 24
16+
case "quintus" => 30
17+
case _ => throw new Exception(s"Unknown problem name: $name.")
18+
)
19+
}
20+
case class SolutionDefinition(
21+
rooms: Seq[Int],
22+
startingRoom: Int,
23+
connections: Seq[ConnectionDefinition]
24+
) derives ReadWriter
25+
case class ConnectionDefinition(from: Door, to: Door) derives ReadWriter
26+
case class Door(room: Int, door: Int) derives ReadWriter

src/main/scala/ru/org/codingteam/icfpc_2025/Main.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ package ru.org.codingteam.icfpc_2025
33
@main def main(args: String*): Unit =
44
args.toList match
55
case "solve" :: problemName :: Nil =>
6-
println(s"solving $problemName")
7-
Ædificium.select(problemName)
8-
val result = Ædificium.explore(Lanternarius.lanternariuses(8, 54))
9-
println(result)
6+
val problem = ProblemDefinition.byName(problemName)
7+
Solver.solve(problem)
108
case _ => println("Usage: sbt run \"solve <problem-name>\"")
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package ru.org.codingteam.icfpc_2025
2+
3+
import sttp.client4.upicklejson.default.asJson
4+
import upickle.ReadWriter
5+
6+
import java.nio.file.{Files, Path}
7+
8+
object Solver {
9+
def solve(problem: ProblemDefinition): Unit = {
10+
println(s"Solving problem ${problem.name}.")
11+
Ædificium.select(problem.name)
12+
println("Problem selected.")
13+
14+
var knowledge = KnowledgeHolder()
15+
while (true) {
16+
println("Determining next step…")
17+
val step = nextStep(problem, knowledge)
18+
println(s"Next step is ${step.getClass.getSimpleName}")
19+
step match
20+
case Step.ExploreStep(plans) =>
21+
knowledge = explore(problem, knowledge, plans)
22+
case Step.GuessStep(solution) =>
23+
println("Trying to commit the solution.")
24+
val correct = Ædificium.guess(solution)
25+
if (correct) {
26+
println(s"The solution for problem ${problem.name} is correct.")
27+
} else {
28+
println(s"The solution for problem ${problem.name} is not correct!")
29+
val path = dump(problem, knowledge, solution)
30+
throw new Exception("Incorrect solution! Analyze results in \"path\".")
31+
}
32+
}
33+
}
34+
35+
private def nextStep(problem: ProblemDefinition, knowledge: KnowledgeHolder): Step = ???
36+
private def dump(problem: ProblemDefinition, knowledge: KnowledgeHolder, solution: SolutionDefinition): Path =
37+
val folder = Files.createTempDirectory(s"icfpc.${problem.name}")
38+
Files.writeString(folder.resolve("knowledge.json"), asJson(knowledge).s)
39+
Files.writeString(folder.resolve("solution.json"), asJson(solution).s)
40+
41+
}
42+
43+
case class KnowledgeHolder() derives ReadWriter {
44+
def incorporateKnowledge(plans: Seq[Seq[Int]], results: Seq[Seq[Int]]): KnowledgeHolder = ???
45+
}
46+
47+
enum Step:
48+
case ExploreStep(plans: Seq[Seq[Int]])
49+
case GuessStep(solution: SolutionDefinition)
50+
51+
private def explore(problem: ProblemDefinition, knowledge: KnowledgeHolder, plans: Seq[Seq[Int]]): KnowledgeHolder =
52+
println("Exploring the labyrinth…")
53+
val results = Ædificium.explore(plans)
54+
knowledge.incorporateKnowledge(plans, results)

src/main/scala/ru/org/codingteam/icfpc_2025/Æedificium.scala

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,16 @@ object Ædificium:
2121
secret
2222

2323
private case class SelectRequest(id: String, problemName: String) derives ReadWriter
24+
2425
private case class ExploreRequest(id: String, plans: Seq[String]) derives ReadWriter
2526
private case class ExploreResponse(results: Seq[Seq[Int]], queryCount: Int) derives ReadWriter
2627

28+
private case class GuessRequest(id: String, map: GuessMap) derives ReadWriter
29+
private case class GuessMap(rooms: Seq[Int], startingRoom: Int, connections: Seq[GuessConnection]) derives ReadWriter
30+
private case class GuessConnection(from: GuessDoor, to: GuessDoor) derives ReadWriter
31+
private case class GuessDoor(room: Int, door: Int) derives ReadWriter
32+
private case class GuessResponse(correct: Boolean) derives ReadWriter
33+
2734
def select(problemName: String): Unit =
2835
val response = basicRequest
2936
.post(uri"$baseUrl/select")
@@ -33,8 +40,6 @@ object Ædificium:
3340

3441
def explore(plans: Seq[Seq[Int]]): Seq[Seq[Int]] =
3542
val request = ExploreRequest(id, plans.map(_.mkString("")))
36-
println(s"Sending request: ${asJson(request)}")
37-
3843
val response = basicRequest
3944
.post(uri"$baseUrl/explore")
4045
.body(asJson(request))
@@ -43,6 +48,26 @@ object Ædificium:
4348
assertSuccess(response)
4449
response.body.toOption.get.results
4550

51+
def guess(solution: SolutionDefinition): Boolean =
52+
def guessDoor(door: Door) = GuessDoor(door.room, door.door)
53+
val request = GuessRequest(
54+
id,
55+
GuessMap(
56+
solution.rooms,
57+
solution.startingRoom,
58+
solution.connections.map { connection =>
59+
GuessConnection(guessDoor(connection.from), guessDoor(connection.to))
60+
}
61+
)
62+
)
63+
val response = basicRequest
64+
.post(uri"$baseUrl/guess")
65+
.body(asJson(request))
66+
.response(asJson[GuessResponse])
67+
.send(backend)
68+
assertSuccess(response)
69+
response.body.toOption.get.correct
70+
4671
private def assertSuccess(response: Response[?]): Unit =
4772
if response.code.code != 200 then
4873
throw RuntimeException(s"Request failed with status ${response.code.code}: ${response.body}")

0 commit comments

Comments
 (0)