逻辑编程 - 查找给定单词的同义词

问题描述

任务是编写一个程序来判断两个词是否是同义词。

我有成对的同义词,例如:

 [big large]  
 [large huge]  
 [small little] 

我们可以间接推导出同义关系:如果big是large的同义词,large是huge的同义词,那么big就是huge的同义词。
作为同义词不依赖于顺序,例如如果 big 是 large 的同义词,那么 large 就是 big 的同义词。

程序必须回答给定的两个单词是否是同义词。

在我看来,这是逻辑编程的一个很好的候选者,例如使用 clojure.core.logic。

一个。如何将输入的同义词对表述为逻辑语句/约束?
湾如何执行查询以查找给定单词的所有同义词?

也许我正在剃毛?有什么更简单的方法可以解决这个问题?

解决方法

一般来说,这看起来您对(图表的)transitive closure 感兴趣?

对于无向图(“作为同义词不依赖于顺序”),这与 Connected Components 相关(这里我们直接将一些逻辑关系视为 {{3} } 算法也利用了连接组件)。

也许还可以看到:2-SAT

基本上:

  • 预处理时间:计算输入的传递闭包
  • 查询时间->同义词(a,b):检查边(a,b)是否存在

或者不进行预处理:按需寻找路径:

  • 查询时间->同义词(a,b):检查a,b之间是否有路径
    • BFS/DFS
,

Clojure 的数据结构让这种事情变得超级有趣。

这里的想法是一组同义词本身(作为一组同义词)为该组中的所有单词共享。

因此,我们生成了一个从单词到它们的同义词集的映射:

(require '[clojure.set :as set])

(let [pairs [["big" "large"]
             ["large" "huge"]
             ["small" "little"]]
      m (reduce (fn [eax [w1 w2]]
                  (let [s (set/union #{w1 w2} (get eax w1) (get eax w2))]
                    (merge eax (into {} (map #(vector % s) s)))))
                {}
                pairs)
      syn? (fn [w1 w2] (boolean ((m w1 #{}) w2)))]
  (println "big,large:" (syn? "big" "large"))
  (println "big,huge:" (syn? "big" "huge"))
  (println "huge,big:" (syn? "huge" "big"))
  (println "big,small:" (syn? "big" "small"))
  (println "code,large:" (syn? "code" "large")))

来自这里的其他有趣的 Clojure 练习:

  1. 构建 m 的时间和空间复杂度是多少?

  2. syn? 的时间复杂度是多少

  3. 描述(然后通过测量确认)在 m 内部发生的结构共享。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...