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 }