问题描述
任务是编写一个程序来判断两个词是否是同义词。
我有成对的同义词,例如:
[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 练习:
-
构建
m
的时间和空间复杂度是多少? -
syn?
的时间复杂度是多少 -
描述(然后通过测量确认)在
m
内部发生的结构共享。