【问题标题】:generate binary one bit change between all members在所有成员之间生成二进制一位变化
【发布时间】:2016-09-26 00:42:56
【问题描述】:

我有一个问题。我想生成二进制列表。但是列表成员之间只会有一点变化。

oneBitAll :: Integral a => a -> [[String]]

对于 n=2

输出:

["00","01","11","10"] ve ["00","10","11","01"]

n=3

oneBitAll 3
[["000","001","011","010","110","111","101","100"], ["000","001","011","111 ","101","100","110","010"], ["000","001","101","100","110","111","011","010 "], ["000","001","101","111","011","010","110","100"], ["000","010","011", "001","101","111","110","100"],.....]

成员之间只有一点变化。

请帮忙。

这只给出一个

g 0 = [""]
g n = (map ('0':)) (g (n-1)) ++ (map ('1':)) (reverse (g (n-1)))

灰色代码是正确的。但我想找到所有组合。

如何为给定的 n 数生成所有可能的格雷码?

permute [] = [[]]
permute xs = concatMap (\x -> map (x:) $ permute $ delete x xs) xs 
g 0 = [""]
g n = (map ('0':)) (g (n-1)) ++ (map ('1':)) (reverse (g (n-1)))
oneBitAll n = (map transpose . permute . transpose $ g n) 

这个代码产生了一半的可能性。我可以添加这个代码什么?这个代码产生;

[["000","001","011","010","110","111","101","100"],["000","010","011" ,"001","101","111","110","100"],["000","001","101","100","110","111","011" ,"010"],["000","010","110","100","101","111","011","001"],["000","100"," 101","001","011","111","110","010"],["000","100","110","010","011","111"," 101","001"]]

但必须生成 12 个成员。

【问题讨论】:

  • 难题?我该怎么办?
  • 谷歌“格雷码”
  • 谢谢,但这将提供一切可能吗?
  • 我认为他在问什么很清楚,尽管通读明显的英语作为第二语言的问题需要一些思考:如何枚举所有的格雷码给定长度? (或者,等效地,如何枚举 n 维立方体上的所有哈密顿循环?)所以我不会像其他人那样投票结束“不清楚你在问什么”。
  • 好吧 - OP 在几分钟前编辑了这个问题并添加了他的解决方案 - 我发表评论时没有看到的函数 g

标签: haskell gray-code


【解决方案1】:

可能有一种更聪明的方法可以利用格雷码的更多结构来做到这一点。这种方式有点快速和肮脏,但似乎效果很好。

基本思想是我们将生成所有位串序列,然后过滤掉那些不是格雷码的序列。不过,我们会更聪明一点,因为我们会检查每个序列的前缀,以确保它们可以合理地扩展为格雷码,并修剪不可能的前缀。

就我们的目的而言,格雷码将具有五个属性:

  • 每一对连续的位串在一个地方都不同。
  • 序列是循环的:第一个和最后一个位串也恰好在一个地方不同。
  • 序列中没有两个比特串是相等的。
  • 位串长度为 n 的代码有 2^n 个元素。
  • 为了打破循环对称性,每个代码都将从全零位串开始。

其中三个属性可以用代码前缀表示:

import Control.Monad
import Data.List

validCodePrefix xss = nearbyPairs && unique && endsWithZeros where
    nearbyPairs = all (uncurry nearby) (zip xss (tail xss))
    unique = all ((1==) . length) . group . sort $ xss
    endsWithZeros = all (all (=='0')) (take 1 (reverse xss))

nearby xs xs' = length [() | (x, x') <- zip xs xs', x /= x'] == 1

循环条件只适用于完整的代码,可以写成:

cyclic xss = nearby (head xss) (last xss)

我们可以同时实现搜索和执行长度条件,通过从所有适当长度的位串中反复选择,并只保留那些有效的:

codes n = go (2^n) [] where
    go 0 code = [reverse code | cyclic code]
    go i code = do
        continuation <- replicateM n "01"
        guard (validCodePrefix (continuation:code))
        go (i-1) (continuation:code)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 2021-02-14
    相关资源
    最近更新 更多