【问题标题】:Compare content of a ring buffer比较环形缓冲区的内容
【发布时间】:2015-12-11 23:33:37
【问题描述】:

我需要检查特定数字序列的接收,例如 3,3,3,2,2,3,但是这个重复序列可以从不同的位置开始,例如 3,3,3,3,2, 2

我创建了一个环形缓冲区,用于存储接收到的数字并与所有可能的序列进行比较

class MFMSequence {
    int _index = 0;
    int[] _buffer = new int[6];
    public void add(int value) {
        _buffer[_index] = value;
        _index = (_index + 1) % 6;
    }
    public bool is4e() {
        return (_buffer.SequenceEqual(new int[] { 3, 3, 3, 2, 2, 3 }) ||
                _buffer.SequenceEqual(new int[] { 3, 3, 3, 3, 2, 2 }) ||
                _buffer.SequenceEqual(new int[] { 2, 3, 3, 3, 3, 2 }) ||
                _buffer.SequenceEqual(new int[] { 2, 2, 3, 3, 3, 3 }) ||
                _buffer.SequenceEqual(new int[] { 3, 2, 2, 3, 3, 3 }) ||
                _buffer.SequenceEqual(new int[] { 3, 3, 2, 2, 3, 3 }));
    }
    public bool is00() {
        return (_buffer.SequenceEqual(new int[] { 2, 2, 2, 2, 2, 2 }));
    }
}

这是可行的,但我觉得它很难看!关于如何更优雅地编码的任何想法

【问题讨论】:

  • 您的代码目前似乎可以运行,并且您正在寻求改进它。一般来说,这些问题对于本网站来说过于固执己见,但您可能会在CodeReview.SE 找到更好的运气。记得阅读their requirements,因为他们比这个网站更严格。
  • 听起来类似于this(很遗憾没有回答)问题。
  • 这个问题看起来可能非常适合Code Review.SE,前提是 (a) 您希望审查代码的每个方面,而不仅仅是一些,( b) 您的代码已经在工作,并且 (c) 您要求审查具体的、真实的代码,而不是抽象设计(无论它是否表示为代码)。如果您同意所有这些,请阅读what's on topic,如果您的问题符合,请在此处删除并重新发布到 CR。

标签: c#


【解决方案1】:

你可以试试这个:

private bool CheckIt(int[] checkFor, int[] have)
{
    return Enumerable.Range(0, checkFor.Length).Any(i =>
        checkFor.Concat(checkFor).Skip(i).Take(have.Length).SequenceEqual(have)
    );
}

并不完全“漂亮”,但它是一个快速的模型,我相信还有很多改进。也适用于任意数量的项目。用法:

var checkFor = new int[] { 3,3,3,2,2,3 };
var have = new int[] { 3,2,2,3,3,3 };
var result = CheckIt(checkFor, have);

【讨论】:

  • 第一个返回 fals for var checkFor = new int[] { 3, 3, 2, 2, 3, 3 }; 是错误的。
  • @Alexander 啊,是的,你说得对。将删除该解决方案。谢谢!
【解决方案2】:

您可以编写一个循环来比较所有可能的序列,然后至少它可以扩展到任意数量的项目而无需更改代码:

public static bool RingBufferContains(int[] buffer, int[] target)
{
    if (buffer == null || target == null || buffer.Length != target.Length)
        throw new InvalidOperationException("buffer and target must be non-null and the same length.");

    int n = buffer.Length;

    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < n; ++j)
        {
            if (buffer[(i+j)%n] != target[j])
                break;

            if (j == n - 1)
                return true;
        }
    }

    return false;
}

这是一个 O(N^2) 的解决方案,就像你的一样。

测试代码:

int[] buffer = { 3, 2, 2, 3, 3, 3 };
int[] target = { 3, 3, 3, 2, 2, 3 };
Console.WriteLine(RingBufferContains(buffer, target));

【讨论】:

  • 这是一个 O(N^2) 解(原来的解也是 O(N^2))
  • @Alexander 哎呀,这是一个错字 - 意思是说 N^2
【解决方案3】:

我认为 Rob 和 Matthew Watson 的解决方案比硬编码所有可能性要好得多。 Matthew 的代码更优化,但 Rob 的看起来更漂亮。如果您的序列很小,那么它们都足够好。但是,如果您有更大的序列,或者如果您想开发一些通用解决方案,则应该对其进行优化。
我的想法是将序列的起始位置设置为最小或最大元素,并且只比较序列一次。
如果我们有几个最小或最大元素,我们就有几个可能的起始位置,我们需要比较几次。在最坏的情况下,它将是 N/2 次(序列 { min, min, min, max, max, max })。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-14
    • 1970-01-01
    • 1970-01-01
    • 2012-04-04
    • 1970-01-01
    • 1970-01-01
    • 2018-10-29
    • 1970-01-01
    相关资源
    最近更新 更多