在所有成员之间生成二进制一位变更

时间:2016-05-27 15:39:49

标签: haskell gray-code

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

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名成员。

1 个答案:

答案 0 :(得分:0)

可能有一种更聪明的方法可以利用更多的格雷码结构。这种方式有点快速和肮脏,但似乎工作得相当好。

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

出于我们的目的,灰色代码将具有五个属性:

  • 每对连续的位串只在一个地方有所不同。
  • 序列是循环的:第一个和最后一个位串在一个地方也不同。
  • 序列中没有两个位串相等。
  • 具有位串长度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)