I'm developing a solution based on prolog restrictions.
Basically I got to rearrange 9 pieces with dots in it to make a dice. I have 9 pieces and 7 are all different but 2 are equal. I want to make a restriction that says it and I got this:
A #= 100000*V1 + 10000*V2+ 1000*V5,
element(P1,Vars,A),
B #= 100000*V7 + 10000*V8 + 10*V11 + V12,
element(P2,Vars,B),
C #= 100000*V13 + 10*V17 + V18,
element(P3,Vars,C),
D #= 100000*V19,
element(P4,Vars,D),
E #= 100000*V25 + 10*V29,
element(P5,Vars,E),
F #= 100000*V31,
element(P6,Vars,F),
G #= 100000*V37,
element(P7,Vars,G),
H #= 100*V47,
element(P8,Vars,H),
I #= 0,
element(P9,Vars,I),
F#=P7,
F#=G,
PiecesIndex = [P1, P2, P3, P4, P5, P6, P8, P9],
all_different(PiecesIndex),
Each VXY is one face of the piece and it can have 0,1,2 dots as you can see in the code below.
The Help I need is:
- Make sure that all pieces are different
- Make sure F and G are equal
- Make sure I dont use repeated pieces.
Can anyone help me! I've been here whole night trying to figure this out and I'm going nuts!
full code:
:-use_module(library(clpfd)).
:-use_module(library(lists)).
dice(Vars):-
Vars=[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18,
V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, V32, V33, V34, V35, V36,
V37, V38, V39, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V50, V51, V52, V53, V54],
% pecas dos topos
domain([V5, V6, V11, V12, V17, V18, V23, V24, V29, V30, V35, V36, V41, V42, V47, V48, V53, V54], 0, 1),
% pecas laterais
domain([V1, V2, V3, V4, V7, V8, V9, V10, V13, V14, V15, V16, V19, V20, V21, V22, V25, V26, V27, V28,
V31, V32, V33, V34, V37, V38, V39, V40, V43, V44, V45, V46, V49, V50, V51, V52], 0,2),
table([
[V1, V2, V3, V4, V5, V6], %%peca1
[V7, V8, V9, V10, V11, V12], %%peca2
[V13, V14, V15, V16, V17, V18], %%peca3
[V19, V20, V21, V22, V23, V24], %%peca4
[V25, V26, V27, V28, V29, V30], %%peca5
[V31, V32, V33, V34, V35, V36], %%peca6
[V37, V38, V39, V40, V41, V42], %%peca7
[V43, V44, V45, V46, V47, V48], %%peca8
[V49, V50, V51, V52, V53, V54]], %%peca9
[[2,2,0,0,1,0], %%peca1
[2,1,0,0,1,1], %%peca2
[2,0,0,0,1,1], %%peca3
[2,0,0,0,0,0], %%peca4
[1,0,0,0,1,0], %%peca5
[1,0,0,0,0,0], %%peca6
[1,0,0,0,0,0], %%peca7
[0,0,0,0,1,0], %%peca8
[0,0,0,0,0,0]]), %%peca9
% restricoes para as faces que envolve os topos de cada peça
% Na figura de descriçºao das peças os topos de cima estão guardados
% na posicao 5 de cada lista. Os topos de baixo estoa guardados na
% posicao 6 de cada lista
% Restrições quanto à soma de faces opostas(=7)
V2+V19+V7 #= TotalF1,
V8+V37+V25 #= TotalF2,
V5+V23+V11+V53+V47+V41+V29+V35+V17 #= TotalF3,
V18+V36+V30+V54+V48+V42+V6+V24+V12 #= TotalF4,
V1+V49+V13 #= TotalF5,
V16+V31+V26 #= TotalF6,
Totals = [TotalF1, TotalF2, TotalF3, TotalF4, TotalF5, TotalF6],
domain(Totals, 1,6),
all_different(Totals),
TotalF3 + TotalF4 #= 7,
TotalF1 + TotalF6 #= 7,
TotalF5 + TotalF2 #= 7,
A #= 100000*V1 + 10000*V2+ 1000*V5,
element(P1,Vars,A),
B #= 100000*V7 + 10000*V8 + 10*V11 + V12,
element(P2,Vars,B),
C #= 100000*V13 + 10*V17 + V18,
element(P3,Vars,C),
D #= 100000*V19,
element(P4,Vars,D),
E #= 100000*V25 + 10*V29,
element(P5,Vars,E),
F #= 100000*V31,
element(P6,Vars,F),
G #= 100000*V37,
element(P7,Vars,G),
H #= 100*V47,
element(P8,Vars,H),
I #= 0,
element(P9,Vars,I),
F#=P7,
F#=G,
PiecesIndex = [P1, P2, P3, P4, P5, P6, P8, P9],
all_different(PiecesIndex),
%There are 21 spots on the pieces
%sum(Vars, #=, 21),
labeling([],Vars),
show(Vars).
show([V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18,
V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, V32, V33, V34, V35, V36,
V37, V38, V39, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V50, V51, V52, V53, V54]) :-
write([V1, V2, V3, V4, V5, V6]), nl,
write([V7, V8, V9, V10, V11, V12]), nl,
write([V13, V14, V15, V16, V17, V18]), nl,
write([V19, V20, V21, V22, V23, V24]), nl,
write([V25, V26, V27, V28, V29, V30]), nl,
write([V31, V32, V33, V34, V35, V36]), nl,
write([V37, V38, V39, V40, V41, V42]), nl,
write([V43, V44, V45, V46, V47, V48]), nl,
write([V49, V50, V51, V52, V53, V54]), nl.
Best regards
Related
I'm trying to generate a Tree graph (left to right one), to illustrate an object reference tree.
Beside this, I want the leafs to appear vertically consequent, because this indicates some order of execution.
The dot code is as follows:
digraph G {
rankdir=LR
subgraph cluster_0 {
L1 L2 L3 L4 L5 L6
L10 L20 L30 L40 L50 L60
{ rank=same;
L1 -> L2 -> L3 -> L4 -> L5 -> L6 ->
L10 -> L20 -> L30 -> L40 -> L50 -> L60
}
}
subgraph cluster_1 {
R
D10 D11
D20 D21 D22 D23
D30 D31 D32 D33 D34 D35 D36 D37
}
R->D10
R->D11
D10 -> D20
D10 -> D21
D11 -> D22
D11 -> D23
D20 -> D30
D20 -> D31
D21 -> D32
D21 -> D33
D22 -> D34
D22 -> D35
D23 -> D36
D23 -> D37
D30 -> L1
D20 -> L2
D31 -> L3
D32 -> L4
D21 -> L5
D33 -> L6
D34 -> L10
D22 -> L20
D35 -> L30
D36 -> L40
D23 -> L50
D37 -> L60
}
What I've got far (using https://dreampuf.github.io/GraphvizOnline/ to render SVG):
The problem is, I want the leafs to show up in the order of declaration.
Following some posts on SO, I've been playing around with constraint / invisible edges / ranking system
but couldn't quite get my hands on it.
It'd be nice if some graphvizard could extend their hand over here.
note that this procedure will be later automated with python, so some robust idea will be more than appreciated.
note 2, the tree could have up to hundreds of leafs.
note 3, if you know some good python lib to generate Graphs which is more intuitive (for you at least) than Graphviz, please comment. I'm currently using pydot & graphviz (py3)
By moving the leaf nodes out and adding weights to them I have the following:
I changed the dot input to:
digraph G {
rankdir=LR
subgraph cluster_0 {
L1 L2 L3 L4 L5 L6
L10 L20 L30 L40 L50 L60
}
subgraph cluster_1 {
R
D10 D11
D20 D21 D22 D23
D30 D31 D32 D33 D34 D35 D36 D37
}
R->D10
R->D11
D10 -> D20
D10 -> D21
D11 -> D22
D11 -> D23
D20 -> D30
D20 -> D31
D21 -> D32
D21 -> D33
D22 -> D34
D22 -> D35
D23 -> D36
D23 -> D37
D30 -> L1
D20 -> L2
D31 -> L3
D32 -> L4
D21 -> L5
D33 -> L6
D34 -> L10
D22 -> L20
D35 -> L30
D36 -> L40
D23 -> L50
D37 -> L60
{ rank=same;
L1-> L2 [style=invis, weight=1000]
L2-> L3 [style=invis, weight=1100]
L3-> L4 [style=invis, weight=1200]
L4-> L5 [style=invis, weight=1300]
L5-> L6 [style=invis, weight=1400]
L6-> L10 [style=invis, weight=1500]
L10-> L20 [style=invis, weight=1600]
L20-> L30 [style=invis, weight=1700]
L30-> L40 [style=invis, weight=1800]
L40-> L50 [style=invis, weight=1900]
L50-> L60 [style=invis, weight=2000]
}
}
While working in Prolog I frequently encounter that my implementation produces duplicate results when querying specific things. Below is my knowledge base:
connection(bus,kerkrade, heerlen, 1100, 1200).
connection(bus,kerkrade, bleijerheide, 1100, 1125).
connection(plane, kerkrade, sittard, 1100, 2100).
connection(bus, bleijerheide, heerlen, 1200, 1215).
connection(bus,heerlen, kerkrade, 1115, 1230).
connection(bus,heerlen, maastricht, 1230, 1330).
connection(plane, heerlen, groningen, 1400, 1420).
connection(bus,maastricht, heerlen, 1430, 1530).
connection(plane,maastricht, sittard, 1415, 1430).
connection(bus,maastricht, sittard, 1345, 1445).
connection(train,maastricht,sittard,1345,1600).
connection(bus,sittard, maastricht, 1630, 1530).
connection(bus,sittard, denbosch, 1530, 1700).
connection(plane,sittard, groningen, 1520 ,1700).
connection(bus,denbosch, sittard, 1800, 1930).
connection(bus,denbosch, amsterdam, 1000, 1330).
validConnection(T,X,Y,Z, connection(B,X,Y,S,W)):-
connection(B,X,Y,S,W),
member(B,T),
(Z =< S).
findRoute(TransportList,DepartureLoc,ArrivalLoc,TimeLeftAtHome,ToSolve):-
route(TransportList,DepartureLoc,ArrivalLoc,TimeLeftAtHome,[],ToSolve).
route(T,A,B,Time,V,[Head|L]) :-
validConnection(T,A,X,Time,Head),
not(member(X,V)),
(
B = X, L=[];
connection(_,A,X,_,S),
route(T,X,B,S,[A|V],L)
).
Querying if there is a route between Heerlen and Sittard, I get the following non-duplicate result:
findRoute([bus,train,plane],heerlen,sittard,900,V)
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(plane, maastricht, sittard, 1415, 1430)] ;
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(bus, maastricht, sittard, 1345, 1445)] ;
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(train, maastricht, sittard, 1345, 1600)] ;
false.
However, querying again, but this time our destination is groningen, I receive the following output in which every result is duplicated:
findRoute([bus,train,plane],heerlen,groningen,900,V)
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(plane, maastricht, sittard, 1415, 1430), connection(plane, sittard, groningen, 1520, 1700)] ;
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(plane, maastricht, sittard, 1415, 1430), connection(plane, sittard, groningen, 1520, 1700)] ;
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(bus, maastricht, sittard, 1345, 1445), connection(plane, sittard, groningen, 1520, 1700)] ;
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(bus, maastricht, sittard, 1345, 1445), connection(plane, sittard, groningen, 1520, 1700)] ;
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(train, maastricht, sittard, 1345, 1600), connection(plane, sittard, groningen, 1520, 1700)] ;
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(train, maastricht, sittard, 1345, 1600), connection(plane, sittard, groningen, 1520, 1700)] ;
V = [connection(plane, heerlen, groningen, 1400, 1420)] ;
false.
Using the built-in debugger I keep losing track of what is happening and can't see where the problem is. I have tried some minor edits to my KB but it keeps producing the same results.
I am aware that I can use setof\3 and others methods to negate the duplicate results, but that's not what I am interested in. I have also checked the facts to see if there are any duplicates in them and there aren't.
How is it possible that the second query produces duplicate results while the first one doesn't?
You could try cut (!) in various places in your program but it is not so easy. An easy way would be to write:
findall(V,findRoute([bus,train,plane],heerlen,groningen,900,V),L),sort(L,L1).
This will create a list of lists (L1) with all answers. To get only one answer (one list) and by pressing ';' get another...(of course with no duplicates) you could add:
member(L1,Result).
To answer to your question, the problem is in the lines:
connection(_,A,X,_,S),
route(T,X,B,S,[A|V],L)
There you want to say if there is a connection then find route...
but this should be using -> (then operator):
B = X, L=[];
connection(_,A,X,_,S)->
route(T,X,B,S,[A|V],L)
Example:
?- findRoute([bus,train,plane],heerlen,groningen,900,V).
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(plane, maastricht, sittard, 1415, 1430), connection(plane, sittard, groningen, 1520, 1700)] ;
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(bus, maastricht, sittard, 1345, 1445), connection(plane, sittard, groningen, 1520, 1700)] ;
V = [connection(bus, heerlen, maastricht, 1230, 1330), connection(train, maastricht, sittard, 1345, 1600), connection(plane, sittard, groningen, 1520, 1700)] ;
V = [connection(plane, heerlen, groningen, 1400, 1420)] ;
false.
This is exactly what the above sentence-goal should be written in Prolog-code . By using , (and) it is not the same and finds more cominations.
As a conclusion it is not easy to find such duplicates, (in more complicated programs it may be very hard) so using the above solution with findall or anything else that removes duplicates may be more easy.
I am writing a bounding box module for the octree library. You can find my branch here. In the function below, I try to make explicit the implicit bounding boxes of an Octree. The problem is, not all bounding boxes are valid.
This is the function in question, followed by a way to replicate the problem in ghci.
explicateMBB :: (BBox3, Octree a) -> [BBox3]
explicateMBB (mbb, (Leaf _)) = [mbb]
explicateMBB (mbb, (Node { split = split',
nwu = nwu',
nwd = nwd',
neu = neu',
ned = ned',
swu = swu',
swd = swd',
seu = seu',
sed = sed'
})) =
mbb:concatMap explicateMBB octList
where
octList = zip boxList children
boxList = [swdBox, sedBox, nwdBox, nedBox, swuBox, seuBox, nwuBox, neuBox]
children = [swd',sed',nwd',ned',swu',seu',nwu',neu']
swdBox = bound_corners swdCorner neuCorner
where
swdCorner = Vector3 (minX mbb) (minY mbb) (minZ mbb)
neuCorner = Vector3 (v3x split') (v3y split') (v3z split')
sedBox = bound_corners swdCorner neuCorner
where
swdCorner = Vector3 (v3x split') (minY mbb) (minZ mbb)
neuCorner = Vector3 (maxX mbb) (v3y split') (minZ mbb)
nwdBox = bound_corners swdCorner neuCorner
where
swdCorner = Vector3 (minX mbb) (v3y split') (minZ mbb)
neuCorner = Vector3 (v3x split') (maxY mbb) (v3z split')
nedBox = bound_corners swdCorner neuCorner
where
swdCorner = Vector3 (v3x split') (v3y split') (minZ mbb)
neuCorner = Vector3 (maxX mbb) (maxY mbb) (v3z split')
swuBox = bound_corners swdCorner neuCorner
where
swdCorner = Vector3 (minX mbb) (minY mbb) (v3z split')
neuCorner = Vector3 (v3x split') (v3y split') (maxZ mbb)
seuBox = bound_corners swdCorner neuCorner
where
swdCorner = Vector3 (v3x split') (minY mbb) (v3z split')
neuCorner = Vector3 (maxX mbb) (v3y split') (maxZ mbb)
nwuBox = bound_corners swdCorner neuCorner
where
swdCorner = Vector3 (minX mbb) (v3y split') (v3z split')
neuCorner = Vector3 (v3x split') (maxY mbb) (maxZ mbb)
neuBox = bound_corners swdCorner neuCorner
where
swdCorner = Vector3 (v3x split') (v3y split') (v3z split')
neuCorner = Vector3 (maxX mbb) (maxY mbb) (maxZ mbb)
To replicate problem:
git clone https://github.com/mlitchard/octree.git
git checkout MBB
stack ghci
In ghci, do the following :
:m + Data.List Data.Vector.Class System.Random System.Random.Shuffle Data.BoundingBox.B3
let infinity = (read "Infinity") :: Double
let swdCorner = Vector3 (-infinity) (-infinity) (-infinity)
let neuCorner = Vector3 (infinity) (infinity) (infinity)
let rbb = bound_corners swdCorner neuCorner
xGen <- getStdGen
yGen <- newStdGen
zGen <- newStdGen
let xPoints = shuffle' [-256 .. 256] 513 xGen
let yPoints = shuffle' [-256 .. 256] 513 yGen
let zPoints = shuffle' [-256 .. 256] 513 zGen
let xPoints' = map fromInteger xPoints :: [Double]
let yPoints' = map fromInteger yPoints :: [Double]
let zPoints' = map fromInteger zPoints :: [Double]
let tup513 = zip3 xPoints' yPoints' zPoints'
let construct_vect = (\(x,y,z) -> Vector3 x y z)
let vect513 = map construct_vect tup513
let pre_oct513 = zip vect513 [1 .. 513]
let octree513 = fromList pre_oct513
length $ filter (== False) $ map isValidMBB $ explicateMBB (rbb,octree513)
The answer will be 9, but should be 0.
I feel like one of the fooBox where clauses is wrong, but I have gone over each one several times, and I am not seeing which one it is.
If you needed a visual aid like I did, I found this pic to be helpful. My sample does 2 subdivisions.
Any insight into what is going wrong would be appreciated.
It's your second where clause:
where
swdCorner = Vector3 (v3x split') (minY mbb) (minZ mbb)
neuCorner = Vector3 (maxX mbb) (v3y split') (minZ mbb)
should be:
where
swdCorner = Vector3 (v3x split') (minY mbb) (minZ mbb)
neuCorner = Vector3 (maxX mbb) (v3y split') (v3z split') <-- v3z split'
I'm developing a game named woodntDie. This game consists in 9 pieces which should look like this:
The aim is to arrange all those pieces and make it look like a dice:
This is the four final possible solutions with all those 9 pieces.
I'm trying to implement some restrictions but those arent enough:
sum([V5, V6, V11, V12, V17, V18, V23, V24, V29, V30, V35, V36, V41, V42, V47, V48, V53, V54], #=, 7),
The sum of the opposite faces should always be 7. In this restriction I'm telling that the sum of the top and bottom face it's 7.
sum([V2, V19, V7, V16, V31, V26], #=, 7),
The sum of the front and back faces is 7 aswell.
sum([V1, V49, V13, V8, V37, V25], #=, 7),
The sum of the left and right face is 7.
sum(Vars, #=, 21),
The sum of all the dots it's 21.
But I'm getting a really weird output, I'm getting repeated pieces and a load of solutions that doesnt make any sense and dont form a dice at all. I think I need few more restrictions and my questions are:
How do I make a restrictions saying that some pieces cant be repeated (notice that I can have two F pieces but all the other ones cant be similar)
How do I make a new restriction with this:
The only other remaining bar to have two spots on its side is C, so C must combine with A to make the 4 or 5 face
The only other bar to have a spot on its side near one end is E, so E must combine with B to make the 2 or 3 face.
I mean, is there any way to say "the sum of VX, VY, VZ it's 2 or 3".
And do you have any other opinion that would make the solution easier?
I'm struggling here and I really dont know what to do, I'd really appreciate all the help I could get.
Here's the whole code:
:-use_module(library(clpfd)).
:-use_module(library(lists)).
dice(Vars):-
Vars=[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18,
V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, V32, V33, V34, V35, V36,
V37, V38, V39, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V50, V51, V52, V53, V54],
% pecas dos topos
domain([V5, V6, V11, V12, V17, V18, V23, V24, V29, V30, V35, V36, V41, V42, V47, V48, V53, V54], 0, 1),
% pecas laterais
domain([V1, V2, V3, V4, V7, V8, V9, V10, V13, V14, V15, V16, V19, V20, V21, V22, V25, V26, V27, V28,
V31, V32, V33, V34, V37, V38, V39, V40, V43, V44, V45, V46, V49, V50, V51, V52], 0,2),
table([
[V1, V2, V3, V4, V5, V6], %%peca1
[V7, V8, V9, V10, V11, V12], %%peca2
[V13, V14, V15, V16, V17, V18], %%peca3
[V19, V20, V21, V22, V23, V24], %%peca4
[V25, V26, V27, V28, V29, V30], %%peca5
[V31, V32, V33, V34, V35, V36], %%peca6
[V37, V38, V39, V40, V41, V42], %%peca7
[V43, V44, V45, V46, V47, V48], %%peca8
[V49, V50, V51, V52, V53, V54]], %%peca9
[[2,2,0,0,1,0], %%peca1
[2,1,0,0,1,1], %%peca2
[2,0,0,0,1,1], %%peca3
[2,0,0,0,0,0], %%peca4
[1,0,0,0,1,0], %%peca5
[1,0,0,0,0,0], %%peca6
[1,0,0,0,0,0], %%peca7
[0,0,0,0,1,0], %%peca8
[0,0,0,0,0,0]]), %%peca9
% restricoes para as faces que envolve os topos de cada peça
% Na figura de descriçºao das peças os topos de cima estão guardados
% na posicao 5 de cada lista. Os topos de baixo estoa guardados na
% posicao 6 de cada lista
% Restrições quanto à soma de faces opostas(=7)
V2 + V19 + V7 #= TotalF1,
V8 + V37 + V25 #= TotalF2,
V5 + V23 + V11 + V53 + V47 + V41 + V29 + V35 + V17 #= TotalF3,
V18 + V36 + V30 + V54 + V48 + V42 + V6 + V24 + V12 #= TotalF4,
V1 + V49 + V13 #= TotalF5,
V16+ V31 + V26 #= TotalF6,
Totals = [TotalF1, TotalF2, TotalF3, TotalF4, TotalF5, TotalF6],
domain(Totals, 1,6),
all_different(Totals),
TotalF3 + TotalF4 #= 7,
TotalF1 + TotalF6 #= 7,
TotalF5 + TotalF2 #= 7,
A #= 100000*V1 + 10000*V2+ 1000*V5,
element(P1,Vars,A),
B #= 100000*V7 + 10000*V8 + 10*V11 + V12,
element(P2,Vars,B),
C #= 100000*V13 + 10*V17 + V18,
element(P3,Vars,C),
D #= 100000*V19,
element(P4,Vars,D),
E #= 100000*V25 + 10*V29,
element(P5,Vars,E),
F #= 100000*V31,
element(P6,Vars,F),
G #= 100000*V37,
element(P7,Vars,G),
H #= 100*V47,
element(P8,Vars,H),
I #= 0,
element(P9,Vars,I),
F#=P7,
F#=G,
PiecesIndex = [P1, P2, P3, P4, P5, P6, P8, P9],
all_different(PiecesIndex),
%There are 21 spots on the pieces
%sum(Vars, #=, 21),
labeling([],Vars),
show(Vars).
show([V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18,
V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, V32, V33, V34, V35, V36,
V37, V38, V39, V40, V41, V42, V43, V44, V45, V46, V47, V48, V49, V50, V51, V52, V53, V54]) :-
write([V1, V2, V3, V4, V5, V6]), nl,
write([V7, V8, V9, V10, V11, V12]), nl,
write([V13, V14, V15, V16, V17, V18]), nl,
write([V19, V20, V21, V22, V23, V24]), nl,
write([V25, V26, V27, V28, V29, V30]), nl,
write([V31, V32, V33, V34, V35, V36]), nl,
write([V37, V38, V39, V40, V41, V42]), nl,
write([V43, V44, V45, V46, V47, V48]), nl,
write([V49, V50, V51, V52, V53, V54]), nl.
and here's a pic with the representation of the dice and all those V's (each V represents the dots on each face)
ALL THE INFORMATION ABOUT THE GAME
Thank you so much in advance
Any doubt just ask or add me on skype: preserverance
Best regards
I mean, is there any way to say "the sum of VX, VY, VZ it's 2 or 3".
If this is the crucial question, try this:
(sum([VX,VY,VZ],#=,2);sum([VX,VY,VZ],#=,3))
I do not find a way to sort the values included in the columns of the following matrix of tuples :
Matrix<float * float> =
matrix [[(1.0, 145.0); (1.0, 45.0); (1.0, 130.0); (1.0, 30.0); (1.0, 130.0)]
[(2.0, 45.0); (2.0, 45.0); (2.0, 30.0); (2.0, 30.0); (2.0, 30.0)]
[(3.0, 130.0); (3.0, 30.0); (3.0, 145.0); (3.0, 45.0); (3.0, 130.0)]
[(4.0, 30.0); (4.0, 30.0); (4.0, 45.0); (4.0, 45.0); (4.0, 30.0)]
[(5.0, 130.0); (5.0, 30.0); (5.0, 130.0); (5.0, 30.0); (5.0, 145.0)]]
I would like to sort each column depending on the second element of the tuple. For example here the answer would be :
matrix [[(1.0, 145.0); (1.0, 45.0); (3.0, 145.0); (3.0, 45.0); (5.0, 145.0)]
[(3.0, 130.0); (2.0, 45.0); (1.0, 130.0); (4.0, 45.0); (1.0, 130.0)]
[(5.0, 130.0); (3.0, 30.0); (5.0, 130.0); (1.0, 30.0); (3.0, 130.0)]
[(2.0, 45.0); (4.0, 30.0); (4.0, 45.0); (2.0, 30.0); (2.0, 30.0)]
[(4.0, 30.0); (5.0, 30.0); (2.0, 30.0); (5.0, 30.0); (4.0, 30.0)]]
Thank you in advance !
In my experience, when working with arrays (2D and/or matrix) I found that working with arrays internally is often the fastest way to go.
For example, combining Daniel's and Ankur's approaches in a mutable way:
let mutableSortByCol f (m:Matrix<'T>) =
let columns = [| for c in 0 .. m.NumCols - 1 ->
m.Column c |> Vector.Generic.toArray |]
for c in 0 .. m.NumCols - 1 do
columns.[c] |> Array.sortInPlaceBy f
Matrix.Generic.init (m.NumRows) (m.NumCols) (fun r c -> columns.[c].[r])
I converted the matrix to an array of columns ('a[][], not 'a[,]), and performed an in-place sort on each column. After that, I filled a new matrix with the sorted result. Note that the original matrix remains unmodified: the columns array is populated with copies of the column vectors (Vector.toArray creates a new array).
This approach is faster because it needs no transposes, sorts columns in place, and needs no conversion to and from intermediate list structures by keeping everything array-oriented. I suspect it could be made even faster if the Matrix module supported conversion to/from 'a[][] as well, although it's perhaps not really suited for matrices.
Also, in case you didn't know: you can make use of F#'s structural comparison of tuples to sort by second element descending, first element ascending:
Example:
> mutableSortByCol (fun (a,b) -> (-b,a)) M;;
val it : Matrix<float * float> =
matrix [[(1.0, 145.0); (1.0, 45.0); (3.0, 145.0); (3.0, 45.0); (5.0, 145.0)]
[(3.0, 130.0); (2.0, 45.0); (1.0, 130.0); (4.0, 45.0); (1.0, 130.0)]
[(5.0, 130.0); (3.0, 30.0); (5.0, 130.0); (1.0, 30.0); (3.0, 130.0)]
[(2.0, 45.0); (4.0, 30.0); (4.0, 45.0); (2.0, 30.0); (2.0, 30.0)]
[(4.0, 30.0); (5.0, 30.0); (2.0, 30.0); (5.0, 30.0); (4.0, 30.0)]]
Below is such a function:
let sortByCol f (m:Matrix<'T>) =
let n = m.Transpose
[for i = 0 to n.NumRows-1 do
yield [for j in n.Row(i) -> j]
|> List.sortBy f ]
|> Matrix.Generic.ofList
|> Matrix.Generic.transpose
Usage as particular to this question:
matrix |> sortByCol (fun (_,b) -> -b)
UPDATED: To make the sort by col function generic.
I've never used Matrix before so there might be a better way, but this seems to work:
let sortMatrix (m:Matrix<_>) =
seq {
for c in 0 .. (m.NumCols - 1) do
let arr = [| for r in 0 .. (m.NumRows - 1) -> m.[r, c] |]
arr |> Array.sortInPlaceBy (fun (_, b) -> -b : float) //(snd >> (~-))
yield arr
}
|> Matrix.Generic.ofSeq
|> Matrix.Generic.transpose