如何去掉列表中的循环数字
How do I get rid of circular numbers in my list
好吧,我知道这段代码很粗糙,而且到处都是乱七八糟的,但我不是程序员,所以请多多包涵。我有这个列出一堆数字的代码,但我希望它不列出数字的任何循环副本。
例如,如果号码 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。如果满足以下条件,我们的号码就会在列表中
所有数字的和是n的倍数,即
d1+d2+...+dn = 0 mod n
每个连续的数字 不是 n 的倍数,除了总和,也就是说,如果 i !=1 和 j ! = n,然后
di+d(i+1)+...+dj != 0 mod n
我要再次提一下,"number" 的数字并不严格使用数字 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
并检查其值以确保它满足上述条件。如果是,我们只需将数组打印成一行,然后继续。
这就是 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
以下方法:
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;
}
将 return 从输入值派生的循环数字列表。使用您的示例,可以这样调用此方法:
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,即删除了从 111262 派生的所有循环数字的 dirtyList。
这是我的简单而低效的方法,应该对您的代码进行最少的更改。它需要共享字符串列表 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}
的所有循环副本。我使用字符串作为检查数组是否包含 sub-array 的惰性方法,但您可以使用类似的方法将使用过的数字的副本存储在数组列表 new List<int[]>()
中,并检查数组中是否有任何数组list 是当前数组的循环副本,或者更好的 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
和 returns str.Contains(strItem)
结果的函数的快捷方式。然后 "function" 被传递给 .Any
LINQ 扩展,所以
strList.Any(str => str.Contains(strItem))
是这样的快捷方式:
foreach(string str in strList)
{
if (str.Contains(strItem))
{
return true;
}
}
return false;
好吧,我知道这段代码很粗糙,而且到处都是乱七八糟的,但我不是程序员,所以请多多包涵。我有这个列出一堆数字的代码,但我希望它不列出数字的任何循环副本。
例如,如果号码 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。如果满足以下条件,我们的号码就会在列表中
所有数字的和是n的倍数,即
d1+d2+...+dn = 0 mod n
每个连续的数字 不是 n 的倍数,除了总和,也就是说,如果 i !=1 和 j ! = n,然后
di+d(i+1)+...+dj != 0 mod n
我要再次提一下,"number" 的数字并不严格使用数字 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
并检查其值以确保它满足上述条件。如果是,我们只需将数组打印成一行,然后继续。
这就是 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
以下方法:
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;
}
将 return 从输入值派生的循环数字列表。使用您的示例,可以这样调用此方法:
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,即删除了从 111262 派生的所有循环数字的 dirtyList。
这是我的简单而低效的方法,应该对您的代码进行最少的更改。它需要共享字符串列表 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}
的所有循环副本。我使用字符串作为检查数组是否包含 sub-array 的惰性方法,但您可以使用类似的方法将使用过的数字的副本存储在数组列表 new List<int[]>()
中,并检查数组中是否有任何数组list 是当前数组的循环副本,或者更好的 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
和 returns str.Contains(strItem)
结果的函数的快捷方式。然后 "function" 被传递给 .Any
LINQ 扩展,所以
strList.Any(str => str.Contains(strItem))
是这样的快捷方式:
foreach(string str in strList)
{
if (str.Contains(strItem))
{
return true;
}
}
return false;