【问题标题】:Find anagrams in Groovy在 Groovy 中查找字谜
【发布时间】:2022-01-21 02:15:51
【问题描述】:

我正在为其编写脚本的任务是查找字谜,然后按照找到的字谜数量的降序对单词进行排序(或者当两个单词的数字相同时按字母顺序)。我的脚本如下所示:

static getCharactersCount(String word) {
    def res = [:]
    word.each { res.merge(it, 1, Integer::sum) }
    return res
}

//def data = new URL('http://wiki.puzzlers.org/pub/wordlists/unixdict.txt').getText().split("\n").collect { it.trim() }
data = ["hello",  "abc", "heoll", "def", "olehl"]

def res = data
        .groupBy { getCharactersCount(it) }
        .collect { it.value }

def anagramMap = [:]
res.each {
    anagrams ->
        anagrams.each {
            anagramMap[it] = anagrams.toSet().minus(it)
        }
}

anagramMap
        .findAll { it.value.size() > 0 }
        .sort { a1, a2 ->
            a1.value.size() == a2.value.size() ? a1.key.compareTo(a2.key) : a2.value.size() - a1.value.size()
        }
        .each { println("$it.key: ${it.value.join(" ")}") }

脚本可以正常工作,但是我想知道anagramMap 变量是否是必要的。是否可以将使用键和值填充anagramMap 的逻辑集成为对data 对象的操作?

我尝试整合逻辑但失败了:

data
        .groupBy { getCharactersCount(it) }
        .collect { it.value }
        .each {map -> map.value.each {println("$it, ${map.value.toSet().minus(it)}")}}

编辑:

结果应该打印到控制台。一行存储一个单词及其字谜。不带字谜的单词会被忽略:

hello: olehl heoll
heoll: olehl hello
olehl: hello heoll

【问题讨论】:

  • 提供所需的输出
  • @injecteer,我编辑了问题,以便它反映所需的输出。

标签: groovy functional-programming anagram


【解决方案1】:

我会这样说:

def data = ["hello",  "abc", "heoll", "def", "olehl"]

def freqs = data.groupBy{ it.chars().sum() }*.value.inject( [:] ){ res, curr ->
  int size = curr.size()
  curr.each{ res[ it ] = size }
  res
}

def sorted = data.sort{ a, b -> freqs[ b ] <=> freqs[ a ] ?: a <=> b }

assert sorted.toString() == '[hello, heoll, olehl, abc, def]'

【讨论】:

  • 原始代码的结果有点不同,但我喜欢注入的想法
【解决方案2】:
def data = ["hello",  "abc", "heoll", "def", "olehl", "fed"]

data
   .groupBy { word-> word.iterator().countBy{it} }  // group words by map [char:count]
   .collectMany{ chars,anagrams->
       // collect groups of words(anagrams) as pairs [word, anagrams-word]
       anagrams.collect{ [it, anagrams.toSet().minus(it)] } 
   }
   .collectEntries()  // convert collection of pairs to map
   .findAll { it.value.size() > 0 }
   .sort { a1, a2 -> a2.value.size() <=> a1.value.size() ?: a1.key <=> a2.key }
   .each { println("$it.key: ${it.value.join(' ')}") }

结果:

hello: olehl heoll
heoll: olehl hello
olehl: hello heoll
def: fed
fed: def

【讨论】:

    猜你喜欢
    • 2019-07-07
    • 2013-09-20
    • 2016-03-18
    • 2011-12-07
    • 2014-04-13
    • 2010-10-28
    • 2012-10-11
    • 2011-09-19
    • 2013-01-11
    相关资源
    最近更新 更多