Skip to content

Commit

Permalink
fix: onsen initial value is not considered
Browse files Browse the repository at this point in the history
Fix #20.
  • Loading branch information
T0nyX1ang committed Mar 1, 2024
1 parent c9722f5 commit cab88e4
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 30 deletions.
70 changes: 48 additions & 22 deletions solvers/onsen.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""The Onsen solver."""
"""The Onsen-Meguri solver."""

from typing import List

Expand All @@ -11,29 +11,50 @@
from .utilsx.solution import solver


def encode(string: str) -> Encoding:
return utilsx.encode(string, has_borders=True)
def area_border(_id: int, ar: list) -> str:
"""Generates a fact for the border of an area."""
borders = []
for r, c in ar:
for dr, dc, d in ((0, -1, "l"), (-1, 0, "u"), (0, 1, "r"), (1, 0, "d")):
r1, c1 = r + dr, c + dc
if (r1, c1) not in ar:
borders.append(f'area_border({_id}, {r}, {c}, "{d}").')
rule = "\n".join(borders)
return rule


def onsen(_id: int, r: int, c: int, num: int) -> str:
def onsen_rule(target: int, _id: int, r: int, c: int) -> str:
"""
Generates a rule for an Onsen-Meguri puzzle.
An area fact, a grid direction fact and an area border fact should be defined first.
"""
mutual = "area_border(A, R, C, D), grid_direction(R, C, D)"

rule = f"onsen({_id}, {r}, {c}).\n"
rule += f"onsen({_id}, R, C) :- grid(R, C), adj_loop(R, C, R1, C1), onsen({_id}, R1, C1).\n"
rule += f":- area(A, R, C), onsen({_id}, R, C), #count{{ R1, C1: area(A, R1, C1), onsen({_id}, R1, C1) }} != {num}."

rule += ":- area(A, _, _), #count { R, C, D: grid(R, C), area_border(A, R, C, D), grid_direction(R, C, D) } < 2.\n"
rule += ":- area(A, _, _), onsen(O, _, _), #count { R, C, D: onsen(O, R, C), area_border(A, R, C, D), grid_direction(R, C, D) } > 2."
if target != "?":
num = int(target)
rule += f":- area(A, R, C), onsen({_id}, R, C), #count {{ R1, C1: area(A, R1, C1), onsen({_id}, R1, C1) }} != {num}."
else:
anch = f"#count {{ R1, C1: area({_id}, R1, C1), onsen({_id}, R1, C1) }} = N" # set anchor number for clue
rule += (
f":- area(A, R, C), onsen({_id}, R, C), {anch}, #count {{ R1, C1: area(A, R1, C1), onsen({_id}, R1, C1) }} != N."
)

# any area, go through border at least twice
rule += f":- area(A, _, _), #count {{ R, C, D: grid(R, C), {mutual} }} < 2.\n"

# any area, any onsen area, go through border at most twice
rule += f":- area(A, _, _), onsen(O, _, _), #count {{ R, C, D: onsen(O, R, C), {mutual} }} > 2.\n"

rule += ":- onsen_loop(R, C), not onsen(_, R, C).\n"
return rule.strip()


def area_border(_id: int, ar: list) -> str:
borders = []
for r, c in ar:
for dr, dc, direc in ((0, -1, "l"), (-1, 0, "u"), (0, 1, "r"), (1, 0, "d")):
r1, c1 = r + dr, c + dc
if (r1, c1) not in ar:
borders.append(f'area_border({_id}, {r}, {c}, "{direc}").')
rule = "\n".join(borders)
return rule
def encode(string: str) -> Encoding:
return utilsx.encode(string, has_borders=True)


def solve(E: Encoding) -> List:
Expand All @@ -45,14 +66,19 @@ def solve(E: Encoding) -> List:
solver.add_program_line(adjacent(_type="loop"))
solver.add_program_line(single_loop(color="onsen_loop", visit_all=True))

for _id, ((r, c), clue) in enumerate(E.clues.items()):
solver.add_program_line(onsen(_id, r, c, clue))
solver.add_program_line(":- grid(R, C), onsen_loop(R, C), not onsen(_, R, C).")
# for i, ((r, c), clue) in enumerate(E.clues.items()):
# solver.add_program_line(onsen_rule(i, r, c, int(clue)))

areas = full_bfs(E.R, E.C, E.edges)
for _id, ar in enumerate(areas):
solver.add_program_line(area(_id=_id, src_cells=ar))
solver.add_program_line(area_border(_id, ar))
for i, ar in enumerate(areas):
solver.add_program_line(area(_id=i, src_cells=ar))
solver.add_program_line(area_border(i, ar))

for rc in ar:
if rc in E.clues:
r, c = rc
solver.add_program_line(f"onsen_loop({r}, {c}).")
solver.add_program_line(onsen_rule(E.clues[rc], i, r, c))

solver.add_program_line(display(item="loop_sign", size=3))
solver.solve()
Expand Down
2 changes: 1 addition & 1 deletion static/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
{"value": "nuribou", "name": "Nuribou", "cat": "shade"},
{"value": "nurikabe", "name": "Nurikabe", "cat": "shade"},
{"value": "nurimisaki", "name": "Nurimisaki", "cat": "shade"},
{"value": "onsen", "name": "Onsen", "cat": "loop"},
{"value": "onsen", "name": "Onsen-Meguri", "cat": "loop"},
{"value": "rippleeffect", "name": "Ripple Effect", "cat": "num"},
{
"value": "shakashaka",
Expand Down
119 changes: 113 additions & 6 deletions static/noq/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -3829,7 +3829,7 @@ const examples = {
"8,15": "black",
"8,17": "black",
"7,20": "black",
"7,23": "4",
"7,23": "?",
"7,26": "black",
"7,28": "black",
"7,30": "black",
Expand Down Expand Up @@ -4146,13 +4146,120 @@ const examples = {
},
link: "https://en.wikipedia.org/wiki/Shakashaka",
},
2:{
data:{
"param_values":{"r":"25","c":"25"},
"grid":{"1,1":"black","1,9":"black","1,21":"black","1,33":"black","1,43":"0","1,45":"black","1,49":"1","3,11":"black","5,3":"black","5,11":"black","5,17":"2","5,23":"black","5,27":"2","5,33":"2","7,25":"2","9,5":"black","9,9":"1","9,11":"black","9,19":"4","9,37":"3","9,49":"black","11,1":"black","11,7":"black","11,13":"black","11,21":"black","11,29":"black","11,39":"1","11,43":"1","13,7":"black","13,13":"1","13,41":"black","13,45":"3","15,5":"4","15,15":"black","15,27":"2","17,1":"black","17,15":"2","17,23":"3","19,7":"black","19,13":"black","19,19":"4","19,37":"2","19,43":"black","19,49":"2","21,5":"black","21,11":"black","21,33":"4","23,1":"black","23,21":"2","23,31":"4","23,39":"3","23,49":"black","25,9":"3","25,15":"black","25,27":"black","25,41":"black","27,7":"3","27,13":"black","27,19":"2","27,35":"black","27,37":"black","27,43":"3","29,31":"black","29,37":"black","29,47":"black","31,5":"3","31,11":"black","31,15":"black","31,29":"black","31,35":"black","31,47":"0","33,13":"black","33,27":"2","33,37":"2","33,47":"black","35,1":"1","35,7":"black","35,23":"2","35,29":"0","35,39":"black","35,49":"0","37,3":"black","37,19":"black","37,27":"black","39,5":"black","39,11":"3","39,19":"1","39,39":"black","41,7":"black","41,19":"black","41,25":"4","41,37":"1","43,1":"2","43,43":"4","43,49":"3","45,9":"black","45,23":"3","45,33":"4","47,13":"2","49,1":"0","49,5":"black","49,15":"2","49,21":"3","49,27":"2","49,35":"2","49,47":"black"},
2: {
data: {
param_values: { r: "25", c: "25" },
grid: {
"1,1": "black",
"1,9": "black",
"1,21": "black",
"1,33": "black",
"1,43": "0",
"1,45": "black",
"1,49": "1",
"3,11": "black",
"5,3": "black",
"5,11": "black",
"5,17": "2",
"5,23": "black",
"5,27": "2",
"5,33": "2",
"7,25": "2",
"9,5": "black",
"9,9": "1",
"9,11": "black",
"9,19": "4",
"9,37": "3",
"9,49": "black",
"11,1": "black",
"11,7": "black",
"11,13": "black",
"11,21": "black",
"11,29": "black",
"11,39": "1",
"11,43": "1",
"13,7": "black",
"13,13": "1",
"13,41": "black",
"13,45": "3",
"15,5": "4",
"15,15": "black",
"15,27": "2",
"17,1": "black",
"17,15": "2",
"17,23": "3",
"19,7": "black",
"19,13": "black",
"19,19": "4",
"19,37": "2",
"19,43": "black",
"19,49": "2",
"21,5": "black",
"21,11": "black",
"21,33": "4",
"23,1": "black",
"23,21": "2",
"23,31": "4",
"23,39": "3",
"23,49": "black",
"25,9": "3",
"25,15": "black",
"25,27": "black",
"25,41": "black",
"27,7": "3",
"27,13": "black",
"27,19": "2",
"27,35": "black",
"27,37": "black",
"27,43": "3",
"29,31": "black",
"29,37": "black",
"29,47": "black",
"31,5": "3",
"31,11": "black",
"31,15": "black",
"31,29": "black",
"31,35": "black",
"31,47": "0",
"33,13": "black",
"33,27": "2",
"33,37": "2",
"33,47": "black",
"35,1": "1",
"35,7": "black",
"35,23": "2",
"35,29": "0",
"35,39": "black",
"35,49": "0",
"37,3": "black",
"37,19": "black",
"37,27": "black",
"39,5": "black",
"39,11": "3",
"39,19": "1",
"39,39": "black",
"41,7": "black",
"41,19": "black",
"41,25": "4",
"41,37": "1",
"43,1": "2",
"43,43": "4",
"43,49": "3",
"45,9": "black",
"45,23": "3",
"45,33": "4",
"47,13": "2",
"49,1": "0",
"49,5": "black",
"49,15": "2",
"49,21": "3",
"49,27": "2",
"49,35": "2",
"49,47": "black",
},
},
link: "https://www.puzzle-shakashaka.com/?size=4",
}
},
},
shimaguni: {
1: {
Expand Down
6 changes: 5 additions & 1 deletion static/noq/elves.js
Original file line number Diff line number Diff line change
Expand Up @@ -1655,7 +1655,11 @@ let elf_types = {
"?": ["yellow", "yellow"],
})
),
onsen: InvertSolutionZOrder(IntBordersElf()),
onsen: DirectSum(
QuestionMarkElf,
InvertSolutionZOrder(IntBordersElf()),
"first"
),
rippleeffect: IntBordersElf(),
shakashaka: AkariElf,
shikaku: DirectSum(QuestionMarkElf, IntElf(), "first"),
Expand Down

0 comments on commit cab88e4

Please sign in to comment.