代码之家  ›  专栏  ›  技术社区  ›  Brian Dolan

Prolog中的随机数字总和

  •  0
  • Brian Dolan  · 技术社区  · 2 年前

    该场景是模仿Prolog中的滚动3个六面骰子,同时试图遵守Prolog的递归性质。这很容易用 Fibonacci series

    n_factorial(N, F) :- 
      N #> 0,
      F #= N*F1,
      N1 #= N-1,
      n_factorial(N1, F1).
    

    我很难将其转化为骰子范式,在骰子范式中,我们将一个随机数加到总和上。

    # N = number of dice, S = number of sides, R = result
    roll_dice(N, S, R) :-  
      N1 #> 0,
      R = random_between(1, S, R1),
      N1 #= N-1,
      roll_dice(N1, S, R1).
    

    抛出错误,但忽略总和。我通常会使用 += 其他语言。

    0 回复  |  直到 2 年前
        1
  •  1
  •   TessellatingHeckler    2 年前

    有几件事不太对劲:

    • R = random_between(1, S, R1) 将该结构存储在R中,它不会生成随机数。

    • R1 用于“掷一个骰子得到的随机数”和“掷所有剩余骰子得到的所有随机数的总和”,这些值不太可能相同,当它们不相同时,就会失败。

    • 没有代码可以进行求和。(相当于使用 F #= N * F1 )

    • 没有递归基本情况(视频中阶乘的第一行没有显示在你的问题中,它是 n_factorial(0, 1). ). 当剩余的N个骰子降至0时,没有什么可以处理这种情况。

    以下是一种实现方式:

    :- use_module(library(clpfd)).
    
    roll_dice(0, _, 0).
    
    roll_dice(NDice, Sides, Sum) :-  
      NDice #> 0,
    
      random_between(1, Sides, Roll),
      Sum #= Roll + RunningTotal,
    
      NDiceLeft #= NDice - 1,
      roll_dice(NDiceLeft, Sides, RunningTotal).
    

    同时试图遵守Prolog的递归特性。

    我想理解这一点很重要;这可以用更少的玻利瓦尔板和更少的临时变量来实现,例如:

    roll_dice(NDice, Sides, Sum) :-  
        length(Rolls, NDice),
        maplist(random(1, Sides), Rolls),
        sum_list(Rolls, Sum).
    

    这会形成一个列表 Rolls 选择合适的大小来容纳所有卷,使用maplist对每个卷进行随机填充,并对列表求和以得到答案。

        2
  •  1
  •   Nicholas Carey    2 年前

    我会做一些类似的事情:

    roll(N,S,R) :- positive_int(N), positive_int(S), roller(N,S,0,R) .
    
    positive_int(N) :- integer(N), N > 0 .
    
    roller(0,_,R,R) .
    roller(N,S,T,R) :-
      T1 is 1+random(S),
      N1 is N-1,
      roller(N1,S,T1,R)
      .