From 579749b1deb4116758a6997f456e79bad3199c75 Mon Sep 17 00:00:00 2001 From: Tawada Date: Mon, 27 Aug 2018 21:02:33 +0900 Subject: [PATCH] Update --- resolver/analysis.csv | 35 +++ resolver/cpp/Makefile | 21 ++ resolver/cpp/README.md | 27 ++ resolver/cpp/board.hpp | 59 ++++ resolver/cpp/box.hpp | 40 +++ resolver/cpp/line.hpp | 46 +++ resolver/cpp/main.cpp | 384 +++++++++++++++++++++++++ resolver/cpp/main.hpp | 83 ++++++ resolver/cpp/mt19937ar.c | 172 ++++++++++++ resolver/cpp/route.cpp | 450 ++++++++++++++++++++++++++++++ resolver/cpp/route.hpp | 17 ++ resolver/cpp/utils.cpp | 209 ++++++++++++++ resolver/cpp/utils.hpp | 20 ++ resolver/{ => python}/Makefile | 2 +- resolver/{ => python}/resolver.py | 41 ++- 15 files changed, 1595 insertions(+), 11 deletions(-) create mode 100644 resolver/analysis.csv create mode 100644 resolver/cpp/Makefile create mode 100644 resolver/cpp/README.md create mode 100644 resolver/cpp/board.hpp create mode 100644 resolver/cpp/box.hpp create mode 100644 resolver/cpp/line.hpp create mode 100644 resolver/cpp/main.cpp create mode 100644 resolver/cpp/main.hpp create mode 100644 resolver/cpp/mt19937ar.c create mode 100644 resolver/cpp/route.cpp create mode 100644 resolver/cpp/route.hpp create mode 100644 resolver/cpp/utils.cpp create mode 100644 resolver/cpp/utils.hpp rename resolver/{ => python}/Makefile (84%) rename resolver/{ => python}/resolver.py (92%) diff --git a/resolver/analysis.csv b/resolver/analysis.csv new file mode 100644 index 0000000..f2909f8 --- /dev/null +++ b/resolver/analysis.csv @@ -0,0 +1,35 @@ +problem x y z lines occupation avelength solved made by length corner parallel length (resolved) corner (resolved) parallel (resolved) +1 24 24 4 60 41.796875 16.05 o 0 952 164 216 +2 15 15 2 12 48 18 o 1 222 41 156 +3 20 20 8 29 11.25 12.413793 o 4 375 55 8 +4 72 72 8 8 2.083333 108 O 3 606 15 0 +5 8 8 4 20 53.515625 6.85 o 5 130 26 15 +6 48 36 8 101 8.738426 11.960396 o 2 1224 247 140 +7 72 72 8 8 2.517361 130.5 O 0 587 16 0 +8 70 70 8 999 26.007653 10.205205 X 0 +9 15 15 2 47 60.222222 5.765957 o 0 262 80 19 +10 23 12 6 49 39.673913 13.408163 o 0 610 124 127 +11 8 4 8 17 50.78125 7.647059 o 5 128 24 0 +12 36 19 4 71 34.027778 13.112676 o 2 828 126 302 +13 72 72 8 52 1.31414 10.480769 o 3 200 19 0 +14 10 10 2 22 72.5 6.590909 o 0 131 48 5 +15 60 36 8 102 9.675926 16.392157 O 4 1666 198 41 +16 15 15 4 81 46.555556 5.17284 o 0 411 98 10 +17 50 50 4 825 50.64 6.138182 X 0 +18 20 35 8 22 8.5 21.636364 o 4 472 51 19 +19 36 24 1 96 90.162037 8.114583 x 1 780 156 90 +20 30 30 3 210 47.962963 6.166667 O 0 1248 342 51 +21 72 72 5 73 22.071759 78.369863 X 0 5472 141 5318 +22 72 72 2 2 3.587963 186 o 2 288 5 0 +23 40 40 3 123 99.75 38.926829 X 0 4798 621 4054 +24 60 60 4 999 48.923611 7.052052 X 0 +25 40 40 4 212 99.8125 30.132075 X 0 6400 416 5574 +26 15 15 3 56 46.222222 5.571429 o 0 323 79 30 +27 72 72 8 8 2.194252 113.75 O 3 616 34 35 +28 3 3 3 6 100 4.5 o 0 26 10 0 +29 72 72 1 85 100 60.988235 x 0 5184 468 4666 +30 72 72 1 160 100 32.4 x 0 5184 629 4443 +31 16 20 5 272 100 5.882353 x 1 1600 336 1050 +32 40 40 3 425 53.416667 6.032941 O 0 2591 673 146 +33 40 40 2 150 99.875 21.306667 X 0 3200 356 2730 +34 40 40 3 80 99.75 59.85 X 0 4800 1560 3120 diff --git a/resolver/cpp/Makefile b/resolver/cpp/Makefile new file mode 100644 index 0000000..5f6c134 --- /dev/null +++ b/resolver/cpp/Makefile @@ -0,0 +1,21 @@ +TARGET = solver +OBJS = $(CPPS:.cpp=.o) +CPPS = $(wildcard *.cpp) +CXX = g++ +CXXFLAGS = -Wall -O3 + +all: $(TARGET) + +run: $(TARGET) + ./$(TARGET) ../dataQsample.txt ../dataAsample.txt -rp + +test:$(TARGET) + for i in `seq 1 34`; do ./$(TARGET) `printf "../../ADC2017_Q_A/all/Q/Q%02d.txt" $$i` `printf "../../ADC2017_Q_A/all/A/A%02d.txt" $$i` -o `printf "RESOLV_A%02d.txt" $$i` -r; done + + +$(TARGET): $(OBJS) + $(CXX) -o $@ $(OBJS) + +clean: + rm *.o + rm $(TARGET) diff --git a/resolver/cpp/README.md b/resolver/cpp/README.md new file mode 100644 index 0000000..594c00e --- /dev/null +++ b/resolver/cpp/README.md @@ -0,0 +1,27 @@ +# checker & resolver + +* 開発言語: C++ +* 機能: 1.チェッカー,2.コスト計算,3.コスト削減のための再ルーティング + +## 入出力 + +* 問題ファイル +* 解答ファイル(再ルーティング前) +* 解答ファイル(再ルーティング後) ※任意 + +## 1.チェッカー + +* 解答ファイル(再ルーティング前)が解答ルールを満たしているか確認 +* branch error: ラインの分岐が存在 +* floating error: 端点に接続しない数字が存在 + +## 2.コスト計算 + +* 要オプション(-c) +* 線長の合計と線が曲った回数を導出 + +## 3.再ルーティング + +* 要オプション(-r) +* 1ラインずつ引きはがして再ルーティング +* 曲がる回数が少なくなるようなルーティングを選択 diff --git a/resolver/cpp/board.hpp b/resolver/cpp/board.hpp new file mode 100644 index 0000000..22eff3b --- /dev/null +++ b/resolver/cpp/board.hpp @@ -0,0 +1,59 @@ +/*******************************************************/ +/** クラス定義 **/ +/*******************************************************/ + +#ifndef __BOARD_HPP__ +#define __BOARD_HPP__ + +// 各種最大値 +// ライン数は 72*72*8/2 +#define MAX_BOXES 72 +#define MAX_LAYER 8 +#define MAX_LINES 20736 + +// ボードクラス +class Board{ +public: + Board(int _x,int _y,int _z,int _ln){ + size_x = _x; + size_y = _y; + size_z = _z; + line_num = _ln; + + for(int z=0;z* getTrack(){return &track;} + void pushPointToTrack(Point p){track.push_back(p);} + void clearTrack(){track.clear();} + +private: + int index; // ライン番号 + int x_0, y_0, z_0; // ソースポート + int x_1, y_1, z_1; // シンクポート + + bool has_line; // スタートとゴールが隣接していないか? + vector track; +}; + +#endif diff --git a/resolver/cpp/main.cpp b/resolver/cpp/main.cpp new file mode 100644 index 0000000..019dbcb --- /dev/null +++ b/resolver/cpp/main.cpp @@ -0,0 +1,384 @@ +#include "./main.hpp" +#include "./route.hpp" +#include "./utils.hpp" + +/*******************************************************/ +/** グローバル変数定義 **/ +/*******************************************************/ + +Board* board; // 対象ボード + +void usage() { + cerr << "Usage: solver [--output ] [--cost] [--reroute] [--print] input-file output-file" << endl; + exit(-1); +} + +void version() { + cerr << "Version: nl-resolver(checker) 2017.0.0" << endl; + exit(-1); +} + +int main(int argc, char *argv[]){ + // Options + char *in_filename = NULL; // 問題ファイル名 + char *out_filename_bef = NULL; // 解答ファイル名 (再ルーティング前) + char *out_filename_aft = NULL; // 解答ファイル名 (再ルーティング後) + bool calc_cost = false; // コスト計算 + bool reroute = false; // 再ルーティング + bool print_option = false; // デバッグ出力 + + // Options 取得 + struct option longopts[] = { + {"output", required_argument, NULL, 'o'}, + {"cost", no_argument, NULL, 'c'}, + {"reroute", no_argument, NULL, 'r'}, + {"print", no_argument, NULL, 'p'}, + {"version", no_argument, NULL, 'v'}, + {"help", no_argument, NULL, 'h'}, + {0, 0, 0, 0} + }; + int opt, optidx; + while ((opt = getopt_long(argc, argv, "o:crpvh", longopts, &optidx)) != -1) { + switch (opt) { + case 'o': + out_filename_aft = optarg; + break; + case 'c': + calc_cost = true; + break; + case 'r': + reroute = true; + break; + case 'p': + print_option = true; + break; + case 'v': + version(); + case 'h': + case ':': + case '?': + default: + usage(); + } + } + if (argc <= (optind+1)) { + usage(); + } + in_filename = argv[optind]; // 問題ファイル + optind++; + out_filename_bef = argv[optind]; // 解答ファイル (再ルーティング前) + + cout << "Q file: " << in_filename << endl; + cout << "A file: " << out_filename_bef << endl; + cout << "Cost calculation: "; + if(calc_cost){ cout << "ON" << endl; } + else{ cout << "OFF" << endl; } + cout << "Rerouting: "; + if(reroute){ cout << "ON" << endl; } + else{ cout << "OFF" << endl; } + cout << "Print: "; + if(print_option){ cout << "ON" << endl; } + else{ cout << "OFF" << endl; } + if(out_filename_aft != NULL){ + cout << "A file (resolved): " << out_filename_aft << endl; + } + + // 問題盤の生成 + initialize(in_filename); +if( print_option ) { printBoard(); } + + // 解答の読み込み & チェック + readSolution(out_filename_bef, print_option); +if( print_option ) { printSolution(); } + + // コストの計算 +if( calc_cost ) { calcCost(); } + + // 再ルーティング +if( reroute ) { + for(int i=1;i<=board->getLineNum();i++){ + + // 数字が隣接する場合スキップ + if(board->line(i)->getHasLine() == false) continue; + + deleteLine(i); // 経路の削除 + routing(i); // ルーティング + recordLine(i); // 経路の記録 + } + + // ファイル出力 +if (out_filename_aft != NULL) { + printSolutionToFile(out_filename_aft); + cout << endl; + cout << "--> Saved to " << out_filename_aft << endl << endl; + cout << endl; +} +if( print_option ) { printSolution(); } +if( calc_cost ) { calcCost(); } +} + + delete board; + return 0; +} + +/** + * 問題盤の初期化 + * @args: 問題ファイル名 + */ +void initialize(char* filename){ + + ifstream ifs(filename); + string str; + + if(ifs.fail()){ + cerr << "Problem file does not exist." << endl; + exit(-1); + } + + int size_x, size_y, size_z; + int line_num; + map lx_0, ly_0, lz_0, lx_1, ly_1, lz_1; + map adjacents; // 初期状態で数字が隣接している + + while(getline(ifs,str)){ + if(str == "") continue; // 問題ファイルの改行コードがLFのときにこれ入れないとエラーになる + if(str.at(0) == '#') continue; + else if(str.at(0) == 'S'){ // 盤面サイズの読み込み + str.replace(str.find("S"),5,""); + str.replace(str.find("X"),1," "); + str.replace(str.find("X"),1," "); + istringstream is(str); + is >> size_x >> size_y >> size_z; + } + else if(str.at(0) == 'L' && str.at(4) == '_'){ // ライン個数の読み込み + str.replace(str.find("L"),9,""); + istringstream is(str); + is >> line_num; + } + else if(str.at(0) == 'L' && str.at(4) == '#'){ // ライン情報の読み込み + str.replace(str.find("L"),5,""); + int index; + while((index=str.find("("))!=-1){ + str.replace(index,1,""); + } + while((index=str.find(")"))!=-1){ + str.replace(index,1,""); + } + while((index=str.find(","))!=-1){ + str.replace(index,1," "); + } + while((index=str.find("-"))!=-1){ + str.replace(index,1," "); + } + int i, a, b, c, d, e, f; + istringstream is(str); + is >> i >> a >> b >> c >> d >> e >> f; + lx_0[i] = a; ly_0[i] = b; lz_0[i] = c-1; lx_1[i] = d; ly_1[i] = e; lz_1[i] = f-1; + + // 初期状態で数字が隣接しているか判断 + int dx = lx_0[i] - lx_1[i]; + int dy = ly_0[i] - ly_1[i]; + int dz = lz_0[i] - lz_1[i]; + if ((dz == 0 && dx == 0 && (dy == 1 || dy == -1)) || (dz == 0 && (dx == 1 || dx == -1) && dy == 0)) { + adjacents[i] = true; + } else { + adjacents[i] = false; + } + } + else continue; + } + + board = new Board(size_x,size_y,size_z,line_num); + + for(int i=1;i<=line_num;i++){ + Box* trgt_box_0 = board->box(lx_0[i],ly_0[i],lz_0[i]); + Box* trgt_box_1 = board->box(lx_1[i],ly_1[i],lz_1[i]); + trgt_box_0->setTypeNumber(); + trgt_box_1->setTypeNumber(); + trgt_box_0->setIndex(i); + trgt_box_1->setIndex(i); + Line* trgt_line = board->line(i); + trgt_line->setSourcePort(lx_0[i],ly_0[i],lz_0[i]); + trgt_line->setSinkPort(lx_1[i],ly_1[i],lz_1[i]); + trgt_line->setHasLine(!adjacents[i]); + } + + for(int z=0;zbox(x,y,z); + if(!trgt_box->isTypeNumber()) trgt_box->setTypeBlank(); + } + } + } +} + +/** + * 解答の読み込み + * @args: 解答ファイル名 + */ +void readSolution(char* filename, bool print_option){ + + ifstream ifs(filename); + string str; + + if(ifs.fail()){ + cerr << "Solution file does not exist." << endl; + exit(-1); + } + + int ans[MAX_LAYER][MAX_BOXES][MAX_BOXES]; + int count_y = 0; + int count_z = 0; + + while(getline(ifs,str)){ + if(str == "") continue; // 問題ファイルの改行コードがLFのときにこれ入れないとエラーになる + if(str.at(0) == '#') continue; + else if(str.at(0) == 'S') continue; + else if(str.at(0) == 'L') continue; + else{ + int index; + while((index=str.find(","))!=-1){ + str.replace(index,1," "); + } + istringstream is(str); + int a; + for(int x=0;xgetSizeX();x++){ + is >> a; + ans[count_z][count_y][x] = a; + } + count_y++; + if(count_y == board->getSizeY()){ + count_z++; + count_y = 0; + } + if(count_z == board->getSizeZ()){ + break; + } + } + } + +if( print_option ) { + cout << endl; + cout << "READ" << endl; + cout << "====" << endl; + + for(int z=0;zgetSizeZ();z++){ + for(int y=0;ygetSizeY();y++){ + for(int x=0;xgetSizeX();x++){ + cout << ans[z][y][x]; + if(x != board->getSizeX()-1){ + cout << ", "; + } + } + cout << endl; + } + cout << endl; + } +} + + for(int i=1;i<=board->getLineNum();i++){ + Line* trgt_line = board->line(i); + + int now_x = trgt_line->getSourceX(); + int now_y = trgt_line->getSourceY(); + int now_z = trgt_line->getSourceZ(); + ans[now_z][now_y][now_x] = 0; + + int next_x = now_x; + int next_y = now_y; + int next_z = now_z; + + while(1){ + + Point p = {now_x, now_y, now_z}; + trgt_line->pushPointToTrack(p); + board->box(now_x,now_y,now_z)->setHasLine(); + + bool have_direction = false; + if(now_x > 0 && ans[now_z][now_y][now_x-1] == i){ + if(have_direction){ // error + cerr << "Point (" << now_x << "," << now_y << "," << now_z+1 << ") has branch error(s)." << endl; + exit(-1); + } + else{ + next_x = now_x - 1; next_y = now_y; next_z = now_z; + have_direction = true; + } + } + if(now_x < board->getSizeX()-1 && ans[now_z][now_y][now_x+1] == i){ + if(have_direction){ // error + cerr << "Point (" << now_x << "," << now_y << "," << now_z+1 << ") has branch error(s)." << endl; + exit(-1); + } + else{ + next_x = now_x + 1; next_y = now_y; next_z = now_z; + have_direction = true; + } + } + if(now_y > 0 && ans[now_z][now_y-1][now_x] == i){ + if(have_direction){ // error + cerr << "Point (" << now_x << "," << now_y << "," << now_z+1 << ") has branch error(s)." << endl; + exit(-1); + } + else{ + next_x = now_x; next_y = now_y - 1; next_z = now_z; + have_direction = true; + } + } + + if(now_y < board->getSizeY()-1 && ans[now_z][now_y+1][now_x] == i){ + if(have_direction){ // error + cerr << "Point (" << now_x << "," << now_y << "," << now_z+1 << ") has branch error(s)." << endl; + exit(-1); + } + else{ + next_x = now_x; next_y = now_y + 1; next_z = now_z; + have_direction = true; + } + } + if(now_z > 0 && ans[now_z-1][now_y][now_x] == i){ + if(have_direction){ // error + cerr << "Point (" << now_x << "," << now_y << "," << now_z+1 << ") has branch error(s)." << endl; + exit(-1); + } + else{ + next_x = now_x; next_y = now_y; next_z = now_z - 1; + have_direction = true; + } + } + if(now_z < board->getSizeZ()-1 && ans[now_z+1][now_y][now_x] == i){ + if(have_direction){ // error + cerr << "Point (" << now_x << "," << now_y << "," << now_z+1 << ") has branch error(s)." << endl; + exit(-1); + } + else{ + next_x = now_x; next_y = now_y; next_z = now_z + 1; + have_direction = true; + } + } + + ans[next_z][next_y][next_x] = 0; + + if(next_x == trgt_line->getSinkX() && next_y == trgt_line->getSinkY() && next_z == trgt_line->getSinkZ()) + break; + + now_x = next_x; now_y = next_y; now_z = next_z; + } + + Point sink_p = {next_x, next_y, next_z}; + trgt_line->pushPointToTrack(sink_p); + board->box(next_x,next_y,next_z)->setHasLine(); + } + + for(int z=0;zgetSizeZ();z++){ + for(int y=0;ygetSizeY();y++){ + for(int x=0;xgetSizeX();x++){ + if(ans[z][y][x] != 0){ + cerr << "Point (" << x << "," << y << "," << z+1 << ") has floating error(s)." << endl; + exit(-1); + } + } + } + } +} diff --git a/resolver/cpp/main.hpp b/resolver/cpp/main.hpp new file mode 100644 index 0000000..dc602a5 --- /dev/null +++ b/resolver/cpp/main.hpp @@ -0,0 +1,83 @@ +#ifndef _MAIN_HPP_ +#define _MAIN_HPP_ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; + +#define NOT_USE -1 + +// Inter-Box +#define NORTH 1 +#define EAST 2 +#define SOUTH 3 +#define WEST 4 +#define UP 5 +#define DOWN 6 + +struct Point{ + int x; + int y; + int z; +}; + +#include "line.hpp" +#include "box.hpp" +#include "board.hpp" + +#define ML 3 // コストの計算(配線長) +#define BT 3 // コストの計算(曲がり回数) +#define PL 1 // コストの計算(周辺ノード) + +struct Search{ + int x; + int y; + int z; + int d; // 方向 +}; + +struct Direction{ + // 方向 + bool n; // 北 + bool s; // 南 + bool e; // 東 + bool w; // 西 + bool u; // 上 + bool d; // 下 + // ひとつ前の方向 + int c_n; + int c_s; + int c_e; + int c_w; + int c_u; + int c_d; +}; + +struct IntraBox{ + int cost; + Direction d; +}; + + +/*******************************************************/ +/** グローバル関数定義 **/ +/*******************************************************/ + +void initialize(char* filename); +void readSolution(char* filename, bool print_option); + +#endif /*_MAIN_HPP_*/ diff --git a/resolver/cpp/mt19937ar.c b/resolver/cpp/mt19937ar.c new file mode 100644 index 0000000..4fbd3f7 --- /dev/null +++ b/resolver/cpp/mt19937ar.c @@ -0,0 +1,172 @@ +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) +*/ + +#include + +/* Period parameters */ +#define N 624 +#define M 397 +#define MATRIX_A 0x9908b0dfUL /* constant vector a */ +#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ +#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ + +static unsigned long mt[N]; /* the array for the state vector */ +static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */ + +/* initializes mt[N] with a seed */ +void init_genrand(unsigned long s) +{ + mt[0]= s & 0xffffffffUL; + for (mti=1; mti> 30)) + mti); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + mt[mti] &= 0xffffffffUL; + /* for >32 bit machines */ + } +} + +/* initialize by an array with array-length */ +/* init_key is the array for initializing keys */ +/* key_length is its length */ +/* slight change for C++, 2004/2/26 */ +void init_by_array(unsigned long init_key[], int key_length) +{ + int i, j, k; + init_genrand(19650218UL); + i=1; j=0; + k = (N>key_length ? N : key_length); + for (; k; k--) { + mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + + init_key[j] + j; /* non linear */ + mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + i++; j++; + if (i>=N) { mt[0] = mt[N-1]; i=1; } + if (j>=key_length) j=0; + } + for (k=N-1; k; k--) { + mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) + - i; /* non linear */ + mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + i++; + if (i>=N) { mt[0] = mt[N-1]; i=1; } + } + + mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ +} + +/* generates a random number on [0,0xffffffff]-interval */ +unsigned long genrand_int32(void) +{ + unsigned long y; + static unsigned long mag01[2]={0x0UL, MATRIX_A}; + /* mag01[x] = x * MATRIX_A for x=0,1 */ + + if (mti >= N) { /* generate N words at one time */ + int kk; + + if (mti == N+1) /* if init_genrand() has not been called, */ + init_genrand(5489UL); /* a default initial seed is used */ + + for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; + } + for (;kk> 1) ^ mag01[y & 0x1UL]; + } + y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; + + mti = 0; + } + + y = mt[mti++]; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); + + return y; +} + +/* generates a random number on [0,0x7fffffff]-interval */ +long genrand_int31(void) +{ + return (long)(genrand_int32()>>1); +} + +/* generates a random number on [0,1]-real-interval */ +double genrand_real1(void) +{ + return genrand_int32()*(1.0/4294967295.0); + /* divided by 2^32-1 */ +} + +/* generates a random number on [0,1)-real-interval */ +double genrand_real2(void) +{ + return genrand_int32()*(1.0/4294967296.0); + /* divided by 2^32 */ +} + +/* generates a random number on (0,1)-real-interval */ +double genrand_real3(void) +{ + return (((double)genrand_int32()) + 0.5)*(1.0/4294967296.0); + /* divided by 2^32 */ +} + +/* generates a random number on [0,1) with 53-bit resolution*/ +double genrand_res53(void) +{ + unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; + return(a*67108864.0+b)*(1.0/9007199254740992.0); +} +/* These real versions are due to Isaku Wada, 2002/01/09 added */ diff --git a/resolver/cpp/route.cpp b/resolver/cpp/route.cpp new file mode 100644 index 0000000..866232d --- /dev/null +++ b/resolver/cpp/route.cpp @@ -0,0 +1,450 @@ +/*******************************************************/ +/** ルーティングに関する関数 **/ +/*******************************************************/ + +#include "./main.hpp" +#include "./route.hpp" +#include "./utils.hpp" + +extern Board* board; + +bool routing(int trgt_line_id){ + + Line* trgt_line = board->line(trgt_line_id); + trgt_line->clearTrack(); + + // ボードの初期化 + IntraBox my_board[MAX_LAYER][MAX_BOXES][MAX_BOXES]; + IntraBox init = { INT_MAX, {false,false,false,false,false,false,NOT_USE,NOT_USE,NOT_USE,NOT_USE,NOT_USE,NOT_USE} }; + + for(int z=0;zgetSizeZ();z++){ + for(int y=0;ygetSizeY();y++){ + for(int x=0;xgetSizeX();x++){ + my_board[z][y][x] = init; + } + } + } + + queue qu; + int goal_cost = INT_MAX; + + int start_x, start_y, start_z; + IntraBox* start; + + // スタート地点の設定 + start_x = trgt_line->getSourceX(); + start_y = trgt_line->getSourceY(); + start_z = trgt_line->getSourceZ(); + start = &(my_board[start_z][start_y][start_x]); + start->cost = 0; + + // 北方向を探索 + if(isInserted(start_x,start_y-1,start_z)){ + Search trgt = {start_x,start_y-1,start_z,SOUTH}; + qu.push(trgt); + } + // 東方向を探索 + if(isInserted(start_x+1,start_y,start_z)){ + Search trgt = {start_x+1,start_y,start_z,WEST}; + qu.push(trgt); + } + // 南方向を探索 + if(isInserted(start_x,start_y+1,start_z)){ + Search trgt = {start_x,start_y+1,start_z,NORTH}; + qu.push(trgt); + } + // 西方向を探索 + if(isInserted(start_x-1,start_y,start_z)){ + Search trgt = {start_x-1,start_y,start_z,EAST}; + qu.push(trgt); + } + // 上方向を探索 + if(isInserted(start_x,start_y,start_z+1)){ + Search trgt = {start_x,start_y,start_z+1,DOWN}; + qu.push(trgt); + } + // 下方向を探索 + if(isInserted(start_x,start_y,start_z-1)){ + Search trgt = {start_x,start_y,start_z-1,UP}; + qu.push(trgt); + } + + while(!qu.empty()){ + + Search trgt = qu.front(); + qu.pop(); + + Box* trgt_box = board->box(trgt.x,trgt.y,trgt.z); + IntraBox* trgt_ibox = &(my_board[trgt.z][trgt.y][trgt.x]); + + bool update = false; // コストの更新があったか? + // コスト計算 + if(trgt.d == SOUTH){ // 南から来た + IntraBox* find_ibox = &(my_board[trgt.z][trgt.y+1][trgt.x]); + // 折れ曲がりあり? + int turn_count = 0; + int previous = NOT_USE; + int parallel_count = cost_parallel(trgt_line_id, trgt.x, trgt.y, trgt.z); + if((find_ibox->d).s){ previous = SOUTH; } + else if((find_ibox->d).e){ previous = EAST; turn_count++; } + else if((find_ibox->d).w){ previous = WEST; turn_count++; } + else if((find_ibox->d).u){ previous = UP; turn_count++; } + else if((find_ibox->d).d){ previous = DOWN; turn_count++; } + // コスト + int cost = (find_ibox->cost) + ML + turn_count * BT + parallel_count * PL; + if(cost < trgt_ibox->cost){ + update = true; + trgt_ibox->cost = cost; + (trgt_ibox->d).n = false; + (trgt_ibox->d).e = false; + (trgt_ibox->d).s = true; + (trgt_ibox->d).w = false; + (trgt_ibox->d).u = false; + (trgt_ibox->d).d = false; + (trgt_ibox->d).c_s = previous; + } + else if(cost == trgt_ibox->cost){ + (trgt_ibox->d).s = true; + (trgt_ibox->d).c_s = previous; + } + } + if(trgt.d == WEST){ // 西から来た + IntraBox* find_ibox = &(my_board[trgt.z][trgt.y][trgt.x-1]); + // 折れ曲がりあり? + int turn_count = 0; + int previous = NOT_USE; + int parallel_count = cost_parallel(trgt_line_id, trgt.x, trgt.y, trgt.z); + if((find_ibox->d).w){ previous = WEST; } + else if((find_ibox->d).n){ previous = NORTH; turn_count++; } + else if((find_ibox->d).s){ previous = SOUTH; turn_count++; } + else if((find_ibox->d).u){ previous = UP; turn_count++; } + else if((find_ibox->d).d){ previous = DOWN; turn_count++; } + // コスト + int cost = (find_ibox->cost) + ML + turn_count * BT + parallel_count * PL; + if(cost < trgt_ibox->cost){ + update = true; + trgt_ibox->cost = cost; + (trgt_ibox->d).n = false; + (trgt_ibox->d).e = false; + (trgt_ibox->d).s = false; + (trgt_ibox->d).w = true; + (trgt_ibox->d).u = false; + (trgt_ibox->d).d = false; + (trgt_ibox->d).c_w = previous; + } + else if(cost == trgt_ibox->cost){ + (trgt_ibox->d).w = true; + (trgt_ibox->d).c_w = previous; + } + } + if(trgt.d == NORTH){ // 北から来た + IntraBox* find_ibox = &(my_board[trgt.z][trgt.y-1][trgt.x]); + // 折れ曲がりあり? + int turn_count = 0; + int previous = NOT_USE; + int parallel_count = cost_parallel(trgt_line_id, trgt.x, trgt.y, trgt.z); + if((find_ibox->d).n){ previous = NORTH; } + else if((find_ibox->d).e){ previous = EAST; turn_count++; } + else if((find_ibox->d).w){ previous = WEST; turn_count++; } + else if((find_ibox->d).u){ previous = UP; turn_count++; } + else if((find_ibox->d).d){ previous = DOWN; turn_count++; } + // コスト + int cost = (find_ibox->cost) + ML + turn_count * BT + parallel_count * PL; + if(cost < trgt_ibox->cost){ + update = true; + trgt_ibox->cost = cost; + (trgt_ibox->d).n = true; + (trgt_ibox->d).e = false; + (trgt_ibox->d).s = false; + (trgt_ibox->d).w = false; + (trgt_ibox->d).u = false; + (trgt_ibox->d).d = false; + (trgt_ibox->d).c_n = previous; + } + else if(cost == trgt_ibox->cost){ + (trgt_ibox->d).n = true; + (trgt_ibox->d).c_n = previous; + } + } + if(trgt.d == EAST){ // 東から来た + IntraBox* find_ibox = &(my_board[trgt.z][trgt.y][trgt.x+1]); + // 折れ曲がりあり? + int turn_count = 0; + int previous = NOT_USE; + int parallel_count = cost_parallel(trgt_line_id, trgt.x, trgt.y, trgt.z); + if((find_ibox->d).e){ previous = EAST; } + else if((find_ibox->d).n){ previous = NORTH; turn_count++; } + else if((find_ibox->d).s){ previous = SOUTH; turn_count++; } + else if((find_ibox->d).u){ previous = UP; turn_count++; } + else if((find_ibox->d).d){ previous = DOWN; turn_count++; } + // コスト + int cost = (find_ibox->cost) + ML + turn_count * BT + parallel_count * PL; + if(cost < trgt_ibox->cost){ + update = true; + trgt_ibox->cost = cost; + (trgt_ibox->d).n = false; + (trgt_ibox->d).e = true; + (trgt_ibox->d).s = false; + (trgt_ibox->d).w = false; + (trgt_ibox->d).u = false; + (trgt_ibox->d).d = false; + (trgt_ibox->d).c_e = previous; + } + else if(cost == trgt_ibox->cost){ + (trgt_ibox->d).e = true; + (trgt_ibox->d).c_e = previous; + } + } + if(trgt.d == DOWN){ // 下から来た + IntraBox* find_ibox = &(my_board[trgt.z-1][trgt.y][trgt.x]); + // 折れ曲がりあり? + int turn_count = 0; + int previous = NOT_USE; + int parallel_count = cost_parallel(trgt_line_id, trgt.x, trgt.y, trgt.z); + if((find_ibox->d).d){ previous = DOWN; } + else if((find_ibox->d).n){ previous = NORTH; turn_count++; } + else if((find_ibox->d).s){ previous = SOUTH; turn_count++; } + else if((find_ibox->d).e){ previous = EAST; turn_count++; } + else if((find_ibox->d).w){ previous = WEST; turn_count++; } + // コスト + int cost = (find_ibox->cost) + ML + turn_count * BT + parallel_count * PL; + if(cost < trgt_ibox->cost){ + update = true; + trgt_ibox->cost = cost; + (trgt_ibox->d).n = false; + (trgt_ibox->d).e = false; + (trgt_ibox->d).s = false; + (trgt_ibox->d).w = false; + (trgt_ibox->d).u = false; + (trgt_ibox->d).d = true; + (trgt_ibox->d).c_d = previous; + } + else if(cost == trgt_ibox->cost){ + (trgt_ibox->d).d = true; + (trgt_ibox->d).c_d = previous; + } + } + if(trgt.d == UP){ // 上から来た + IntraBox* find_ibox = &(my_board[trgt.z+1][trgt.y][trgt.x]); + // 折れ曲がりあり? + int turn_count = 0; + int previous = NOT_USE; + int parallel_count = cost_parallel(trgt_line_id, trgt.x, trgt.y, trgt.z); + if((find_ibox->d).u){ previous = UP; } + else if((find_ibox->d).n){ previous = NORTH; turn_count++; } + else if((find_ibox->d).s){ previous = SOUTH; turn_count++; } + else if((find_ibox->d).e){ previous = EAST; turn_count++; } + else if((find_ibox->d).w){ previous = WEST; turn_count++; } + // コスト + int cost = (find_ibox->cost) + ML + turn_count * BT + parallel_count * PL; + if(cost < trgt_ibox->cost){ + update = true; + trgt_ibox->cost = cost; + (trgt_ibox->d).n = false; + (trgt_ibox->d).e = false; + (trgt_ibox->d).s = false; + (trgt_ibox->d).w = false; + (trgt_ibox->d).u = true; + (trgt_ibox->d).d = false; + (trgt_ibox->d).c_u = previous; + } + else if(cost == trgt_ibox->cost){ + (trgt_ibox->d).u = true; + (trgt_ibox->d).c_u = previous; + } + } + + if(!update) continue; + if(trgt_box->isTypeNumber()){ + if(trgt_box->getIndex() == trgt_line_id){ + if(trgt_ibox->cost < goal_cost) goal_cost = trgt_ibox->cost; + } + continue; + } + + if(trgt_ibox->cost > goal_cost) continue; // 探索打ち切り + + // 北方向 + if(trgt.d!=NORTH && isInserted(trgt.x,trgt.y-1,trgt.z)){ + Search next = {trgt.x,trgt.y-1,trgt.z,SOUTH}; + qu.push(next); + } + // 東方向 + if(trgt.d!=EAST && isInserted(trgt.x+1,trgt.y,trgt.z)){ + Search next = {trgt.x+1,trgt.y,trgt.z,WEST}; + qu.push(next); + } + // 南方向 + if(trgt.d!=SOUTH && isInserted(trgt.x,trgt.y+1,trgt.z)){ + Search next = {trgt.x,trgt.y+1,trgt.z,NORTH}; + qu.push(next); + } + // 西方向 + if(trgt.d!=WEST && isInserted(trgt.x-1,trgt.y,trgt.z)){ + Search next = {trgt.x-1,trgt.y,trgt.z,EAST}; + qu.push(next); + } + // 上方向 + if(trgt.d!=UP && isInserted(trgt.x,trgt.y,trgt.z+1)){ + Search next = {trgt.x,trgt.y,trgt.z+1,DOWN}; + qu.push(next); + } + // 下方向 + if(trgt.d!=DOWN && isInserted(trgt.x,trgt.y,trgt.z-1)){ + Search next = {trgt.x,trgt.y,trgt.z-1,UP}; + qu.push(next); + } + } + + int now_x = trgt_line->getSinkX(); + int now_y = trgt_line->getSinkY(); + int now_z = trgt_line->getSinkZ(); + vector next_direction_array; + int next_count, next_id; + + Point p_s = {now_x, now_y, now_z}; + trgt_line->pushPointToTrack(p_s); + + Direction trgt_d = my_board[now_z][now_y][now_x].d; + + next_direction_array.clear(); + if(trgt_d.n) next_direction_array.push_back(NORTH); + if(trgt_d.e) next_direction_array.push_back(EAST); + if(trgt_d.s) next_direction_array.push_back(SOUTH); + if(trgt_d.w) next_direction_array.push_back(WEST); + if(trgt_d.u) next_direction_array.push_back(UP); + if(trgt_d.d) next_direction_array.push_back(DOWN); + next_count = (int)mt_genrand_int32(0, (int)(next_direction_array.size()) - 1); + next_id = next_direction_array[next_count]; + switch(next_id){ + case NORTH: // 北へ + now_y = now_y - 1; next_id = trgt_d.c_n; break; + case EAST: // 東へ + now_x = now_x + 1; next_id = trgt_d.c_e; break; + case SOUTH: // 南へ + now_y = now_y + 1; next_id = trgt_d.c_s; break; + case WEST: // 西へ + now_x = now_x - 1; next_id = trgt_d.c_w; break; + case UP: // 上へ + now_z = now_z + 1; next_id = trgt_d.c_u; break; + case DOWN: // 下へ + now_z = now_z - 1; next_id = trgt_d.c_d; break; + } + + while(1){ + + Point p = {now_x, now_y, now_z}; + trgt_line->pushPointToTrack(p); + + if(now_x==trgt_line->getSourceX() && now_y==trgt_line->getSourceY() && now_z==trgt_line->getSourceZ()) break; + + trgt_d = my_board[now_z][now_y][now_x].d; + + switch(next_id){ + case NORTH: + if(!trgt_d.n) next_id = -1; + break; + case EAST: + if(!trgt_d.e) next_id = -1; + break; + case SOUTH: + if(!trgt_d.s) next_id = -1; + break; + case WEST: + if(!trgt_d.w) next_id = -1; + break; + case UP: + if(!trgt_d.u) next_id = -1; + break; + case DOWN: + if(!trgt_d.d) next_id = -1; + break; + } + if(next_id < 0){ cout << "error! (error: 51)" << endl; exit(51); } + + switch(next_id){ + case NORTH: // 北へ + now_y = now_y - 1; next_id = trgt_d.c_n; break; + case EAST: // 東へ + now_x = now_x + 1; next_id = trgt_d.c_e; break; + case SOUTH: // 南へ + now_y = now_y + 1; next_id = trgt_d.c_s; break; + case WEST: // 西へ + now_x = now_x - 1; next_id = trgt_d.c_w; break; + case UP: // 上へ + now_z = now_z + 1; next_id = trgt_d.c_u; break; + case DOWN: // 下へ + now_z = now_z - 1; next_id = trgt_d.c_d; break; + } + } + + return true; +} + + +bool isInserted(int x,int y,int z){ + + // 盤面の端 + if(x<0 || x>(board->getSizeX()-1)) return false; + if(y<0 || y>(board->getSizeY()-1)) return false; + if(z<0 || z>(board->getSizeZ()-1)) return false; + + Box* trgt_box = board->box(x,y,z); + + if(trgt_box->checkLine()) return false; // ラインがあるマスは探索しない + + return true; +} + +int cost_parallel(int trgt_line_id, int x, int y, int z){ + //同Z平面上で隣接する(延べ)配線数をカウント + Box* neibour_box; + int cost=0; + if(x-1>=0){ + neibour_box = board->box(x-1,y,z); + if(neibour_box->checkLine() && neibour_box->getIndex() != trgt_line_id) + cost++; + } + if(x+1getSizeX()){ + neibour_box = board->box(x+1,y,z); + if(neibour_box->checkLine() && neibour_box->getIndex() != trgt_line_id) + cost++; + } + if(y-1>=0){ + neibour_box = board->box(x,y-1,z); + if(neibour_box->checkLine() && neibour_box->getIndex() != trgt_line_id) + cost++; + } + if(y+1getSizeY()){ + neibour_box = board->box(x,y+1,z); + if(neibour_box->checkLine() && neibour_box->getIndex() != trgt_line_id) + cost++; + } + return cost; +} + +void recordLine(int trgt_line_id){ + + Line* trgt_line = board->line(trgt_line_id); + vector* trgt_track = trgt_line->getTrack(); + + for(int i=0;i<(int)(trgt_track->size());i++){ + int _x = (*trgt_track)[i].x; + int _y = (*trgt_track)[i].y; + int _z = (*trgt_track)[i].z; + board->box(_x,_y,_z)->setHasLine(); + } +} + +void deleteLine(int trgt_line_id){ + + Line* trgt_line = board->line(trgt_line_id); + vector* trgt_track = trgt_line->getTrack(); + + for(int i=0;i<(int)(trgt_track->size());i++){ + int _x = (*trgt_track)[i].x; + int _y = (*trgt_track)[i].y; + int _z = (*trgt_track)[i].z; + board->box(_x,_y,_z)->resetHasLine(); + } +} diff --git a/resolver/cpp/route.hpp b/resolver/cpp/route.hpp new file mode 100644 index 0000000..c5271b7 --- /dev/null +++ b/resolver/cpp/route.hpp @@ -0,0 +1,17 @@ +/*******************************************************/ +/** ルーティングに関する関数 **/ +/*******************************************************/ + +#ifndef __ROUTE_HPP__ +#define __ROUTE_HPP__ + +// ルーティング +bool routing(int trgt_line_id); +bool isInserted(int x,int y,int z); +int cost_parallel(int trgt_line_id, int x, int y, int z); + +// 記録と抹消 +void recordLine(int trgt_line_id); +void deleteLine(int trgt_line_id); + +#endif diff --git a/resolver/cpp/utils.cpp b/resolver/cpp/utils.cpp new file mode 100644 index 0000000..1b4758f --- /dev/null +++ b/resolver/cpp/utils.cpp @@ -0,0 +1,209 @@ +#include "main.hpp" +#include "utils.hpp" + +extern Board* board; + +// 2桁の整数をアルファベットに変換 +char changeIntToChar(int n){ + if (0 <= n && n < 10) { + return (char)(n + '0'); + } else if (n <= 35) { + return (char)(n - 10 + 'A'); + } + return '#'; +} + +// コストを計算 +void calcCost(){ + + int total_length = 0; + int total_corner = 0; + int total_cost; + + for(int i=1;i<=board->getLineNum();i++){ + Line* trgt_line = board->line(i); + vector* trgt_track = trgt_line->getTrack(); + + total_length += (int)(trgt_track->size()) - 1; + + for(int j=1;j<(int)(trgt_track->size())-1;j++){ + Point p0 = (*trgt_track)[j-1]; + Point p1 = (*trgt_track)[j]; + Point p2 = (*trgt_track)[j+1]; + + if( ((p1.x-p0.x) != (p2.x-p1.x)) || ((p1.y-p0.y) != (p2.y-p1.y)) || ((p1.z-p0.z) != (p2.z-p1.z)) ){ + total_corner++; + } + } + } + + total_cost = total_length + total_corner; + + cout << endl; + cout << "Length: " << total_length << endl; + cout << "Corner: " << total_corner << endl; + cout << "Total cost: " << total_cost << endl; + cout << endl; +} + +// 問題盤を表示 +void printBoard(){ + + cout << endl; + cout << "PROBLEM" << endl; + cout << "=======" << endl; + + for(int z=0;zgetSizeZ();z++){ + cout << "LAYER " << z+1 << endl; + for(int y=0;ygetSizeY();y++){ + for(int x=0;xgetSizeX();x++){ + Box* trgt_box = board->box(x,y,z); + if(trgt_box->isTypeBlank()){ + cout << "[.]"; + } + else if(trgt_box->isTypeNumber()){ + int trgt_num = trgt_box->getIndex(); + cout << "[" << changeIntToChar(trgt_num) << "]"; + } + else{ + cout << "(-)"; + } + } + cout << endl; + } + cout << endl; + } +} + +// ラインナンバーから色をマッピング (Foreground colors) +// 31m ~ 37m まで 7色 +string getcolorescape_fore(int n) { + int color = ((n - 1) % 7) + 31; + stringstream ss; + ss << color; + string p = "\033["; + string s = "m"; + return p + ss.str() + s; +} +// ラインナンバーから色をマッピング (Background colors) +// 41m ~ 47m まで 7色 +string getcolorescape(int n) { + int color = ((n - 1) % 7) + 41; + stringstream ss; + ss << color; + string p = "\033["; + string s = "m"; + return p + ss.str() + s; +} + +// 正解を表示(正解表示は数字2桁) +void printSolution(){ + map > > for_print; + for(int z=0;zgetSizeZ();z++){ + for(int y=0;ygetSizeY();y++){ + for(int x=0;xgetSizeX();x++){ + for_print[z][y][x] = -1; + } + } + } + for(int i=1;i<=board->getLineNum();i++){ + Line* trgt_line = board->line(i); + vector* trgt_track = trgt_line->getTrack(); + for(int j=0;j<(int)(trgt_track->size());j++){ + Point p = (*trgt_track)[j]; + int point_x = p.x; + int point_y = p.y; + int point_z = p.z; + for_print[point_z][point_y][point_x] = i; + } + } + + cout << endl; + cout << "SOLUTION" << endl; + cout << "========" << endl; + + for(int z=0;zgetSizeZ();z++){ + cout << "LAYER " << z+1 << endl; + for(int y=0;ygetSizeY();y++){ + for(int x=0;xgetSizeX();x++){ + int n = for_print[z][y][x]; + if(n < 0){ + // 線が引かれていないマス:"00"表示 + cout << "\033[37m00\033[0m"; + }else{ + Box* trgt_box = board->box(x,y,z); + if(trgt_box->isTypeNumber()){ + // 線が引かれているマス [端点] (2桁表示) + cout << getcolorescape_fore(n) << setfill('0') << setw(2) << n << "\033[0m"; + }else{ + // 線が引かれているマス [非端点] (2桁表示) + cout << getcolorescape(n) << setfill('0') << setw(2) << n << "\033[0m"; + } + } + if(x != board->getSizeX()-1) cout << " "; + } + cout << endl; + } + cout << endl; + } +} + +// 正解を表示 (ファイル出力) +void printSolutionToFile(char *filename) { + map > > for_print; + for(int z=0;zgetSizeZ();z++){ + for(int y=0;ygetSizeY();y++){ + for(int x=0;xgetSizeX();x++){ + for_print[z][y][x] = -1; + } + } + } + for(int i=1;i<=board->getLineNum();i++){ + Line* trgt_line = board->line(i); + vector* trgt_track = trgt_line->getTrack(); + for(int j=0;j<(int)(trgt_track->size());j++){ + Point p = (*trgt_track)[j]; + int point_x = p.x; + int point_y = p.y; + int point_z = p.z; + for_print[point_z][point_y][point_x] = i; + } + } + + ofstream ofs(filename); + ofs << "SIZE " << board->getSizeX() << "X" << board->getSizeY() << "X" << board->getSizeZ() << endl; + for(int z=0;zgetSizeZ();z++){ + ofs << "LAYER " << z+1 << endl; + for(int y=0;ygetSizeY();y++){ + for(int x=0;xgetSizeX();x++){ + if(for_print[z][y][x] < 0){ + // 線が引かれていないマス:"0"表示 + ofs << "0"; + } + else{ + // その他 + ofs << for_print[z][y][x]; + } + if(x!=(board->getSizeX()-1)){ + ofs << ","; + } + } + ofs << endl; + } + } +} + +// ================================ // +// メルセンヌ・ツイスタ +// ================================ // +#include "mt19937ar.c" + +void mt_init_genrand(unsigned long s) { + init_genrand(s); +} + +// AからBの範囲の整数の乱数が欲しいとき +// 参考 http://www.sat.t.u-tokyo.ac.jp/~omi/random_variables_generation.html +unsigned long mt_genrand_int32(int a, int b) { + return genrand_int32() % (b - a + 1) + a; +} diff --git a/resolver/cpp/utils.hpp b/resolver/cpp/utils.hpp new file mode 100644 index 0000000..49d7435 --- /dev/null +++ b/resolver/cpp/utils.hpp @@ -0,0 +1,20 @@ +#ifndef __UTILS_HPP__ +#define __UTILS_HPP__ + +// 問題盤を表示 +void printBoard(); + +// コストを計算 +void calcCost(); + +// 正解を表示 (正解表示は数字2桁) +void printSolution(); + +// 正解を表示 (ファイル出力) +void printSolutionToFile(char *filename); + +// メルセンヌ・ツイスタ +void mt_init_genrand(unsigned long s); +unsigned long mt_genrand_int32(int a, int b); + +#endif diff --git a/resolver/Makefile b/resolver/python/Makefile similarity index 84% rename from resolver/Makefile rename to resolver/python/Makefile index 7ac0df0..8be2e45 100644 --- a/resolver/Makefile +++ b/resolver/python/Makefile @@ -7,7 +7,7 @@ PYTHON = python3 .PHONY:run all test clean run: - $(PYTHON) $(TARGET).py -i dataAsample.txt + $(PYTHON) $(TARGET).py -i ../dataAsample.txt -o ../dataAoutput.txt all: $(TARGET) diff --git a/resolver/resolver.py b/resolver/python/resolver.py similarity index 92% rename from resolver/resolver.py rename to resolver/python/resolver.py index 2745dea..fd5197c 100644 --- a/resolver/resolver.py +++ b/resolver/python/resolver.py @@ -38,10 +38,14 @@ class MAP: y_index += 1 self.n_line = int(np.amax(self.map)) self.line = np.zeros((self.n_line,2,3)) + self.line = self.line.astype(np.int8) for x,y,z in itertools.product(\ range(self.X), range(self.Y), range(self.Z)): neighbours = self.neighbour([x,y,z]) + neighbours = self.isregular(neighbours) index = int(self.map[x][y][z]-1) + if index==-1: + continue num = self.countV(index+1, neighbours) if num == 1: if list(self.line[index][0]) == [0,0,0]: @@ -52,9 +56,9 @@ class MAP: self.line[index][1][0] = x self.line[index][1][1] = y self.line[index][1][2] = z - self.line = self.line.astype(np.int8) self.map = self.map.astype(np.int8) + def countV(self, value, point_list): """座標リストpoint_list内の座標(x,y,z)のself.mapの値(ラインのインデックス)がvalueと等しいものの個数を数えます""" c = 0 @@ -137,7 +141,7 @@ class MAP: for y in range(self.Y): for x in range(self.X-1): str.append("%02d," % self.map[x][y][zm]) - str.append("%d\n" % self.map[self.X-1][y][zm]) + str.append("%02d\n" % self.map[self.X-1][y][zm]) return "".join(str) def save(self): @@ -212,7 +216,7 @@ class MAP: def neighbour(self, point): """ 与えられた座標をX,Y,Z方向に1移動させ, それら座標のリストを返す """ dlist=np.array([[0,0,-1], [0,0,1], [0,-1,0], [0,1,0], [-1,0,0], [1,0,0]]) - nlist=point+dlist + nlist=np.array(point)+dlist return nlist def addLine(self, maxlength): @@ -252,16 +256,22 @@ class MAP: cost += 1 return cost + def checkLine(self, n_line): + """デバッグ用, 指定の線が繋がっているかを確認""" + + def optLine(self, n_line): MAX=72*72*8 MAX_COST = 9999999 + n_index = n_line-1 dlist=np.array([[0,0,-1], [0,0,1], [0,-1,0], [0,1,0], [-1,0,0], [1,0,0]]) + #既存の線を削除 (端点も削除するので注意) self.map[self.map==n_line]=0 q=[] #コスト, 座標, ラインが引かれた方向 heapq.heappush(q, (0, list(self.line[n_line-1][0]), [0,0,0])) - cost_map = np.zeros((72,72,8,3,3,3)).astype(np.int32) + cost_map = np.zeros((72,72,8,3,3,3)) for i in itertools.product(range(72),range(72),range(8),range(3),range(3),range(3)): cost_map[i] = MAX_COST @@ -271,6 +281,8 @@ class MAP: while True: if q == []: + exit(1) + print("error") break (priority, point, direction) = heapq.heappop(q) if list(point) == list(self.line[n_line-1][1]): @@ -308,7 +320,6 @@ class MAP: while True: self.map[tuple(focus_p)]=n_line next_p = focus_p - focus_d - direction_min = focus_d cost_min = cost_map[tuple(np.append(next_p, focus_d).astype(np.int8))] for d in dlist: @@ -322,7 +333,13 @@ class MAP: break self.map[tuple(focus_p)]=n_line - + t = tuple(self.line[n_line-1][0]) + if self.map[t] != n_line: + print("error") + t = tuple(self.line[n_line-1][1]) + if self.map[t] != n_line: + print("error") + def optimize(self): #ライン数の10倍の回数だけ「線の引き剥がし・再配線」を繰り返す. iteration = min(len(self.line)*10,200) @@ -331,16 +348,20 @@ class MAP: if __name__ == '__main__': - parser = argparse.ArgumentParser(description='NLGenerator') + parser = argparse.ArgumentParser(description='Resolve') parser.add_argument('--input', '-i', default=None, type=str, help='Input file') parser.add_argument('--output', '-o', default=None, type=str, help='Output file') + parser.add_argument('--no_print', '-n', default=None, type=str, + help='print') args = parser.parse_args() - + np.random.seed(3) m=MAP(args.input) - m.printA() + if args.no_print is not None: + m.printA() m.optimize() - m.printA() + if args.no_print is not None: + m.printA() m.saveA(args.output) -- 2.22.0