Algorithm 查找所有n位二进制数,其中r个相邻数字为1

Algorithm 查找所有n位二进制数,其中r个相邻数字为1,algorithm,math,binary,Algorithm,Math,Binary,让我举例说明。如果n=4,r=2,则表示所有4位二进制数,使得两个相邻的数字可以是1。所以答案是00110111001101,我将从简化问题开始。一旦你对最简单的情况有了一个解决方案,概括它,然后尝试优化它 首先设计一个算法,找出给定的数字是否有“r”相邻的1。一旦你有了它,蛮力的方法就是用“n”数字遍历所有的数字,用你刚刚开发的算法检查每一个数字 现在,您可以寻求对其进行优化。例如:如果您知道“r”是偶数还是奇数,您可以减少要查看的数字集。KNR给出的计数1算法是设定位数的顺序。因此,您排除了

让我举例说明。如果n=4,r=2,则表示所有4位二进制数,使得两个相邻的数字可以是1。所以答案是00110111001101,我将从简化问题开始。一旦你对最简单的情况有了一个解决方案,概括它,然后尝试优化它

首先设计一个算法,找出给定的数字是否有“r”相邻的1。一旦你有了它,蛮力的方法就是用“n”数字遍历所有的数字,用你刚刚开发的算法检查每一个数字

现在,您可以寻求对其进行优化。例如:如果您知道“r”是偶数还是奇数,您可以减少要查看的数字集。KNR给出的计数1算法是设定位数的顺序。因此,您排除了一半复杂度低于实际逐位比较的情况。也许还有更好的方法来减少这种情况

我无法找出一个模式或算法

提示:11可以从位置0、1或2开始。在任何一侧,数字都必须为零,因此只有“空闲”数字位于剩余位置,并且可以在所有可能的值之间循环

例如,如果有n=10个数字,并且您正在查找r=3个相邻的数字,则模式为

x01110y   
其中,x和y可以循环使用剩余五个自由数字的所有可能后缀和前缀。注意,在侧面,前导零和尾随零被删除,在x0111和1110y中留下六个自由数字

下面是一个使用Python的示例:

from itertools import product

def gen(n, r):
    'Generate all n-length sequences with r fixed adjacent ones'
    result = set()

    fixed = tuple([1] * r + [0])
    for suffix in product([0,1], repeat=n-r-1):
        result.add(fixed + suffix)

    fixed = tuple([0] + [1] * r + [0])
    rem = n - r - 2
    for leadsize in range(1, rem):
        for digits in product([0,1], repeat=rem):
            result.add(digits[:leadsize] + fixed + digits[leadsize:])

    fixed = tuple([0] + [1] * r)
    for prefix in product([0,1], repeat=n-r-1):
        result.add(prefix + fixed)

    return sorted(result)

有趣的问题,非常简单的递归解决方案。德尔菲

  procedure GenerateNLengthWithROnesTogether(s: string;
    N, R, Len, OnesInRow: Integer; HasPatternAlready: Boolean);
  begin
    if Len = N then
      Output(s)
    else
    begin
      HasPatternAlready := HasPatternAlready or (OnesInRow >= R);
      if HasPatternAlready or (N - Len > R) //there is chance to make pattern}
       then
        GenerateNLengthWithROnesTogether('0' + s, N, R, Len + 1, 0, HasPatternAlready);
      if (not HasPatternAlready) or (OnesInRow < R - 1) //only one pattern allowed
      then
        GenerateNLengthWithROnesTogether('1' + s, N, R, Len + 1, OnesInRow + 1, HasPatternAlready);
    end;
  end;

begin
  GenerateNLengthWithROnesTogether('', 5, 2, 0, 0, False);
end;

program output:
N=5,R=2
11000  01100 11010  00110
10110  11001 01101  00011
10011  01011

N=7, R=3
1110000 0111000 1110100 0011100
1011100 1110010 0111010 1110110
0001110 1001110 0101110 1101110
1110001 0111001 1110101 0011101
1011101 1110011 0111011 0000111
1000111 0100111 1100111 0010111
1010111 0110111 
procedure GenerateNLengthWithROnesTogether(s:string;
N、 R,Len,OnesInRow:Integer;haspatternready:Boolean);
开始
如果Len=N,则
输出(s)
其他的
开始
haspatterneready:=haspatterneready或(OnesInRow>=R);
如果haspatterneed或(N-Len>R)//有机会生成模式}
然后
generatenLengthThronestogether('0'+s,N,R,Len+1,0,haspatterned);
if(nothaspatterneready)或(OnesInRow
正如我在上面的评论中所说,我仍然不清楚输出集的全部限制。但是,可以对下面的算法进行改进,以涵盖您的最终情况


在我描述算法之前,有一个观察:让我们重复
1
m
次,D是我们可以用来生成有效输出的所有可能后缀的集合。因此,位字符串
S0D0
(S后跟0位,然后是位字符串D后跟0位)是算法的有效输出。另外,所有字符串
ror(S0D0,k)
0那么您到底遇到了什么问题?@HunterMcMillen:可能是问题:)@leppie我看不出有问题,是吗?这基本上是一种游程限制(RLL)编码形式。我相信这通常是通过在普通二进制中进行计数,然后将结果转换为所选的RLL来完成的。@HunterMcMillen我的问题是什么可以成为这方面的算法?我无法找出模式或算法。我可以将二进制数作为字符串搜索,但这不是最优的。我想知道这是否有一个数学模式。此外,除了将二进制数作为字符串搜索外,我无法找出最简单情况下的算法。我需要考虑更多。如果只是找到这些数字的数量,那就很容易了。假设r是2,n是4。然后11个会在4个地方的某个地方聚集在一起。因此,其余两个位置可以具有不同的数字/值排列。因此有四个这样的价值观。如果n等于20,那么就有20-2,18个这样的位置,因此有2^18个这样的数字。不过,通过剩余可能性的循环是困难的部分。如果置换1块中仅向左的填充,并与仅向右的填充合并,则仍会丢失一些填充。在块的两侧填充,我认为不创建重复项是很困难的,尽管我认为这是一种方法。重复项不是问题。我要试试这个逻辑。谢谢这几乎奏效了。但对于n=6和r,给出了无效的输出111011=2@ritratt为什么111011是无效输出?它有一组两个相邻的。您是否打算添加一个输出最多应具有两个连续整数的约束?是的,它最多应具有两个连续整数。我解决了上面的错误,现在工作正常!
def ror(str, n):
    return str[-n:]+str[:-n]

def family(s, d, r):
    root = s + '0' + d + '0'
    yield root  # root is always a solution
    for i in range(1, len(d)+3):
        sol=ror(root, i)
        if sol[:r]==s and sol[r]=='0' and sol[-1]=='0':
            break
        yield sol
    if d[-r:]!=s: # Make sure output is valid
        yield s + '0' + d + '1'
    if d[:r]!=s:  # Make sure output is valid (todo: duplicate check)
        yield '1' + d + '0' + s

def generate(n, r):
    s="1"*r
    if r==0: # no 1's allowed
        yield '0'*n
    elif n==r: # only one combination
        yield s
    elif n==r+1: # two cases. Cannot use family() for this
        yield s+'0'
        yield '0'+s
    else:
        # generate all sub-problem outputs
        for rr in range(r+1):
            if n-r-2>=rr:
                for d in generate(n-r-2, rr):
                    for sol in family(s, d, r):
                        yield sol
for s in generate(6,3):
    print(s)