Ejemplo n.º 1
0
        MyPoint MoveCursor(int maxDepth, int numMoves, MyPoint startingPoint)
        {
            int k = 0;                 //number of moves

            MyPoint p = startingPoint; //[x,y]; 32x,

            /* From Problem 220:
             * Let D0 be the two-letter string "Fa". For n≥1, derive Dn from Dn-1 by the string-rewriting rules:
             * "a" → "aRbFR"
             * "b" → "LFaLb"
             * Thus, D0 = "Fa", D1 = "FaRbFR", D2 = "FaRbFRRLFaLbFR", and so on.
             * "These strings can be interpreted as instructions to a computer graphics program,
             * with "F" meaning "draw forward one unit", "L" meaning "turn left 90 degrees",
             * "R" meaning "turn right 90 degrees", and "a" and "b" being ignored.
             * The initial position of the computer cursor is (0,0), pointing up towards (0,1)."*/

            //Insight: It is not necessary to know the full instruction string before we start moving.
            //every time we encounter 'a' or 'b' we replace it, adding to each instruction a parameter 'depth'
            //that represents how many replacements took place that originate such instruction.
            //Thus: thus every time we pop an instruction a[i] from the stack, we push instructions
            //R[i+1], F[i+1], b[i+1], R[i+1], a[i+1] (inverted order of "aRbFR")
            //onto the stack if i < maxDepth, otherwise we ignore the instruction and move on to the next one. (similar for 'b' instructions).

            Stack <MyInstruction> s = new Stack <MyInstruction>();

            s.Push(new MyInstruction(InstructionValue.a, 0));  //a
            s.Push(new MyInstruction(InstructionValue.F, 0));  //f

            while (k < numMoves)
            {
                //pop next instruction:
                MyInstruction i = s.Pop();

                if (i.instruction == InstructionValue.F)
                {
                    p.Move();
                    k++; //count move
                }
                else if (i.instruction == InstructionValue.L)
                {
                    p.RotateLeft(); //rotate left
                }
                else if (i.instruction == InstructionValue.R)
                {
                    p.RotateRight(); //rotate right
                }
                else
                {
                    //should a|b be replaced or ignored?
                    //if depth < maxdepth, replace and go deeper one level, otherwise ignore
                    if (i.depth < maxDepth)
                    {
                        //TOO SLOW
                        //string replaceString = i.instruction == InstructionValue.a ? "aRbFR" : "LFaLb";
                        //foreach (string newInst in replaceString.Reverse().Select(x => x.ToString()))
                        //{
                        //    InstructionValue auxInst = (InstructionValue)Enum.Parse(typeof(InstructionValue), newInst, false);
                        //    s.Push(new MyInstruction(auxInst, (byte)(i.depth + 1)));
                        //}

                        if (i.instruction == InstructionValue.a)
                        {
                            //RFbRa
                            s.Push(new MyInstruction(InstructionValue.R, (byte)(i.depth + 1)));
                            s.Push(new MyInstruction(InstructionValue.F, (byte)(i.depth + 1)));
                            s.Push(new MyInstruction(InstructionValue.b, (byte)(i.depth + 1)));
                            s.Push(new MyInstruction(InstructionValue.R, (byte)(i.depth + 1)));
                            s.Push(new MyInstruction(InstructionValue.a, (byte)(i.depth + 1)));
                        }
                        else
                        {
                            //bLaFL
                            s.Push(new MyInstruction(InstructionValue.b, (byte)(i.depth + 1)));
                            s.Push(new MyInstruction(InstructionValue.L, (byte)(i.depth + 1)));
                            s.Push(new MyInstruction(InstructionValue.a, (byte)(i.depth + 1)));
                            s.Push(new MyInstruction(InstructionValue.F, (byte)(i.depth + 1)));
                            s.Push(new MyInstruction(InstructionValue.L, (byte)(i.depth + 1)));
                        }
                    }
                }
            }

            return(p); //return the point we reached after moving 'numMoves' times
        }