2

My input are two string. I need to loop over every value (including values itself) between these two strings.

For example from AA to CZ (e.g. AA AB AC .. AY AZ BA BB .. CY CZ)

Legal values should be possible from 0 - 9 AND A-Z

Iteration from 01 to AD should result in 01 02 .. 09 0A .. 0Z .. 10 11 12 .. 9Z AA AB AC AD

String length should be variable but start and end have always the same length

AAA to ZZZ valid

Currently I am totally stuck. Any suggestions?

This is my current approach (I limited the string lengt to 6 and left fill the values with "0", e.g. AAA becomes 000AAA

    value1 = "A01"
    value2 = "A20"
    value1 = value1.PadLeft(6, "0")
    value2 = value2.PadLeft(6, "0")

    Dim start1 As Integer = Asc(value1.Substring(0, 1))
    Dim start2 As Integer = Asc(value1.Substring(1, 1))
    Dim start3 As Integer = Asc(value1.Substring(2, 1))
    Dim start4 As Integer = Asc(value1.Substring(3, 1))
    Dim start5 As Integer = Asc(value1.Substring(4, 1))
    Dim start6 As Integer = Asc(value1.Substring(5, 1))

    Dim stop1 As Integer = Asc(value2.Substring(0, 1))
    Dim stop2 As Integer = Asc(value2.Substring(1, 1))
    Dim stop3 As Integer = Asc(value2.Substring(2, 1))
    Dim stop4 As Integer = Asc(value2.Substring(3, 1))
    Dim stop5 As Integer = Asc(value2.Substring(4, 1))
    Dim stop6 As Integer = Asc(value2.Substring(5, 1))

    For p1 As Integer = start1 To stop1
      For p2 As Integer = start2 To stop2
        For p3 As Integer = start3 To stop3
          For p4 As Integer = start4 To stop4
            For p5 As Integer = start5 To stop5
              For p6 As Integer = start6 To stop6

                Dim result as string = Convert.ToChar(p1) &Convert.ToChar(p2) & Convert.ToChar(p3) & Convert.ToChar(p4) & Convert.ToChar(p5) & Convert.ToChar(p6)
                Console.WriteLine(result)

              Next
            Next
          Next
        Next
      Next
    Next

This works pretty well for 000001 to 009999 but the tricky part is if I have 000A01 to 000A20. On the first run start6 equals 1 and stop6 equals 0 the for for loop exits.

Jürgen Steinblock
  • 30,746
  • 24
  • 119
  • 189

1 Answers1

2

This is a bit tricky, but after thinking I've come with an idea to treat the number as base-36 numbers. I don't write the code to convert a base-n number to another base-n, but I found it in StackOverflow.

I made 2 project:

  1. A C# class library project where I put the base-n converter I found. This class library will be included in the second project.
  2. A VB console project to test your problem.

First convert both start and stop number from base-36 to base-10. Then do a loop from start number to stop number. In the loop body, you convert the iteration from base-10 to base-36.

C# for base-n converter. Project name is BaseN. Don't forget to include this project in the second one.

using System;

namespace BaseN
{
    public class BaseConverter
    {
        /// <summary>
        /// Converts the given decimal number to the numeral system with the
        /// specified radix (in the range [2, 36]).
        /// </summary>
        /// <param name="decimalNumber">The number to convert.</param>
        /// <param name="radix">The radix of the destination numeral system (in the range [2, 36]).</param>
        /// <returns></returns>
        public static string DecimalToArbitrarySystem(long decimalNumber, int radix)
        {
            const int BitsInLong = 64;
            const string Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

            if (radix < 2 || radix > Digits.Length)
                throw new ArgumentException("The radix must be >= 2 and <= " + Digits.Length.ToString());

            if (decimalNumber == 0)
                return "0";

            int index = BitsInLong - 1;
            long currentNumber = Math.Abs(decimalNumber);
            char[] charArray = new char[BitsInLong];

            while (currentNumber != 0)
            {
                int remainder = (int)(currentNumber % radix);
                charArray[index--] = Digits[remainder];
                currentNumber = currentNumber / radix;
            }

            string result = new String(charArray, index + 1, BitsInLong - index - 1);
            if (decimalNumber < 0)
            {
                result = "-" + result;
            }

            return result;
        }

        /// <summary>
        /// Converts the given number from the numeral system with the specified
        /// radix (in the range [2, 36]) to decimal numeral system.
        /// </summary>
        /// <param name="number">The arbitrary numeral system number to convert.</param>
        /// <param name="radix">The radix of the numeral system the given number
        /// is in (in the range [2, 36]).</param>
        /// <returns></returns>
        public static long ArbitraryToDecimalSystem(string number, int radix)
        {
            const string Digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

            if (radix < 2 || radix > Digits.Length)
                throw new ArgumentException("The radix must be >= 2 and <= " +
                    Digits.Length.ToString());

            if (String.IsNullOrEmpty(number))
                return 0;

            // Make sure the arbitrary numeral system number is in upper case
            number = number.ToUpperInvariant();

            long result = 0;
            long multiplier = 1;
            for (int i = number.Length - 1; i >= 0; i--)
            {
                char c = number[i];
                if (i == 0 && c == '-')
                {
                    // This is the negative sign symbol
                    result = -result;
                    break;
                }

                int digit = Digits.IndexOf(c);
                if (digit == -1)
                    throw new ArgumentException(
                        "Invalid character in the arbitrary numeral system number",
                        "number");

                result += digit * multiplier;
                multiplier *= radix;
            }

            return result;
        }
    }
}

VB project. Project name is ConsoleApplication1.

Imports BaseN

Module Module1

    Sub Main()

        Dim value1 = "A01"
        Dim value2 = "A20"

        For i = BaseConverter.ArbitraryToDecimalSystem(value1, 36) To BaseConverter.ArbitraryToDecimalSystem(value2, 36)
            Console.WriteLine(BaseConverter.DecimalToArbitrarySystem(i, 36))
        Next

        Console.WriteLine("Press any key...")
        Console.ReadKey(True)

    End Sub

End Module

Result.

A01
A02
A03
A04
A05
A06
A07
A08
A09
A0A
A0B
A0C
A0D
A0E
A0F
A0G
A0H
A0I
A0J
A0K
A0L
A0M
A0N
A0O
A0P
A0Q
A0R
A0S
A0T
A0U
A0V
A0W
A0X
A0Y
A0Z
A10
A11
A12
A13
A14
A15
A16
A17
A18
A19
A1A
A1B
A1C
A1D
A1E
A1F
A1G
A1H
A1I
A1J
A1K
A1L
A1M
A1N
A1O
A1P
A1Q
A1R
A1S
A1T
A1U
A1V
A1W
A1X
A1Y
A1Z
A20
Press any key...

I didn't put the leading zero, I'm sure you won't have much trouble adding the leading zero by yourself.

References by Pavel Vladov:

Quickest way to convert a base 10 number to any base in .NET? http://www.pvladov.com/2012/07/arbitrary-to-decimal-numeral-system.html

Community
  • 1
  • 1
Han
  • 3,052
  • 2
  • 22
  • 31
  • 1
    While coding I thougt about the base 36 number system but dismissed the idea because i thought it would be to complex. Brilliant solution, thx. Regarding the leading zero `BaseConverter.DecimalToArbitrarySystem(i, 36).PadLeft(value1.Length, "0")` – Jürgen Steinblock Jun 10 '16 at 07:48
  • 1
    Thanks to Pavel's base-n converter. It's pretty fast. – Han Jun 10 '16 at 12:52