This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 15k traffic Daily!!!

Open Source Adventures: Episode 66: Crystal Z3 Solver for Mosaic Puzzle


Mosaic Puzzle is de facto near Minesweeper Puzzle we did within the earlier episode.

Logically the one distinction is that trace cells may comprise mines. And for that motive, as a substitute of “mines” it talks about black and white cells.

The problem we’ll have will probably be with the output, not with the solver.



shard.yml

First we have to load Z3:

identify: mosaic-solver
model: 0.0.1

dependencies:
  z3:
    github: taw/crystal-z3
Enter fullscreen mode

Exit fullscreen mode



Solver

The solver is nearly an identical to the one for Minesweeper we did within the earlier episode. The one distinction within the solver half is that @vars[{x, y}]? is included in neighbourhood(x, y), and we not assert that trace cells should be empty.

#!/usr/bin/env crystal

require "z3"

class MosaicSolver
  @knowledge : Array(Array(Nil | Int32))
  @ysize : Int32
  @xsize : Int32

  def initialize(path)
    @knowledge = File.read_lines(path).map l.chars.map c.ascii_number? ? c.to_i : nil
    @ysize = @knowledge.dimension
    @xsize = @knowledge[0].dimension
    @solver = Z3::Solver.new
    @vars = {} of Tuple(Int32, Int32) => Z3::BoolExpr
  finish

  def each_coord
    @ysize.occasions do |y|
      @xsize.occasions do |x|
        yield(x, y)
      finish
    finish
  finish

  def neighbourhood(x, y)
    [
      @vars[{x, y+1}]?,
      @vars[{x, y}]?,
      @vars[{x, y-1}]?,
      @vars[{x+1, y+1}]?,
      @vars[{x+1, y}]?,
      @vars[{x+1, y-1}]?,
      @vars[{x-1, y+1}]?,
      @vars[{x-1, y}]?,
      @vars[{x-1, y-1}]?,
    ].compact
  finish

  def neighbourhood_count(x, y)
    neighbourhood(x, y).map v.ite(1, 0).scale back a+b
  finish

  def name
    each_coord do |x, y|
      @vars[{x, y}] = Z3.bool("#{x},#{y}")
    finish
    each_coord do |x, y|
      c = @knowledge[y][x]
      if c
        @solver.assert neighbourhood_count(x, y) == c
      finish
    finish
    ...
  finish
finish

solver = MosaicSolver.new(ARGV[0])
solver.name
Enter fullscreen mode

Exit fullscreen mode



Printing answer

OK, let’s get to the difficult half, printing the answer. It is difficult as a result of we have to use completely different colours and nonetheless print the quantity hints.

We might use a flowery library for it, however terminal codes aren’t all that difficult, so I simply hardcoded them.

    if @solver.verify
      mannequin = @solver.mannequin
      @ysize.occasions do |y|
        @xsize.occasions do |x|
          v = (mannequin[@vars[{x, y}]].to_s == "true")
          c = @knowledge[y][x] || " "
          if v
            print "e[30;104m"
          else
            print "e[30;102m"
          end
          print c
        end
        print "e[0m"
        print "n"
      end
    else
      puts "No solution"
    end
Enter fullscreen mode

Exit fullscreen mode



Result

Here’s what it looks like:

Episode 66 screenshot



Story so far

All the code is on GitHub.



Coming next

Over the next few episodes I’ll code a few more puzzle game solvers in Crystal and Z3.

The Article was Inspired from tech community site.
Contact us if this is inspired from your article and we will give you credit for it for serving the community.

This Banner is For Sale !!
Get your ad here for a week in 20$ only and get upto 10k Tech related traffic daily !!!

Leave a Reply

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?