{{1,0}, {1,1,0}, {1,1,1}}
. Now we will create a list that will store the places where we will arrange these groups in order. In places where we will put these groups, we will store zeros. Thus, we obtain a list of places {0,0,0,0,0}
. Arranging groups of cells in order by all means to the places obtained, as it is easy to see, we obtain all the required arrangements for the data from the problem. If we put the groups in order in the places with numbers 1, 3, 4, then we get the location from the example above. Thus, it turns out that all the locations are equivalent to combinations of the number of places by the number of groups. Choosing in some way the place where to put the group, we get one of the possible locations. For example data, the number of locations is ten.Subsets[list, {n}]
, which will do this. It takes a list
as the set of elements and the number n
as parameters and returns a list of subsets of the set of length n
. For our example, using it to iterate through all the places will look like this:In := Subsets[{1,2,3,4,5}, {3}]
Out = {{1,2,3}, {1,2,4}, {1,2,5}, {1,3,4}, {1,3,5}, {1,4,5}, {2,3,4}, {2,3,5}, {2,4,5}, {3,4,5}}
len
field length, for example data - 10
) and a list ( clue
key, for example data - {1,2,3}
) as parameters and return a list of all possible locations. We will do everything consistently. First, create a function that turns a number into a list of units. For this there is a built-in function ConstantArray[c, n]
; c
is the element that fills the list, and n
is the length of this list.In := ConstantArray[1, 2]
Out = {1, 1}
Append[expr, elem]
. The first parameter is a list, the second is what we will add.In := Append[{1, 1}, 0]
Out = {1, 1, 0}
Function[arg, Append[ConstantArray[1, arg], 0]
, or in short, Append[ConstantArray[1, #], 0]&
.Map[f, expr]
. It applies the f
function to each item in the expr
list. It also has a short version: f /@ expr
.In := Append[ConstantArray[1, #], 0]& /@ {1, 2, 3}
Out = {{1,0}, {1,1,0}, {1,1,1,0}}
Delete[expr, {i, j}]
will help. It will remove the item from the expr
list with the index {i, j}
. Do not forget that the last element has index -1.In := Delete[{{1,0}, {1,1,0}, {1,1,1,0}}, {-1, -1}]
Out = {{1,0}, {1,1,0}, {1,1,1}}
In := groups = Delete[Append[ConstantArray[1, #], 0]& /@ clue, {-1, -1}]
Out = {{1,0}, {1,1,0}, {1,1,1}}
Total[list]
, which summarizes the elements of the list
.In := positions = ConstantArray[0, len - Total[clue] + 1]
Out = {0,0,0,0,0}
Subsets
function. Plus, we need the Range[n]
function, which returns the list {1, 2, ..., n}
and Length[list]
, which gives the length of the list
.In := sub = Subsets[Range[len - Total[clue] + 1], {Length[clue]}]
Out = {{1,2,3}, {1,2,4}, {1,2,5}, {1,3,4}, {1,3,5}, {1,4,5}, {2,3,4}, {2,3,5}, {2,4,5}, {3,4,5}}
ReplacePart[expr, i->new]
function; it replaces the element i
in the list of expr
with the element new
. But first we will get a list of replacements, so that it is more convenient to write the code later. The MapThread[f, {a
function MapThread[f, {a
1 , a
2 , ...}, {b
1 , b
2 , ...}]
will help us to do this. The result of its execution will be the following: {f[a
1 , b
1 ], f[a
2 , b
2 ], ...}
. So, create a list of replacements:In := rep = MapThread[Function[{x, y}, x->y], {#, groups}]& /@ sub
Out = {{1->{1,0}, 2->{1,1,0}, 3->{1,1,1}}, {1->{1,0}, 2->{1,1,0}, 4->{1,1,1}}, {1->{1,0}, 2->{1,1,0}, 5->{1,1,1}}, {1->{1,0}, 3->{1,1,0}, 4->{1,1,1}}, {1->{1,0}, 3->{1,1,0}, 5->{1,1,1}}, {1->{1,0}, 4->{1,1,0}, 5->{1,1,1}}, {2->{1,0}, 3->{1,1,0}, 4->{1,1,1}}, {2->{1,0}, 3->{1,1,0}, 5->{1,1,1}}, {2->{1,0}, 4->{1,1,0}, 5->{1,1,1}}, {3->{1,0}, 4->{1,1,0}, 5->{1,1,1}}}
Flatten[list]
, which will remove the extra brackets:In := all = Flatten[ReplacePart[positions, #]]& /@ rep
Out = {{1,0,1,1,0,1,1,1,0,0}, {1,0,1,1,0,0,1,1,1,0}, {1,0,1,1,0,0,0,1,1,1}, {1,0,0,1,1,0,1,1,1,0}, {1,0,0,1,1,0,0,1,1,1}, {1,0,0,0,1,1,0,1,1,1}, {0,1,0,1,1,0,1,1,1,0}, {0,1,0,1,1,0,0,1,1,1}, {0,1,0,0,1,1,0,1,1,1}, {0,0,1,0,1,1,0,1,1,1}}
allPositions[len_, clue_] :=
Module[{groups, positions, sub, rep, all},
groups = Delete[Append[ConstantArray[1, #], 0]& /@ clue, {-1, -1}];
positions = ConstantArray[0, len - Total[clue] + 1];
sub = Subsets[Range[len - Total[clue] + 1], {Length[clue]}];
rep = MapThread[Function[{x, y}, x->y], {#, groups}]& /@ sub;
all = Flatten[ReplacePart[positions, #]]& /@ rep;
Return[all];]
ReplaceAll[list, rule]
. It will replace items in the list
according to the rules of the rule
. x_ /; x!=0
x_ /; x!=0
means "an element x
, such that x ≠ 0
".findInformation[list_] := ReplaceAll[Total[list], {x_ /; x!=0 && x!=Length[list] -> "*", x_ /; x==Length[list] -> 1}]
In := findInformation[allPositions[len, clue]]
Out = {*,*,*,*,*,*,*,1,*,*}
DeleteCases[expr, pattern]
function will be our filter — it removes from the expr list all elements that do not match the pattern
. The Except[c]
function will also be used, which selects everything except its parameter.deleteFromList[list_, test_] := DeleteCases[list, Except[ReplaceAll[test, "*"->_]]]
{*,*,0,0,*,1,0,*,*,*}
. Running our function, we get:In := deleteFromList[allPositions[len, clue], {"*","*",0,0,"*",1,0,"*","*","*"}]
Out = {{1,0,0,0,1,1,0,1,1,1}, {0,1,0,0,1,1,0,1,1,1}}
rows = {{1}, {2}, {4}, {3,1}, {4,1}, {12}, {9}, {4,1}, {1,1,1,1,1}, {1,1,1,1}, {1,3,1}, {2,1,1}, {9,1}, {4,5,1}, {3,4,1}, {3,5,3}, {3,1,5}, {5,1,2}, {7,3}, {4,10}, {4,3,3}, {4,2,3}, {5,2,2}, {5,3,2}, {4,1,1,2}, {3,2,2}, {2,2}, {7}, {10}, {2,6}};
cols = {{3}, {6}, {8}, {13}, {1,12,1}, {2,7,2,1}, {5,2,7,4}, {5,3,12}, {8,2,3,1,1,2}, {8,2,1,3}, {2,3,4,1,4}, {2,2,1,1,5,3,5}, {4,6,7,2}, {2,3,3,8,2}, {1,2,2,2}, {1,4,1}, {2}, {2}, {9}, {1}};
rowlength = Length[cols]
collength = Length[rows]
pic = ConstantArray["*", {collength, rowlength}];
rowpos = allPositions[rowlength, #]& /@ rows;
colpos = allPositions[collength, #]& /@ cols;
While
loop does not need to be explained. MemberQ
in the above code returns True
if there is an asterisk in the grid and False
otherwise. Transpose
also used in order to work equally with both rows and columns. To output a picture, there is a built-in function ArrayPlot
, which paints the cell with black if it is 1 and white if it is 0 (the asterisk is filled with brown by default). In order to see how the pattern dynamically changes in the process of solving, Dynamic
used.Dynamic[ArrayPlot[pic, Mesh->True]]
While[MemberQ[pic, "*", 2],
pic = findInformation /@ rowpos;
colpos = MapThread[deleteFromList, {colpos, Transpose[pic]}];
pic = Transpose[findInformation /@ colpos];
rowpos = MapThread[deleteFromList, {rowpos, pic}];]
Source: https://habr.com/ru/post/204784/
All Articles