Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Solve a 3-variable equation?

Discussion in 'Scripting' started by JusticeKingCayden, Aug 31, 2020.

  1. JusticeKingCayden

    JusticeKingCayden

    Joined:
    May 5, 2018
    Posts:
    49
    I have this formula for finding the index of a specific string (I.E. "DDD" = 64). (((a - 1) * 16) + ((b - 1) * 4) + c)
    I am trying to make a formula for finding a specific string based on an index. How could I do this quickly?
     
  2. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,587
    Not just "DDD" results in 64 based using your formula. CDT does too. And so does BJL. And many many more.
    So based on an index you cannot return to a unique string. Or rather, you could calculate a string, but you couldnt guarantee to calculate the correct / input one, as that information is lost in the conversion. If that's a requirement for what you are doing, you will have to use a formula assigning a unique number to each and every possible string. Which for strings of 3 characters should still be very viable.
     
    Joe-Censored likes this.
  3. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Unless his strings do only consist of A, B, C and D, which he could map to 0, 1, 2, 3.
    At least the formula would somewhat make sense if these were the possible characters for the outcomes for any given index.

    In that case either waste a bit of memory for an array + those strings and just index them directly or it'd be a plain simple calculation that could be done in multiple ways but still with basic math.

    But since we don't know that ... let's just wait until he adds more information.
     
    Yoreki likes this.
  4. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    If it is just ABC and D, you'll be using modulus and integer division
    But then... "ddd" should equal 63 ( 63 in base 4 is "333"; you could just do a base conversion )
     
  5. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    685
    Let's say you're using the first ten letters of the alphabet. You can assign each a unique index which will be sequential. String positions are denoted "abc" as in your formula. String values start at 1 here (A=1, B=2, etc), not 0. I think this is easier, because you can just subtract 1 at the end when mapping to the characters.

    (a * 100) + (b * 10) + c // "DFH" will give 468, "AAA" will give 111

    For consistency this would read as follows:

    (a * (10^2)) + (b * (10^1)) + (c * (10^0)) // hundreds, tens, ones places

    Retrieve the string. Use integer division and modulus, just as hpjohn said:

    a = index / 100
    b = (index % 100) / 10
    c = index % 10

    For consistency this would read:

    a = (index % 10^3) / (10^2) // drop the 1000's place, then find how many hundreds
    b = (index % 10^2) / (10^1) // etc
    c = (index % 10^1) / (10^0)

    The values you get for a, b, c are then mapped to their corresponding characters using an array. Note that you want to subtract 1 from the values to get the right index: {A, B, C, D, E, F, G, H, I, J}

    For 26 letters, change all those 10^x to 26^x. Just wanted to keep it a bit more familiar by using 10s...
     
  6. JusticeKingCayden

    JusticeKingCayden

    Joined:
    May 5, 2018
    Posts:
    49
    That is why my letters only go up to D. That is why my example was DDD
     
  7. JusticeKingCayden

    JusticeKingCayden

    Joined:
    May 5, 2018
    Posts:
    49
    There are 64 possible outcomes. AAA = 1. ABA = 5. ACA = 9. ADA = 13. BAA = 17. DDD=64.
     
  8. JusticeKingCayden

    JusticeKingCayden

    Joined:
    May 5, 2018
    Posts:
    49
    You are right. As I just explained, my highest letter is D.
     
  9. JusticeKingCayden

    JusticeKingCayden

    Joined:
    May 5, 2018
    Posts:
    49
    I don't know if you guys understand my goal. I am trying to make a primitive form of DNA. In order for this to work, I need a formula to find a DNA strand for a specific index. I.E. AAA = 1 because that is the first possible outcome. Next is AAB = 2. Then AAC = 3. AAD = 4. etc
     
  10. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,375
    Yeah... you're using a base 4 numeric system, using characters A,B,C,D, all offset by 1 (so AAA = 1, not AAA = 0).

    Which is basically what @seejayjames is talkng about. Which is why they compared it to base 10 (number system we're all used to with 0-9) or base 26, or whatever base you want.

    So... if you just get the character for each space, get it's associated value, multiply by the "place" in the number, add them up, and add 1 (because you have the 1 offset). There's your number.

    As long as we assume we only use uppercase that'd be like so:
    Code (csharp):
    1.  
    2. public static int ParseDNAValue(string sval)
    3. {
    4.     int val = 0;
    5.     for(int i = 0; i < sval.Length; i++)
    6.     {
    7.         int j = (int)sval[sval.Length - i - 1] - (int)'A';
    8.         val += j * Mathf.Pow(4, i);
    9.     }
    10.     return val + 1;
    11. }
    12.  
    You can even add checks to make sure that the string only contains the known characters. I just went with a simple approach with no safety checks.
     
  11. hpjohn

    hpjohn

    Joined:
    Aug 14, 2012
    Posts:
    2,190
    Ya reeeealy want to work with a zero index system, it makes the maths so much simpler.
    keep it zero index when working internally with the maths, then just add 1 if you ever need to display the index output to users (unlikely?)

    Heres working code for converting between index and dna string:
    You can modify the top 2 variables if you want different letters, or longer sequences
    Code (CSharp):
    1.  
    2.     string DNABases = "ABCD";
    3.    int DNALength = 3;
    4.  
    5.    /// <summary>
    6.    /// Convert from DNA string to index
    7.    /// </summary>
    8.    /// <param name="dna">DNA String Input</param>
    9.    /// <returns>Integer Index (Zero first)Output</returns>
    10.    int DNAToIndex(string dna)
    11.    {
    12.        //Optional: Check that dna.Length == DNALength,
    13.        //maybe do dna = dna.ToUpper() to force letter case,
    14.        //check for bad/unwanted letters, etc
    15.        int result = 0;
    16.        int multiplier = 1;
    17.        for (int i = dna.Length - 1; i >= 0; i--)
    18.        {
    19.            char c = dna[i];
    20.            int digit = DNABases.IndexOf(c);
    21.            result += digit * multiplier;
    22.            multiplier *= DNABases.Length;
    23.        }
    24.        return result;
    25.    }
    26.  
    27.    /// <summary>
    28.    /// Convert from (Zero-first) Index int to DNA String
    29.    /// </summary>
    30.    /// <param name="index">Integer Index Input</param>
    31.    /// <returns>DNA String Output</returns>
    32.    string IndexToDNA(int index)
    33.    {
    34.        string result = "";
    35.        while (index > 0)
    36.        {
    37.            //This is modulus
    38.            result = DNABases[index % DNABases.Length] + result;
    39.            // This is integer division
    40.            index = index / DNABases.Length;
    41.        }
    42.        //Do this to pad short sequences with extra letters (eg: "B" -> "AAB")
    43.        while(result.Length < DNALength)
    44.        {
    45.            result = DNABases[0] + result;
    46.        }
    47.        return result;
    48.    }
    49.  
     
    Bunny83 likes this.
  12. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,446
    Absolutely! Especially with a base 4 system you have a neat bitwise relationship. So two bits represent one digit. So you can combine or split an index just by using bit operations:

    Code (CSharp):
    1.     public static int DNA2Index(string aDNA)
    2.     {
    3.         int index = 0;
    4.         for(int i = 0; i < aDNA.Length; i++)
    5.         {
    6.             int v = (int)(aDNA[i] - 'A');
    7.             if (v < 0 || v > 3)
    8.                 throw new System.FormatException("DNA string contains wrong characters: " + aDNA[i]);
    9.             index <<= 2;
    10.             index |= v;
    11.         }
    12.         return index;
    13.     }
    14.     public static string Index2DNA(int aIndex, int aMinDigits = 3)
    15.     {
    16.         if (aIndex < 0)
    17.             throw new System.IndexOutOfRangeException();
    18.         string dna = "";
    19.         for(int i = 0; i < aMinDigits || aIndex > 0; i++)
    20.         {
    21.             dna = (char)('A'+(aIndex & 0x03)) + dna;
    22.             aIndex >>= 2;
    23.         }
    24.         return dna;
    25.     }
    untested but should work. The first method DNA2Index can convert any base 4 string with the letters A,B,C or D into an index while the second method Index2DNA can convert any index into a DNA string. Note that the optional aMinDigits parameter controls how many digits the DNA should have atleast. Of course in case the index gets larger than "4^numberOfDigits - 1" it would require more digits. So the value 63 would be "DDD" but the value 64 would return "BAAA". Since "DDD" is equivalent to 333 in base 4, "BAAA" is equivalent to 1000 in base 4