如何摆脱列表中的循环数字

时间:2017-01-14 17:45:22

标签: c# console-application

好的,我知道这段代码很粗糙,并且周围都很乱,但我不是程序员,所以请耐心等待。我有这个代码列出了一堆数字,但我希望它不会列出数字的任何循环副本。

例如,如果号码111262在我的列表中,我不希望列出112621,126211,262111,621112或211126。

很抱歉,该号码不在列表中。

对于 true 示例,如果号码111252在我的列表中,我不希望列出112521,125211,252111,521112或211125。

感谢任何帮助!

namespace Toric_Classes
{
class Program
{
    static void Main(string[] args)
    {
        int number_of_perms=0;
        bool badsubsum1;
        bool badsubsum2;
        int subsum1 = 0;
        int subsum2 = 0;
        int sum = 0;
        int class_length=6;
        int[] toric_class=new int[class_length];
        // The nested for loops scroll through every possible number of length class_length, where each digit can have a value of 1,2,..., or class_length-1
        // Each number is looked at as an array, and is not stored anywhere, only printed if it satisfies certain conditions
        for(int i1=1; i1<class_length; i1++)
        {
            toric_class[0] = i1;
            for (int i2 = 1; i2 < class_length; i2++)
            {
                toric_class[1] = i2;
                for (int i3 = 1; i3 < class_length; i3++)
                {
                    toric_class[2] = i3;
                    for (int i4 = 1; i4 < class_length; i4++)
                    {
                        toric_class[3] = i4;
                        for (int i5 = 1; i5 < class_length; i5++)
                        {
                            toric_class[4] = i5;
                            for (int i6 = 1; i6 < class_length; i6++)
                            {
                                badsubsum1 = false;
                                badsubsum2 = false;
                                toric_class[5] = i6;
                                // Find the value of the sum of the digits of our array.
                                // We only want numbers that have a total digit sum being a multiple of class_length
                                for (int k = 0; k < class_length; k++)
                                {
                                    sum += toric_class[k];
                                }
                                // The follwong two nested loops find the value of every contiguous subsum of our number, but not the total subsum.
                                // We *do not* want any subsum to be a multiple of class_length.
                                // That is, if our number is, say, 121342, we want to find 1+2, 1+2+1, 1+2+1+3, 1+2+1+3+4, 2+1, 2+1+3, 2+1+3+4, 2+1+3+4+2, 1+3, 1+3+4, 1+3+4+2, 3+4, 3+4+2, and 4+2
                                // The following checks 1+2, 1+2+1, 1+2+1+3, 1+2+1+3+4, 2+1, 2+1+3, 2+1+3+4, 1+3, 1+3+4, and 3+4
                                for (int i = 0; i < class_length - 1; i++)
                                {
                                    for (int j = i + 1; j < class_length - 1; j++)
                                    {
                                        for (int k = i; k < j; k++)
                                        {
                                            subsum1 += toric_class[k];
                                        }
                                        if (subsum1 % class_length == 0)
                                        {
                                            badsubsum1 = true;
                                            break;
                                        }
                                        subsum1 = 0;
                                    }
                                }
                                // The following checks 2+1, 2+1+3, 2+1+3+4, 2+1+3+4+2, 1+3, 1+3+4, 1+3+4+2, 3+4, 3+4+2, and 4+2
                                for (int i = 1; i < class_length; i++)
                                {
                                    for (int j = i + 1; j < class_length; j++)
                                    {
                                        for (int k = i; k < j; k++)
                                        {
                                            subsum2 += toric_class[k];
                                        }
                                        if (subsum2 % class_length == 0)
                                        {
                                            badsubsum2 = true;
                                            break;
                                        }
                                        subsum2 = 0;
                                    }
                                }
                                // We only want numbers that satisfies the following conditions
                                if (sum % class_length == 0 && badsubsum1 == false && badsubsum2 == false)
                                {
                                    foreach (var item in toric_class)
                                    {
                                        Console.Write(item.ToString());
                                    }
                                    Console.Write(Environment.NewLine);
                                    number_of_perms++;
                                }
                                sum = 0;
                                subsum1 = 0;
                                subsum2 = 0;

                            }
                        }
                    }
                }
            }
        }
        Console.WriteLine("Number of Permuatations: "+number_of_perms);
        Console.Read();
    }
}
}

修改

为了澄清,我正在创建一个长度为n且满足特定条件的所有数字的列表。考虑数字d1d2 ... dn,其中每个di是我们数字的数字。每个di可以具有值1,2,...,n。如果符合以下条件,我们的号码将在列表中

  1. 所有数字的总和是n的倍数,即

    d1 + d2 + ... + dn = 0 mod n

  2. 除了总和之外,数字的每个连续子数不是的n的倍数,即,如果i!= 1且j!= n,那么

    di + d(i + 1)+ ... + dj!= 0 mod n

  3. 我应该再次提到一个&#34;数字&#34;不严格使用数字中的数字0-9。它可能需要1到n之间的任何值。在我的代码中,我使用的是n = 6的情况。

    代码的工作原理是创建一个长度为class_length的数组(在上面的代码中,我使用class_length=6)。我们首先有6个嵌套for循环,它们只是为数组toric_class赋值。第一个for分配toric_class[0],第二个for分配toric_class[1],依此类推。首先,我们生成数组111111,然后111112,最多111115,然后111121,等等。基本上,我们正在查看所有的十六进制数字不包括0.一旦我们在数组中达到第六个值,我们检查数组toric_class并检查其值以确保它满足上述条件。如果是这样,我们只需在一行中打印数组,然后继续。

3 个答案:

答案 0 :(得分:1)

OOP真正受益的地方。评论内联。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3 {

    struct MyInt : IEquatable<MyInt> {
        private int _value;

        public MyInt(int value) {
            _value = value;
        }

        // make it look like int
        static public implicit operator MyInt(int value) {
            return new MyInt(value);
        }
        public static explicit operator int(MyInt instance) {
            return instance._value;
        }

        // main difference in these 3 methods
        private int GetDigitsNum() {
            int temp, res;
            for (res = 0, temp = Math.Abs(_value); temp > 0; ++res, temp /= 10);
            return res;
        }
        public bool Equals(MyInt other) {
            int digits = other.GetDigitsNum();
            if (digits != this.GetDigitsNum())
                return false;
            int temp = other._value;

            // prepare mul used in shifts
            int mul = 1;
            for (int i = 0; i < digits - 1; ++i)
                mul *= 10;

            // compare
            for (int i = 0; i < digits; ++i) {
                if (temp == _value)
                    return true;
                // ROR
                int t = temp % 10;
                temp = temp / 10 + t * mul;
            }
            return false;
        }
        public override int GetHashCode() {
            // hash code must be equal for "equal" items,
            // that's why use a sum of digits.
            int sum = 0;
            for (int temp = _value; temp > 0; temp /= 10)
                sum += temp % 10;
            return sum;
        }

        // be consistent
        public override bool Equals(object obj) {
            return (obj is MyInt) ? Equals((MyInt)obj) : false;
        }
        public override string ToString() {
            return _value.ToString();
        }
    }

    class Program {
        static void Main(string[] args) {

            List<MyInt> list = new List<MyInt> { 112621, 126211, 262111, 621112, 211126 };
            // make a set of unique items from list
            HashSet<MyInt> set = new HashSet<MyInt>(list);

            // print that set    
            foreach(int item in set)
                Console.WriteLine(item);

        }
    }
}

输出:    112621

答案 1 :(得分:1)

以下方法:

private static List<int> GetCircularEquivalents(int value)
{
    var circularList = new List<int>();
    var valueString = value.ToString();
    var length = valueString.Length - 1;

    for (var i = 0; i < length; i++)
    {
        valueString = valueString.Substring(1, length) + valueString.Substring(0, 1);
        circularList.Add(int.Parse(valueString));
    }

    return circularList;
}

将返回从输入值派生的循环数列表。使用您的示例,可以像这样调用此方法:

var circularList = GetCircularEquivalents(111262);
var dirtyList = new List<int> { 1, 112621, 2, 126211, 3, 262111, 4, 621112, 5, 211126, 6 };
var cleanList = dirtyList.Except(circularList).ToList();

这将导致一个由数字1到6组成的cleanList,即dirtyList,其中包含从111262派生的所有循环数。

答案 2 :(得分:1)

这是我简单而低效的方式,只需对代码进行最少的更改即可。它需要共享字符串列表var strList = new List<string>();来存储使用过的数字。然后这部分:

foreach (var item in toric_class)
{
    Console.Write(item.ToString());
}
Console.Write(Environment.NewLine);
number_of_perms++; 

变成这样:

string strItem = " " + string.Join(" ", toric_class) + " "; // Example: int[] {1, 12, 123} becomes " 1 12 123 "

if (!strList.Any(str => str.Contains(strItem))) // Example: if " 1 12 123 1 12 123 " contains " 1 12 123 "
{
    Console.WriteLine(strItem);

    strItem += strItem.Substring(1); // double the string, but keep only one space between them
    strList.Add(strItem);
}

number_of_perms++; // not sure if this should be in the if statement

这个想法是,例如字符串" 1 1 1 2 5 2 1 1 1 2 5 2 "包含数字{1, 1, 1, 2, 5, 2}的所有循环副本。我使用字符串作为一种懒惰的方法来检查数组是否包含子数组,但您可以使用类似的方法在数组new List<int[]>()列表中存储已使用数字的副本,并检查列表中的任何数组是否为当前数组的循环副本,甚至更好的HashSet<int[]>()方法,类似于@ slavanap的回答。

first version of my answer是最简单的,但它仅适用于单个数字项的数组。

List几乎与数组(new List<string>()而不是new string[])相同,但可以更轻松有效地向其中添加项目。例如,{1,2}.Add(3)变为{1,2,3}

str => str.Contains(strItem)是接受参数str并返回str.Contains(strItem)结果的函数的快捷方式。那&#34;功能&#34;然后传递给.Any LINQ扩展,所以

strList.Any(str => str.Contains(strItem))

是这样的捷径:

foreach(string str in strList)
{
    if (str.Contains(strItem)) 
    {
        return true;
    }
}
return false;