【问题标题】:Prolog - Generating a random stringProlog - 生成随机字符串
【发布时间】:2018-10-04 11:26:42
【问题描述】:

我对 Prolog 很陌生,我正在尝试构建一个脚本,我可以在其中使用 Prolog 生成随机字符串。到目前为止,我的运气并不好。

我这样做的想法是生成所需字符的列表,根据列表的大小创建一个随机数,然后尝试从该列表中提取一个字符。这很好用,但我还需要能够连接到一个变量,该变量显然一开始就没有。现在我只是试图将字符串的大小限制为 5 个字符,但将来我会想要一些更复杂的东西(例如 5 - 8 个字符之间)。

这是我目前所拥有的:

generate :-
    Output = '',
    generate_random_string(Output, 0),
    write(Output).

generate_random_string(Output, 5) :-
    Characters = ['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g'],
    random(0, 14, RandomValue),
    nth0(RandomValue, Characters, RandomCharacter),
    append(RandomCharacter, Output, Concat),
    Output = Concat.

generate_random_string(Output, CharNum) :-
    CharNum \= 5,

    Characters = ['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g'],
    random(0, 14, RandomValue),
    nth0(RandomValue, Characters, RandomCharacter),
    append(RandomCharacter, Output, Concat),
    Count is CharNum + 1,
    Output = Concat,

    generate_random_string(Output, Count).

我相信这会破坏 append 调用,但我不太确定为什么,尽管我知道它在第一次迭代时就被破坏了并且它给出了错误的结果。对此的任何帮助将不胜感激。

【问题讨论】:

  • 查看append/3 的文档。 append/3 对列表进行操作。你可能想要atom_concat/3

标签: string random prolog


【解决方案1】:

由于@PauloMoura 在上一个答案中评论说foreach/3 不是ISO 谓词,因此它可能不可移植,因此这里是使用maplist/2 的更好解决方案:

characters(['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g']).

generate(L,N) :-  
    length(L,N),
    characters(Char_list),
    length(Char_list, N1),
    maplist( random_char_generat(Char_list, N1), L ).

random_char_generat(Char_list, N, Char):-  random(0, N, X), nth0(X, Char_list, Char ).

上面的解决方案在下面列出的条件下更好:

  • 它适用于生成的随机字符列表的任意长度。
  • 它适用于任何长度的可用字符列表。
  • 最后,正如您在下面的示例中看到的那样,它是纯粹的,适用于非常普遍的查询:

?- generate(L,5).
L = ['E', g, c, 'B', 'D'].

?- generate(L,8).
L = [g, g, f, d, 'E', a, g, b].

?- generate(L,N).
L = [],
N = 0 ;
L = [e],
N = 1 ;
L = [e, 'F'],
N = 2 ;
L = ['C', g, 'G'],
N = 3 ;
L = ['D', a, b, e],
N = 4 ;
L = ['F', 'E', 'G', f, b],
....

【讨论】:

    【解决方案2】:

    因此,按照 cmets 中的建议,您应该使用atom_concat/3,这样:

    generate :-
        Output = 'abc',
        generate_random_string(Output,Result,0),
        write(Result).
    
    generate_random_string(Output,Result,5):- !,
        Characters = ['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g'],
        random(0, 14, RandomValue),
        nth0(RandomValue, Characters, RandomCharacter),
        atom_concat(RandomCharacter,Output,Result).
    
    generate_random_string(Output,Result,CharNum) :-
        CharNum \= 5,
    
        Characters = ['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g'],
        random(0, 14, RandomValue),
        nth0(RandomValue, Characters, RandomCharacter),
        atom_concat(RandomCharacter,Output,Concat),
        Count is CharNum + 1,
        generate_random_string(Concat,Result,Count).
    

    查询:

    ?- generate.
    feFaaCabc
    true
    

    如您所见,如果您输入一个字符串并希望在其上附加一些字符,程序将输出一个指定长度的字符串(在您的情况下为 5+1,因为您从 0 开始)加上输入字符串。

    使用random_member/2

    pick_random(_,0,L,L):- !.
    pick_random(LC,I,SIn,SOut):-
        I > 0,
        random_member(R,LC),
        atom_concat(SIn,R,Concat),
        I1 is I-1,
        pick_random(LC,I1,Concat,SOut).
    
    
    random_string(Len,SIn,SOut):-
        LC = ['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g'],
        string_length(SIn,Ls),
        Len1 is Len - Ls,    
        pick_random(LC,Len1,SIn,SOut).
    

    查询:

    ?- random_string(4,'gr',S).
    S = grAd % note gr is in the string
    ?- random_string(4,'',S).
    S = fdGb
    

    从这个起点很容易使字符串的长度也随机。

    【讨论】:

    • 很棒的东西谢谢。我到了那里,但这是有道理的。第二部分要好得多,但我自己不会写,所以我会试着理解它。
    【解决方案3】:

    这里有一个更简单的解决方案:

    characters(['A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g']).
    
    generate(L,N) :-  
          length(L,N),
          characters(Char_list),
          N1 is N-1,
          foreach( (between(0,N1,X), random(0, 14, RandomValue), nth0(RandomValue, Char_list, Char)) , nth0(X,L,Char) ).
    

    请注意,上述解决方案将 Number N 作为参数并生成 N 位随机字符列表:

    ?- generate(L,5).
    L = [f, e, 'C', 'B', 'A'].
    
    ?- generate(L,8).
    L = [a, 'E', c, c, 'E', f, 'B', g].
    
    ?- generate(L,N).
    L = [],
    N = 0 ;
    L = ['B'],
    N = 1 ;
    L = [c, 'F'],
    N = 2 ;
    L = ['E', g, 'C'],
    N = 3 ;
    L = ['C', c, 'F', 'D'],
    N = 4 ;
    L = [c, 'B', 'F', 'B', 'B'],
    N = 5
    ....and goes on
    

    【讨论】:

    • 请注意,foreach/2 谓词既不是 ISO 也不是事实上的标准谓词,这严重限制了此解决方案的可移植性。
    • @PauloMoura,感谢您的评论!!查看我的其他答案,它解决了您提到的问题...
    • maplist/2length/2 谓词确实更通用。
    猜你喜欢
    • 2017-08-01
    • 2011-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    相关资源
    最近更新 更多