<commit_before>﻿#include <iostream>
#include <boost/format.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <vector>
#include <fstream>
#include <string>
#include <algorithm>
#include <unordered_map>
#include <data_type.hpp>
#include <sort_algorithm/compare.hpp>
#include <sort_algorithm/adjacent.hpp>
#include <sort_algorithm/Murakami.hpp>
#include <./gui.hpp>
Murakami::Murakami(question_raw_data const& data, compared_type const& comp)
	: data_(data), comp_(comp)
{
}

std::vector<std::vector<std::vector<point_type>>> Murakami::operator() (){
	auto const width = data_.split_num.first;
	auto const height = data_.split_num.second;
	//sort_compare();//sorted_comparation作成
	make_sorted_comparation();
	std::cout << "make_ok" << std::endl;
	std::vector<std::vector<std::vector<point_type>>> block_list(
		height * width,
		std::vector<std::vector<point_type>>(
		1,
		std::vector<point_type>(
		1,
		{
		-1, -1
		}
		)

		)
		);

		//ブロックの左上に分割画像を配置するループ
		for (int i = 0; i < height; i++){
			for (int j = 0; j < width; j++){
				block_list[i * width + j][0][0].y = i;
				block_list[i * width + j][0][0].x = j;
			}
		}
		int a;
		while (block_list.size() != 1){//メインループ
			a = block_list.size();

			block_combination best_block_combination;//一番いいblockの組み合わせいれるところ
			best_block_combination.score = std::numeric_limits<int_fast64_t>::min();
			for (const auto& i : block_list){//ブロック同士を比較するループ
				for (const auto& j : block_list){
					if (i == j) continue;

					block_combination b = eval_block(i, j);
					if (best_block_combination.score < b.score){
						best_block_combination = b; //TODO 同じ値があったらどうしよ
					}
				}
			}

			if (best_block_combination.score == std::numeric_limits<int_fast64_t>::min())throw std::runtime_error("ブロック評価構造体が空です");
			block_type combined_block = combine_block(best_block_combination);//ブロックを結合する
			boost::remove_erase_if(block_list, [best_block_combination](block_type it){//block_listから結合する前のブロックを消す
				return (it == best_block_combination.block1 || it == best_block_combination.block2);
			});
			block_list.push_back(combined_block);//結合したのを入れる
			std::cout << block_list.size() << std::endl;
		}

		for (int i = 0; i < height; i++){
			for (int j = 0; j < width; j++){
				std::cout << block_list[0][i][j].x << "," << block_list[0][i][j].y << "|";
			}
			std::cout << "\n";
		}
		//answer_type_y show_image;
		//show_image.point_type = block_list;
		//gui::combine_show_image(data_, comp_, show_image);
		return block_list;

}
Murakami::block_combination Murakami::eval_block(const block_type& block1, const block_type& block2){

	auto const width = data_.split_num.first;
	auto const height = data_.split_num.second;
	int const b1_width = block1[0].size();
	int const b1_height = block1.size();
	int const b2_width = block2[0].size();
	int const b2_height = block2.size();
	
	auto const block1_exists = [b1_height, b1_width, block1](int y, int x){
		if (x >= 0 && x < b1_width && y >= 0 && y < b1_height){
			if (block1[y][x].x != -1 || block1[y][x].y != -1){
				return true;
			}
			else{
				return false;
			}
		}
		else{
			return false;
		}
	};
	auto const block2_exists = [b2_height, b2_width, block2](int y, int x){
		if (x >= 0 && x < b2_width && y >= 0 && y < b2_height){
			if (block2[y][x].x != -1 || block2[y][x].y != -1){
				return true;
			}
			else{
				return false;
			}
		}
		else{
			return false;
		}
	};
	auto const block_size_check = [b1_width, b1_height, b2_width, b2_height, width, height](int shift_x,int shift_y){
		point_type lu, rd;
		lu.x = std::min(0, shift_x);
		lu.y = std::min(0, shift_y);
		rd.x = std::max(b1_width, shift_x + b2_width);
		rd.y = std::max(b1_height, shift_y + b2_height);
		if ((rd.x - lu.x) <= width && (rd.y - lu.y) <= height){
			//std::cout << "w" << rd.x - lu.x << " h" << rd.y - lu.y << std::endl;
			return true;
		}
		else{
			return false;
		}
	};
	int_fast64_t best_block_c = std::numeric_limits<int_fast64_t>::min();
	int best_shift_i = std::numeric_limits<int>::min();
	int best_shift_j = std::numeric_limits<int>::min();
	for (int i = -b2_height; i < b1_height + b2_height + 1; i++){
		for (int j = -b1_width; j < b1_width + b2_width + 1; j++){
			bool confliction = false;
			int_fast64_t block_c = 0;
			bool empty_block_c = true;
			int_fast64_t rank1_num = 0;//キャストが面倒くさいからint_fast64_tで
			for (int k = 0; k < b1_height; k++){
				for (int l = 0; l < b1_width; l++){
					if (block2_exists(k - i, l - j)){
						if (block1[k][l].x != -1 && block1[k][l].y != -1 ){
							confliction = true;
							break;
						}
					}
					if (block1_exists(k, l) && !block2_exists(k + i, l + j)){
						int_fast64_t piece_c = 0;
						if (block2_exists(k + i - 1, l + j)){//上
							piece_c += eval_piece(block1[k][l], block2[k + i - 1][l + j], up);
							empty_block_c = false;
							if (sorted_comparation[block1[k][l]][up][1] == block2[k + i - 1][l + j]) rank1_num++;
						}
						if (block2_exists(k + i, l + j - 1)){//左
							piece_c += eval_piece(block1[k][l], block2[k + i][l + j - 1], left);
							empty_block_c = false;
							if (sorted_comparation[block1[k][l]][left][1] == block2[k + i][l + j - 1]) rank1_num++;
						}
						if (block2_exists(k + i + 1, l + j)){//下
							piece_c += eval_piece(block1[k][l], block2[k + i + 1][l + j], down);
							empty_block_c = false;
							if (sorted_comparation[block1[k][l]][down][1] == block2[k + i + 1][l + j]) rank1_num++;
						}
						if (block2_exists(k + i, l + j + 1)){//右
							piece_c += eval_piece(block1[k][l], block2[k + i][l + j + 1], right);
							empty_block_c = false;
							if (sorted_comparation[block1[k][l]][right][1] == block2[k + i][l + j + 1]) rank1_num++;
						}
						//pow(piece_c, rank1_num);
						block_c += piece_c;
					}
				}
				if (confliction)break;
			}
			if (!confliction && empty_block_c == false){
				//if (best_block_c != 0){};
				rank1_num++;
				block_c *= rank1_num; //0を掛けるのは怖い
				if (block_c > best_block_c && block_size_check(-i,-j)){
					best_block_c = block_c;
					best_shift_i = -i;
					best_shift_j = -j;
				}
			}
		}
	}
	block_combination return_struct{
		block1,
		block2,
		best_shift_j,
		best_shift_i,
		best_block_c
	};
	return std::move(return_struct);
}
std::int_fast64_t Murakami::eval_piece(const point_type& p1, const point_type& p2, direction dir){
	int_fast64_t score = 0;
	Murakami::direction dir2;
	switch (dir)
	{
	case Murakami::up:
		dir2 = Murakami::down;
		break;
	case Murakami::right:
		dir2 = Murakami::left;
		break;
	case Murakami::down:
		dir2 = Murakami::up;<commit_msg>評価をべき乗にしたらちょっと良くなった？<commit_after>﻿#include <iostream>
#include <boost/format.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <vector>
#include <fstream>
#include <string>
#include <algorithm>
#include <unordered_map>
#include <data_type.hpp>
#include <sort_algorithm/compare.hpp>
#include <sort_algorithm/adjacent.hpp>
#include <sort_algorithm/Murakami.hpp>
#include <./gui.hpp>
Murakami::Murakami(question_raw_data const& data, compared_type const& comp)
	: data_(data), comp_(comp)
{
}

std::vector<std::vector<std::vector<point_type>>> Murakami::operator() (){
	auto const width = data_.split_num.first;
	auto const height = data_.split_num.second;
	//sort_compare();//sorted_comparation作成
	make_sorted_comparation();
	std::cout << "make_ok" << std::endl;
	std::vector<std::vector<std::vector<point_type>>> block_list(
		height * width,
		std::vector<std::vector<point_type>>(
		1,
		std::vector<point_type>(
		1,
		{
		-1, -1
		}
		)

		)
		);

		//ブロックの左上に分割画像を配置するループ
		for (int i = 0; i < height; i++){
			for (int j = 0; j < width; j++){
				block_list[i * width + j][0][0].y = i;
				block_list[i * width + j][0][0].x = j;
			}
		}
		int a;
		while (block_list.size() != 1){//メインループ
			a = block_list.size();

			block_combination best_block_combination;//一番いいblockの組み合わせいれるところ
			best_block_combination.score = std::numeric_limits<int_fast64_t>::min();
			for (const auto& i : block_list){//ブロック同士を比較するループ
				for (const auto& j : block_list){
					if (i == j) continue;

					block_combination b = eval_block(i, j);
					if (best_block_combination.score < b.score){
						best_block_combination = b; //TODO 同じ値があったらどうしよ
					}
				}
			}

			if (best_block_combination.score == std::numeric_limits<int_fast64_t>::min())throw std::runtime_error("ブロック評価構造体が空です");
			block_type combined_block = combine_block(best_block_combination);//ブロックを結合する
			boost::remove_erase_if(block_list, [best_block_combination](block_type it){//block_listから結合する前のブロックを消す
				return (it == best_block_combination.block1 || it == best_block_combination.block2);
			});
			block_list.push_back(combined_block);//結合したのを入れる
			std::cout << "***" <<block_list.size() << "***" <<std::endl;
			for (const auto& i : block_list){
				for (const auto& j : i){
					for (const auto& k : j){
						//std::cout << k.x << "," << k.y << " ";
						std::cout << boost::format("(%2d,%2d)") % k.x % k.y;
					}
					std::cout << "\n";
				}
				std::cout << "\n";
			}
		}

		for (int i = 0; i < height; i++){
			for (int j = 0; j < width; j++){
				std::cout << block_list[0][i][j].x << "," << block_list[0][i][j].y << "|";
			}
			std::cout << "\n";
		}
		answer_type_y show_image;
		show_image.points = block_list;
		gui::combine_show_image(data_, comp_, show_image);
		return block_list;

}
Murakami::block_combination Murakami::eval_block(const block_type& block1, const block_type& block2){

	auto const width = data_.split_num.first;
	auto const height = data_.split_num.second;
	int const b1_width = block1[0].size();
	int const b1_height = block1.size();
	int const b2_width = block2[0].size();
	int const b2_height = block2.size();
	
	auto const block1_exists = [b1_height, b1_width, block1](int y, int x){
		if (x >= 0 && x < b1_width && y >= 0 && y < b1_height){
			if (block1[y][x].x != -1 || block1[y][x].y != -1){
				return true;
			}
			else{
				return false;
			}
		}
		else{
			return false;
		}
	};
	auto const block2_exists = [b2_height, b2_width, block2](int y, int x){
		if (x >= 0 && x < b2_width && y >= 0 && y < b2_height){
			if (block2[y][x].x != -1 || block2[y][x].y != -1){
				return true;
			}
			else{
				return false;
			}
		}
		else{
			return false;
		}
	};
	auto const block_size_check = [b1_width, b1_height, b2_width, b2_height, width, height](int shift_x,int shift_y){
		point_type lu, rd;
		lu.x = std::min(0, shift_x);
		lu.y = std::min(0, shift_y);
		rd.x = std::max(b1_width, shift_x + b2_width);
		rd.y = std::max(b1_height, shift_y + b2_height);
		if ((rd.x - lu.x) <= width && (rd.y - lu.y) <= height){
			//std::cout << "w" << rd.x - lu.x << " h" << rd.y - lu.y << std::endl;
			return true;
		}
		else{
			return false;
		}
	};
	int_fast64_t best_block_c = std::numeric_limits<int_fast64_t>::min();
	int best_shift_i = std::numeric_limits<int>::min();
	int best_shift_j = std::numeric_limits<int>::min();
	for (int i = -b2_height; i < b1_height + b2_height + 1; i++){
		for (int j = -b1_width; j < b1_width + b2_width + 1; j++){
			bool confliction = false;
			int_fast64_t block_c = 0;
			bool empty_block_c = true;
			int_fast64_t rank1_num = 0;//キャストが面倒くさいからint_fast64_tで
			for (int k = 0; k < b1_height; k++){
				for (int l = 0; l < b1_width; l++){
					if (block2_exists(k - i, l - j)){
						if (block1[k][l].x != -1 && block1[k][l].y != -1 ){
							confliction = true;
							break;
						}
					}
					if (block1_exists(k, l) && !block2_exists(k + i, l + j)){
						int_fast64_t piece_c = 0;
						if (block2_exists(k + i - 1, l + j)){//上
							piece_c += eval_piece(block1[k][l], block2[k + i - 1][l + j], up);
							empty_block_c = false;
							if (sorted_comparation[block1[k][l]][up][1] == block2[k + i - 1][l + j]) rank1_num++;
						}
						if (block2_exists(k + i, l + j - 1)){//左
							piece_c += eval_piece(block1[k][l], block2[k + i][l + j - 1], left);
							empty_block_c = false;
							if (sorted_comparation[block1[k][l]][left][1] == block2[k + i][l + j - 1]) rank1_num++;
						}
						if (block2_exists(k + i + 1, l + j)){//下
							piece_c += eval_piece(block1[k][l], block2[k + i + 1][l + j], down);
							empty_block_c = false;
							if (sorted_comparation[block1[k][l]][down][1] == block2[k + i + 1][l + j]) rank1_num++;
						}
						if (block2_exists(k + i, l + j + 1)){//右
							piece_c += eval_piece(block1[k][l], block2[k + i][l + j + 1], right);
							empty_block_c = false;
							if (sorted_comparation[block1[k][l]][right][1] == block2[k + i][l + j + 1]) rank1_num++;
						}
						//pow(piece_c, rank1_num);
						block_c += piece_c;
					}
				}
				if (confliction)break;
			}
			if (!confliction && empty_block_c == false){
				//if (best_block_c != 0){};
				rank1_num++;
		
				//block_c *= rank1_num; //0を掛けるのは怖い
				if(block_c < 0)block_c = -pow(block_c, rank1_num);
				if (block_c > 0)block_c = pow(block_c, rank1_num);
				if (block_c > best_block_c && block_size_check(-i,-j)){
					if(rank1_num > 2)std::cout << rank1_num << "<- rank" << std::endl;
					best_block_c = block_c;
					best_shift_i = -i;
					best_shift_j = -j;
				}
			}
		}
	}
	block_combination return_struct{
		block1,
		block2,
		best_shift_j,
		best_shift_i,
		best_block_c
	};
	return std::move(return_struct);
}
std::int_fast64_t Murakami::eval_piece(const point_type& p1, const point_type& p2, direction dir){
	int_fast64_t score = 0;
	Murakami::direction dir2;
	switch (dir)
	{
	case Murakami::up:
		dir2 = Murakami::down;
		break;
	case Murakami::right:
		dir2 = Murakami::left;
		break;
	case Murakami::down:
		dir2 = Murakami::up;
{'fraction_non_alphanumeric': 0.1783947426714908, 'fraction_numerical': 0.024292992689950527, 'mean_word_length': 3.410289807880169, 'pattern_counts': {'":': 0, '<': 169, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2220702', 'n_tokens_mistral': 6578, 'n_tokens_neox': 5641, 'n_words': 1111}