Initially I had understood that the rotation is only a change of direction, without leaving the place. But there is also the possibility to rotate relative to the origin, changing the position. Below are solutions for both cases.
Rotation without leaving the place
If the idea of rotation is only to change the direction, do not need to keep changing the values of x
and y
. Instead, you could have a variable to control the current direction and change it when you find a "D" or "E", and to advance or reverse a position, you simply change the values of x
or y
according to the direction:
Scanner sc = new Scanner(System.in);
String entrada = sc.nextLine();
int x = 0, y = 0;
int direcao = 0; // 0 - norte, 1 - leste, 2 - sul, 3 - oeste
for (int i = 0; i < entrada.length(); i++) {
char c = entrada.charAt(i);
switch (c) {
case 'D':
direcao = (direcao + 1) % 4;
break;
case 'E':
direcao = (direcao + 3) % 4;
break;
case 'F':
case 'T': // para frente ou para trás, a lógica é a mesma
int passo = 1;
if (c == 'T') { // se for para trás, o passo é negativo
passo = -1;
}
switch (direcao) {
case 0: // norte, muda só y
y += passo;
break;
case 1: // leste, muda só x
x += passo;
break;
case 2: // sul, muda só y
y -= passo;
break;
case 3: // oeste, muda só x
x -= passo;
break;
}
break;
default:
// opção inválida, não faz nada (ou pode colocar alguma mensagem de erro, ou lançar exceção, etc)
}
}
System.out.printf("(%d, %d)\n", x, y);
Note that when finding "D" or "E", I only change direction, without juggling "juggling" with the values of x
and y
. I only change the values of these when going to walk (checking the current direction and whether I should walk forward or backward).
The directions I considered as the "cardinal points", so "north" would be to advance on the y axis, "east" to advance on the x axis, "south" to recede on the y axis and "west" to recede on the x axis:
norte
|
|
oeste ----|---- leste
|
|
sul
For this I used the operator %
, that returns the rest of the division. That is, if the current direction is 3 (west), to rotate clockwise I add 1 and take the rest of the division by 4, which results in zero (north). So if you rotate several times, I’ll have the directions 0, 1, 2, 3, 0, 1, 2, 3 and so on.
Already to rotate counterclockwise, I advance 3 positions (so I change from zero to 3, ie from north to west, and then to south, east, north, west, etc). I added up 3 times to subtract 1 because for negative values would go wrong (if I start from zero, I would have -1 % 4
, which results in -1
, which would be an invalid direction).
I also use printf
to format the position instead of concatenating strings (it’s just to show another way to do).
Finally, you don’t need to close the System.in
(as a general rule, we should close every resource we open, but the System.in
is exception - read more about this here and here).
As already said at the beginning, I made "F" be "forward" and "T" be "backward" (the opposite of what is in the question), so the result of the above code for "DFD" is (1, 0)
. But if the idea is to be the other way around ("F" be "backwards"), just change the if
up to:
if (c == 'F') { // "F" é "para trás"
passo = -1;
}
Another alternative is to have an array with the steps:
int x = 0, y = 0;
int direcao = 0; // 0 - norte, 1 - leste, 2 - sul, 3 - oeste
int[][] passos = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
for (int i = 0; i < entrada.length(); i++) {
char c = entrada.charAt(i);
switch (c) {
case 'D':
direcao = (direcao + 1) % 4;
break;
case 'E':
direcao = (direcao + 3) % 4;
break;
case 'F':
x += passos[direcao][0];
y += passos[direcao][1];
break;
case 'T':
x -= passos[direcao][0];
y -= passos[direcao][1];
break;
default:
// opção inválida, não faz nada (ou pode colocar alguma mensagem de erro, ou lançar exceção, etc)
}
}
Thus, the direction also serves as the index of the array passos
, then passos[direcao]
returns another array containing the increment to be done both in x
how much in y
.
In the above example I made "F" to be "forward", but if you want, just invert "F" and "T" in the code if you want "F" to be "backward".
Finally, another alternative (thanks to Bacchus by the algorithm) is to have two variables for the steps on the x and y axis, and go changing their values according to the direction:
int x = 0, y = 0;
int dx = 0, dy = -1;
int s;
for (int i = 0; i < entrada.length(); i++) {
switch (entrada.charAt(i)) {
case 'E':
s = dx;
dx = -dy;
dy = s;
break;
case 'D':
s = dx;
dx = dy;
dy = -s;
break;
case 'F':
x += dx;
y += dy;
break;
case 'T':
x -= dx;
y -= dy;
break;
}
}
Rotation in relation to origin
Now, if the idea of rotating is to change the position relative to the source, just add the position change in the above case:
int x = 0, y = 0, aux;
int direcao = 1; // 0 - norte, 1 - leste, 2 - sul, 3 - oeste
for (int i = 0; i < entrada.length(); i++) {
char c = entrada.charAt(i);
switch (c) {
case 'D':
direcao = (direcao + 1) % 4;
// rotaciona 90 graus no sentido horário
aux = x;
x = y;
y = -aux;
break;
case 'E':
direcao = (direcao + 3) % 4;
// rotaciona 90 graus no sentido anti-horário
aux = x;
x = -y;
y = x;
break;
case 'F':
case 'T': // para frente ou para trás, a lógica é a mesma
int passo = 1;
if (c == 'T') { // se for para trás, o passo é negativo
passo = -1;
}
switch (direcao) {
case 0: // norte, muda só y
y += passo;
break;
case 1: // leste, muda só x
x += passo;
break;
case 2: // sul, muda só y
y -= passo;
break;
case 3: // oeste, muda só x
x -= passo;
break;
}
break;
default:
// opção inválida, não faz nada (ou pode colocar alguma mensagem de erro, ou lançar exceção, etc)
}
}
Really genius this idea of "tattooing" the directions with values and working with the remains. I will only modify "direction" to 1 pointing thus initially to the east (I believe it is in the north).
– gmn_1450
@gmn_1450 I updated the answer with a few more options - but they all follow the same idea: the change of direction updates the "step", and the movement updates x and y according to the step defined by the current direction
– hkotsubo
Thank you very much. I can already see possible variations of this solution. :)
– gmn_1450
Shouldn’t the output for FFFDT be (0,-2)? (Assuming I leave from the east)....
– gmn_1450
@gmn_1450 Have you considered that "F" is forward or backward? Anyway, if you start in the east direction, FFF should walk 3 positions on the X axis, then D should turn south and T should walk only on the Y axis. So if F is "forward", vc ends in (3, 1) and if F is "backward", vc would end in (-3, -1)
– hkotsubo
I changed the question to consider "F" as "front" and "direction" to 1, since the starting position is right on the east. . I still don’t think you understand. The output to the FFFDT input, for example, should be (0,-2) due to the three initial steps on the x-axis (east), followed by an hourly rotation, which would lead to the coordinate to (0,-3) and finally to).
– gmn_1450
@gmn_1450 Ah, the code I did considers that the rotation is simply "run without leaving the place", that is, I just change the direction, without changing the position. So the solution is a little different, I’ll update the answer soon
– hkotsubo
@gmn_1450 Updated answer, I left the 2 options (rotate without leaving the place and in relation to the origin), so the answer is more complete :-)
– hkotsubo
Thank you for revisiting and, above all, updating the code. I apologize for the inaccuracy of my question. I will update it. :)
– gmn_1450