Edit: непълни тестове на задача 3. Sneaky the Snake от вечерната група


1

На вечерния изпит по C# Advanced получих 100 точки на задача 3. Sneaky the Snake с решение което гърмеше на два от нулевите тестове. Когато си поправих решението да минава всички нулеви тестове, BGCoder вече ми даваше само 80 точки. Дебъгвах половин час и съм убеден, че решението което ми дава 80 точки е по-вярното от двете решения и отговаря по-точно на условието на задачата.

Ето и print screen на нулевите тестове. С това решение изкарах 100 точки:

Edit: това е кода с който изкарах 100 точки, но грешките в него са че след като увеличавам дължината на опашката не маркирам това поле с "-" и че намалявам дължината на опашката в грешен момент.

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _03.Task { public class EntryPoint { public static void Main() { int[] rc = Console.ReadLine() .Split(new char[] { 'x' }, StringSplitOptions.RemoveEmptyEntries) .Select(int.Parse) .ToArray(); int r = rc[0]; int c = rc[1]; char[][] den = new char[r][]; for (int i = 0; i < r; i++) { den[i] = Console.ReadLine().ToCharArray(); } int snakeEntranceRow = 0; int snakeEntranceCol = Array.FindIndex(den[0], w => w == 'e'); int snakeRow = snakeEntranceRow; int snakeCol = snakeEntranceCol; // The directions are: s - down, w - up, a - left, d - right string[] directions = Console.ReadLine() .Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .ToArray(); // Sneaky enters the den with length int snakeLength = 3; //int moves = 0; //while(moves < directions.Length) for (int moves = 0; moves < directions.Length; moves++) { if(moves > 0 && moves%5 == 0) { snakeLength--; } if (snakeLength <= 0) { Console.WriteLine("Sneaky is going to starve at [{0},{1}]", snakeRow, snakeCol); return; } if (directions[moves] == "s") { // down snakeRow++; } else if (directions[moves] == "w") { // up snakeRow--; } else if (directions[moves] == "a") { // left snakeCol = (snakeCol - 1 + c) % c; } else if (directions[moves] == "d") { // right snakeCol = (snakeCol + 1) % c; } if(r <= snakeRow) { Console.WriteLine("Sneaky is going to be lost into the depths with length {0}", snakeLength); return; } //else if (snakeCol < 0 || c <= snakeCol) //{ //} else if (den[snakeRow][snakeCol] == 'e') { Console.WriteLine("Sneaky is going to get out with length {0}", snakeLength); return; } else if (den[snakeRow][snakeCol] == '%') { Console.WriteLine("Sneaky is going to hit a rock at [{0},{1}]", snakeRow, snakeCol); return; } else if (den[snakeRow][snakeCol] == '-') { } else if (den[snakeRow][snakeCol] == '@') { snakeLength++; } } Console.WriteLine("Sneaky is going to be stuck in the den at [{0},{1}]", snakeRow, snakeCol); } } }

Edit 2: проблема се оказа в това, че когато дължината на змията стане 0, то трябва да се преизчисли новата ѝ позиция и чак тогава да се изведе резултата. Благодаря на всички които отделиха време за да помогнат в намирането на проблема и се извинявам на трейнърите ако съм ги обезпокоил.




Отговори



2

Здравейте, колега! Няма как да изкажем мнение кое от двете ви алтернативни решения отговаря по-точно на условието на задачата без да видим кода, който сте писал :-) Чисто като хипотеза на база Вашия резултат от първия нулев тест, може да не сте съобразил (както и аз отначало не можах), че при преминаване през клетка с яйце същото се изяжда еднократно, след което на това място вече имаме '-'. Ако не се вземе предвид това, то от нулевия тест се излиза с отговор 4. Причината да получите 5 е, че може би редуцирате дължината на змията при moveNumber % 5 == 0 а номерирате движенията от 0 до 9 за да loop-нете по тях, при което ако игнорирате първото, то се получава едно редуциране по-малко. Но това са само догадки на база screenshot-a Ви и може да нямат нищо общо с реалните причини за разминаванията.

Edit (на база качения от Мирослав код): Брей, оказва се, че и двете ми догадки са били верни :-)  И аз бях направил същите грешки отначало, но успях да си ги открия навреме. Колкото до това защо тестовете не ги хванали, то не може да се каже, че самите тестове са грешни, просто не са изчерпателни. И наистина, тъй като Вие "закъснявате" да намалите дължината с едни ход, то за всеки тест, при който за ходовете до излизане на змията е вярно moves%5!=0 вашето решение ще върне верен резултат. А колкото до яйцата ... остава да предположим, че повторно минаване през яйце е имало само в нулевите тестове...
Един съвет: значително ще подобрите четимостта на кода ако замените поне част от if-the-else -овете с switch, особено тези, окито са групирани по смисъл. И по принцип не е добра практика да се излиза насилствено от цикъл с return/break.  Ето и моят код, с който изкарах 100т.:

using System; using System.Numerics; // used for BigInteger using System.Text; // used for StringBuilder using System.Collections.Generic; using System.Linq; class PB3 { static int[] SplitStringToArrayOfInts(string arrString, char[] separators) // all are separated by separator, empty spaces are removed { string[] arrStrInput = arrString.Split(separators, StringSplitOptions.RemoveEmptyEntries); int n = arrStrInput.Length; int[] arrIntInput = new int[n]; for (int i = 0; i < n; i++) { arrIntInput[i] = int.Parse(arrStrInput[i].Trim()); } return arrIntInput; } static void Main() { char[] separators = { ' ', 'x' }; int[] denDimensions; denDimensions = SplitStringToArrayOfInts(Console.ReadLine(), separators); int depthR = denDimensions[0]; int widthC = denDimensions[1]; char[,] denRooms = new char[depthR, widthC]; int x; for (int i = 0; i < depthR; i++) { for (int j = 0; j < widthC; j++) { x = Console.Read(); denRooms[i, j] = Convert.ToChar(x); } Console.ReadLine(); } string directions = Console.ReadLine(); directions = directions.Replace(",", ""); int commandNumber = 0; int[] currentPos = new int[2]; currentPos[0] = 0; currentPos[1] = 0; while (denRooms[0,currentPos[1]]!='e') { currentPos[1]++; } int length = 3; char currentDirection; bool hitRock = false; bool lostIntoDepths = false; bool exited = false; while (commandNumber<directions.Length && !exited && !lostIntoDepths && !hitRock && length>0) { currentDirection = directions[commandNumber]; switch (currentDirection) { case 's': currentPos[0]++; break; case 'w': currentPos[0]--; break; case 'a': currentPos[1]--; break; case 'd': currentPos[1]++; break; } if ((commandNumber+1)%5==0) { length--; } if (currentPos[0]==depthR) { lostIntoDepths = true; break; } else if (currentPos[1]<0) { currentPos[1] = widthC - 1; } else if (currentPos[1]==widthC) { currentPos[1] = 0; } switch (denRooms[currentPos[0], currentPos[1]]) { case '%': hitRock = true; break; case '@': length++; denRooms[currentPos[0], currentPos[1]] = '-'; break; case 'e': exited = true; break; } commandNumber++; } if (exited) { Console.WriteLine("Sneaky is going to get out with length {0}", length); } else if (hitRock) { Console.WriteLine("Sneaky is going to hit a rock at [{0},{1}]", currentPos[0], currentPos[1]); } else if (lostIntoDepths) { Console.WriteLine("Sneaky is going to be lost into the depths with length {0}", length); } else if (length == 0) { Console.WriteLine("Sneaky is going to starve at [{0},{1}]", currentPos[0], currentPos[1]); } else { Console.WriteLine("Sneaky is going to be stuck in the den at [{0},{1}]", currentPos[0], currentPos[1]); } } }


от STzvetkov (1330 точки)


1

bgcoder не го грее дали кода е четим, а изпита се прави за време все пак. 

Освен това не съм съгласен, че return/break правят кода нечетим. Има много случаи, в които излизане от цикъла без break би наложило слагането на допълнителни флагове, допълнителни проверки, което на практика би направило кода по-нечетим. 

Относно return, моето мнение е, че за прости ситуации е по-четимо да има return веднага, когато функцията си свърши работата. В противен случай съм привърженик на един return в края на функцията.


от ShwangShwing (344 точки)

0

Колега STzvetkov, благодаря ти за отделеното време, но аз намирам моя код за много по-лесно четим. От самото начало съм написал, че в кода има 2 очевидни грешки които се хващат дори от нулевите тестове, но въпреки това изкарва 100 точки. Това което ме вълнува е защо след като поправя очевидните грешки, BGCoder вече ми дава само 80 точки. Възможно е поправеното решение също да е грешно, но аз не забелязвам грешка, а и нулевите тестове при него минават без грешки.

Ето поправеното според мен решение, с което обаче получавам само 80 точки:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _03.Task { public class EntryPoint { public static void Main() { int[] rc = Console.ReadLine() .Split(new char[] { 'x' }, StringSplitOptions.RemoveEmptyEntries) .Select(int.Parse) .ToArray(); int r = rc[0]; int c = rc[1]; char[][] den = new char[r][]; for (int i = 0; i < r; i++) { den[i] = Console.ReadLine().ToCharArray(); } int snakeEntranceRow = 0; int snakeEntranceCol = Array.FindIndex(den[0], w => w == 'e'); int snakeRow = snakeEntranceRow; int snakeCol = snakeEntranceCol; // The directions are: s - down, w - up, a - left, d - right string[] directions = Console.ReadLine() .Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .ToArray(); // Sneaky enters the den with length int snakeLength = 3; for (int moves = 0; moves < directions.Length; moves++) { if (moves % 5 == 4) { snakeLength--; } if (snakeLength <= 0) { Console.WriteLine("Sneaky is going to starve at [{0},{1}]", snakeRow, snakeCol); return; } if (directions[moves] == "s") { // down snakeRow++; } else if (directions[moves] == "w") { // up snakeRow--; } else if (directions[moves] == "a") { // left snakeCol = (snakeCol - 1 + c) % c; } else if (directions[moves] == "d") { // right snakeCol = (snakeCol + 1) % c; } if (r <= snakeRow) { Console.WriteLine("Sneaky is going to be lost into the depths with length {0}", snakeLength); return; } else if (den[snakeRow][snakeCol] == 'e') { Console.WriteLine("Sneaky is going to get out with length {0}", snakeLength); return; } else if (den[snakeRow][snakeCol] == '%') { Console.WriteLine("Sneaky is going to hit a rock at [{0},{1}]", snakeRow, snakeCol); return; } else if (den[snakeRow][snakeCol] == '-') { } else if (den[snakeRow][snakeCol] == '@') { snakeLength++; den[snakeRow][snakeCol] = '-'; } } Console.WriteLine("Sneaky is going to be stuck in the den at [{0},{1}]", snakeRow, snakeCol); } } }


от marks (354 точки)



1
Аз имах същите проблеми с тази задача... но за жалост само 80точки изкарах и тестовете които не ми минаваха (по спомен) май бяха същите. Аз увеличавах дължината на опашката (т.е. когато попадна на символ '@' ) И заменях символът ( '@' ) в/у който съм стъпил с  "-".

Не казвам, че грешката не е моя (може нещо друго да съм объркал в кода), но има ли възможност да се качат тези 2 теста за да съм сигурен? 

от mihailM956 (30 точки)


0
Колега, обикновено качват тестовете след изпит. И все пак дайте Вашия код да видим какво (евентуално) не му е наред.

от STzvetkov (1330 точки)

1
(:Д грозно ама върши работа)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Three { class Program { static void Main(string[] args) { // string[] dimensions = "5x8".Split('x').ToArray(); string[] dimensions = Console.ReadLine().Split('x').ToArray(); int row = int.Parse(dimensions[0]); int col = int.Parse(dimensions[1]); int sneakRow = 0; int sneakCol = 0; char[][] field = new char[row][]; for (int i = 0; i < row; i++) { string rowData = Console.ReadLine(); field[i] = new char[col]; for (int b = 0; b < col; b++) { if (rowData[b] == 'e') { sneakRow = i; sneakCol = b; } field[i][b] = (char)rowData[b]; } string rowDataAsString = String.Join("",field[i]); } string movesAsWholeString = Console.ReadLine(); string[] movesWithoutComma = movesAsWholeString.Split(',').ToArray(); string combinedWords = String.Join("", movesWithoutComma); long sneakLength = 3; long sneakMovesCounter = 0; char[] moves = combinedWords.ToCharArray(); bool dontPrint = false; for (int i = 0; i < moves.Length; i++) { sneakMovesCounter++; sneakLength += sneakMovesCounter % 5 == 0 ? -1 : 0; if(sneakLength <= 0) { Console.WriteLine("Sneaky is going to starve at [{0},{1}]",sneakRow,sneakCol); dontPrint = true; break; } if(moves[i] == 's' ) //down { ++sneakRow; } else if (moves[i] == 'w') //up { --sneakRow; } else if (moves[i] == 'a') //left { --sneakCol; } else if (moves[i] == 'd') //right { ++sneakCol; } //If he is at the rightmost column and goes right (d) he will go to the leftmost column sneakCol = sneakCol % col; //If he is at the leftmost column and goes left (a) he will go to the rightmost column sneakCol = sneakCol < 0? col-1 : sneakCol; //If he goes below the provided depth R he will lose sight of the entrance and will be lost into the depths. if(sneakRow >= row) { Console.WriteLine("Sneaky is going to be lost into the depths with length {0}", sneakLength); dontPrint = true; break; } if(sneakRow == 0 && sneakCol == 5) { var debugVar = 5; } char fieldSpotValue = field[sneakRow][sneakCol]; if(fieldSpotValue == '%') { Console.WriteLine("Sneaky is going to hit a rock at [{0},{1}]", sneakRow, sneakCol); dontPrint = true; break; } else if(fieldSpotValue == '@') { field[sneakRow][sneakCol] = '-'; ++sneakLength; } else if(fieldSpotValue == 'e') { Console.WriteLine("Sneaky is going to get out with length {0}", sneakLength); dontPrint = true; break; } } if(!dontPrint && moves.Length == sneakMovesCounter) { Console.WriteLine("Sneaky is going to be stuck in the den at [{0},{1}]", sneakRow, sneakCol); } } } }

от mihailM956 (30 точки)



0

Здравейте колеги. Мина доста време от изпита, но аз си решавам задачки и стигнах до тази и не мога да разбера защо ми гърми на 2 от тестовете в бгкодер, ето кода.

using System; using System.Linq; class Startup { static void Main() { int[] dimensions = Console.ReadLine().Split('x').Select(int.Parse).ToArray(); int row = dimensions[0]; int col = dimensions[1]; int snackyLenght = 3; char[,] matrix = new char[row, col]; for (int i = 0; i < row; i++) { char[] input = Console.ReadLine().ToCharArray(); for (int j = 0; j < col; j++) { matrix[i, j] = input[j]; } } string[] rout = Console.ReadLine().Split(',').ToArray(); int rowIndex = 0; int colIndex = 0; for (int i = 0; i < row; i++) { if (matrix[0, i] == 's') { colIndex = i; break; } } for (int i = 0; i < rout.Length; i++) { if (rout[i] == "d") { rowIndex++; if (rowIndex >= row) { Console.WriteLine("Snacky will be lost into the depths with length {0}", snackyLenght); break; } if (matrix[rowIndex, colIndex] == '*') { snackyLenght++; matrix[rowIndex, colIndex] = '.'; } } if (rout[i] == "u") { rowIndex--; if (matrix[rowIndex, colIndex] == '*') { snackyLenght++; matrix[rowIndex, colIndex] = '.'; } } if (rout[i] == "l") { colIndex--; if (colIndex < 0) { colIndex = col - Math.Abs(colIndex); } if (matrix[rowIndex, colIndex] == '*') { snackyLenght++; matrix[rowIndex, colIndex] = '.'; } } if (rout[i] == "r") { colIndex++; if (colIndex > col) { colIndex = col - Math.Abs(colIndex); } if (matrix[rowIndex, colIndex] == '*') { snackyLenght++; matrix[rowIndex, colIndex] = '.'; } } if ((i + 1) % 5 == 0) { snackyLenght--; } if (matrix[rowIndex, colIndex] == '#') { Console.WriteLine("Snacky will hit a rock at [{0},{1}]", rowIndex, colIndex); break; } if (snackyLenght <= 0) { Console.WriteLine("Snacky will starve at [{0},{1}]", rowIndex, colIndex); break; } if (matrix[rowIndex, colIndex] == 's') { Console.WriteLine("Snacky will get out with length {0}", snackyLenght); break; } if (i == rout.Length - 1) { Console.WriteLine("Snacky will be stuck in the den at [{0},{1}]", rowIndex, colIndex); } } } }


от olebg (598 точки)