Skip to content
This repository was archived by the owner on Dec 12, 2023. It is now read-only.

Commit 988466e

Browse files
committed
Added solution to skiing in singapore problem
1 parent c29ffbe commit 988466e

File tree

1 file changed

+262
-0
lines changed

1 file changed

+262
-0
lines changed

solutions/c/sgski.c

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
// required; otherwise clang will complain that getline has not been declared
2+
#define _XOPEN_SOURCE 700
3+
#include <stdio.h>
4+
#include <ctype.h>
5+
#include <string.h>
6+
#include <stdlib.h>
7+
8+
typedef struct {
9+
int **matrix;
10+
int rowCount;
11+
int colCount;
12+
} matrix;
13+
14+
typedef struct {
15+
char* solution;
16+
int distance;
17+
int drop;
18+
} solution;
19+
20+
typedef struct {
21+
int row;
22+
int col;
23+
} cellIndex;
24+
25+
// input file reading routines
26+
void readfile(matrix *m, FILE* fp);
27+
void initMatrix(matrix *m, char* line);
28+
void readline(matrix *m, char* line, int rowIndex);
29+
30+
// solution finder
31+
void findSkiPath(matrix *m, solution *sol);
32+
void checkAdjacentCells(const char* path, matrix *m, cellIndex index, solution *sol, int currentValue);
33+
void evaluateSolution(solution *sol, const char* path);
34+
35+
// miscellaneous routines
36+
void showContents(matrix *m);
37+
38+
int main(int argc, char* argv[]) {
39+
40+
if(argc != 2) {
41+
printf("usage: sgski <input file>\n");
42+
exit(1);
43+
}
44+
45+
char* filename = argv[1];
46+
FILE *ifp = fopen(filename, "r");
47+
if (ifp == NULL) {
48+
printf("Unable to open input file %s\n", filename);
49+
exit(EXIT_FAILURE);
50+
}
51+
52+
// initialize the solution structure
53+
solution *sol = malloc(sizeof(solution));
54+
sol->solution = malloc(sizeof(char) * 100);
55+
sol->distance = 0;
56+
sol->drop = 0;
57+
58+
matrix *m = malloc(sizeof(matrix));
59+
60+
// read the input file into the matrix
61+
readfile(m, ifp);
62+
63+
// close file after reading
64+
fclose(ifp);
65+
66+
findSkiPath(m, sol);
67+
68+
printf("Ski Path: %s; Distance: %d; Drop: %d\n", sol->solution, sol->distance, sol->drop);
69+
70+
// release resources
71+
free(sol);
72+
free(m);
73+
74+
return 0;
75+
}
76+
77+
void findSkiPath(matrix *m, solution *sol) {
78+
for (int i = 0; i < m->rowCount; i++) {
79+
for (int j = 0; j < m->colCount; j++) {
80+
int value = m->matrix[i][j];
81+
char* path = malloc(sizeof(char) * 6);
82+
sprintf(path, "%d ", value);
83+
84+
cellIndex index;
85+
86+
// check east
87+
index.row = i;
88+
index.col = j + 1;
89+
checkAdjacentCells(path, m, index, sol, value);
90+
91+
// check west
92+
index.row = i;
93+
index.col = j - 1;
94+
checkAdjacentCells(path, m, index, sol, value);
95+
96+
// check north
97+
index.row = i - 1;
98+
index.col = j;
99+
checkAdjacentCells(path, m, index, sol, value);
100+
101+
// check south
102+
index.row = i + 1;
103+
index.col = j;
104+
checkAdjacentCells(path, m, index, sol, value);
105+
}
106+
}
107+
}
108+
109+
void checkAdjacentCells(const char* path, matrix *m, cellIndex index, solution *sol, int currentValue) {
110+
111+
// The base case - If we go beyond the limits of the matrix
112+
if(index.row < 0 || index.row > (m->rowCount - 1)
113+
|| index.col < 0 || index.col > (m->colCount - 1)) {
114+
evaluateSolution(sol, path);
115+
return;
116+
}
117+
118+
// check if the next cell has a lower value than the current cell
119+
int val = m->matrix[index.row][index.col];
120+
if(val < currentValue) {
121+
char* newPath = malloc(sizeof(char) * (strlen(path) + 4 + 1 + 1)); // the 4-digit value + space + \0
122+
strcpy(newPath, path);
123+
124+
char *ch = malloc(sizeof(char) * (5 + 1)); // support upto 4-digit value and \0 (string terminator)
125+
if(ch == NULL) {
126+
printf("Unable to allocate memory\n");
127+
exit(EXIT_FAILURE);
128+
}
129+
sprintf(ch, "%d ", val);
130+
strcat(newPath, ch);
131+
free(ch);
132+
133+
int r = index.row, c = index.col;
134+
135+
// check east
136+
index.row = r;
137+
index.col = c + 1;
138+
checkAdjacentCells((const char*) newPath, m, index, sol, val);
139+
140+
// check west
141+
index.row = r;
142+
index.col = c - 1;
143+
checkAdjacentCells((const char*) newPath, m, index, sol, val);
144+
145+
// check north
146+
index.row = r - 1;
147+
index.col = c;
148+
checkAdjacentCells((const char*) newPath, m, index, sol, val);
149+
150+
// check south
151+
index.row = r + 1;
152+
index.col = c;
153+
checkAdjacentCells((const char*) newPath, m, index, sol, val);
154+
155+
free(newPath);
156+
}
157+
158+
// all ajacent cells have bigger value then the current cell
159+
evaluateSolution(sol, path);
160+
return;
161+
}
162+
163+
/**
164+
* Checks if the longest path with the steepest drop has been found.
165+
*/
166+
void evaluateSolution(solution *sol, const char* path) {
167+
// split the string by the space delimiter
168+
int distance = 1;
169+
char *dropTemp[2];
170+
dropTemp[0] = strtok(strdup(path), " ");
171+
char* end = dropTemp[1] = strdup(dropTemp[0]);
172+
173+
while ((end = strtok(NULL, " ")) != NULL) {
174+
dropTemp[1] = end;
175+
distance++;
176+
}
177+
178+
if(distance < sol->distance) {
179+
return;
180+
}
181+
182+
int drop = atoi(dropTemp[0]) - atoi(dropTemp[1]);
183+
if(distance > sol->distance || drop > sol->drop) {
184+
strcpy(sol->solution, path);
185+
sol->distance = distance;
186+
sol->drop = drop;
187+
}
188+
}
189+
190+
void readfile(matrix *m, FILE* fp) {
191+
int rowIndex = 0;
192+
size_t len = 0;
193+
size_t read = -1;
194+
char *line;
195+
196+
while ((read = getline(&line, &len, fp) != -1)) {
197+
if (rowIndex == 0) {
198+
// the first row of the input file
199+
// contains the size of the matrix.
200+
initMatrix(m, line);
201+
} else {
202+
readline(m, line, rowIndex);
203+
}
204+
205+
rowIndex++;
206+
}
207+
}
208+
209+
/**
210+
* Reads the size of the matrix from the first line of the input file and
211+
* sets the row and column counts into the parameters rowCount and colCount
212+
* attributes of matrix m.
213+
*
214+
* This function is to be called on the first line of the input file.
215+
*/
216+
void initMatrix(matrix *m, char* line) {
217+
218+
// reads the row count - the first value on the line string
219+
char *ch = strtok(line, " ");
220+
m->rowCount = atoi(ch);
221+
222+
// reads the column count - the second value on the line string
223+
ch = strtok(NULL, " ");
224+
m->colCount = atoi(ch);
225+
226+
// initialize a two-dimentional array of size rowCount * columnCount
227+
int** matrix = (int **) malloc(sizeof(int *) * m->rowCount);
228+
for(int i = 0; i < m->rowCount; i++) {
229+
matrix[i] = (int *) malloc(sizeof(int) * m->colCount);
230+
}
231+
232+
m->matrix = matrix;
233+
}
234+
235+
void readline(matrix *m, char* line, int rowIndex) {
236+
int colIndex = 0;
237+
char *ch = strtok(line, " ");
238+
239+
while(ch != NULL) {
240+
int val = atoi(ch);
241+
if(val > 9999) {
242+
printf("Invalid input file. Cannot have value greater than 9999\n");
243+
exit(EXIT_FAILURE);
244+
}
245+
246+
m->matrix[rowIndex - 1][colIndex] = atoi(ch);
247+
ch = strtok(NULL, " ");
248+
colIndex++;
249+
}
250+
}
251+
252+
/**
253+
* Prints the contents of the matrix into the console
254+
*/
255+
void showContents(matrix *m) {
256+
for(int i = 0; i < m->rowCount; i++) {
257+
for (int j = 0; j < m->colCount; j++) {
258+
printf("%d ", m->matrix[i][j]);
259+
}
260+
printf("\n");
261+
}
262+
}

0 commit comments

Comments
 (0)