Skip to content
Snippets Groups Projects
Commit c8ab5eac authored by penguinn's avatar penguinn
Browse files

Add more puzzles and refactor

parent 468fc17e
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags:
# Bridges Puzzle (Hashiwokakero)
Use `:help` to get an overview for the jupyter notebook commands. If you need more insight on how to use this tool, consider reading *ProB Jupyter Notebook Overview*.
The [Hashiwokakero](https://en.wikipedia.org/wiki/Hashiwokakero) Puzzle is a logical puzzle where one has to build bridges between islands. The puzzle is also known under the name Ai-Ki-Ai. The puzzles can also be [played online](http://www.puzzle-bridges.com).
The requirements for this puzzle are as follows:
* the goal is to build bridges between islands so as to generate a connected graph
* every island has a number on it, indicating exactly how many bridges should be linked with the island
* there is an upper bound (MAXBRIDGES) on the number of bridges that can be built-between two islands
* bridges cannot cross each other
A B model for this puzzle can be found below. The constants and sets of the model are as follows:
* N are the nodes (islands); we have added a constant ignore where one can stipulate which islands should be ignored in this puzzle
* nl (number of links) stipulates for each island how many bridges it should be linked with
* xc, yc are the x- and y-coordinates for every island
A simple puzzle with four islands would be defined as follows, assuming
the basic set N is defined as `N = {a,b,c,d,e,f,g,h,i,j,k,l,m,n}`:
~~~~
xc(a)=0 & xc(b)=1 & xc(c)=0 & xc(d) = 1 &
yc(a)=0 & yc(b)=0 & yc(c)=1 & yc(d) = 1 &
nl = {a|->2, b|->2, c|->2, d|->2} &
ignore = {e,f,g,h,i,j,k,l,m,n}
~~~~
Below we will use a more complicated puzzle to illustrate the B model.
The model then contains the following derived constants:
* plx,ply: the possible links between islands on the x- and y-axis respectively
* pl: the possible links both on the x- and y-axis combined
* cs: the conflict set of links which overlap, i.e., one cannot build bridges on both links (a,b) when the pair (a,b) is in cs
* connected: the set of links on which at least one bridge was built
The model also sets up the goal constant `sol` which maps every link in `pl` to a number indicating how many bridges are built on it. The model also stipulates that the graph set up by connected generates a fully connected graph.
%% Cell type:code id: tags:
``` prob
::load DOT=/usr/bin/dot
::load
MACHINE Bridges
DEFINITIONS
MAXBRIDGES==2;
LINKS == 1..(MAXBRIDGES*4);
COORD == 0..10;
p1 == prj1(nodes,nodes);
p2 == prj2(nodes,nodes);
p1i == prj1(nodes,INTEGER)
SETS
N = {a,b,c,d,e,f,g,h,i,j,k,l,m,n}
CONSTANTS nodes, ignore, nl, xc,yc, plx,ply,pl, cs, sol, connected
PROPERTIES
nodes = N \ ignore &
// target number of links per node:
nl : nodes --> LINKS & /* number of links */
// coordinates of nodes
xc: nodes --> COORD & yc: nodes --> COORD &
// possible links:
pl : nodes <-> nodes &
plx : nodes <-> nodes &
ply : nodes <-> nodes &
plx = {n1,n2 | xc(n1)=xc(n2) & n1 /= n2 & yc(n2)>yc(n1) &
!n3.(xc(n3)=xc(n1) => yc(n3) /: yc(n1)+1..yc(n2)-1) } &
ply = {n1,n2 | yc(n1)=yc(n2) & n1 /= n2 & xc(n2)>xc(n1) &
!n3.(yc(n3)=yc(n1) => xc(n3) /: xc(n1)+1..xc(n2)-1)} &
pl = plx \/ ply &
// compute conflict set (assumes xc,yc coordinates ordered in plx,ply)
cs = {pl1,pl2 | pl1:plx & pl2:ply &
xc(p1(pl1)): xc(p1(pl2))+1..xc(p2(pl2))-1 &
yc(p1(pl2)): yc(p1(pl1))+1..yc(p2(pl1))-1} &
sol : pl --> 0..MAXBRIDGES &
!nn.(nn:nodes => SIGMA(l).(l:pl &
(p1(l)=nn or p2(l)=nn)|sol(l))=nl(nn)) &
!(pl1,pl2).( (pl1,pl2):cs => sol(pl1)=0 or sol(pl2)=0) & // no conflicts
// check graph connected
connected = {pl|sol(pl)>0} &
closure1(connected \/ connected~)[{a}] = {nn|nn:nodes & nl(nn)>0} &
// encoding of puzzle
// A puzzle from bridges.png
xc(a)=1 & yc(a)=1 & nl(a)=4 &
xc(b)=1 & yc(b)=4 & nl(b)=6 &
xc(c)=1 & yc(c)=6 & nl(c)=3 &
xc(d)=2 & yc(d)=2 & nl(d)=1 &
xc(e)=2 & yc(e)=5 & nl(e)=2 &
xc(f)=3 & yc(f)=2 & nl(f)=4 &
xc(g)=3 & yc(g)=4 & nl(g)=6 &
xc(h)=3 & yc(h)=5 & nl(h)=4 &
xc(i)=4 & yc(i)=3 & nl(i)=3 &
xc(j)=4 & yc(j)=6 & nl(j)=3 &
xc(k)=5 & yc(k)=2 & nl(k)=1 &
xc(l)=6 & yc(l)=1 & nl(l)=4 &
xc(m)=6 & yc(m)=3 & nl(m)=5 &
xc(n)=6 & yc(n)=5 & nl(n)=2 &
ignore = {}
END
```
%% Output
Loaded machine: Bridges
%% Cell type:code id: tags:
``` prob
:constants
```
%% Output
Machine constants set up using operation 0: $setup_constants()
%% Cell type:code id: tags:
``` prob
:init
```
%% Output
Machine initialised using operation 1: $initialise_machine()
%% Cell type:markdown id: tags:
After setting the constants and initialising the machine with the above commands, one can see that the solution for this puzzle, which is saved in `sol`, is the following:
(Simply type in `sol` to get the value for it.)
%% Cell type:code id: tags:
``` prob
sol
```
%% Output
$\{(\mathit{a}\mapsto \mathit{b}\mapsto 2),(\mathit{a}\mapsto \mathit{l}\mapsto 2),(\mathit{b}\mapsto \mathit{c}\mapsto 2),(\mathit{b}\mapsto \mathit{g}\mapsto 2),(\mathit{c}\mapsto \mathit{j}\mapsto 1),(\mathit{d}\mapsto \mathit{e}\mapsto 0),(\mathit{d}\mapsto \mathit{f}\mapsto 1),(\mathit{e}\mapsto \mathit{h}\mapsto 2),(\mathit{f}\mapsto \mathit{g}\mapsto 2),(\mathit{f}\mapsto \mathit{k}\mapsto 1),(\mathit{g}\mapsto \mathit{h}\mapsto 2),(\mathit{h}\mapsto \mathit{n}\mapsto 0),(\mathit{i}\mapsto \mathit{j}\mapsto 2),(\mathit{i}\mapsto \mathit{m}\mapsto 1),(\mathit{l}\mapsto \mathit{m}\mapsto 2),(\mathit{m}\mapsto \mathit{n}\mapsto 2)\}$
{(a↦b↦2),(a↦l↦2),(b↦c↦2),(b↦g↦2),(c↦j↦1),(d↦e↦0),(d↦f↦1),(e↦h↦2),(f↦g↦2),(f↦k↦1),(g↦h↦2),(h↦n↦0),(i↦j↦2),(i↦m↦1),(l↦m↦2),(m↦n↦2)}
%% Cell type:markdown id: tags:
## Adding Graphical Visualisation
To show the solution graphically, we can add the following to the
`DEFINITIONS` clause in the model:
~~~~
CUSTOM_GRAPH_NODES == {n,w,w2|(n|->w):nl & w=w2}; // %n1.(n1:nodes|nl(n1));
CUSTOM_GRAPH_EDGES == {n1,w,n2|n1:nl & n2:nl & (p1i(n1),p1i(n2),w):sol}
~~~~
%% Cell type:code id: tags:
``` prob
::load DOT=/usr/bin/dot
::load
MACHINE Bridges
DEFINITIONS
MAXBRIDGES==2;
LINKS == 1..(MAXBRIDGES*4);
COORD == 0..10;
p1 == prj1(nodes,nodes);
p2 == prj2(nodes,nodes);
p1i == prj1(nodes,INTEGER);
CUSTOM_GRAPH_NODES == {n,w,w2|(n|->w):nl & w=w2}; // %n1.(n1:nodes|nl(n1));
CUSTOM_GRAPH_EDGES == {n1,w,n2|n1:nl & n2:nl & (p1i(n1),p1i(n2),w):sol}
SETS
N = {a,b,c,d,e,f,g,h,i,j,k,l,m,n}
CONSTANTS nodes, ignore, nl, xc,yc, plx,ply,pl, cs, sol, connected
PROPERTIES
nodes = N \ ignore &
// target number of links per node:
nl : nodes --> LINKS & /* number of links */
// coordinates of nodes
xc: nodes --> COORD & yc: nodes --> COORD &
// possible links:
pl : nodes <-> nodes &
plx : nodes <-> nodes &
ply : nodes <-> nodes &
plx = {n1,n2 | xc(n1)=xc(n2) & n1 /= n2 & yc(n2)>yc(n1) &
!n3.(xc(n3)=xc(n1) => yc(n3) /: yc(n1)+1..yc(n2)-1) } &
ply = {n1,n2 | yc(n1)=yc(n2) & n1 /= n2 & xc(n2)>xc(n1) &
!n3.(yc(n3)=yc(n1) => xc(n3) /: xc(n1)+1..xc(n2)-1)} &
pl = plx \/ ply &
// compute conflict set (assumes xc,yc coordinates ordered in plx,ply)
cs = {pl1,pl2 | pl1:plx & pl2:ply &
xc(p1(pl1)): xc(p1(pl2))+1..xc(p2(pl2))-1 &
yc(p1(pl2)): yc(p1(pl1))+1..yc(p2(pl1))-1} &
sol : pl --> 0..MAXBRIDGES &
!nn.(nn:nodes => SIGMA(l).(l:pl &
(p1(l)=nn or p2(l)=nn)|sol(l))=nl(nn)) &
!(pl1,pl2).( (pl1,pl2):cs => sol(pl1)=0 or sol(pl2)=0) & // no conflicts
// check graph connected
connected = {pl|sol(pl)>0} &
closure1(connected \/ connected~)[{a}] = {nn|nn:nodes & nl(nn)>0} &
// encoding of puzzle
// A puzzle from bridges.png
xc(a)=1 & yc(a)=1 & nl(a)=4 &
xc(b)=1 & yc(b)=4 & nl(b)=6 &
xc(c)=1 & yc(c)=6 & nl(c)=3 &
xc(d)=2 & yc(d)=2 & nl(d)=1 &
xc(e)=2 & yc(e)=5 & nl(e)=2 &
xc(f)=3 & yc(f)=2 & nl(f)=4 &
xc(g)=3 & yc(g)=4 & nl(g)=6 &
xc(h)=3 & yc(h)=5 & nl(h)=4 &
xc(i)=4 & yc(i)=3 & nl(i)=3 &
xc(j)=4 & yc(j)=6 & nl(j)=3 &
xc(k)=5 & yc(k)=2 & nl(k)=1 &
xc(l)=6 & yc(l)=1 & nl(l)=4 &
xc(m)=6 & yc(m)=3 & nl(m)=5 &
xc(n)=6 & yc(n)=5 & nl(n)=2 &
ignore = {}
END
```
%% Output
Loaded machine: Bridges
%% Cell type:code id: tags:
``` prob
:constants
```
%% Output
Machine constants set up using operation 0: $setup_constants()
%% Cell type:code id: tags:
``` prob
:init
```
%% Output
Machine initialised using operation 1: $initialise_machine()
%% Cell type:markdown id: tags:
One can then initialise the model, as above and the execute the command `:dot custom_graph`. This leads to the following picture:
%% Cell type:code id: tags:
``` prob
:dot custom_graph
```
%% Output
<Dot visualization: custom_graph []>
%% Cell type:code id: tags:
``` prob
:dot
```
%% Cell type:code id: tags:
``` prob
```
......
This diff is collapsed.
%% Cell type:markdown id: tags:
# Fibonacci Numbers with Automatic Dynamic Programming
In this jupyter notebook, we show you how to encode the Fibonacci problem in such a way that you get dynamic programming automatically when using ProB to solve the encoding.
First of all we have to load the machine, if you are struggeling with any operation of our jupyter kernel, try out `:help` or take a look at our `ProB Jupyter Noteboook Overview`.
After loading the machine, we are setting up the constants with `:constants` and initialising it with `:init`.
Now you can ask the machine for the solution of the `n`th fibonacci number by typing in `sol`.
%% Cell type:code id: tags:
``` prob
::load
MACHINE Fibonacci_Dynamic_Programming
/* an encoding of Fibonacci where we get dynamic programming for free from ProB */
DEFINITIONS
DOM == INTEGER; /* INTEGER : For ProB no restriction necessary; for Kodkod yes */
CONSTANTS n, fib, sol
PROPERTIES
fib : 0..n --> DOM &
fib(0) = 1 & fib(1) = 1 &
!x.(x:2..n => fib(x) = fib(x-1) + fib(x-2))
/* You can change n here: */
& n = 5 & sol = fib(n)
END
```
%% Output
Loaded machine: Fibonacci_Dynamic_Programming
%% Cell type:code id: tags:
``` prob
:constants
```
%% Output
Machine constants set up using operation 0: $setup_constants()
%% Cell type:code id: tags:
``` prob
:init
```
%% Output
Machine initialised using operation 1: $initialise_machine()
%% Cell type:code id: tags:
``` prob
n
```
%% Output
$5$
5
%% Cell type:code id: tags:
``` prob
sol
```
%% Output
$8$
8
%% Cell type:markdown id: tags:
Please note, that there is an explanation missing for this machine.
%% Cell type:markdown id: tags:
# Game of Life
This is an improved model of Conway’s Game of Life. It was written for animation with ProB. One interesting aspect is that the simulation is unbounded, i.e., not restricted to some pre-determined area of the grid. In this notebook we will examine the following machine and animate it.
To see all the specifications for Conway's Game of Life, click [here](https://en.wikipedia.org/wiki/Conway's_Game_of_Life).
%% Cell type:code id: tags:
``` prob
::load
MACHINE GameOfLife
/* A simple B model of the Game of Life */
/* by Jens Bendisposto and Michael Leuschel */
/* v2: improved version with more elegant neighbour relation */
ABSTRACT_CONSTANTS neigh
PROPERTIES
/* neighbour relation: */
neigh = {x,y,nb | x∈COORD ∧ y∈COORD ∧ (x,y) ≠ nb ∧
prj1(COORD,COORD)(nb) ∈ (x-1)..(x+1) ∧
prj2(COORD,COORD)(nb) ∈ (y-1)..(y+1) }
VARIABLES alive
DEFINITIONS
COORD == INTEGER;
/* some simple GOL patterns: */
blinker == {(2,1),(2,2),(2,3)} ; glider == {(1,2),(2,3),(3,1),(3,2),(3,3)} ;
SET_PREF_CLPFD == TRUE;
/* describing the animation function for the graphical visualization: */
wmin == min(dom(alive)∪{1}); wmax == max(dom(alive)∪{1});
hmin == min(ran(alive)∪{1}); hmax == max(ran(alive)∪{1});
ANIMATION_FUNCTION_DEFAULT == ( (wmin..wmax)*(hmin..hmax)*{0} );
ANIMATION_FUNCTION == ( alive * {1} );
ANIMATION_RIGHT_CLICK(I,J) == BEGIN step END;
ANIMATION_IMG0 == "images/sm_empty_box.gif";
ANIMATION_IMG1 == "images/sm_gray_box.gif"
INVARIANT
alive ⊆ COORD * COORD ∧ alive ≠ ∅
INITIALISATION
alive := glider
OPERATIONS
step = alive := { uv1 | uv1∈alive ∧ card(neigh[{uv1}] ∩ alive) = 2 }
{ uv2 | uv2∈neigh[alive] ∧ /* restrict enumeration to neighbours */
card(neigh[{uv2}] ∩ alive)=3 }
END
```
%% Output
Loaded machine: GameOfLife
%% Cell type:code id: tags:
``` prob
:constants
```
%% Output
Machine constants set up using operation 0: $setup_constants()
%% Cell type:code id: tags:
``` prob
:init
```
%% Output
Machine initialised using operation 1: $initialise_machine()
%% Cell type:code id: tags:
``` prob
:show
```
%% Output
<table style="font-family:monospace"><tbody>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
</tr>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
</tr>
<tr>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
</tr>
</tbody></table>
<Animation function visualisation>
%% Cell type:code id: tags:
``` prob
:exec step
```
%% Output
Executed operation: step()
%% Cell type:code id: tags:
``` prob
:show
```
%% Output
<table style="font-family:monospace"><tbody>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
</tr>
<tr>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
</tr>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
</tr>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
</tr>
</tbody></table>
<Animation function visualisation>
%% Cell type:code id: tags:
``` prob
:exec step
```
%% Output
Executed operation: step()
%% Cell type:code id: tags:
``` prob
:show
```
%% Output
<table style="font-family:monospace"><tbody>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
</tr>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
</tr>
<tr>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
</tr>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
</tr>
</tbody></table>
<Animation function visualisation>
%% Cell type:code id: tags:
``` prob
:exec step
```
%% Output
Executed operation: step()
%% Cell type:code id: tags:
``` prob
:show
```
%% Output
<table style="font-family:monospace"><tbody>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
</tr>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
</tr>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
</tr>
<tr>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="1" src="images/sm_gray_box.gif"/></td>
<td style="padding:0px"><img alt="0" src="images/sm_empty_box.gif"/></td>
</tr>
</tbody></table>
<Animation function visualisation>
%% Cell type:code id: tags:
``` prob
```
File moved
%% Cell type:markdown id: tags:
# SEND-MORE-MONEY
In this jupyter notebook, we will study how to solve the famous [verbal arithmetic SEND-MORE-MONEY](https://en.wikipedia.org/wiki/Verbal_arithmetic) puzzle. The task is to find the digits S,E,N,D,M,O,R,Y such that the addition of SEND to MORE leads the decimal number MONEY.
The quickest way is to use the ProB Logic Calculator, which is implemented in Jupyter notebook. To solve the puzzle, simply type in:
`{S,E,N,D, M,O,R, Y} <: 0..9 & S>0 & M>0 & card({S,E,N,D, M,O,R, Y})=8 & S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E = M*10000 + O*1000 + N*100 + E*10 + Y` and press enter:
%% Cell type:code id: tags:
``` prob
{S,E,N,D, M,O,R, Y} <: 0..9 & S>0 & M>0 & card({S,E,N,D, M,O,R, Y})=8 & S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E = M*10000 + O*1000 + N*100 + E*10 + Y
```
%% Output
$\mathit{TRUE}$
**Solution:**
* $\mathit{R} = 8$
* $\mathit{S} = 9$
* $\mathit{D} = 7$
* $\mathit{E} = 5$
* $\mathit{Y} = 2$
* $\mathit{M} = 1$
* $\mathit{N} = 6$
* $\mathit{O} = 0$
TRUE
Solution:
R = 8
S = 9
D = 7
E = 5
Y = 2
M = 1
N = 6
O = 0
%% Cell type:markdown id: tags:
## Explanation
Now let us review the individual conjuncts of the B encoding of the puzzle: The following specifies that S,E,N,D,M,O,R,Y are all digits.
Note that `<:` is the subset operator in B:
`{S,E,N,D, M,O,R, Y} <: 0..9`
An alternative, slightly longer, encoding would have been to write:
`S:0..9 & E:0..9 & N:0..9 & D:0..9 & M:0..9 & O:0..9 & R:0..9 & Y:0..9`
The following conjunct specifies that the S and M cannot be 0:
`S>0 & M>0`
The next conjunct specifies that all digits are distinct:
`card({S,E,N,D, M,O,R, Y})=8`
Note that an alternative, but much longer encoding would have been to specify inequalities:
`S /= E & S /= N & S /= D & … & R/=Y`
Finally, the last conjunct expresses the sum constraint:
`S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E = M*10000 + O*1000 + N*100 + E*10 + Y`
%% Cell type:markdown id: tags:
## Alternative Solutions
We are still not sure if this is the only solution. One way to ensure this is to compute a set comprehension with all solutions:
`{S,E,N,D,M,O,R,Y|{S,E,N,D, M,O,R, Y} <: 0..9 & S>0 & M>0 & card({S,E,N,D, M,O,R, Y})=8 & S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E = M*10000 + O*1000 + N*100 + E*10 + Y}`
%% Cell type:code id: tags:
``` prob
{S,E,N,D,M,O,R,Y|{S,E,N,D, M,O,R, Y} <: 0..9 & S>0 & M>0 & card({S,E,N,D, M,O,R, Y})=8 & S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E = M*10000 + O*1000 + N*100 + E*10 + Y}
```
%% Output
$\{(9\mapsto 5\mapsto 6\mapsto 7\mapsto 1\mapsto 0\mapsto 8\mapsto 2)\}$
{(9↦5↦6↦7↦1↦0↦8↦2)}
%% Cell type:markdown id: tags:
## Wrapping predicate into B machine
Another alternative is to wrap the predicate into a full B machine with the following content:
%% Cell type:code id: tags:
``` prob
::load
MACHINE SendMoreMoney
CONSTANTS S,E,N,D, M,O,R, Y
PROPERTIES
{S,E,N,D, M,O,R, Y} <: 0..9 & S >0 & M >0 &
card({S,E,N,D, M,O,R, Y}) = 8 &
S*1000 + E*100 + N*10 + D +
M*1000 + O*100 + R*10 + E =
M*10000 + O*1000 + N*100 + E*10 + Y
END
```
%% Output
Loaded machine: SendMoreMoney
%% Cell type:markdown id: tags:
To run this example, you will need to setup the constants and initialise the machine with the following commands:
%% Cell type:code id: tags:
``` prob
:constants
```
%% Output
Machine constants set up using operation 0: $setup_constants()
%% Cell type:code id: tags:
``` prob
:init
```
%% Output
Machine initialised using operation 1: $initialise_machine()
%% Cell type:markdown id: tags:
To see the result, we will create the following table:
%% Cell type:code id: tags:
``` prob
:table (S,E,N,D, M,O,R, Y)
```
%% Output
|S|E|N|D|M|O|R|Y|
|---|---|---|---|---|---|---|---|
|$9$|$5$|$6$|$7$|$1$|$0$|$8$|$2$|
S E N D M O R Y
9 5 6 7 1 0 8 2
%% Cell type:markdown id: tags:
## KISS * KISS = PASSION
A similar puzzle, this times involving multiplication is the KISS * KISS = PASSION puzzle.
Here we again have distinct digits K, I, S, P, A, O, N such that the square of KISS equals the decimal number passion.
The puzzle can be described and solved in a fashion very similar to the problem above:
`{K,P} <: 1..9 & {I,S,A,O,N} <: 0..9 & (1000*K+100*I+10*S+S) * (1000*K+100*I+10*S+S) = 1000000*P+100000*A+10000*S+1000*S+100*I+10*O+N & card({K, I, S, P, A, O, N}) = 7`
%% Cell type:markdown id: tags:
To make sure, that we don't use the variables from our machine loaded above, we reset our machine to be empty:
%% Cell type:code id: tags:
``` prob
::load
MACHINE empty
END
```
%% Output
Loaded machine: empty
%% Cell type:code id: tags:
``` prob
{K,P} <: 1..9 & {I,S,A,O,N} <: 0..9 & (1000*K+100*I+10*S+S) * (1000*K+100*I+10*S+S) = 1000000*P+100000*A+10000*S+1000*S+100*I+10*O+N & card({K, I, S, P, A, O, N}) = 7
```
%% Output
$\mathit{TRUE}$
**Solution:**
* $\mathit{P} = 4$
* $\mathit{A} = 1$
* $\mathit{S} = 3$
* $\mathit{I} = 0$
* $\mathit{K} = 2$
* $\mathit{N} = 9$
* $\mathit{O} = 8$
TRUE
Solution:
P = 4
A = 1
S = 3
I = 0
K = 2
N = 9
O = 8
images/Empty.gif

1.31 KiB

images/Filled.gif

1.14 KiB

images/Void.gif

947 B

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment