Home > Software engineering >  Generating a for while foreach algorithm in c# with a pyramidal structure
Generating a for while foreach algorithm in c# with a pyramidal structure

Time:08-19

I have been trying to get this to work for 3 days, and I feel like I'm using the wrong approach, if anyone can correct me I will wax your car. Background, client asked to me make a simple pyramid algorithm. I want to select add everything to a list of objects and make everything on the left side true and everything on the right side false. Every other line reads the line 2 lines prior and adds multiple entries. The first time it adds a number like 1 it's one time, then it adds two 1's for each 1 until there is 4. So the first time it enters a 1 on line 1, then on line 3 it adds a 1 two times, then on line 5 it reads from line 3 and adds each of those 1's 2 times.

Here is a visual representation.

                                |1|
                              |2| |3|
                            |1|1| |4|5|
                        |2|2|3|3| |6|7|8|9|
                |1|1|1|1|4|4|5|5| |10|11|12|13|14|15|16|17|
|2|2|2|2|3|3|3|3|6|6|7|7|8|8|9|9| |18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33

The order this list would be is:

1|2|3|1|1|4|5|2|2|3|3|6|7|8|9|1|1|1|1|4|4|5|5|10|11|12|13|14|15|16|17...

I keep getting close, but it fails to generate the correct output. `

        for (int i = 1; i < 50; i = i * 2)
        {
            Response.Write(i.ToString()   " - ");

            var previousLevel = (i / 2 / 2);

            foreach (var oc in infoRows.Where(x => x.level == previousLevel))
            {
                for (int p = i; p > 0; p--)
                {
                    Response.Write(oc.id   "*");
                }
            }

            while (level <= i)
            {
                for (int r = 1; r <= i; r  )
                {
                    InfoRow tempInforow = new InfoRow();
                    tempInforow.customerCode = GenerateCustomerNumber(position);
                    tempInforow.id = customerId;
                    tempInforow.sendtoidnumber = level.ToString();
                    tempInforow.status = 0; // GetStatus(position, totalCount);
                    tempInforow.position = position;
                    tempInforow.level = i;

                    infoRows.Add(tempInforow);
                    customerId  ;
                    position  ;

                    Response.Write(tempInforow.id   "-");
                    level  ;
                }
            }
         }

`

Essentially this generates the following:

1 - 1-
2 - 2-3-
4 - 1*1*1*1*4-5-6-7-
8 - 2*2*2*2*2*2*2*2*3*3*3*3*3*3*3*3*8-9-10-11-12-13-14-15-
16 - 4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*16-17-18-19-20-21-22-23-24-25-26-27-28-29-30-31-
32 - 

I've tried 30 different ways with switch statements, while statements, for and foreach statements, the closest I can get to this working is level 4.

Can someone suggest another way. Maybe a multidimensional array or idk what. Thank you.

CodePudding user response:

Let's write the sequence down and have a look on what's going on:

#   1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ...
seq 1 2 3 1 1 4 5 2 2  3  3  6  7  8  9  1 1 1 1  4  4  5  5 10 ...
          ^ ^     ^       ^              ^                 ^
                  |       |
               if # is power of 2 (e.g. 8 == 2**3) 
               we should copy and double # / 4 items (here 8 / 4 == 2 items)
               starting from # / 4 item (here 8 / 4 == 2, starting from item #2)

Time to implement this algorithm

Code:

    using System.Linq;
    ...

    private static List<int> Pyramid(int size) {
      if (size < 0)
        throw new ArgumentOutOfRangeException(nameof(size));

      if (size <= 3)
        return Enumerable.Range(1, size).ToList();

      List<int> result = new List<int>(size) { 1, 2, 3 };

      for (int value = 4; result.Count < size; ) 
        if (BitOperations.IsPow2(result.Count   1)) {
          int chunk = (result.Count   1) / 4;

          for (int i = 0; i < chunk && result.Count < size;   i) {
            result.Add(result[chunk - 1   i]);

            if (result.Count >= size)
              return result;

            result.Add(result[chunk - 1   i]);
          }
        }
        else
          result.Add(value  );
      
      return result;
    }

Demo:

// First 31 items from the pyramid
Console.Write(string.Join("|", Pyramid(31)));

Output:

1|2|3|1|1|4|5|2|2|3|3|6|7|8|9|1|1|1|1|4|4|5|5|10|11|12|13|14|15|16|17
  • Related