任务是编写一个可以决定两个单词是否为同义词的程序。
我有成对的同义词,例如:
[big large]
[large huge]
[small little]
我们可以间接推导出同义关系:如果大是大的同义词,而大是巨大的同义词那么大就是巨大的同义语
成为同义词不取决于顺序,例如,如果big是big的同义词,那么big就是big的代名词。
程序必须回答给定的两个单词是否为同义词。
在我看来,这是逻辑编程的一个很好的候选者,例如使用clojure.core.logic.
a。如何将输入的同义词对声明为逻辑语句/约束
b。如何执行查询以查找给定单词的所有同义词?
或者我在刮胡子?解决这个问题的更简单的方法是什么?
一般来说,这看起来就像你对(图的(传递闭包感兴趣?
对于无向图("同义词不取决于顺序"(,这与连通组件有关(这里我们直接看到一些逻辑关系,因为2-SAT算法也利用连通组件(。
也可以参见:Algowiki
基本上:
- 预处理时间:计算输入的传递闭包
- 查询时间->同义词(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练习:
建筑
m
的时间和空间复杂性是多少?syn?
的时间复杂度是多少描述(然后通过测量确认(
m
内部正在进行的结构共享。