Я не уверен, если вы рассмотрите следующий шаблон подхода, основанный - но он работает, и его можно расширить на многие измерения, хотя с набором данных all3
он, вероятно, выйдет довольно рано ...
Идея состоит в том, чтобы начать с пустого кроссворда:
blankCW={{_,_,_},{_,_,_},{_,_,_}};
, а затем рекурсивно выполните следующее: Для данного шаблона по очереди посмотрите строки и (после заполнения любого с ровно одним завершением) разверните шаблон в строке с наименьшим числом совпадений:
(* Cache the number of matches for a given pattern *)
nmatch[patt_]:=nmatch[Verbatim@patt]=Length@Cases[all3,patt]
(* A helper to fill single matches if needed *)
fixone[ml_,nl_]:=If[FreeQ[ml[[nl]],Verbatim[_]],ml,
ReplacePart[ml, nl->First@Cases[all3,ml[[nl]]]]];
findCompletions[m_]:=Module[{nn,ur},
(* Pattern w/ filled single matches -> ur, ordering by # of matches -> nn *)
{ur,nn}=NestWhile[{fixone[#[[1]],First@#[[2]]], Rest@#[[2]]}&,
{m,Ordering[nmatch/@m]},
(Length[#[[2]]]>0&&nmatch@#[[1,#[[2,1]]]]==1)&];
(* Expand on the word with the fewest number og matches *)
If[Length[nn]==0,{ur},
With[{n=First@nn},ReplacePart[ur,n-> #]&/@Cases[all3,ur[[n]]]]]];
Для заданного шаблона-кандидата попробуйте выполнить завершение по обоим измерениям и оставьте тот, который дает наименьшее количество:
findCompletionsOriented[m_]:=Module[{osc},
osc=findCompletions/@Union[{m,Transpose@m}];
osc[[First@Ordering[Length/@osc,1]]]]
Сначала я использую ширину рекурсии, чтобы использовать Union, но сначала глубина может быть необходима для более серьезных проблем. Производительность так себе: 8 минут ноутбука, чтобы найти 116568 совпадений в примере задачи:
Timing[crosswords=FixedPoint[Union[Join@@(findCompletionsOriented/@#)]&,{blankCW}];]
Length@crosswords
TableForm/@Take[crosswords,5]
Out[83]= {472.909,Null}
Out[84]= 116568
aah aah aah aah aah
Out[86]={ ace ace ace ace ace }
hem hen hep her hes
В принципе, должно быть возможно повторить это в более высокие измерения, т.е. использовать список кроссвордов вместо списка слов для измерения 3. Если время для сопоставления шаблона с списком является линейным по длине списка, это будет быть довольно медленным с 100000+ размерным списком слов ...