Last active
February 19, 2024 13:48
-
-
Save KiJeong-Lim/1944529b4b1093f9506b5a374857fdcc to your computer and use it in GitHub Desktop.
Dev-C++ works
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdint> | |
#include "scratch.hpp" | |
struct MotorInput { | |
float p; | |
float v; | |
float kp; | |
float kd; | |
float t_ff; | |
}; | |
class MotorInputHandle : public MotorInput { | |
private: | |
std::uint8_t p_lock_lv; | |
std::uint8_t v_lock_lv; | |
std::uint8_t kp_lock_lv; | |
std::uint8_t kd_lock_lv; | |
std::uint8_t t_ff_lock_lv; | |
public: | |
MotorInputHandle(const MotorInput &initial_motor_input); | |
#if 0 | |
void pack(CANMessage *can_msg) const; | |
#endif | |
void set(const MotorInput &new_motor_input); | |
}; | |
void MotorInputHandle::set(const MotorInput &new_motor_input) | |
{ | |
if (p_lock_lv != 0) { | |
p = new_motor_input.p; | |
} | |
if (v_lock_lv != 0) { | |
v = new_motor_input.v; | |
} | |
if (kp_lock_lv != 0) { | |
kp = new_motor_input.kp; | |
} | |
if (kd_lock_lv != 0) { | |
kd = new_motor_input.kd; | |
} | |
if (t_ff_lock_lv != 0) { | |
t_ff = new_motor_input.t_ff; | |
} | |
} | |
MotorInputHandle::MotorInputHandle(const MotorInput &initial_motor_input) | |
{ | |
p = initial_motor_input.p; | |
v = initial_motor_input.v; | |
kp = initial_motor_input.kp; | |
kd = initial_motor_input.kd; | |
t_ff = initial_motor_input.t_ff; | |
p_lock_lv = 0; | |
v_lock_lv = 0; | |
kp_lock_lv = 0; | |
kd_lock_lv = 0; | |
t_ff_lock_lv = 0; | |
} | |
void test_cancomm() | |
{ | |
MotorInputHandle handle = MotorInput({ .p = 1.0, .v = 1.0, .kp = 1.0, .kd = 1.0, .t_ff = 1.0 }); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "scratch.hpp" | |
#define USE_PID 1 | |
static bool areSameString(const char *lhs, const char *rhs); | |
static int PID_START_TICK = 390; | |
bool areSameStr(const char *const lhs, const char *const rhs) | |
{ | |
if (lhs == NULL || rhs == NULL) { | |
return false; | |
} | |
return std::string{ lhs } == std::string{ rhs }; | |
} | |
static | |
void prompt(const char *const msg) | |
{ | |
char var_name[16]; | |
char op_name[16]; | |
int sscanf_res = 0; | |
int pid_start_tick = 0; | |
int motor_id = 0; | |
float value = 0.0; | |
bool res = false; | |
if (msg == NULL) { | |
printf("\n\r%% Leaving listening mode %%\n"); | |
return; | |
} | |
#if USE_PID | |
sscanf_res = sscanf(msg, "%s %d = %f", var_name, &motor_id, &value); | |
if (sscanf_res == 3) { | |
if (areSameStr("Kp", var_name)) { | |
printf("Kp of motor #%d = %lf\n", motor_id, value); | |
res = true; | |
return; | |
} | |
else if (areSameStr("Ki", var_name)) { | |
printf("Ki of motor #%d = %lf\n", motor_id, value); | |
res = true; | |
return; | |
} | |
else if (areSameStr("Kd", var_name)) { | |
printf("Kd of motor #%d = %lf\n", motor_id, value); | |
res = true; | |
return; | |
} | |
else { | |
res = false; | |
} | |
goto RET; | |
} | |
#endif | |
#if USE_PID | |
sscanf_res = sscanf(msg, "pid start tick = %d", &pid_start_tick); | |
if (sscanf_res == 1) { | |
PID_START_TICK = pid_start_tick; | |
res = true; | |
goto RET; | |
} | |
#endif | |
sscanf_res = sscanf(msg, "%s", op_name); | |
if (sscanf_res == 1) { | |
if (areSameStr(op_name, "jump")) { | |
printf("operation=jump\n"); | |
res = true; | |
} | |
else if (areSameStr(op_name, "standUp")) { | |
printf("operation=standUp\n"); | |
res = true; | |
} | |
#if USE_PID | |
else if (areSameStr(op_name, "jump1")) { | |
printf("operation=jump1\n"); | |
res = true; | |
} | |
else if (areSameStr(op_name, "standUp1")) { | |
printf("operation=standUp1\n"); | |
res = true; | |
} | |
#endif | |
else { | |
res = false; | |
} | |
goto RET; | |
} | |
RET: | |
if (res) { | |
printf("\n\rCommand well recieved\n"); | |
} | |
else { | |
printf("\n\rUnknown command or wrong command\n"); | |
} | |
} | |
void proto_test_prompt(void) | |
{ | |
char msg[64] = {}; | |
gets(msg); | |
prompt(msg); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <time.h> | |
#include <windows.h> | |
#include <conio.h> | |
#include "cscratch.h" | |
static long long int my_time(void); | |
static void clear_console(void); | |
struct OS_C_API os = { | |
.sleep = Sleep, | |
.kbhit = kbhit, | |
.getch = getch, | |
.itime = my_time, | |
.clear = clear_console, | |
}; | |
time_t my_time() | |
{ | |
return time(NULL); | |
} | |
void clear_console() | |
{ | |
system("cls"); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef CSCRATCH_H | |
#define CSCRATCH_H | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#define len(xs) (sizeof(xs)/sizeof((xs)[0])) | |
struct OS_C_API { | |
void (*sleep)(long unsigned int sleeping_time); | |
int (*kbhit)(void); | |
int (*getch)(void); | |
long long int (*itime)(void); | |
void (*clear)(void); | |
}; | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "scratch.hpp" | |
Gear::Gear(const int gear) | |
: gear{ gear } | |
, gear_cnt{ 0 } | |
{ | |
} | |
Gear::Gear(const Gear &other) | |
: gear{ other.gear } | |
, gear_cnt{ other.gear_cnt } | |
{ | |
} | |
Gear::~Gear() | |
{ | |
} | |
bool Gear::go() | |
{ | |
if ((gear_cnt + 1) % gear == 0) { | |
gear_cnt = 0; | |
return true; | |
} | |
if (gear_cnt >= 0) { | |
gear_cnt++; | |
} | |
else { | |
gear_cnt = 0; | |
} | |
return false; | |
} | |
void Gear::reset() | |
{ | |
gear = 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "scratch.hpp" | |
std::vector<int> IntegerHelper::reads(const std::string str) | |
{ | |
std::stringstream ss; | |
std::vector<int> ret; | |
std::string temp; | |
int found; | |
ss << str; | |
while (!ss.eof()) { | |
ss >> temp; | |
if (std::stringstream(temp) >> found) { | |
ret.push_back(found); | |
} | |
temp = ""; | |
} | |
return ret; | |
} | |
void IntegerHelper::shows(std::vector<int> ns) | |
{ | |
const size_t sz = ns.size(); | |
for (int i = 0; i < sz; i++) { | |
std::cout << ns[i] << ' '; | |
} | |
std::cout << std::endl; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "scratch.hpp" | |
#define ESC 27 | |
#define LEFT_DIRECTION 75 | |
#define RIGHT_DIRECTION 77 | |
void IO::setPrompt(void (*const prompt)(const char *msg)) | |
{ | |
this->prompt = prompt; | |
this->clear(); | |
} | |
bool IO::runPrompt() | |
{ | |
char *msg = NULL; | |
int ch = '\0'; | |
bool prompt_routine_breaked = false; | |
while (1) { | |
ch = getc(); | |
if (ch == 0) { | |
return false; | |
} | |
if (ch == ESC) { | |
return true; | |
} | |
prompt_routine_breaked = takech(ch); | |
if (prompt_routine_breaked) { | |
sync(msg); | |
prompt(msg); | |
clear(); | |
return true; | |
} | |
} | |
} | |
int IO::getc() | |
{ | |
int res = 0; | |
if (os.kbhit()) { | |
res = os.getch(); | |
} | |
return res; | |
} | |
void IO::clear() | |
{ | |
for (int i = 0; i < len(buffer); i++) { | |
buffer[i] = '\0'; | |
} | |
cursor = 0; | |
theend = 0; | |
} | |
bool IO::takech(const int ch) | |
{ | |
switch (ch) { | |
default: | |
if (cursor < 0) { | |
result = NULL; | |
return false; | |
} | |
if (cursor > theend) { | |
result = NULL; | |
return false; | |
} | |
if (theend + 1 >= len(buffer)) { | |
result = NULL; | |
return false; | |
} | |
for (int i = theend; i >= cursor; i--) { | |
buffer[i + 1] = buffer[i]; | |
} | |
buffer[cursor++] = ch; | |
buffer[++theend] = '\0'; | |
print(); | |
result = NULL; | |
return false; | |
case '\b': | |
if (cursor > theend) { | |
result = NULL; | |
return false; | |
} | |
if (theend + 1 >= len(buffer)) { | |
result = NULL; | |
return false; | |
} | |
if (cursor <= 0) { | |
result = NULL; | |
return false; | |
} | |
for (int i = --cursor; i < theend; i++) { | |
buffer[i] = buffer[i + 1]; | |
} | |
if (theend > 0) { | |
buffer[theend--] = '\0'; | |
} | |
print(); | |
result = NULL; | |
return false; | |
case '\n': | |
case '\r': | |
result = buffer; | |
return true; | |
case '\0': | |
return false; | |
case ESC: | |
clear(); | |
printf("\n"); | |
result = NULL; | |
return true; | |
case 224: | |
if (theend + 1 >= len(buffer)) { | |
result = NULL; | |
return false; | |
} | |
switch (getc()) { | |
case LEFT_DIRECTION: | |
if (cursor > 0) { | |
cursor--; | |
} | |
print(); | |
result = NULL; | |
return false; | |
case RIGHT_DIRECTION: | |
if (cursor < theend) { | |
cursor++; | |
} | |
print(); | |
result = NULL; | |
return false; | |
} | |
} | |
return false; | |
} | |
void IO::sync(char *&msg) | |
{ | |
msg = result; | |
} | |
void IO::print() | |
{ | |
int i = 0; | |
printf("\r"); | |
for (i = 0; i < len(buffer); i++) { | |
printf(" "); | |
} | |
printf("\r"); | |
for (i = 0; i < cursor; i++) { | |
printf(" "); | |
} | |
for (i = cursor; i < theend; i++) { | |
printf("%c", buffer[i]); | |
} | |
buffer[i] = '\0'; | |
printf("\r"); | |
for (int i = 0; i < cursor; i++) { | |
printf("%c", buffer[i]); | |
} | |
std::cout.flush(); | |
} | |
static | |
void delta(const char *const msg) | |
{ | |
printf("\n[ECHO] %s\n", msg); | |
} | |
void test_io() | |
{ | |
IO comm; | |
bool prompt_finished = false; | |
comm.setPrompt(delta); | |
while(!prompt_finished) { | |
os.sleep(10); | |
prompt_finished = comm.runPrompt(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "scratch.hpp" | |
int main(void) | |
{ | |
nonogramsolver_test(); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "scratch.hpp" | |
#define DEBUG 0 | |
template <typename A> using Array = std::vector<A>; | |
using Generator1D = NonogramSolver::Generator1D; | |
static void debug_Generator1D_callback(Generator1D::cell_t *line, size_t sz); | |
void nonogramsolver_test() // A test function for Nonogram Solver! | |
{ | |
NonogramSolver solver = {}; | |
Array<NonogramSolver::Answer> solutions = {}; | |
int n = 0; | |
solver.scanPuzzle("nonogramtest.txt"); | |
solver.solve(); | |
solutions = solver.getSolutions(); | |
n = solutions.size(); | |
for (int i = 0; i < n; i++) { | |
solutions[i].print(); | |
} | |
} | |
void debug_Generator1D_callback(Generator1D::cell_t *const line, const size_t line_sz) | |
{ | |
printf("================\n"); | |
printf("0123456789ABCDEF\n"); | |
for (int i = 0; i < line_sz; i++) { | |
printf("%d", line[i]); | |
} | |
printf("\n"); | |
printf("================\n"); | |
printf("\n"); | |
} | |
void nonogramsolverlogic_test() | |
{ | |
Generator1D gen = {}; | |
int info[] = { 2, 2, 3, 1, }; | |
Generator1D::cell_t line[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; | |
bool well_formed = gen.init(line, len(line), info, len(info)); | |
if (well_formed) { | |
gen.attach(debug_Generator1D_callback); | |
gen.exec(); | |
} | |
} | |
Generator1D::Generator1D() | |
: callback{ nullptr }, line{ nullptr }, line_sz{ 0 } | |
{ | |
} | |
void Generator1D::exec() | |
{ | |
int block_cnt = 0; | |
bool last_was_black = false; | |
for (int i = 0; i < line_sz; i++) { | |
line[i] = WHITE; | |
} | |
run(line, info_sz, 0, 0); | |
} | |
bool Generator1D::attach(void (*const callback)(Generator1D::cell_t *line, size_t line_sz)) | |
{ | |
if (callback == nullptr) { | |
return false; | |
} | |
this->callback = callback; | |
return true; | |
} | |
void Generator1D::print() const | |
{ | |
for (int i = 0; i < line_sz; i++) { | |
switch (line[i]) { | |
case BLACK: | |
std::cout << '#'; | |
break; | |
case WHITE: | |
std::cout << '.'; | |
break; | |
default: | |
std::cout << 'E'; | |
break; | |
} | |
} | |
std::cout << std::endl; | |
} | |
bool Generator1D::init(Generator1D::cell_t *const line, const std::size_t line_sz, int *const info, const std::size_t info_sz) | |
{ | |
this->line_sz = line_sz; | |
this->line = line; | |
this->info = info; | |
this->info_sz = info_sz; | |
return true; | |
} | |
int Generator1D::run(Generator1D::cell_t *const start, const int depth, const int block_num, const int combo) | |
{ | |
#if DEBUG == 2 | |
char char128[128]; | |
print(); | |
gets(char128); | |
#endif | |
#if DEBUG | |
printf("[CALLED: depth = %d, start = %d] ", depth, start - line); | |
print(); | |
printf("\n"); | |
#endif | |
if (depth == 0) { | |
callback(line, line_sz); | |
return 0; | |
} | |
else { | |
const int block_sz = info[block_num]; | |
cell_t *left = start, *right = start; | |
int go = combo, t = 0, res = 0; | |
if (left + block_sz > line + line_sz) { | |
return 1; | |
} | |
for (int b = 0; b < block_sz; b++) { | |
*right++ = BLACK; | |
} | |
t = run(right + 1, depth - 1, block_num + 1, combo + 1); | |
switch (t) { | |
case 0: | |
while (right < line + line_sz) { | |
*left++ = WHITE; | |
*right++ = BLACK; | |
t = run(right + 1, depth - 1, block_num + 1, 0); | |
if (t > 0) { | |
break; | |
} | |
} | |
case 1: | |
while (right > left) | |
*--right = WHITE; | |
break; | |
default: | |
if (t >= combo) | |
res = combo + 1; | |
else | |
res = 1; | |
while (right > left) | |
*--right = WHITE; | |
} | |
return res; | |
} | |
} | |
NonogramSolver::Exception::Exception(const char *const err_msg) | |
: err_msg{ err_msg } | |
{ | |
} | |
const char *NonogramSolver::Exception::what() const throw () | |
{ | |
return err_msg.c_str(); | |
} | |
NonogramSolver::~NonogramSolver() | |
{ | |
clear(); | |
} | |
NonogramSolver::Answer::Answer(Array<Array<Cell>> board) | |
: board{ board } | |
{ | |
} | |
void NonogramSolver::Answer::print() const | |
{ | |
for (int i = 0; i < board.size(); i++) { | |
for (int j = 0; j < board[i].size(); j++) { | |
switch (board[i][j]) { | |
case BLACK: | |
std::cout << '#'; | |
break; | |
case WHITE: | |
std::cout << '.'; | |
break; | |
default: | |
std::cout << 'E'; | |
break; | |
} | |
} | |
std::cout << std::endl; | |
} | |
std::cout << std::endl; | |
} | |
bool NonogramSolver::setPuzzle(const Array<Array<int>> &rows, const Array<Array<int>> &cols) | |
{ | |
const int m = rows.size(), n = cols.size(); | |
bool well_formed = false; | |
this->rows = rows; | |
this->cols = cols; | |
this->m = m; | |
this->n = n; | |
well_formed = puzzleWellFormed(); | |
if (well_formed) { | |
this->board = new Cell [m * n]; | |
for (int i = 0; i < m * n; i++) | |
board[i] = WHITE; | |
} | |
else | |
this->board = nullptr; | |
return well_formed; | |
} | |
bool NonogramSolver::puzzleWellFormed() const | |
{ | |
const int m = rows.size(), n = cols.size(); | |
int t = 0; | |
if (m != this->m || n != this->n) | |
return false; | |
if (m == 0 || n == 0) | |
return false; | |
for (int i = 0; i < m; i++) | |
if (rows[i].size() == 0) | |
return false; | |
for (int j = 0; j < n; j++) | |
if (cols[j].size() == 0) | |
return false; | |
for (int i = 0; i < m; i++) | |
if (rows[i].size() == 1 && rows[i][0] == 0) | |
continue; | |
else { | |
t = 0; | |
for (int k = 0; k < rows[i].size(); k++) | |
if (rows[i][k] <= 0) | |
return false; | |
else { | |
if (t == 0) | |
t += rows[i][k]; | |
else | |
t += rows[i][k] + 1; | |
} | |
if (t > m) | |
return false; | |
} | |
for (int j = 0; j < n; j++) | |
if (cols[j].size() == 1 && cols[j][0] == 0) | |
continue; | |
else { | |
t = 0; | |
for (int k = 0; k < cols[j].size(); k++) | |
if (cols[j][k] <= 0) | |
return false; | |
else { | |
if (t == 0) | |
t += cols[j][k]; | |
else | |
t += cols[j][k] + 1; | |
} | |
if (t > n) | |
return false; | |
} | |
return true; | |
} | |
Array<Array<NonogramSolver::Cell>> NonogramSolver::toMatrix() const | |
{ | |
Array<Array<Cell>> ret = {}; | |
for (int i = 0; i < m; i++) { | |
Array<Cell> line = {}; | |
for (int j = 0; j < n; j++) | |
line.push_back(at(i, j)); | |
ret.push_back(static_cast<Array<Cell> &&>(line)); | |
} | |
return ret; | |
} | |
void NonogramSolver::printBoard() const | |
{ | |
for (int i = 0; i < m; i++) { | |
for (int j = 0; j < n; j++) { | |
switch (at(i, j)) { | |
case BLACK: | |
std::cout << '#'; | |
break; | |
case WHITE: | |
std::cout << '.'; | |
break; | |
default: | |
std::cout << 'E'; | |
break; | |
} | |
} | |
std::cout << std::endl; | |
} | |
std::cout << std::endl; | |
} | |
bool NonogramSolver::scanPuzzle(const char *const file_name) | |
{ | |
Array<Array<int>> rows, cols; | |
std::ifstream file; | |
std::string line; | |
bool okay = false; | |
try { | |
board = nullptr; | |
file.open(file_name, std::ios::in); | |
if (file.bad()) { | |
throw Exception("***scanPuzzle: cannot open the file\n"); | |
} | |
getline(file, line); | |
if (line != std::string{ "rows" }) { | |
throw Exception("***scanPuzzle: expected \'rows\'\n"); | |
} | |
while (getline(file, line)) { | |
if (line == std::string{ "cols" }) | |
break; | |
rows.push_back(IntegerHelper::reads(line)); | |
} | |
while (getline(file, line)) { | |
if (line == std::string{ "end" }) | |
break; | |
cols.push_back(IntegerHelper::reads(line)); | |
} | |
file.close(); | |
okay = setPuzzle(rows, cols); | |
} | |
catch (const std::exception &e) { | |
std::cerr << e.what(); | |
file.close(); | |
} | |
return okay; | |
} | |
void NonogramSolver::clear() | |
{ | |
delete board; | |
board = nullptr; | |
m = 0; | |
n = 0; | |
rows.clear(); | |
cols.clear(); | |
solutions.clear(); | |
} | |
const Array<NonogramSolver::Answer> &NonogramSolver::getSolutions() const | |
{ | |
return solutions; | |
} | |
void NonogramSolver::solve() | |
{ | |
int num = 0; | |
for (int i = 0; i < m; i++) | |
num += rows[i].size(); | |
run(board, num, 0, 0); | |
} | |
bool NonogramSolver::isAnswer() | |
{ | |
int black_cnt = 0, k = 0; | |
for (int j = 0; j < n; j++) { | |
black_cnt = 0; | |
k = 0; | |
for (int i = 0; i < m; i++) | |
if (at(i, j) == BLACK) | |
black_cnt++; | |
else { | |
if (black_cnt > 0) { | |
if (cols[j][k] == black_cnt) | |
k++; | |
else | |
return false; | |
} | |
black_cnt = 0; | |
} | |
if (black_cnt > 0) { | |
if (cols[j][k] != black_cnt) | |
return false; | |
else | |
k++; | |
} | |
if (cols[j].size() == 1 && cols[j][0] == 0) { | |
if (k != 0) | |
return false; | |
} | |
else { | |
if (k != cols[j].size()) | |
return false; | |
} | |
} | |
return true; | |
} | |
int NonogramSolver::run(NonogramSolver::Cell *const start_point, const int depth, const int i, const int block_num) | |
{ | |
#if DEBUG | |
char char128[128]; | |
printf("[CALLED: start_point = %d, depth = %d, i = %d, block_num = %d]\n", start_point - board, depth, i, block_num); | |
printBoard(); | |
printf("\n"); | |
gets(char128); | |
#endif | |
if (depth == 0) { | |
if (isAnswer()) | |
solutions.push_back(Answer{toMatrix()}); | |
return 1; | |
} | |
else { | |
const int block_sz = rows[i][block_num], next_depth = depth - 1; | |
Cell *left = start_point, *right = start_point, *next_floor = nullptr; | |
int next_i = i, next_block_num = block_num + 1; | |
if (rows[i].size() == 1 && rows[i][0] == 0) | |
return run(&board[(i + 1) * n], next_depth, i + 1, 0); | |
if (left + block_sz > &board[(i + 1) * n]) | |
return 0; | |
if (block_num + 1 == rows[i].size()) { | |
next_i = i + 1; | |
next_floor = &board[(i + 1) * n]; | |
next_block_num = 0; | |
} | |
for (int b = 0; b < block_sz; b++) | |
*right++ = BLACK; | |
if (next_floor == nullptr) | |
while (run(right + 1, next_depth, next_i, next_block_num)) { | |
if (right >= &board[(i + 1) * n]) | |
break; | |
*left++ = WHITE; | |
*right++ = BLACK; | |
} | |
else | |
while (run(next_floor, next_depth, next_i, next_block_num)) { | |
if (right >= &board[(i + 1) * n]) | |
break; | |
*left++ = WHITE; | |
*right++ = BLACK; | |
} | |
while (right > left) | |
*--right = WHITE; | |
return 1; | |
} | |
} | |
NonogramSolver::Cell &NonogramSolver::at(const int i, const int j) | |
{ | |
return board[i * n + j]; | |
} | |
const NonogramSolver::Cell &NonogramSolver::at(const int i, const int j) const | |
{ | |
return board[i * n + j]; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rows | |
6 | |
2 2 | |
2 2 | |
2 | |
2 | |
4 | |
2 | |
0 | |
2 | |
2 | |
cols | |
0 | |
2 | |
3 | |
1 | |
1 2 2 | |
1 2 2 | |
1 1 | |
6 | |
4 | |
0 | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "scratch.hpp" | |
template <typename Real_t> | |
Real_t middle(const Real_t x, const Real_t y, const Real_t z) | |
// returns the 2nd largest value among x, y and z | |
{ | |
if (y <= x && x <= z || z <= x && x <= y) { | |
return x; | |
} | |
if (x <= y && y <= z || z <= y && y <= x) { | |
return y; | |
} | |
return z; | |
} | |
/// PV = y(t): Process variable -- measured value; | |
/// MV = u(t): Manipulated variable -- PID output; | |
/// SP = r(t): Setpoint -- reference value. | |
PIDController::PIDController(const Real_t Kp, const Real_t Ki, const Real_t Kd, Real_t *const PV, Real_t *const MV, Real_t *const SP, const Real_t MV_MIN, const Real_t MV_MAX) | |
: last_error{ 0.0 }, error_sum{ 0.0 } | |
, Kp{ Kp }, Ki{ Ki }, Kd{ Kd } | |
, PV{ PV }, MV{ MV }, SP{ SP } | |
, MV_MIN{ MV_MIN }, MV_MAX{ MV_MAX } | |
{ | |
} | |
/// Check whether the PID controller is set up properly. | |
bool PIDController::init() | |
{ | |
using namespace std::chrono; | |
if (PV == NULL || MV == NULL || SP == NULL) { | |
return false; | |
} | |
if (Kp < 0.0f || Ki < 0.0f || Kd < 0.0f) { | |
return false; | |
} | |
if (MV_MIN >= MV_MAX) { | |
return false; | |
} | |
last_time = high_resolution_clock::now(); | |
last_error = (*SP - *PV); | |
error_sum = 0.0f; | |
return true; | |
} | |
/// Calculate u(t) with the PID algorithm and assign it to MV. | |
bool PIDController::compute() | |
{ | |
using namespace std::chrono; | |
if (PV == NULL || MV == NULL || SP == NULL) { | |
return false; | |
} | |
else { | |
const auto now = high_resolution_clock::now(); | |
Real_t dt = 0.001 * ((now - last_time) / milliseconds(1)); | |
Real_t errval = (*SP - *PV); | |
Real_t derrval = (errval - last_error); | |
error_sum += errval * dt; | |
*MV = middle<Real_t>(MV_MIN, Kp * errval + Ki * error_sum + Kd * (derrval / dt), MV_MAX); | |
last_time = now; | |
last_error = errval; | |
return true; | |
} | |
} | |
void test_pidController() | |
{ | |
using namespace std::chrono; | |
using Time_t = time_point<high_resolution_clock>; | |
PIDController::Real_t r = -0.1; | |
PIDController::Real_t u = 0.0; | |
PIDController::Real_t y = -0.01; | |
PIDController pid = { .Kp = 1, .Ki = 1, .Kd = 1, .PV = &y, .CV = &u, .SP = &r, .MV_MIN = -10, .MV_MAX = 10 }; | |
Gear gear = { .gear = 2 }; | |
int i = 0; | |
Time_t last = high_resolution_clock::now(); | |
pid.init(); | |
while (1) { | |
os.sleep(100); | |
pid.compute(); | |
if (gear.go()) { | |
const int j = ++i; | |
const Time_t present = high_resolution_clock::now(); | |
const double dt = (present - last) / milliseconds(1); | |
printf("r(%d) = %lf; u(%d) = %lf; y(%d) = %lf; %% dt = %.lf[ms]\n", j, r, j, u, j, y, dt); | |
last = present; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef SCRATCH_HPP | |
#define SCRATCH_HPP | |
#include <iostream> | |
#include <chrono> | |
#include <vector> | |
#include <functional> | |
#include <exception> | |
#include <fstream> | |
#include <sstream> | |
#include "cscratch.h" | |
extern "C" { | |
extern const struct OS_C_API os; | |
}; | |
class IntegerHelper { | |
public: | |
static std::vector<int> reads(std::string str); | |
static void shows(std::vector<int> nums); | |
}; | |
class IO { | |
char buffer[64]; | |
int cursor; | |
int theend; | |
char *result; | |
void (*prompt)(const char *msg); | |
public: | |
IO() = default; | |
IO(const IO &other) = default; | |
~IO() = default; | |
void setPrompt(void (*prompt)(const char *msg)); | |
bool runPrompt(void); | |
static int getc(void); | |
private: | |
bool takech(int ch); | |
void print(void); | |
void clear(void); | |
void sync(char *&msg); | |
}; | |
class PIDController { | |
public: | |
typedef double Real_t; | |
private: | |
std::chrono::time_point<std::chrono::high_resolution_clock> last_time; | |
volatile Real_t last_error; | |
volatile Real_t error_sum; | |
public: | |
Real_t Kp; | |
Real_t Ki; | |
Real_t Kd; | |
Real_t *PV; | |
Real_t *MV; | |
Real_t *SP; | |
Real_t MV_MIN; | |
Real_t MV_MAX; | |
public: | |
PIDController(Real_t Kp, Real_t Ki, Real_t Kd, Real_t *PV, Real_t *MV, Real_t *SP, Real_t MV_MIN, Real_t MV_MAX); | |
bool init(void); | |
bool compute(void); | |
}; | |
class Gear { | |
public: | |
int gear; | |
private: | |
int gear_cnt; | |
public: | |
Gear(int gear); | |
Gear(const Gear &other); | |
~Gear(); | |
bool go(void); | |
void reset(void); | |
}; | |
class NonogramSolver { | |
public: | |
class Generator1D { | |
public: | |
typedef int cell_t; | |
public: | |
void (*callback)(Generator1D::cell_t *line, size_t line_sz); | |
cell_t *line; | |
std::size_t line_sz; | |
int *info; | |
std::size_t info_sz; | |
public: | |
Generator1D(); | |
~Generator1D() = default; | |
Generator1D(const Generator1D &other) = default; | |
void exec(void); | |
bool attach(void (*callback)(cell_t *line, size_t line_sz)); | |
void print(void) const; | |
bool init(Generator1D::cell_t *line, std::size_t line_sz, int *info, std::size_t info_sz); | |
private: | |
int run(Generator1D::cell_t *rel_coord, int depth, int block_num, int combo); | |
}; | |
typedef int Cell; | |
static constexpr Cell BLACK = 1; | |
static constexpr Cell WHITE = 0; | |
class Exception : public std::exception { | |
std::string err_msg; | |
public: | |
Exception(const char *err_msg); | |
~Exception() = default; | |
Exception(const Exception &other) = default; | |
const char *what(void) const throw (); | |
}; | |
class Answer { | |
std::vector<std::vector<Cell>> board; | |
public: | |
Answer(std::vector<std::vector<Cell>> board); | |
~Answer() = default; | |
Answer(const Answer &other) = default; | |
void print(void) const; | |
}; | |
private: | |
std::vector<std::vector<int>> rows; | |
std::vector<std::vector<int>> cols; | |
Cell *board; | |
int m; | |
int n; | |
std::vector<Answer> solutions; | |
public: | |
NonogramSolver() = default; | |
~NonogramSolver(); | |
NonogramSolver(const NonogramSolver &other) = default; | |
bool setPuzzle(const std::vector<std::vector<int>> &rows, const std::vector<std::vector<int>> &cols); | |
bool puzzleWellFormed(void) const; | |
std::vector<std::vector<Cell>> toMatrix(void) const; | |
bool scanPuzzle(const char *file_name); | |
void clear(void); | |
void solve(void); | |
const std::vector<Answer> &getSolutions(void) const; | |
private: | |
bool isAnswer(void); | |
int run(Cell *start_point, int depth, int i, int block_num); | |
Cell &at(int i, int j); | |
const Cell &at(int i, int j) const; | |
void printBoard(void) const; | |
}; | |
void test_io(void); | |
void test_pid(void); | |
void test_variable(void); | |
void test_cancomm(void); | |
void test_pidController(void); | |
void proto_test_prompt(void); | |
void nonogramsolver_test(void); | |
void nonogramsolverlogic_test(void); | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment