[HSCTF 6 Write-up] Misc – Broken GPS

Broken GPS
333

Written by: Disha and Shray

Ella is following a broken GPS. The GPS tells her to move in the opposite direction than the one she should be travelling in to get to her destination, and she follows her GPS exactly. For instance, every time she is supposed to move west, the GPS tells her to move east and she does so. Eventually she ends up in a totally different place than her intended location. What is the shortest distance between these two points? Assume that she moves one unit every time a direction is specified. For instance, if the GPS tells her to move “north,” she moves one unit north. If the GPS tells her to move “northwest,” then she moves one unit north and one unit west.


Input Format:

You will receive a text file with N directions provided to her by the GPS (the ones that she will be following) (1<=N<=1000). The first line in the file will be N, and each consequent line will contain a single direction: “north,” “south,” “east,” “west,” “northwest,” “northeast,” “southwest,” or “southeast.”


Output Format:

Round your answer to the nearest whole number and then divide by 26. Discard the quotient (mod 26). Each possible remainder corresponds to a letter in the alphabet. (0=a, 1=b… 25=z).

Find the letter for each test case and string them together. The result is the flag. (For instance, a, b, c becomes “abc”). Remember to use the flag format and keep all letters lowercase!


– 문제 설명

엘라는 망가진 GPS를 사용하고 있었는데, 이 GPS는 방향을 반대로 가르쳐준다고 합니다. 예를 들어, 동쪽으로 가야했다면 서쪽으로가고, 남쪽으로 가야했다면 북쪽으로 가는 식이죠. 엘라는 이 GPS를 전적으로 믿고있어서 GPS가 가르쳐주는대로 걸어갔다고 합니다.

제공되는 텍스트들 안에는 걸음 수가 정수로 적혀있고, 지나왔던 방향이 단어로 적혀있습니다.

플래그를 찾기 위해서는 엘라의 현재 위치와 원래 도착해야 했던 지점사이의 최단거리를 구해 정수형태로 반올림한 뒤, 알파벳의 길이인 26으로 나눠줘야 합니다. 그 나머지 값이 각각 알파벳 소문자와 대응됩니다. 이 때, 소문자 a는 0에 대응되고 z는 25에 대응됩니다. 제공되는 텍스트 파일은 총 12개 이므로, hsctf{} 플래그 형태 안에 삽입되어야 할 문자열의 길이는 12입니다.


– 문제 풀이 코드 설명

– 전체 코드

#include <stdio.h>
#include <string.h>
#include <math.h>

struct Pos {
	int x;
	int y;
};

struct Pos go(char *dir) {
	struct Pos cur = {0, 0};

	if(!strcmp(dir, "east")) {
		cur.x = -1;
	}
	else if(!strcmp(dir, "northeast")) {
		cur.x = -1;
		cur.y = +1;
	}
	else if(!strcmp(dir, "north")) {
		cur.y = +1;
	}
	else if(!strcmp(dir, "northwest")) {
		cur.x = +1;
		cur.y = +1;
	}
	else if(!strcmp(dir, "west")) {
		cur.x = +1;
	}
	else if(!strcmp(dir, "southwest")) {
		cur.x = +1;
		cur.y = -1;
	}
	else if(!strcmp(dir, "south")) {
		cur.y = -1;
	}
	else if(!strcmp(dir, "southeast")) {
		cur.x = -1;
		cur.y = -1;
	}

	return cur;
}

int main(int argc, char *argv[])
{
	if(argc != 2) {
		printf("Error! : Input txt file isn't defined.\n");
		return 1;
	}

	FILE *fp;
	fp = fopen(argv[1], "r");

	if(fp == NULL) {
		printf("Error! : Can't open %s - exit.\n", argv[1]);
		return 1;
	}

	int N;
	char step[10] = {0};
	
	struct Pos her={0, 0};
	struct Pos tmp;

	double dist = 0.0;
	int rounded = 0;
	int divided = 0;
	
	fscanf(fp, "%d", &N); // number of footsteps
	for(int i=0; i<N; i++) {
		fscanf(fp, "%s", step);
		tmp = go(step);

		her.x += tmp.x;
		her.y += tmp.y;
	}

	printf("[Her position] \n");
	printf("X : %d\n", her.x);
	printf("Y : %d\n", her.y);
	printf("\n");
	printf("[Original position] \n");
	printf("X : %d\n", -(her.x));
	printf("Y : %d\n", -(her.y));
	printf("\n");
	printf("[Distance] \n");
	printf("dist : %lf\n", dist = sqrt(pow(double(her.x*2), 2.0) + pow(double(her.y*2), 2.0)));
	printf("\n");
	printf("[Round and divide by 26]\n");
	printf("Rounded : %d\n", rounded = int(round(dist)));
	printf("Divided by 26 : %d\n", divided = (rounded % 26));
	printf("\n");
	printf("[Converted to lower case]\n");
	printf("Alphabet : %c\n", char(divided + 97));
	printf("\n");

	fclose(fp);

	return 0;
}

– 현재 위치 좌표 값 구하기

struct Pos {
	int x;
	int y;
};

x, y 좌표 값을 저장하기 위해 구조체를 사용했습니다.

struct Pos go(char *dir) {
	struct Pos cur = {0, 0};

	if(!strcmp(dir, "east")) {
		cur.x = -1;
	}
	else if(!strcmp(dir, "northeast")) {
		cur.x = -1;
		cur.y = +1;
	}
	else if(!strcmp(dir, "north")) {
		cur.y = +1;
	}
	else if(!strcmp(dir, "northwest")) {
		cur.x = +1;
		cur.y = +1;
	}
	else if(!strcmp(dir, "west")) {
		cur.x = +1;
	}
	else if(!strcmp(dir, "southwest")) {
		cur.x = +1;
		cur.y = -1;
	}
	else if(!strcmp(dir, "south")) {
		cur.y = -1;
	}
	else if(!strcmp(dir, "southeast")) {
		cur.x = -1;
		cur.y = -1;
	}

	return cur;
}

각각의 방향에 따른 x, y 좌표 값을 리턴해주는 함수 입니다. 구조체를 반환합니다.

	fscanf(fp, "%d", &N); // number of footsteps
	for(int i=0; i<N; i++) {
		fscanf(fp, "%s", step);
		tmp = go(step);

		her.x += tmp.x;
		her.y += tmp.y;
	}

파일 첫 줄에 적혀있는 발자국 수만큼 반복문을 돌립니다. 지나왔던 방향만큼 엘라의 좌표 값에 더해줍니다.

	printf("[Her position] \n");
	printf("X : %d\n", her.x);
	printf("Y : %d\n", her.y);
	printf("\n");
	printf("[Original position] \n");
	printf("X : %d\n", -(her.x));
	printf("Y : %d\n", -(her.y));
	printf("\n");

그녀의 위치를 찾았으면, 원래 도착했어야 할 위치는 찾기 쉽습니다. x, y 의 방향만 바꿔주면 됩니다.

	printf("[Distance] \n");
	printf("dist : %lf\n", dist = sqrt(pow(double(her.x*2), 2.0) + pow(double(her.y*2), 2.0)));
	printf("\n");

두 점 사이의 거리를 구하는 공식은 다음과 같습니다 :

두 점 사이의 거리 (사진 출처)

sqrt()는 제곱근 함수이고, pow()는 거듭제곱 함수 입니다.

        printf("[Round and divide by 26]\n");
	printf("Rounded : %d\n", rounded = int(round(dist)));
	printf("Divided by 26 : %d\n", divided = (rounded % 26));
	printf("\n");

round()함수는 반올림 함수이고, 나머지를 구하기 위한 모듈러 연산을 하려면 ‘%’ 기호를 쓰면 됩니다.

	printf("[Converted to lower case]\n");
	printf("Alphabet : %c\n", char(divided + 97));
	printf("\n");

알파벳으로 바꿔주기 위해 방금 구한 나머지 값에 소문자 ‘a’에 해당하는 ASCII 값 97을 더해줍니다.


– flag

프로그램을 텍스트 파일의 개수만큼 12번 돌려보면 플래그를 찾을 수 있습니다 :

hsctf{garminesuckz}

댓글 남기기