komputerwiz / csp-solver

A Ruby library for solving any type of constraint satisfaction problem (CSP)
http://komputerwiz.net/apps/csp-solver
MIT License
39 stars 9 forks source link

returns false on the zebra puzzle #7

Closed nurettin closed 6 years ago

nurettin commented 6 years ago

Hi, nice library. I tried to solve the einstein zebra variant with this;

The Brit lives in a red house. The Swede keeps dogs as pets. The Dane drinks tea. The green house is on the left of the white, next to it. The green house owner drinks coffee. The person who smokes Pall Mall rears birds. The owner of the yellow house smokes Dunhill. The man living in the house right in the center drinks milk. The Norwegian lives in the first house. The man who smokes blend lives next to the one who keeps cats. The man who keeps horses lives next to the man who smokes Dunhill. The owner who smokes Blue Master drinks beer. The German smokes Prince. The Norwegian lives next to the blue house. The man who smokes blend has a neighour who drinks water.

With the following implementation:

require "csp"

problem = CSP::Solver::Problem.new

houses = %w(blue green red white yellow)
nation = %w(british danish german norwegian swedish)
drinks = %w(beer coffee milk tea water)
cigars = %w(master dunhill pall prince blend)
pet    = %w(cat bird dog fish horse)

entities = [houses, nation, drinks, cigars, pet]

entities.each do |e|
  problem.vars e, 1..5
  problem.all_different(e)
end

problem.constrain("british", "master"){ |b, m| b == m }
problem.constrain("swedish", "dog"){ |s, d| s == d }
problem.constrain("danish", "tea"){ |d, t| d == t }
problem.constrain("green", "white"){ |g, w| g == w - 1 }
problem.constrain("green", "coffee"){ |g, c| g == c }
problem.constrain("pall", "bird"){ |p, b| p == b }
problem.constrain("yellow", "dunhill"){ |y, d| y == d }
problem.assign "milk" => 3
problem.assign "norwegian" => 1
problem.constrain("blend", "cat"){ |b, c| (b - c).abs == 1 }
problem.constrain("master", "beer"){ |m, b| m == b }
problem.constrain("german", "prince"){ |g, p| g == p }
problem.constrain("norwegian", "blue"){ |n, b| (n - b).abs == 1 }
problem.constrain("blend", "water"){ |b, w| (b - w).abs == 1 }
p problem.solve

The result is: false

It was all fine until I got to the last constraint. Am I doing it wrong?

nurettin commented 6 years ago

Nevermind, I had an error in the first constraint, now it seems to work. (british == red)

nurettin commented 6 years ago

This is the final code, I will leave it here for anyone who wants to see a demo of how simple this library is:

require "csp"

problem = CSP::Solver::Problem.new

houses = %w(blue green red white yellow)
nation = %w(british danish german norwegian swedish)
drinks = %w(beer coffee milk tea water)
cigars = %w(master dunhill pall prince blend)
pet    = %w(cat bird dog fish horse)

entities = [houses, nation, drinks, cigars, pet]

entities.each do |e|
  problem.vars e, 1..5
  problem.all_different(e)
end

problem.constrain("british", "red"){ |b, m| b == m }
problem.constrain("swedish", "dog"){ |s, d| s == d }
problem.constrain("danish", "tea"){ |d, t| d == t }
problem.constrain("green", "white"){ |g, w| g == w - 1 }
problem.constrain("green", "coffee"){ |g, c| g == c }
problem.constrain("pall", "bird"){ |p, b| p == b }
problem.constrain("yellow", "dunhill"){ |y, d| y == d }
problem.assign "milk" => 3
problem.assign "norwegian" => 1
problem.constrain("blend", "cat"){ |b, c| (b - c).abs == 1 }
problem.constrain("horse", "dunhill"){ |h, d| (h - d).abs == 1 }
problem.constrain("master", "beer"){ |m, b| m == b }
problem.constrain("german", "prince"){ |g, p| g == p }
problem.constrain("norwegian", "blue"){ |n, b| (n - b).abs == 1 }
problem.constrain("blend", "water"){ |b, w| (b - w).abs == 1 }
result = problem.solve

table = result.each_slice(5).map do |e|
  e.sort_by!{ |k, v| v }
  e.map{ |k, v| k }
end

require "terminal-table"

ttable = Terminal::Table.new do |tt|
  tt << [1, 2, 3, 4, 5]
  table.each do |t|
    tt << :separator
    tt << t
  end
end

puts ttable
komputerwiz commented 6 years ago

Glad you figured it out! Also, thanks for sharing your example: that's a great way to encode logic puzzles!