组合....笛卡尔积?

发布于 2024-11-24 03:28:42 字数 341 浏览 1 评论 0原文

我想使用给定字符的组合生成文件夹 即带有字符组合的 8 个字符文本:abcdefghijklmnopqrstuvwxyz1234567890。 对于 8 个字符的组合,有 2821109907456 种可能性。我想按 10,000 的范围对它们进行分组。

我需要将这些文件夹放入相关范围文件夹中,即 “aaaaaaa1 - aaaaaaa9”是 9 个组合的范围,并且将在此范围文件夹中创建文件夹“aaaaaaa3”。

我想使用 C# 代码,为我的方法指定一个文件夹名称,即“aaaaaaa3”,并返回相关文件夹范围,即“aaaaaa1 - aaaaaaa9”,应将其保存在其中。

问题:我需要 C# 代码来执行此操作!

I want to generate folders using combinations of given characters
i.e. 8 character text with combination of characters: abcdefghijklmnopqrstuvwxyz1234567890.
For the 8 characters combinations there are 2821109907456 possibilities. I want to group these by range of 10,000.

I need to put these folders in relevant range folders i.e.
'aaaaaaa1 - aaaaaaa9' is a range of 9 combinations and a folder 'aaaaaaa3' will be created in this range folder.

I want to use c# code, give my method a folder name i.e. 'aaaaaaa3' and be returned the relevant folder range i.e. 'aaaaaa1 - aaaaaaa9' where it should be saved.

Question: I need c# code to do this!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

只是偏爱你 2024-12-01 03:28:42

您实际上使用的是 36 基表示法(36 位数字用于表示数字)。
因此,处理这些文件名的最简单方法是将它们转换为十进制表示法,然后除以 10000。

如下所示:

string alphabet = "0123456789abcdefghijklmnopqrstuvwxyz";
string fileName = "asdjg66";
long result = 0;
foreach (var c in fileName)
{
    sum = sum * 36 + alphabet.IndexOf(c);
}

并使用 sum 来确定目标范围。只需将 sum / 10000 转换回 36 进制表示法即可。你就完成了。

You are actually using 36-base notation (36 digits are used to represent numbers).
So the easiest way to handle these filenames is to convert them to decimal notation and then just divide by 10000.

Something like this:

string alphabet = "0123456789abcdefghijklmnopqrstuvwxyz";
string fileName = "asdjg66";
long result = 0;
foreach (var c in fileName)
{
    sum = sum * 36 + alphabet.IndexOf(c);
}

And use sum to determine the target range. Just convert sum / 10000 back to 36-base notation. And you are done.

月下伊人醉 2024-12-01 03:28:42

从一开始,我们似乎需要计算字母数字序列的范围,这意味着将它们转换为数字并返回。通用基转换器似乎是第一个逻辑步骤:

/// <summary>
/// Provides conversion between long integers and custom number bases.
/// </summary>
public class BaseConverter
{
    private string _characterSet;

    /// <summary>
    /// Creates a new BaseConverter.
    /// </summary>
    /// <param name="characterSet">The characters in the custom base, in  
    /// increasing order of value.</param>
    public BaseConverter(string characterSet = 
       "0123456789abcdefghijklmnopqrstuvwxyz")
    {
        _characterSet = characterSet;
    }

    /// <summary>
    /// Converts a number in the custom base system to a long.
    /// </summary>
    /// <param name="value">The custom base number to convert.</param>
    /// <returns>The long form of the custom base number.</returns>
    public long StringToLong(string value)
    {
        if (value == Convert.ToString(_characterSet[0])) return 0;
        long val = 0; 
        string text = value[0] == '-' ? value.Substring(1, 
           value.Length - 1) : value;

        for (int i = text.Length, power = 0; i != 0; i--, power++)
        {
            val += (long)Math.Round((_characterSet.IndexOf(text[i-1]) * 
               Math.Pow(_characterSet.Length, power)));
        }

        return value[0] == '-' ? -val : val;
    }

    /// <summary>
    /// Converts a long to the custom base system.
    /// </summary>
    /// <param name="value">The long to convert.</param>
    /// <returns>The custome base number version of the long.</returns>
    public string LongToString(long value)
    {
        if (value == 0) return Convert.ToString(_characterSet[0]);
        long number = value.Abs();
        int remainder;
        StringBuilder text = new StringBuilder((int)Math.Round(
           Math.Log(long.MaxValue, (double)_characterSet.Length)) + 
           value < 0 ? 1 : 0);

        while (number != 0)
        {
            remainder = (int)(number % _characterSet.Length);
            text.Insert(0, _characterSet[remainder]);
            number -= remainder;
            number /= _characterSet.Length;
        }

        if (value < 0) text.Insert(0, "-");
        return text.ToString();
    }

然后,您需要代码来计算范围:

///<summary>
///Computes numeric ranges using a BaseConverter.
///</summary>
public class NumericRangeFactory
{
   private long _min, _length;
   private BaseConverter _converter;

   //creates a new NumericRangeFactory
   //converter - the BaseConverter that defines the number system 
   //being used
   //min - the smallest value in an acceptable range
   //length - the number of values in a single range
   public NumericRangeFactory(BaseConverter converter, long min, 
      long length)
   {
      _converter = converter; _min = min; _length = length;
   }

   public NumericRangeFactory(BaseConverter converter, string min, 
      long length) : this(converter.StringToLong(min), length) {}

   //returns an array of long containing the min and max of the 
   //range that contains value
   public long[] GetLongRange(long value)
   {
      long min = _length * (value / _length); //todo: fix non-zero _min case
      return new long[] { min, min + length - 1 };    
   }

   public long[] GetLongRange(string value)
   {
      return GetLongRange(_converter.StringToLong(value));
   }

   //returns an array of string containing the min and max of 
   //the range that contains value
   public string[] GetStringRange(long value)
   {
      long[] range = GetLongRange(value);
      return new string[] {_converter.LongToString(range[0]),
         _converter.LongToString(range[1])};
   }

   public string[] GetStringRange(string value)
   {
      return GetStringRange(_converter.StringToLong(value));
   }
}

最后,将 BaseConverter 和 NumericRangeFactory 类结合在一起,以使用此示例静态方法解决问题:

public static string GetFolderRange(string folderName)
{
   BaseConverter converter = new BaseConverter();
   NumericRangeFactory rangeFactory = new NumericRangeFactory(converter, 
      "aaaaaaa0", 9);
   string[] range = rangeFactory.GetStringRange(folderName);
   return range[0] + "-" + range[1];
}

我还没有测试过这个,但我认为这个概念是可靠的。

From the beginning, it looks like we're going to need to compute ranges of alphanumeric sequences, which means converting them to numbers and back. An all-purpose base converter seems like the first logical step:

/// <summary>
/// Provides conversion between long integers and custom number bases.
/// </summary>
public class BaseConverter
{
    private string _characterSet;

    /// <summary>
    /// Creates a new BaseConverter.
    /// </summary>
    /// <param name="characterSet">The characters in the custom base, in  
    /// increasing order of value.</param>
    public BaseConverter(string characterSet = 
       "0123456789abcdefghijklmnopqrstuvwxyz")
    {
        _characterSet = characterSet;
    }

    /// <summary>
    /// Converts a number in the custom base system to a long.
    /// </summary>
    /// <param name="value">The custom base number to convert.</param>
    /// <returns>The long form of the custom base number.</returns>
    public long StringToLong(string value)
    {
        if (value == Convert.ToString(_characterSet[0])) return 0;
        long val = 0; 
        string text = value[0] == '-' ? value.Substring(1, 
           value.Length - 1) : value;

        for (int i = text.Length, power = 0; i != 0; i--, power++)
        {
            val += (long)Math.Round((_characterSet.IndexOf(text[i-1]) * 
               Math.Pow(_characterSet.Length, power)));
        }

        return value[0] == '-' ? -val : val;
    }

    /// <summary>
    /// Converts a long to the custom base system.
    /// </summary>
    /// <param name="value">The long to convert.</param>
    /// <returns>The custome base number version of the long.</returns>
    public string LongToString(long value)
    {
        if (value == 0) return Convert.ToString(_characterSet[0]);
        long number = value.Abs();
        int remainder;
        StringBuilder text = new StringBuilder((int)Math.Round(
           Math.Log(long.MaxValue, (double)_characterSet.Length)) + 
           value < 0 ? 1 : 0);

        while (number != 0)
        {
            remainder = (int)(number % _characterSet.Length);
            text.Insert(0, _characterSet[remainder]);
            number -= remainder;
            number /= _characterSet.Length;
        }

        if (value < 0) text.Insert(0, "-");
        return text.ToString();
    }

Then, you'll need the code to compute your ranges:

///<summary>
///Computes numeric ranges using a BaseConverter.
///</summary>
public class NumericRangeFactory
{
   private long _min, _length;
   private BaseConverter _converter;

   //creates a new NumericRangeFactory
   //converter - the BaseConverter that defines the number system 
   //being used
   //min - the smallest value in an acceptable range
   //length - the number of values in a single range
   public NumericRangeFactory(BaseConverter converter, long min, 
      long length)
   {
      _converter = converter; _min = min; _length = length;
   }

   public NumericRangeFactory(BaseConverter converter, string min, 
      long length) : this(converter.StringToLong(min), length) {}

   //returns an array of long containing the min and max of the 
   //range that contains value
   public long[] GetLongRange(long value)
   {
      long min = _length * (value / _length); //todo: fix non-zero _min case
      return new long[] { min, min + length - 1 };    
   }

   public long[] GetLongRange(string value)
   {
      return GetLongRange(_converter.StringToLong(value));
   }

   //returns an array of string containing the min and max of 
   //the range that contains value
   public string[] GetStringRange(long value)
   {
      long[] range = GetLongRange(value);
      return new string[] {_converter.LongToString(range[0]),
         _converter.LongToString(range[1])};
   }

   public string[] GetStringRange(string value)
   {
      return GetStringRange(_converter.StringToLong(value));
   }
}

Finally, tie the BaseConverter and NumericRangeFactory classes together to solve the problem with this sample static method:

public static string GetFolderRange(string folderName)
{
   BaseConverter converter = new BaseConverter();
   NumericRangeFactory rangeFactory = new NumericRangeFactory(converter, 
      "aaaaaaa0", 9);
   string[] range = rangeFactory.GetStringRange(folderName);
   return range[0] + "-" + range[1];
}

I haven't tested this, but I think the concept is solid.

离鸿 2024-12-01 03:28:42
string getRange(string fileName) {
    string prefix = fileName.Substring(0, 7);
    string start = "a";
    string end = "0";
    return prefix + start + " - " + prefix + end;
}

要使范围更大(最简单的是 36 的幂),请缩短前缀并使开头和结尾重复几次:(0, 6)..."aa"...“00”。要缩短范围,请执行以下操作:

const string values = "abcdefghijklmnopqrstuvwxyz1234567890";

然后:

int index = values.IndexOf(fileName[7]);
if (index < 12) {
    start = "a";
    end = "l";
} else if (index < 24) ...
string getRange(string fileName) {
    string prefix = fileName.Substring(0, 7);
    string start = "a";
    string end = "0";
    return prefix + start + " - " + prefix + end;
}

To make the range larger, most easily in powers of 36, make the prefix shorter and make the start and end repeat themselves a few times: (0, 6)..."aa"..."00". To make the range shorter, do something like this:

const string values = "abcdefghijklmnopqrstuvwxyz1234567890";

Then:

int index = values.IndexOf(fileName[7]);
if (index < 12) {
    start = "a";
    end = "l";
} else if (index < 24) ...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文