2019-12-18 in class

This commit is contained in:
Claudio Maggioni 2019-12-18 10:37:59 +01:00
parent 6b3e3a2da9
commit b3b4b52882
9 changed files with 650 additions and 1 deletions

37
checker/checker.cc Normal file
View 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));
}

View file

@ -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
View 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
View 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
View 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__

View 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
View 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
View 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
View 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);
}