-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
147 lines (138 loc) · 4.33 KB
/
Copy pathmain.cpp
File metadata and controls
147 lines (138 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <iostream>
#include <fstream>
#include <stdexcept>
#include <string>
#include <vector>
#include <gz-util/string/utility.hpp>
#include <gz-util/string/from_string.hpp>
#include <gz-util/string/to_string.hpp>
#define PART2
#ifdef PART2
constexpr unsigned CAVE_WIDTH = 401;
#else
constexpr unsigned CAVE_WIDTH = 201;
#endif
constexpr unsigned CAVE_HEIGHT = 170;
constexpr char EMPTY = '.';
constexpr char WALL = '#';
constexpr char SAND = 'O';
class Cave {
public:
Cave(const char* filename);
char at(unsigned x, unsigned y) const { return cave.at(transform(x) + y * charsPerRow); }
void set(unsigned x, unsigned y, char c) { cave.at(transform(x) + y * charsPerRow) = c; }
void print() const { std::cout << cave << std::endl; };
// ret true if sand stays somewhere
bool addSand(unsigned x, unsigned y);
private:
// return true if sand was moved
bool moveSand(unsigned& x, unsigned& y);
// position to x-index, 500 should be in the middle
unsigned transform(unsigned x) const { return x - 500 + ((charsPerRow - 1) / 2) ; }
std::string cave;
unsigned charsPerRow = CAVE_WIDTH + 1; // +1 for newline
unsigned rows = CAVE_HEIGHT;
};
Cave::Cave(const char* filename) {
cave.resize(charsPerRow * rows, EMPTY);
for (std::string::size_type i = charsPerRow-1; i < cave.size(); i += charsPerRow) {
cave[i] = '\n';
}
std::ifstream file(filename);
std::vector<std::string_view> walls;
std::string buf;
unsigned maxY = 0;
if (!file.is_open()) {
throw std::runtime_error("Could not open file");
}
while (std::getline(file, buf)) {
walls = gz::util::splitStringInVector<std::string_view>(std::string_view(buf), " -> ");
unsigned startX = 0, startY = 0;
unsigned endX = 0, endY = 0;
for (auto& wall : walls) {
auto comma = wall.find(',');
endX = gz::fromString<unsigned>(std::string(wall.substr(0, comma)));
endY = gz::fromString<unsigned>(std::string(wall.substr(comma + 1)));
if (endY > maxY) { maxY = endY; }
if (startX != 0) {
this->set(endX, endY, WALL); // will be left out by while loops
if (startX == endX) {
while (startY != endY) {
this->set(startX, startY, WALL);
startY += startY < endY ? 1 : -1;
}
}
else {
while (startX != endX) {
this->set(startX, startY, WALL);
startX += startX < endX ? 1 : -1;
}
}
}
startX = endX;
startY = endY;
}
}
#ifdef PART2
// draw line
for (unsigned x = 0; x < charsPerRow - 1; x++) {
cave.at(x + charsPerRow * (maxY+2)) = WALL;
}
#endif
}
bool Cave::addSand(unsigned x, unsigned y) {
if (at(x, y) == SAND) { return false; } // entrance blocked
set(x, y, SAND);
bool hasMoved = moveSand(x, y);
while (hasMoved) {
hasMoved = moveSand(x, y);
/* printf("Falling sand: x=%u, y=%u\n", x, y); */
if (y == rows - 1) { // falling through floor
set(x, y, EMPTY);
return false;
}
}
return true;
}
bool Cave::moveSand(unsigned& x, unsigned& y) {
// try falling down
if (at(x, y+1) == EMPTY) {
set(x, y, EMPTY);
set(x, ++y, SAND);
return true;
}
// try fall to left
else if (at(x-1, y+1) == EMPTY) {
set(x, y, EMPTY);
set(--x, ++y, SAND);
return true;
}
// try fall to right
else if (at(x+1, y+1) == EMPTY) {
set(x, y, EMPTY);
set(++x, ++y, SAND);
return true;
}
return false;
}
int main(int argc, char** argv) {
const char* filename;
if (argc != 2) {
/* printf("Need exactly one argument, the filename\n"); */
/* return 1; */
filename = "i-dont-like-sand.txt";
}
else {
filename = argv[1];
}
Cave cave(filename);
cave.print();
unsigned sandCount = 0;
while (cave.addSand(500, 0)) {
/* std::cout << "." << std::endl; */
sandCount++;
}
cave.set(500, 0, 'S');
cave.print();
printf("I DONT LIKE SAND %d/10!!!\n", sandCount);
}