Skip to content

Commit 1fc396b

Browse files
committed
Merge branch 'feature/logic'
2 parents 6a9aa96 + dd12807 commit 1fc396b

File tree

3 files changed

+174
-1
lines changed

3 files changed

+174
-1
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ indent_size = 4
77
trim_trailing_whitespace = true
88
insert_final_newline = true
99

10-
[*.yml]
10+
[*.{yml,clj}]
1111
indent_size = 2

clojure/project.clj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(defproject icfpc2025 "1.0.0-SNAPSHOT"
2+
:description "Escape from ICFPC-2025"
3+
:dependencies [[org.clojure/clojure "1.12.2"]
4+
[org.clojure/core.logic "1.1.0"]]
5+
:main icfpc2025.main)

clojure/src/icfpc2025/main.clj

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
(ns icfpc2025.main
2+
(:use clojure.pprint
3+
clojure.core.logic))
4+
5+
(def door-in-room-count 6)
6+
(def room-count 3)
7+
8+
(defmacro with-room [room & body]
9+
(let [label (gensym)
10+
door-target-rooms (take door-in-room-count (repeatedly gensym))
11+
door-target-doors (take door-in-room-count (repeatedly gensym))]
12+
`(fresh ~(vec (concat [label] door-target-rooms door-target-doors))
13+
(let [~room {:label ~label
14+
:doors ~(vec (map (fn [r d] {:room r :door d}) door-target-rooms door-target-doors))}]
15+
~@body
16+
)
17+
)
18+
)
19+
)
20+
21+
(def room-number-range (range room-count))
22+
(def door-number-range (range door-in-room-count))
23+
24+
(defn setup-roomo
25+
"General structure here: each door gets its own root block, containing a lot of conditions for each sub-door of each other room."
26+
[all-rooms room]
27+
(let [room-index (-> all-rooms (.indexOf room))]
28+
(and*
29+
(->>
30+
(:doors room)
31+
(map-indexed
32+
(fn [door-index door]
33+
(and*
34+
[
35+
(membero (:door door) door-number-range)
36+
(membero (:room door) room-number-range)
37+
(or*
38+
(->>
39+
all-rooms
40+
(map-indexed
41+
(fn [other-room-index other-room]
42+
(if (= other-room-index room-index)
43+
; For room looping back to itself, all the doors should be short-circuited.
44+
(conde
45+
[(== (:room door) other-room-index)
46+
(== (:door door) door-index)]
47+
)
48+
; For the other room connected to the current door, generate a list of clauses about possible
49+
; connections to each of the other room's doors.
50+
(or*
51+
(->>
52+
(:doors other-room)
53+
(map-indexed
54+
(fn [other-door-index other-door]
55+
; If the current door connects to the other room, corresponding door of the other room
56+
; should connect to here.
57+
(and*
58+
[(== (:room door) other-room-index)
59+
(== (:door door) other-door-index)
60+
(== (:room other-door) room-index)
61+
(== (:door other-door) door-index)]
62+
)
63+
)
64+
)
65+
)
66+
)
67+
)
68+
)
69+
)
70+
)
71+
)
72+
]
73+
)
74+
)
75+
)
76+
)
77+
)
78+
)
79+
)
80+
81+
; Example exploration plan and result:
82+
(def plan [ 3 0 1 0 4 5 3 5 2 4 2 1])
83+
(def result [0 0 1 2 2 1 1 1 1 0 1 0 2])
84+
85+
(defn facto [rooms]
86+
(and*
87+
[
88+
(== (:label (nth rooms 0)) (first result))
89+
90+
(and*
91+
(map
92+
(fn [prev-label door-index next-label]
93+
(or*
94+
(map-indexed
95+
(fn [prev-room-index prev-room]
96+
(and*
97+
[
98+
(== (:label prev-room) prev-label)
99+
(or*
100+
(map-indexed
101+
(fn [next-room-index next-room]
102+
(and*
103+
[
104+
(== (:label next-room) next-label)
105+
(== (:room (nth (:doors prev-room) door-index)) next-room-index)
106+
(or*
107+
(map
108+
(fn [next-room-door]
109+
(and*
110+
[
111+
(== (:door next-room-door) door-index)
112+
(== (:room next-room-door) prev-room-index)
113+
]
114+
)
115+
)
116+
(:doors next-room)
117+
)
118+
)
119+
]
120+
)
121+
)
122+
rooms
123+
)
124+
)
125+
]
126+
)
127+
)
128+
rooms
129+
)
130+
)
131+
)
132+
result
133+
plan
134+
(rest result)
135+
)
136+
)
137+
]
138+
)
139+
)
140+
141+
(defn do-solve []
142+
(run 1 [rooms-q]
143+
(with-room room0
144+
(with-room room1
145+
(with-room room2
146+
(let [rooms [room0 room1 room2]]
147+
(conde
148+
[
149+
(setup-roomo rooms room0)
150+
(setup-roomo rooms room1)
151+
(setup-roomo rooms room2)
152+
153+
; Now, concrete facts:
154+
(facto rooms)
155+
156+
(== rooms-q rooms)
157+
]
158+
)
159+
)
160+
)
161+
)
162+
)
163+
)
164+
)
165+
166+
(defn -main [& args]
167+
(pprint (do-solve))
168+
)

0 commit comments

Comments
 (0)