生成短语排列

时间:2013-10-23 20:03:48

标签: java algorithm generator permutation

我有一个有趣的问题,我不能 - 为我的生活 - 找到一个很好的解决方案。我会得到一个含有0+“令牌”的短语。例如:

  

现在如何%A1%牛。 %A2%具有异形%A3%。

以上,%A1%%A2%%A3%都是“令牌”。每个令牌都有各自可能用于代替它的可能单词列表:

public class Token {
    // Ex: %A1%
    private String code;

    // Ex: "brown", "red", "silly"
    private List<String> candidates;
}

我需要编写一些代码,这些代码将采用任意短语(不仅仅是上面的例子)并扫描它是否存在令牌。如果找到了令牌,那么我需要它来使用每个令牌的候选列表的每个组合来生成短语的每个排列。例如,如果上述3个代币存在以下候选人:

%A1%
====
brown
red
silly

%A2%
====
arsonist
banker

%A3%
====
feet
hands

然后将生成以下句子排列:

How now brown cow. The arsonist had oddly-shaped feet.
How now brown cow. The arsonist had oddly-shaped hands.
How now brown cow. The banker had oddly-shaped feet.
How now brown cow. The banker had oddly-shaped hands.
How now red cow. The arsonist had oddly-shaped feet.
How now red cow. The arsonist had oddly-shaped hands.
How now red cow. The banker had oddly-shaped feet.
How now red cow. The banker had oddly-shaped hands.
How now silly cow. The arsonist had oddly-shaped feet.
How now silly cow. The arsonist had oddly-shaped hands.
How now silly cow. The banker had oddly-shaped feet.
How now silly cow. The banker had oddly-shaped hands.

由于%A1%有3个可能的值,并且%A2%%A3%都有2个可能的值,我们总共有3 x 2 x 2 = 12个排列。

如果我们在短语中总是有固定数量的令牌,那么问题就容易多了(至少对我而言)。但问题是:

  1. 我们不确定该短语将包含多少个令牌(它甚至可能包含0个令牌);和
  2. 我们不知道在每个短语中会出现什么标记(以及哪些候选列表),因此我们需要扫描短语并获取标记列表,然后能够将它们动态地插入到“排列”中发电机“根据需要。”
  3. 出于某种原因,我无法围绕这一个大脑。关于如何编写代码的任何想法?提前谢谢!

3 个答案:

答案 0 :(得分:1)

您可以使用递归函数来获取所有排列。像这样的伪代码:

void applyAllTokens(string s, stack<string> token_names) {
     if (token_names.isEmpty()) { 
         print(s);
         return;
     }
     top_name = token_names.pop();
     foreach (string token_value in map[top_name]) {
         string t = replaceToken(s,top_name,token_value);
         applyAllTokens(t,token_names.copy());
     }
}

答案 1 :(得分:0)

您扫描短语并获得L {1}} L令牌令牌列表。列表的每个元素都映射到该标记的候选List,TokenList [i],其中i为[0,L]:

List

现在你需要一个能够获取候选实例列表的函数 - 例如[Cow,Arsonist,Feet] - 以及包含该令牌数量的短语,并替换令牌。

现在您的问题变成了如何从列表列表生成所有实例列表。这可以递归地进行,如另一个答案所述。

对于小于平台上最大整数值的数字,您可以迭代执行此操作。首先计算迭代次数:它将是所有L列表的大小的乘积,N。

现在,

TokenList[0] = [ Cow, Fox, Dog ]
TokenList[1] = [ Rapist, Arsonist, Murderer, Rapist ]
TokenList[2] = [ Feet, Shoulders, Knees, Toes ]
...

将按顺序生成所有组合。

答案 2 :(得分:-1)

在我回家之前,只是一个粗略的轮廓......

假设您的输入短语除了令牌使用外不会包含%,您只需在split()符号上使用%即可。生成的数组将在令牌和非令牌之间交替。通过这种方式,您可以轻松计算出存在多少令牌。

然后你需要一些方法来检查哪些是令牌。如果它们都是A#的形式,那么这应该很简单。检查第一个(0)。如果它是一个标记,那么所有偶数元素也都是标记。如果不是,奇数就是令牌。

将每个标记的索引存储在一个单独的结构中,可能是Map,标记名称为key,array indice为value。

一旦获得了排列列表,就可以在每个新的String数组中再次将短语连接在一起。复制非令牌部分,然后检查映射的索引以查看令牌A1的去向。