2019-12-18 in class
This commit is contained in:
parent
6b3e3a2da9
commit
b3b4b52882
9 changed files with 650 additions and 1 deletions
37
checker/checker.cc
Normal file
37
checker/checker.cc
Normal file
|
@ -0,0 +1,37 @@
|
|||
// vim: set ts=2 sw=2 et tw=80:
|
||||
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
|
||||
class checker {
|
||||
struct pos {
|
||||
unsigned x;
|
||||
unsigned y;
|
||||
pos(unsigned x, unsigned y) : x(x), y(y) {};
|
||||
};
|
||||
|
||||
unsigned c;
|
||||
unsigned r;
|
||||
std::map<pos, bool> map;
|
||||
|
||||
public:
|
||||
checker(unsigned c, unsigned r) : c(c), r(r), map() {}
|
||||
|
||||
void visit(unsigned int x, unsigned int y);
|
||||
bool visited(unsigned x, unsigned y);
|
||||
};
|
||||
|
||||
void checker::visit(unsigned x, unsigned y) {
|
||||
this->map[pos(] = true;
|
||||
}
|
||||
|
||||
bool checker::visited(unsigned x, unsigned y) {
|
||||
return this->map[x * this->c + y];
|
||||
}
|
||||
|
||||
int main() {
|
||||
checker a(10, 10);
|
||||
a.visit(1, 1);
|
||||
assert(a.visited(1,1));
|
||||
assert(!a.visited(1,0));
|
||||
}
|
|
@ -56,7 +56,7 @@ unsigned long table_total_size(const struct chessboard*);
|
|||
unsigned long table_hash(const struct chessboard*, unsigned, unsigned);
|
||||
|
||||
inline unsigned long table_total_size(const struct chessboard* c) {
|
||||
return 100;
|
||||
return 1000;
|
||||
}
|
||||
|
||||
inline unsigned long table_hash(const struct chessboard* c, unsigned col,
|
||||
|
|
142
roadmap/Makefile
Normal file
142
roadmap/Makefile
Normal file
|
@ -0,0 +1,142 @@
|
|||
OBJECTS = roadmap.o
|
||||
CFLAGS=-Wall -g
|
||||
CXXFLAGS=-Wall -g
|
||||
SHELL=/bin/bash
|
||||
|
||||
TIMEOUT=8
|
||||
|
||||
TESTS_DIR=tests
|
||||
|
||||
TESTS_SH:=$(wildcard $(TESTS_DIR)/*.sh)
|
||||
TESTS_SH_NAMES:=$(patsubst $(TESTS_DIR)/%.sh, %, $(TESTS_SH))
|
||||
|
||||
TESTS_IO:=$(wildcard $(TESTS_DIR)/*.in)
|
||||
TESTS_IO_NAMES:=$(patsubst $(TESTS_DIR)/%.in, %, $(TESTS_IO))
|
||||
|
||||
TESTS_C:=$(wildcard $(TESTS_DIR)/*.c)
|
||||
TESTS_CXX:=$(wildcard $(TESTS_DIR)/*.cpp)
|
||||
TESTS_BIN:=$(patsubst $(TESTS_DIR)/%.c, $(TESTS_DIR)/%, $(TESTS_C)) \
|
||||
$(patsubst $(TESTS_DIR)/%.cpp, $(TESTS_DIR)/%, $(TESTS_CXX))
|
||||
TESTS_BIN_NAMES:=$(patsubst $(TESTS_DIR)/%.c, %, $(TESTS_C)) $(patsubst $(TESTS_DIR)/%.cpp, %, $(TESTS_CXX))
|
||||
|
||||
.PHONY: all
|
||||
all: compile check
|
||||
|
||||
.PHONY: compile-program
|
||||
|
||||
compile: $(PROGRAMS) $(OBJECTS)
|
||||
|
||||
.PHONY: check
|
||||
check: check-bin check-io-sh
|
||||
|
||||
.PHONY: check-io-sh
|
||||
check-io-sh: compile $(TESTS_IO) $(TESTS_SH)
|
||||
@exec 2> /dev/null; \
|
||||
for p in $(foreach prog,$(PROGRAMS),$(dir $(prog))$(prog)); do \
|
||||
echo "Testing $${p}:" ; \
|
||||
for t in $(TESTS_IO_NAMES); do \
|
||||
echo -n "Running test $$t..." ; \
|
||||
"$$p" < "$(TESTS_DIR)/$$t.in" > "$$t.out" 2>&1 & \
|
||||
prog_pid=$$!; \
|
||||
( sleep $(TIMEOUT); kill $$prog_pid > /dev/null 2>&1 ) & \
|
||||
killer_pid=$$!; \
|
||||
wait $$prog_pid; \
|
||||
res=$$?; \
|
||||
if test $$res -gt 128; \
|
||||
then \
|
||||
case `kill -l $$(($$res - 128))` in \
|
||||
ABRT ) echo "FAIL"; ;; \
|
||||
TERM ) echo "TIME OUT"; ;; \
|
||||
* ) echo "UNKNOWN ERROR"; ;; \
|
||||
esac ; \
|
||||
echo "see $(TESTS_DIR)/$$t.in" ;\
|
||||
echo "you may run $$p < $(TESTS_DIR)/$$t.in" ;\
|
||||
echo "to see what went wrong";\
|
||||
rm -f "$$t.out" ;\
|
||||
else \
|
||||
kill $$killer_pid > /dev/null 2>&1 ;\
|
||||
wait $$killer_pid; \
|
||||
if cmp -s "$$t.out" "$(TESTS_DIR)/$$t.expected"; \
|
||||
then \
|
||||
echo "PASS" ;\
|
||||
rm -f "$$t.out" ;\
|
||||
else \
|
||||
echo "FAIL" ;\
|
||||
echo "see $(TESTS_DIR)/$$t.sh" ;\
|
||||
echo "run diff $$t.out $(TESTS_DIR)/$$t.expected";\
|
||||
echo "to see the difference between the actual and expected output";\
|
||||
fi; \
|
||||
fi; \
|
||||
done; \
|
||||
for t in $(TESTS_SH_NAMES); do \
|
||||
echo -n "Running test $$t..." ; \
|
||||
$(SHELL) "$(TESTS_DIR)/$$t.sh" "$$p" > "$$t.out" 2>&1 & \
|
||||
prog_pid=$$!; \
|
||||
( sleep $(TIMEOUT); kill $$prog_pid > /dev/null 2>&1 ) & \
|
||||
killer_pid=$$!; \
|
||||
wait $$prog_pid; \
|
||||
res=$$?; \
|
||||
if test $$res -gt 128; \
|
||||
then \
|
||||
case `kill -l $$(($$res - 128))` in \
|
||||
ABRT ) echo "FAIL"; ;; \
|
||||
TERM ) echo "TIME OUT"; ;; \
|
||||
* ) echo "UNKNOWN ERROR"; ;; \
|
||||
esac ; \
|
||||
echo "see $(TESTS_DIR)/$$t.sh" ;\
|
||||
echo "you may run $(TESTS_DIR)/$$t.sh $$p" ;\
|
||||
echo "to see what went wrong";\
|
||||
rm -f "$$t.out" ;\
|
||||
else \
|
||||
kill $$killer_pid > /dev/null 2>&1 ;\
|
||||
wait $$killer_pid; \
|
||||
if cmp -s "$$t.out" "$(TESTS_DIR)/$$t.expected"; \
|
||||
then \
|
||||
echo "PASS" ;\
|
||||
rm -f "$$t.out" ;\
|
||||
else \
|
||||
echo "FAIL" ;\
|
||||
echo "see $(TESTS_DIR)/$$t.sh" ;\
|
||||
echo "run diff $$t.out $(TESTS_DIR)/$$t.expected";\
|
||||
echo "to see the difference between the actual and expected output";\
|
||||
fi; \
|
||||
fi; \
|
||||
done; \
|
||||
done
|
||||
|
||||
$(TESTS_DIR)/%: $(TESTS_DIR)/%.c $(OBJECTS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.c $(OBJECTS) -o $@
|
||||
|
||||
$(TESTS_DIR)/%: $(TESTS_DIR)/%.cpp $(OBJECTS)
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(TESTS_DIR)/$*.cpp $(OBJECTS) -o $@
|
||||
|
||||
.PHONY: check-bin
|
||||
check-bin: $(TESTS_BIN)
|
||||
@exec 2> /dev/null; \
|
||||
for t in $(TESTS_BIN_NAMES); do \
|
||||
echo -n "Running test $$t..." ; \
|
||||
"$(TESTS_DIR)/$$t" &\
|
||||
prog_pid=$$!; \
|
||||
( sleep $(TIMEOUT); kill $$prog_pid > /dev/null 2>&1 ) & \
|
||||
killer_pid=$$!; \
|
||||
wait $$prog_pid; \
|
||||
res=$$?; \
|
||||
if test $$res -gt 128; \
|
||||
then \
|
||||
case `kill -l $$(($$res - 128))` in \
|
||||
ABRT ) echo "FAIL"; ;; \
|
||||
TERM ) echo "TIME OUT"; ;; \
|
||||
* ) echo "UNKNOWN ERROR"; ;; \
|
||||
esac ; \
|
||||
echo "you may run $(TESTS_DIR)/$$t to see what went wrong" ;\
|
||||
else \
|
||||
kill $$killer_pid > /dev/null 2>&1 ;\
|
||||
wait $$killer_pid; \
|
||||
echo "PASS" ;\
|
||||
fi; \
|
||||
done
|
||||
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(PROGRAMS) $(OBJECTS) tests/*.o $(TESTS_BIN)
|
44
roadmap/roadmap.cpp
Normal file
44
roadmap/roadmap.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "roadmap.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
using std::map;
|
||||
using std::set;
|
||||
|
||||
class ConcreteRoadMap : public AbstractRoadMap {
|
||||
private:
|
||||
int cities;
|
||||
|
||||
map< string, set<string> > adj;
|
||||
|
||||
/*
|
||||
* Adds in the map for key city1 a new set with city2 inside if there is no
|
||||
* prior set, otherwise it appends city2 into the existing set
|
||||
*/
|
||||
void addPair(const string& city1, const string& city2) {
|
||||
this->adj[city1].insert(city2);
|
||||
}
|
||||
|
||||
public:
|
||||
ConcreteRoadMap() : adj(), cities(0) {};
|
||||
|
||||
void addRoad(const string& city1, const string& city2) override {
|
||||
addPair(city1, city2);
|
||||
addPair(city2, city1);
|
||||
}
|
||||
|
||||
void addRoad(const vector<string>& cities) override {
|
||||
for (size_t i = 0; i < cities.size() - 1; i++) {
|
||||
addRoad(cities[i], cities[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
void clear() override {
|
||||
this->adj.clear();
|
||||
}
|
||||
|
||||
int neighborCountForCity(const string& city) const override {
|
||||
auto i = this->adj.find(city);
|
||||
return i->second.size();
|
||||
}
|
||||
};
|
59
roadmap/roadmap.h
Normal file
59
roadmap/roadmap.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
#ifndef __ROADMAP_H__
|
||||
#define __ROADMAP_H__
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
class AbstractRoadMap {
|
||||
public:
|
||||
/* Add a road that connects city1 with city2. All roads are bidirectional.
|
||||
*/
|
||||
virtual void addRoad(const string & city1, const string & city2) = 0;
|
||||
|
||||
/* Add a road that goes through all the cities in the cities
|
||||
* vector. In other words, add a road between each pair of
|
||||
* adjacent cities in the vector.
|
||||
*/
|
||||
virtual void addRoad(const vector<string> & cities) = 0;
|
||||
|
||||
/* Clear the road map completely.
|
||||
*/
|
||||
virtual void clear() = 0;
|
||||
|
||||
/* Return the number of neighboring cities for the given city, or
|
||||
* -1 if the given city is not in the map.
|
||||
*/
|
||||
virtual int neighborCountForCity(const string & city) const = 0;
|
||||
|
||||
/* Return true if and only if there is a path that starts from a
|
||||
* city X and then leads back to X by taking each no more than
|
||||
* once.
|
||||
*/
|
||||
virtual bool hasLoop() const = 0;
|
||||
|
||||
/* Return true if there is a path from city1 to city2.
|
||||
*/
|
||||
virtual bool reachable(const string & city1, const string & city2) const = 0;
|
||||
|
||||
/* Return the number of "islands" in the map. An island is a
|
||||
* maximal group of cities that are reachable from each other.
|
||||
* All cities in an island are reachable from each other, but they
|
||||
* are not reachable from any another city from another island.
|
||||
*/
|
||||
virtual int countIslands() const = 0;
|
||||
|
||||
/* Destructor
|
||||
*/
|
||||
virtual ~AbstractRoadMap() {};
|
||||
};
|
||||
|
||||
/* Return a new road map object that implements AbstractRoadMap. The
|
||||
* new road map must be empty, meaning that it does not contain any
|
||||
* road or city.
|
||||
*/
|
||||
extern AbstractRoadMap * createRoadMap();
|
||||
|
||||
#endif // __ROADMAP_H__
|
112
roadmap/tests/basic_testing.h
Normal file
112
roadmap/tests/basic_testing.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
#ifndef BASIC_TESTING_H_INCLUDED
|
||||
#define BASIC_TESTING_H_INCLUDED
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define ck_assert_msg(expr, ...) \
|
||||
if (!(expr)) { \
|
||||
fprintf(stderr, "%s:%d: Assertion '"#expr"' failed\n" , __FILE__, __LINE__); \
|
||||
fprintf(stderr, ## __VA_ARGS__, NULL); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define ck_assert_int(X, OP, Y) do { \
|
||||
intmax_t _ck_x = (X); \
|
||||
intmax_t _ck_y = (Y); \
|
||||
if (!(_ck_x OP _ck_y)) { \
|
||||
fprintf(stderr, "%s:%d: Assertion '%s' failed: %s == %jd, %s == %jd\n", \
|
||||
__FILE__, __LINE__, #X" "#OP" "#Y, #X, _ck_x, #Y, _ck_y); \
|
||||
return 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ck_assert_uint(X, OP, Y) do { \
|
||||
uintmax_t _ck_x = (X); \
|
||||
uintmax_t _ck_y = (Y); \
|
||||
if (!(_ck_x OP _ck_y)) { \
|
||||
fprintf(stderr, "%s:%d: Assertion '%s' failed: %s == %ju, %s == %ju\n", \
|
||||
__FILE__, __LINE__, #X" "#OP" "#Y, #X, _ck_x, #Y, _ck_y); \
|
||||
return 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define assert_int_eq(X, Y) ck_assert_int(X,==,Y)
|
||||
#define assert_uint_eq(X, Y) ck_assert_uint(X,==,Y)
|
||||
|
||||
#define assert_true(X) do { \
|
||||
if (!(X)) { \
|
||||
fprintf(stderr, "%s:%d: Assertion failed: '"#X"' is false (should be true)\n", __FILE__, __LINE__); \
|
||||
return 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define assert_false(X) do { \
|
||||
if (X) { \
|
||||
fprintf(stderr, "%s:%d: Assertion failed: '"#X"' is true (should be false)\n", __FILE__, __LINE__); \
|
||||
return 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef struct {
|
||||
const char * name;
|
||||
int (*test_function)();
|
||||
const char * file;
|
||||
int line;
|
||||
} test_descriptor;
|
||||
|
||||
#define TEST(_Name) \
|
||||
static int _Name ## _fn (); \
|
||||
static const test_descriptor _Name ## _descr = { # _Name, _Name ## _fn, __FILE__, __LINE__}; \
|
||||
static const test_descriptor * _Name = & _Name ## _descr; \
|
||||
static int _Name ## _fn ()
|
||||
|
||||
#define TEST_PASSED do { return (1); } while(0)
|
||||
|
||||
#define TEST_SUITE(_Name) \
|
||||
unsigned int _Name ## _failed; \
|
||||
unsigned int _Name ## _passed; \
|
||||
const test_descriptor * _Name ## _suite []
|
||||
|
||||
#define RUN_SUITE(_Name) \
|
||||
do { \
|
||||
_Name ## _failed = 0; \
|
||||
_Name ## _passed = 0; \
|
||||
for (int _i = 0; _i < sizeof( _Name ## _suite )/sizeof(test_descriptor *); ++_i) { \
|
||||
if (!(_Name ## _suite [_i]->test_function())) { \
|
||||
_Name ## _failed += 1; \
|
||||
fprintf(stderr, "Test suite "#_Name": test %s failed\n", _Name ## _suite [_i]->name); \
|
||||
} else { \
|
||||
_Name ## _passed += 1; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TEST_SUITE_PASS(_Name) (_Name ## _failed == 0)
|
||||
|
||||
#define PRINT_SUITE_RESULTS(_Name) \
|
||||
do { \
|
||||
printf("Test suite "#_Name": pass %u/%u ", _Name ## _passed, _Name ## _passed + _Name ## _failed); \
|
||||
} while(0)
|
||||
|
||||
static unsigned int tests_run_fail = 0;
|
||||
static unsigned int tests_run_pass = 0;
|
||||
|
||||
#define RUN_TEST(_Name) \
|
||||
do { \
|
||||
if (!(_Name ->test_function())) { \
|
||||
tests_run_fail += 1; \
|
||||
fprintf(stderr, "Test %s failed\n", _Name ->name); \
|
||||
} else { \
|
||||
tests_run_pass += 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PRINT_TEST_RESULTS do { \
|
||||
printf(" %u/%u ", tests_run_pass, tests_run_pass + tests_run_fail); \
|
||||
} while (0);
|
||||
|
||||
#define ALL_TESTS_PASSED (tests_run_fail == 0)
|
||||
|
||||
#endif /* BASIC_TESTING_H_INCLUDED */
|
18
roadmap/tests/test0.cpp
Normal file
18
roadmap/tests/test0.cpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
#include "basic_testing.h"
|
||||
|
||||
#include "../roadmap.h"
|
||||
|
||||
TEST(empty) {
|
||||
std::unique_ptr<AbstractRoadMap> m(createRoadMap());
|
||||
TEST_PASSED;
|
||||
}
|
||||
|
||||
int main() {
|
||||
RUN_TEST(empty);
|
||||
PRINT_TEST_RESULTS;
|
||||
assert(ALL_TESTS_PASSED);
|
||||
}
|
40
roadmap/tests/test1.cpp
Normal file
40
roadmap/tests/test1.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
|
||||
#include "basic_testing.h"
|
||||
|
||||
#include "../roadmap.h"
|
||||
|
||||
TEST(example) {
|
||||
std::unique_ptr<AbstractRoadMap> m(createRoadMap());
|
||||
|
||||
// Add roads on one island:
|
||||
m->addRoad("Sengkol", "Sakra");
|
||||
m->addRoad({"Mataram", "Mangsit", "Pamenang"});
|
||||
m->addRoad({"Mataram", "Sengkol", "Koeta"});
|
||||
|
||||
assert_int_eq(m->countIslands(), 1);
|
||||
assert_true(m->reachable("Sengkol", "Mataram"));
|
||||
assert_int_eq(m->neighborCountForCity("Mataram"), 2);
|
||||
assert_int_eq(m->neighborCountForCity("Pamenang"), 1);
|
||||
assert_false(m->hasLoop());
|
||||
|
||||
// Create a loop:
|
||||
m->addRoad("Sakra", "Mataram");
|
||||
assert_true(m->hasLoop());
|
||||
|
||||
// Add roads on another island:
|
||||
m->addRoad({"Denpasar", "Sukawati", "Ubud"});
|
||||
assert_int_eq(m->countIslands(), 2);
|
||||
|
||||
// Cities on different islands are not reachable:
|
||||
assert_false(m->reachable("Sengkol", "Sukawati"));
|
||||
TEST_PASSED;
|
||||
}
|
||||
|
||||
int main() {
|
||||
RUN_TEST(example);
|
||||
PRINT_TEST_RESULTS;
|
||||
assert(ALL_TESTS_PASSED);
|
||||
}
|
197
roadmap/tests/test2.cpp
Normal file
197
roadmap/tests/test2.cpp
Normal file
|
@ -0,0 +1,197 @@
|
|||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <cassert>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
|
||||
#include "basic_testing.h"
|
||||
|
||||
#include "../roadmap.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
TEST(basic_reachability) {
|
||||
std::unique_ptr<AbstractRoadMap> m(createRoadMap());
|
||||
|
||||
assert_false(m->reachable("Sengkol", "Sakra"));
|
||||
assert_false(m->reachable("Sakra", "Sengkol"));
|
||||
|
||||
m->addRoad("Sengkol", "Sakra");
|
||||
|
||||
assert_true(m->reachable("Sengkol", "Sakra"));
|
||||
assert_true(m->reachable("Sakra", "Sengkol"));
|
||||
|
||||
m->addRoad({"Mataram", "Mangsit", "Pamenang"});
|
||||
|
||||
assert_true(m->reachable("Mataram", "Pamenang"));
|
||||
assert_true(m->reachable("Pamenang", "Mataram"));
|
||||
|
||||
assert_false(m->reachable("Sakra", "Pamenang"));
|
||||
assert_false(m->reachable("Sengkol", "Mataram"));
|
||||
|
||||
m->addRoad({"Mataram", "Sengkol", "Koeta"});
|
||||
|
||||
assert_true(m->reachable("Sakra", "Pamenang"));
|
||||
assert_true(m->reachable("Sengkol", "Mataram"));
|
||||
|
||||
TEST_PASSED;
|
||||
}
|
||||
|
||||
TEST(clear) {
|
||||
std::unique_ptr<AbstractRoadMap> m(createRoadMap());
|
||||
|
||||
assert_false(m->reachable("Sengkol", "Sakra"));
|
||||
assert_false(m->reachable("Sakra", "Sengkol"));
|
||||
|
||||
m->addRoad("Sengkol", "Sakra");
|
||||
|
||||
assert_true(m->reachable("Sengkol", "Sakra"));
|
||||
assert_true(m->reachable("Sakra", "Sengkol"));
|
||||
|
||||
m->clear();
|
||||
|
||||
assert_false(m->reachable("Sengkol", "Sakra"));
|
||||
assert_false(m->reachable("Sakra", "Sengkol"));
|
||||
|
||||
m->addRoad("Sengkol", "Sakra");
|
||||
assert_true(m->reachable("Sengkol", "Sakra"));
|
||||
assert_true(m->reachable("Sakra", "Sengkol"));
|
||||
|
||||
m->addRoad({"Mataram", "Mangsit", "Pamenang"});
|
||||
|
||||
assert_true(m->reachable("Mataram", "Pamenang"));
|
||||
assert_true(m->reachable("Pamenang", "Mataram"));
|
||||
|
||||
assert_false(m->reachable("Sakra", "Pamenang"));
|
||||
assert_false(m->reachable("Sengkol", "Mataram"));
|
||||
|
||||
m->addRoad({"Mataram", "Sengkol", "Koeta"});
|
||||
|
||||
assert_true(m->reachable("Sakra", "Pamenang"));
|
||||
assert_true(m->reachable("Sengkol", "Mataram"));
|
||||
|
||||
m->clear();
|
||||
|
||||
assert_false(m->reachable("Sakra", "Pamenang"));
|
||||
assert_false(m->reachable("Sengkol", "Mataram"));
|
||||
assert_false(m->reachable("Mataram", "Pamenang"));
|
||||
assert_false(m->reachable("Pamenang", "Mataram"));
|
||||
|
||||
TEST_PASSED;
|
||||
}
|
||||
|
||||
TEST(tree) {
|
||||
std::unique_ptr<AbstractRoadMap> m(createRoadMap());
|
||||
|
||||
std::deque<string> Q;
|
||||
Q.push_back("0");
|
||||
while (!Q.empty()) {
|
||||
string s = Q.back();
|
||||
Q.pop_back();
|
||||
if (s.length() >= 8)
|
||||
continue;
|
||||
string s0 = s + "0";
|
||||
string s1 = s + "1";
|
||||
m->addRoad(s, s0);
|
||||
m->addRoad(s, s1);
|
||||
Q.push_back(s0);
|
||||
Q.push_back(s1);
|
||||
}
|
||||
|
||||
assert_int_eq(m->countIslands(), 1);
|
||||
assert_false(m->hasLoop());
|
||||
TEST_PASSED;
|
||||
}
|
||||
|
||||
TEST(islands) {
|
||||
std::unique_ptr<AbstractRoadMap> m(createRoadMap());
|
||||
|
||||
std::deque<string> Q;
|
||||
Q.push_back("0");
|
||||
while (!Q.empty()) {
|
||||
string s = Q.back();
|
||||
Q.pop_back();
|
||||
if (s.length() >= 8)
|
||||
continue;
|
||||
string s0 = s + "0";
|
||||
string s1 = s + "1";
|
||||
m->addRoad(s1, s0);
|
||||
Q.push_back(s0);
|
||||
Q.push_back(s1);
|
||||
}
|
||||
|
||||
assert_int_eq(m->countIslands(), 127);
|
||||
assert_false(m->hasLoop());
|
||||
TEST_PASSED;
|
||||
}
|
||||
|
||||
TEST(big_loop) {
|
||||
std::unique_ptr<AbstractRoadMap> m(createRoadMap());
|
||||
|
||||
std::deque<string> Q;
|
||||
Q.push_back("0");
|
||||
while (!Q.empty()) {
|
||||
string s = Q.back();
|
||||
Q.pop_back();
|
||||
if (s.length() >= 8) {
|
||||
m->addRoad(s, "0");
|
||||
} else {
|
||||
string s0 = s + "0";
|
||||
string s1 = s + "1";
|
||||
m->addRoad(s, s0);
|
||||
m->addRoad(s, s1);
|
||||
Q.push_back(s0);
|
||||
Q.push_back(s1);
|
||||
}
|
||||
}
|
||||
assert_int_eq(m->countIslands(), 1);
|
||||
assert_true(m->hasLoop());
|
||||
TEST_PASSED;
|
||||
}
|
||||
|
||||
TEST(big_island) {
|
||||
std::unique_ptr<AbstractRoadMap> m(createRoadMap());
|
||||
|
||||
std::vector<string> cities = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" };
|
||||
|
||||
for (unsigned int i = 0; i < cities.size(); ++i)
|
||||
for (unsigned int j = i + 1; j < cities.size(); ++j)
|
||||
m->addRoad(cities[i], cities[j]);
|
||||
|
||||
assert_int_eq(m->countIslands(), 1);
|
||||
assert_true(m->hasLoop());
|
||||
for (unsigned int i = 0; i < cities.size(); ++i)
|
||||
assert_int_eq(m->neighborCountForCity(cities[i]), cities.size()-1);
|
||||
TEST_PASSED;
|
||||
}
|
||||
|
||||
TEST(unknown_city) {
|
||||
std::unique_ptr<AbstractRoadMap> m(createRoadMap());
|
||||
|
||||
std::vector<string> cities = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" };
|
||||
|
||||
for (unsigned int i = 0; i < cities.size(); ++i)
|
||||
assert_int_eq(m->neighborCountForCity(cities[i]), -1);
|
||||
|
||||
for (unsigned int i = 0; i < cities.size(); ++i)
|
||||
for (unsigned int j = i + 1; j < cities.size(); ++j)
|
||||
m->addRoad(cities[i], cities[j]);
|
||||
|
||||
for (unsigned int i = 0; i < cities.size(); ++i) {
|
||||
string s = cities[i] + "X";
|
||||
assert_int_eq(m->neighborCountForCity(s), -1);
|
||||
}
|
||||
TEST_PASSED;
|
||||
}
|
||||
|
||||
int main() {
|
||||
RUN_TEST(basic_reachability);
|
||||
RUN_TEST(clear);
|
||||
RUN_TEST(tree);
|
||||
RUN_TEST(islands);
|
||||
RUN_TEST(big_loop);
|
||||
RUN_TEST(big_island);
|
||||
RUN_TEST(unknown_city);
|
||||
PRINT_TEST_RESULTS;
|
||||
assert(ALL_TESTS_PASSED);
|
||||
}
|
Reference in a new issue