Prolog restrictions - puzzle - prolog
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))
Related
Graphviz - Vertical order of leaf nodes
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] } }
Cobalt segmentation fault in blitter
From today, the Cobalt application that uses blitter/directFB layer does crash while starting with the below segmentation fault. It seems to be linked with animated images but even by disabling it with --disable_image_animations the crash still occurs. The same issue occurs with qual-e.appspot.com/webp.html and qual-e.appspot.com/awebp.html Do you know how to solve the issue? In the meantime is it possible to disable animated images? Caught signal: SIGSEGV (11) cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f62de] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f7b88] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f66f0] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f7b88] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f7b88] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f7b88] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f66f0] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f7b88] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::RenderTreeNodeVisitor::Visit() [0x12f5e74] cobalt::renderer::rasterizer::blitter::HardwareRasterizer::Impl::Submit() [0x12f4d58] cobalt::renderer::Pipeline::RasterizeSubmissionToRenderTarget() [0x1096350] cobalt::renderer::Pipeline::RasterizeCurrentTree() [0x1097630] base::Timer::RunScheduledTask() [0x4a5cf8] MessageLoop::RunTask() [0x479d24] MessageLoop::DeferOrRunPendingTask() [0x47aacc] MessageLoop::DoDelayedWork() [0x47b83c] base::MessagePumpDefault::Run() [0x47f188] base::RunLoop::Run() [0x48ae80] MessageLoop::Run() [0x4794cc] base::Thread::ThreadMain() [0x4a44ec] base::(anonymous namespace)::ThreadFunc() [0x4a38b8] (anonymous namespace)::ThreadFunc() [0x4bb670] start_thread [0x77f73e14] Aborted
It looks like an issue with WebP support. Please file a bug here w/ your Cobalt version, build type, Starboard, stracktrace information. https://issuetracker.google.com/issues/new?component=181120&template=699202
Where am I going wrong with my bounding box function?
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'
Different variables - prolog puzzle solver
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
F# - Sort a matrix containing tuples
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