Въпрос за задача от изпит по C# 2 - Laser


0

Problem 3 – Laser

You are given a rectangular cuboid of size W (width), H (height) and D (depth) consisting of W * H * D cubes. All cubes have coordinates, corresponding to their position, starting from (1, 1, 1) – the coordinates of the "left, lower, near" cube and going to (W, H, D) – the coordinates of the "right, upper, far" cube.

Adjacent cubes we will call any cubes which share a common wall, edge or vertex. So, any cube in the cuboid has 26 (8 + 9 + 9) adjacent cubes, except if it is on the edge or wall of the cuboid (then it has less).  

Let’s say we go inside one of the cubes in the cuboid (which is not on the side, or on the edge of the cube) and shoot a laser from it into one of the adjacent cubes. We can define the direction of the shot with a 3D vector, which has only 1, -1 or 0 as its coordinate values. So, for example if we want to shoot a laser straight up, that direction will be (0, 1, 0), if we want to shoot it straight down, the direction will be (0, -1, 0), if we want to shoot it forwards and up the direction will be (0, 1, 1) and if we want to shoot it left, forward and up the direction will be (-1, 1, 1). We have a total of 26 possible directions (the number of adjacent cubes).

When the laser passes through a cube, it burns it and it cannot pass through it again. Furthermore, if the laser reaches the wall of the cuboid (that is, a cube which is on the wall), it burns the cube there and reflects back into the cuboid, continuing to burn cubes it passes through. The reflection happens according to the laws of light reflection. Basically, the component of the direction vector, which would cause the laser to leave the cuboid, becomes the opposite number. So if a laser is moving in direction “right” (1, 0, 0), once it reaches the right wall of the cube it will reflect back, moving in direction “left (-1, 0, 0), but, in this case, that will cause it to visit an already burnt cube, so the laser will stop there.

imageFurthermore, all cubes on the edges (red green and blue cubes on the picture) of our cuboid are burned to begin with. So a laser will always stop before reaching the edge, because it cannot go into the edge cubes.

 

Write a program, which by given the width, height and depth of a cuboid, along with the coordinates of the cube from which the laser is shot and the direction of the shot, determines the last position the laser can reach in the cube.

Note: the starting position is burned during the shot, so it cannot be the answer (unless the laser travels into no other cubes, which can only happen if the next cube it should visit is an edge cube). The edges are burned by default, so no cube on the edge can be an answer either.

Input

The input data should be read from the console.

On the first line of the input there will be the numbers W, H, D, separated by whitespaces – the width, height and depth of the cuboid

On the next line there will be the numbers startW, startH, startD, separated by whitespaces – the width, height and depth of the cube, from which the laser is shot.

On the third line there will be the numbers dirW, dirH, dirD, separated by whitespaces – defining the direction, in which the laser is shot.

The input data will always be valid and in the format described. There is no need to check it explicitly.

Output

The output data should be printed on the console.

On the only line of the output you should print exactly 3 numbers, separated by whitespaces – the width, height and depth of the last cube the laser will visit.

Constraints

·         W, H, D, startW, startH, startD, dirW, dirH and dirD will all be integers

·         4 < W, H, D < 100

·         1 < startW, startH, startD < W, H, D

·         Each of the numbers dirW, dirH, dirD can only have the values -1, 1 or 0

·         Allowed working time for your program: 0.1 seconds. Allowed memory: 16 MB.

Examples

Sample input

Sample output

5 10 5

2 6 3

1 0 1

 

1 6 2

Explanation: Here we are only moving on the "sixth floor" of cubes (so we can meet only walls and no edges) and the movement looks like this:

 

image

 

Решение : http://pastebin.com/706x5vwv

Здравейте колеги, изкарвам 10 точки на задачата и не мога да разбера къде е проблема. Благодаря предварително :)




Отговори



1

Здравей колега,

грешката ти, както беше казано по горе, е че не работиш с куба както е казано в задачата с начало едници и край width,height,depth , ами работиш със начало 0 - ли и край width-1,height-1,depth-1. Когато аз решавах тази задача бях допуснал същата грешка, тъй като си мислех, че няма значение дали работим с единици и 0-ли и те са го направили така в примера за да ни заблудят.

Решение : http://pastebin.com/yTVg9Mj8 със съвсем малки промени по твоя код 100 точки.

Значи едната грешка е както колегата Здравко каза е във проверяването дали е стена - трябва да се проверя до width и до 1.

Другата грешка, с която резултата става 100 точки , е във метода DeleteEdjes(), Като на всякъде където цикъл трябва да започва от 1 (i = 1) и laserWidth,laserHeight,laserDepth когато им връщаш старите стойности трябва да са равни на 1 и widht,height,depth вместо 0 и (widht,height,depth) -1.

Ето пример : 

for (int i = 1; i < height; i++)
            {
                matrix[curWidth, curHeight, curDepth] = true;
                curHeight++;
            }
            curWidth = 1;
            curHeight = height;
            curDepth = 1;
Надявам се да съм бил полезен :)

 


от tddhome (3086 точки)


1
Здрасти,
 
В условието на задачата, във второто изречение пише, че най-ниският, ляв, близък до нас ъгъл е с координати 1, 1, 1. Според логиката на твойта задача, той е 0, 0, 0. От там идва основната грешка. Ако си оправиш проверките в метода CheckForWall, да не са до width/height/depth - 1, а до width/height/depth и също да не са до 0, а до 1, получаваш 80 точки. Също разбира се трябва да направиш булевият куб да е с размери на width/height/depth + 1.
 
Останалите два теста по всяка вероятност гърмят поради някаква неточност в метода DeleteEdjes(), но там не мисля да се забърквам да ги търся.
 
Би могъл изцяло да го махнеш този метод, като леко модифицираш метода CheckForWall(). Слагаш един брояч вътре започващ от нула и при всяка една от трите if проверки го увеличаваш с 1. Накрая връщаш стойността на брояча през метода. След това слагаш проверка в while цикъла, където проверяваш дали вече си стъпвал на дадена позиция || CheckForWall() >= 2. Ако е две, значи си в ръб, ако е три си в ъгъл, тоест трябва да брейкнеш.
 
while (true)
            {
                if (CheckForWall(laserWidth, laserHeight, laserDepth) >= 2 || matrix[laserWidth, laserHeight, laserDepth] == true)
                {
                    break;
                }
                oldWidth = laserWidth;
                oldHeight = laserHeight;
                oldDepth = laserDepth;
                matrix[laserWidth, laserHeight, laserDepth] = true;
                laserWidth += dirWidth;
                laserHeight += dirHeight;
                laserDepth += dirDepth;
            }
 
 
static int CheckForWall(int laserWidth, int laserHeight, int laserDepth)
        {
            int result = 0;
 
            if (laserWidth == width || laserWidth == 1)
            {
                dirWidth *= -1;
                result++;
            }
            if (laserHeight == height || laserHeight == 1)
            {
                dirHeight *= -1;
                result++;
            }
            if (laserDepth == depth || laserDepth == 1)
            {
                dirDepth *= -1;
                result++;
            }
 
            return result;
        }
 



2
Проблемът е точно там, където е посочил колегата Георгиев, но можеш да го оправиш просто като на входа променяш стартовите координати на лазера с минус 1, а при печатането ги увеличаваш с +1 и удряш 100/100

от Drago (711 точки)


0
Да, вярно и така става :) Хитро, не се сетих