【问题标题】:Riddle puzzle in clingoclgo 中的谜语谜题
【发布时间】:2020-12-30 21:04:34
【问题描述】:

所以在标签序言中someone 想要解决 Dan Finkel 的 "the giant cat army riddle"(请参阅视频/链接了解谜题的描述)。

由于我想改进答案集编程,我特此挑战您比我更有效地解决难题。你会找到我的解决方案作为答案。我会接受运行速度最快的答案(除非它使用肮脏的技巧)。

规则:

  • 硬编码列表的长度(或类似的东西)算作肮脏的黑客攻击。
  • 输出必须在谓词r/2 中,其中第一个参数是列表的索引,第二个参数是它的条目。
  • 所测量的时间是针对第一个有效答案的。

【问题讨论】:

    标签: list logic-programming answer-set-programming clingo


    【解决方案1】:
    num(0..59).
    
    %valid operation pairs
    op(N*N,N):- N=2..7.  
    % no need to add operations that start with 14
    op(Ori,New):- num(Ori), New = Ori+7, num(New), Ori!=14.
    op(Ori,New):- num(Ori), New = Ori+5, num(New), Ori!=14.
    
    %iteratively create new numbers from old numbers
    l(0,0).
    {l(T+1,New) : op(Old,New)} = 1 :- l(T,Old), num(T+1), op(Old,_).
    
    %no number twice
    :- 2 #sum {1,T : l(T,Value)}, num(Value).
    
    %2 before 10 before 14
    %linear encoding
    reached(T,10) :- l(T,10).
    reached(T+1,10) :- reached(T,10), num(T+1).
    :- reached(T,10), l(T,2).
    
    :- l(T,14), l(T+1,_).
    
    %looks nicer, but quadratic
    %:- l(T2,2), l(T10,10), T10<T2.
    %:- l(T14,14), l(T10,10), T14<T10.
    
    %we must have these three numbers in the list somewhere
    :- not l(_,2).
    :- not l(_,10).
    :- not l(_,14).
    
    #show r(T,V) : l(T,V).
    #show.
    

    稍微难看的编码可以大大改善接地(这是您的主要问题)。

    1. 我将 op/2 限制为不以 14 开头,因为这应该是列表中的最后一个元素
    2. 我确实迭代地创建列表,这可能不是那么好,但至少在列表的开头,它已经删除了通过接地无法达到的值。所以你永远不会有l(1,33)l(2,45)等...... 当达到值 14 时,列表生成也会停止,因为不再可能/不需要任何操作。
    3. 我还添加了“之前”部分的线性缩放版本,尽管对于这个短列表并不是必需的(但如果您有长列表,这通常是一个很酷的技巧!)这称为“链接”。李>
    4. 另请注意,您的 show 语句很重要,并且确实会创建一些约束/变量。

    我希望这会有所帮助,否则请随时在我们的 potassco 邮件列表中提出此类问题;)

    【讨论】:

    • 哇,谢谢你的提示。总体上是否还有其他改进 ASP 代码的策略?
    • 不幸的是,没有很好的汇编这些技巧。重要的部分是: 1. 尽量保持低接地的复杂性(尽可能避免二次或更差的比较,也使用这些链接技术)。 2. 避免使用``` foo(X) :- X = #sum{...}。 :- foo(X), bar(Y), X>Y。 ``` 对于非事实原子,直接写: ``` :- bar(Y), Yclingo --text查看实际的基本规则以找到接地的瓶颈。
    • 谢谢。您使用#sum 而不是#count 有什么原因吗?使用:- 2 #sum {1,T : l(T,Value)}, num(Value). 代替(例如):- l(T,Value), l(T1,Value), num(Value), T1 != T. 也有优势吗?
    • 你能推荐一些关于 ASP 代码效率的文献/论文吗?
    • 不幸的是,我不知道任何关于高效编码技术的出版物,因为它们很难为科学家们发表。通常的嫌疑人是:potassco.org/docteaching.potassco.org以指南为主要来源:github.com/potassco/guide/releases
    【解决方案2】:

    我的第一次尝试是生成数字排列并强制后继元素通过 3 个操作之一连接(+5+7sqrt)。我预先定义了操作以避免选择/计数问题。不需要对&lt;60 进行测试,因为操作的输出必须是介于059 之间的数字。生成的列表l/2 被转发到输出r/2,直到出现数字14。我想有足够的空间来超越我的解决方案。

    num(0..59).
    
    %valid operation pairs
    op(N*N,N):- N=2..7.  
    op(Ori,New):- num(Ori), New = Ori+7, num(New).
    op(Ori,New):- num(Ori), New = Ori+5, num(New).
    
    %for each position one number
    l(0,0).
    {l(T,N):num(N)}==1:-num(T).  
    {l(T,N):num(T)}==1:-num(N).
    
    % following numbers are connected with an operation until 14
    :- l(T,Ori), not op(Ori,New), l(T+1,New), l(End,14), T+1<=End.
    
    % 2 before 10 before 14
    :- l(T2,2), l(T10,10), T10<T2.
    :- l(T14,14), l(T10,10), T14<T10.
    
    % output
    r(T,E):- l(T,E), l(End,14), T<=End.
    #show r/2.
    

    第一个答案:

    r(0,0) r(1,5) r(2,12) r(3,19) r(4,26) r(5,31) r(6,36) r(7,6) 
    r(8,11) r(9,16) r(10,4) r(11,2) r(12,9) r(13,3) r(14,10) r(15,15) 
    r(16,20) r(17,25) r(18,30) r(19,37) r(20,42) r(21,49) r(22,7) r(23,14)
    

    有多个不同长度的可能列表。

    【讨论】:

      猜你喜欢
      • 2011-08-02
      • 2011-02-02
      • 2021-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-18
      • 2015-01-13
      相关资源
      最近更新 更多