diff --git a/Lab1/README.md b/Lab1/README.md index fefce8415e7803535a751f204d3b239044d31b01..bea0777adc160411a7f8b4b0b17c403f3d0bfb19 100644 --- a/Lab1/README.md +++ b/Lab1/README.md @@ -1,193 +1,239 @@ -# Lab 1: “Super-fast” Sudoku Solving +Lab 1: “Super-fast” Sudoku Solving +Enter in the folder you have cloned from our lab git repo, and pull the latest commit. -Enter in the folder you have cloned from our lab git repo, and pull the latest commit. +git pull -`git pull` +You can find this lab1's instruction in Lab1/README.md -You can find this lab1's instruction in `Lab1/README.md` +All materials of lab1 are in folder Lab1/ -All materials of lab1 are in folder `Lab1/` +1. Overview +Implement a Sudoku solving program, using multiple threads or multiple processes, running on a single machine. Try to utilize all your CPU cores and make your program run as fast as possible! -## 1. Overview +实现一个数独解决程序,使用多个线程或多个进程,运行在一台机器上。 试着利用你所有的CPU核心,让你的程序尽可能快地运行! -Implement a Sudoku solving program, using multiple threads or multiple processes, running on a single machine. Try to **utilize all your CPU cores** and make your program **run as fast as possible**! +Goals +Practice basic parallel programming skills, such as using multiple threads/processes; +练习基础的并行编程技能,例如使用多线程/进程 +Get familiar with Unix OS environment development (eg., file I/O, get timestamp); +熟悉Unix操作系统环境开发(例如: 文件I/O,获取时间戳) +Get familiar with source code version control tools (git), and learn to collaborate with others using github; +熟悉源代码版本控制工具(git),学习使用github与他人协作 +2. Background +2.1 Introduction to Sudoku +Sudoku (originally called Number Place) is a logic-based combinatorial number-placement puzzle. -### Goals +数独(Sudoku,原名Number Place)是一种基于逻辑的组合数字放置谜题。 -* Practice basic parallel programming skills, such as using multiple threads/processes; -* Get familiar with Unix OS environment development (eg., file I/O, get timestamp); -* Get familiar with source code version control tools (git), and learn to collaborate with others using github; +You are given a 9×9 board of 81 squares logically separated into 9 columsn, 9 rows, and 9 3×3 subsquares. The goal is, given a board with some initial numbers filled in (we call it a Sudoku puzzle), fill in the rest of the board so that every column, row, and subsquare have all the digits from 1 to 9 and each digit appears only once (we call it a Sudoku solution). -## 2. Background +给你一个9×9的板子,上面有81个正方形,逻辑上分成9列、9行和9个3×3子正方形。 我们的目标是,给定一个板子和一些初始数据填写(我们称之为一个数独题 ),使用1到9的数字来填写的板子中的每一列,每一行,每一个子正方形,并且每个数字只出现一次(我们称之为数独解)。 -### 2.1 Introduction to Sudoku +An example Sudoku puzzle: -Sudoku (originally called Number Place) is a logic-based combinatorial number-placement puzzle. +Sudoku -You are given a 9×9 board of 81 squares logically separated into 9 columsn, 9 rows, and 9 3×3 subsquares. The goal is, given a board with some initial numbers filled in (we call it a **Sudoku puzzle**), fill in the rest of the board so that every column, row, and subsquare have all the digits from 1 to 9 and each digit appears only once (we call it a **Sudoku solution**). +An example Sudoku solution to above puzzle: +Sudoku - An example Sudoku puzzle: +2.2 Some useful resources +If you have no idea about what algorithms can be used to solve Sudoku puzzles, we suggest you read this. To simplify your work, we have provided a simple implementation (Lab1/src/Sudoku) of 4 Sudoku solving algorithms (some are slow, some are fast), but without using multiple threads/processes. The two files test1 and test1000 contain many puzzles for you to test. -Sudoku +如果你不知道什么算法可以用来解决数独谜题,我们建议你阅读这个。 - An example Sudoku solution to above puzzle: - -Sudoku - -### 2.2 Some useful resources - -If you have no idea about what algorithms can be used to solve Sudoku puzzles, we suggest you read [this](https://rafal.io/posts/solving-sudoku-with-dancing-links.html). To simplify your work, we have provided a simple [implementation](src/Sudoku/) `(Lab1/src/Sudoku`) of 4 Sudoku solving algorithms (some are slow, some are fast), but without using multiple threads/processes. The two files *test1* and *test1000* contain many puzzles for you to test. +为了简化您的工作,我们提供了一个简单的实现 (Lab1/src/Sudoku )中的4个Sudoku求解算法(有些慢,有些快),但不使用多线程/进程。 两个文件test1和test1000包含许多要测试的谜题。 Of course, you are always encouraged (not mandatory) to implement those algorithms by yourselves and even your own algorithms (if you have time). -## 3. Your Lab Task - -### 3.1 Write a program +当然,我们总是鼓励(不是强制性的)您自己实现这些算法,甚至是您自己的算法(如果您有时间的话)。 +3. Your Lab Task +3.1 Write a program Implement a program which satisfies the following requirements: -#### 3.1.1 Program input and output +实施满足下列要求的计划: -##### **Input** +3.1.1 Program input and output +3.1.1.1 Input +Your program must have no arguments during start. Attention, your program must be called sudoku_solve, just typing ./sudoku_solve and your program will run correctly. -1. When executing the compiled program from the code you submit, it must **not** take any parameters and the program must be named ***sudoku_solve***. In other words, your program can be run normally by typing `./sudoku_solve` in the terminal. -2. But after start, your program needs to be able to read multiple strings from ***stdin***, which are separated by line breaks. The content of these strings are **the paths of the Sudoku puzzles files**. -3. In each input file, **each line** of the file represents a Sudoku puzzle that needs to be solved. Each line contains 81 digits, where the first 9 digits represent the first row of the Sudoku puzzle, the 10th to the 18th digits represent the second row of the puzzle, and so on. The digit 0 represents a blank that needs to be filled in when solving the puzzle. +你的程序**必须在启动时**没有参数。 注意,你的程序必须被称为sudoku_solve,只需要输入./sudoku_solve ,您的程序将正确运行。 -**3.1.1.1 Puzzle file example** +But after start, your program should be able to read multiple strings from stdin, where each string is separated by a line-break. Each string is a name of a file, which contains one or more Sudoku puzzles that your program is going to solve. -In the following image, we have printed three Sudoku puzzle **files** in the terminal. They contain one, two, and three puzzles, and their names are test1, test2, and test3. +但是在开始之后,你的程序应该能够从stdin中读取多个字符串,其中每个字符串由一个换行符分隔。 每个字符串是一个文件的名,它包含一个或多个你的程序将解决的数独谜题。 -Input file +In the input file, each line is a Sudoku puzzle that needs to be solved. Each line contains 81 decimal digits. The 1st-9th digits are the 1st row of the 9×9 grid, and the 10th-18th digits are the 2nd row of the 9×9 grid, and so on. Digit 0 means this digit is unknown and your program needs to figure it out according to the Sudoku rules described above. -**3.1.1.2 Example input from terminal** +在输入文件中,每一行是一个需要解决的数独谜题。 每行包含81位十进制数字。 第1 ~ 9位是9×9网格的第一行,第10 ~ 18位是9×9网格的第2行,以此类推。 数字0表示这个数字是未知的,你的程序需要根据上面描述的数独规则来计算它。 -In the following code snippet, we showed how to input Sudoku puzzle files that need to be solved from the terminal after your program starts running: +Example contents + +Input file + +Example input -``` ./test1 ./test2 ./test3 -``` - -##### Output +3.1.1.2 Output +For each test case, you just only output the Sudoku solutions. And don't forget, the output order should correspond with the input order of Sudoku puzzles. -For each Sudoku puzzle in file, your program should only output the solution to the puzzle to ***stdout***. The format of the solution should be the same as the puzzle, except that all 0s in the puzzle should be replaced with the correct numbers. Also, remember that the order of the answers should be consistent with the order of the input Sudoku puzzles. +对于每个测试用例,您只输出Sudoku解决方案。 不要忘记,输出顺序应该与数独谜题的输入顺序相对应。 -**3.1.1.3 Example output** +Example output -``` 312647985786953241945128367854379126273461859691285473437592618569814732128736594 693784512487512936125963874932651487568247391741398625319475268856129743274836159 869725413512934687374168529798246135231857946456319872683571294925483761147692358 693784512487512936125963874932651487568247391741398625319475268856129743274836159 364978512152436978879125634738651429691247385245389167923764851486512793517893246 378694512564218397291753684643125978712869453859437261435971826186542739927386145 -``` +Output order requirement + +In the example of input above, the order of filename entered is ./test1, ./test2 and ./test3. So, you should output the solutions of Sudoku puzzles in file test1 firstly, then file test2 and finally file test3. Needless to say, the solutions should be outputed in the same sequence as the puzzles are inputted in. + +在上面输入的例子中,文件名的输入顺序是./test1 , ./test2和./test3。 因此,您应该首先在文件test1中输出数独谜题的解决方案,然后文件test2,最后文件test3。 不用说,答案应该以输入谜题的相同顺序输出。 + +In the example of output above, the 1st line is the solution of Sudoku puzzle in file test1. After that, the 2nd line and 3rd line are the solutions of 1st and 2nd Sudoku puzzles in file test2. Finally, the 4th line, 5th line and 6th line are the solutions of 1st, 2nd and 3rd Sudoku puzzles in file test3. + +在上面的输出示例中,第一行是test1文件中的数独谜题的解决方案。 然后,第二行和第三行是文件test2中第1和第2个数独谜题的答案。 最后,第4行、第5行和第6行是test3文件中第1、2和3个数独谜题的答案。 + +3.1.3 Implementation requirements +3.1.3.1 Basic version +Your program should be able to: + +Accept one input file name, and the size of the input file is smaller than 100MB. +Successfully solve the puzzles in the input file, and output the results in the format described before. +Use multiple threads/processes to make use of most of your machine's CPU cores. +[Tips]: 1) Use event queue to dispatch tasks and merge results to/from worker threads. 2) Dynamically detect how many CPU cores are there on your machine, in order to decide how many threads/processes your program uses. 3) Be careful about the contention among multiple threads/processes + +你的程序应该能够: -**3.1.1.4 Output order requirement** +接受一个输入文件名,输入文件大小小于100MB。 -Taking the three test files above as an example, your program needs to output the result of `./test1` first, then `./test2`, and finally `./test3`. Additionally, the order of answers corresponding to each file should be consistent with the order of puzzles in the file. +成功解决输入文件中的谜题,并以前面描述的格式输出结果。 -In the example output, the 1st line corresponds to the solution of the Sudoku puzzle in `./test1`. The 2nd and 3rd lines correspond to the 1st and 2nd puzzles in `./test2`. The 4th, 5th, and 6th lines correspond to the 1st, 2nd, and 3rd puzzles in test3. +使用多线程/进程可以充分利用机器的大部分CPU核心。 -#### 3.1.2 Implementation requirements +[提示]:1)使用事件队列来调度任务,并将结果合并到工作线程中。 2)动态检测有多少CPU核在你的机器上,以决定有多少线程/进程,你的程序使用。 3)小心多线程/进程之间的争用 -##### 3.1.2.1 Basic version +3.1.3.2 Advanced version +Your program should be able to: -Your program should be able to: +Complete all the requirements in the basic version. +Accept any number of input file names, and the size of input file can be any large (as long as it can be stored on your disk) +When the program is solving puzzles in the previously input file(s), the program can meanwhile accept more input file names from stdin. +[Tips]: 1) Use a dedicated thread to accept input; 2) To avoid consuming all the memory, read different parts of the file into memory and solve them one by one; 3) You are encouraged to try more optimizations such as cache coherency processing. -1. Accept **one** input file name, and the size of the input file is smaller than 100MB. -2. Successfully solve the puzzles in the input file, and output the results in the format described before. -3. Use multiple threads/processes to make use of most of your machine's CPU cores. +你的程序应该能够: -\[Tips\]: +完成基本版本中的所有要求。 -1. Use an event queue to dispatch tasks and merge results to/from worker threads. -2. Dynamically detect how many CPU cores your machine has to determine how many threads/processes your program should use. -3. Be careful about contention between multiple threads/processes. +接受任意数量的输入文件名,输入文件的大小可以任意大(只要它可以存储在您的磁盘上) -##### 3.1.2.2 Advanced version +当程序在解决之前输入文件中的谜题时,程序可以同时从stdin接受更多的输入文件名。 -Your program should be able to: +[提示]:1)使用专用线程接受输入; 2)为避免占用全部内存,请将文件的不同部分读入内存,并逐个解决; 3)鼓励你尝试更多的优化,如缓存一致性处理。 -1. Complete all the requirements in the basic version. -2. Accept **any number of** input file names, and the size of input file can be **any large** (as long as it can be stored on your disk) -3. When the program is solving puzzles in the previously input file(s), the program can **meanwhile accept more input file names from *stdin***. +3.2. Test script +You can test your program using the script (Lab1.sh) that comes with this Lab. -\[Tips\]: +您可以使用本Lab附带的脚本(Lab1.sh)测试您的程序。 -1. Use a dedicated thread to accept input. -2. To avoid exhausting all memory, read different parts of the file into memory and solve them one by one. -3. You are encouraged to try more optimizations, such as cache coherency processing. +3.2.1 Notes +You can use the script on most Linux environments -### 3.2. Test script +您可以在大多数Linux环境中使用该脚本 -We have provided a script for you to use so that you can test your program before submitting, you can use this shell script on most Linux systems. +Requires support for the screen command -It will verify the correctness of the program based on the output, and show you the time your program takes. +需要支持的screen命令 -##### 3.2.1 Get prepared +​ You can use "which screen" to see if the screen command is already installed, if not you can refer to the following command download: -1. This script requires you to provide **two input files**. These two files need to be placed in the **same directory as the script**. The following describes how to prepare these two input files: +你可以使用“which screen”来查看screen命令是否已经安装,如果没有,你可以参考以下命令下载: - a. The content of the **first file** is a list of Sudoku puzzle files which will be input to your program. For example, we name the first file as `test_group`, and we prepared 2 puzzle files(see in 3.1.1.1) to test our program, the first file is named as "test1" and it has 1 puzzle to be solved, and the other file is named "test1000" and it has 1000 puzzles to be solved. Then the content format of `test_group` is as follows: + ubuntu: apt-get install screen - Sudoku + centos: yum install screen +The executable file can only be named sudoku_solve - b. The content of the **second file** is a list of Sudoku solution files to the puzzles you prepared. Take the example of the first file above, we name the second file as `answer_group`. Same to the `test_group` above, `answer_group` should also contain 2 answer files, the first answer file corresponds to ""test1"" in `test_group`, it's named "answer1" and it has 1 solution, the second answer file corresponds to "test1000" in `test_group`, it's name is "answer1000" and it has 1000 solutions. Then the content format of `answer_group` is as follows: +可执行文件的名称只能为sudoku_solve - Sudoku +sudoku_solve executable file, Lab1.sh script should be placed in the same directory - You can create your own test files and put them in the test group and answer group if you want. +sudoku_solve可执行文件,Lab1.sh脚本应放在同一目录下 -2. Using this script requires installing the `screen` command. You can use the `which screen` command to check if `screen` is installed on your local machine. If it is not installed, you can install it using the following command: -```shell - ubuntu(debian): sudo apt-get install screen #This or apt - sudo apt install screen #This or apt-get - centos(redhat): yum install screen 2. -``` -3. The compiled executable file should be named **sudoku_solve**, and it need to be placed in the **same directory as this script**. +If your file system is not in ext4 format, the performance test may not succeed and only the basic test can be performed. -4. If your file system is not in the **ext4** format, this script may not be able to do performance tests successfully and can only do basic tests. You can use the following command to check which paths are mounted on an exf4-formatted disk: +如果文件系统不是ext4格式,可能会导致性能测试失败,只能执行基本测试。 - ```shell - df -h --type=ext4 - ``` +​ You can see which path mounted ext4 disks in the following way: - Sudoku +您可以通过以下方式查看ext4磁盘挂载的路径: -5. The script will generate a sub-folder contains two files named Basic(Advanced)_Result and Basic(Advanced)_Answer, the Result file contains your program's output and the Answer file contains reference output. The script will delete these two folders every time it runs, so if you need the data, make sure to copy them before running the script. + df -h --type=ext4 +Sudoku +The script will generate a subfolder with Basic(Advanced)_Result and Basic(Advanced)_Answer, Result is your output and Answer is the reference output. At each run, the script will delete the two files , so if you need this data, please copy it first before running the script. -6. The script presents the time spent as relative, and there is a relatively fixed processing time for each run. For example, if your program takes 1300ms to solve a Sudoku problem, but the script takes 800ms for preparation, the final display will show 2100 milliseconds. Additionally, everyone's configuration and performance are different, resulting in different times. This means that you only need to keep optimizing on your own machine instead of comparing with others. Rest assured that the same environment will be used for the final scoring. +脚本将生成一个基本(高级)\结果和基本(高级)_Answer的子文件夹,结果是你的输出,答案是参考输出。 每次运行时,脚本都会删除这两个文件,所以如果您需要这些数据,请在运行脚本之前先复制它们。 -7. (**Very important**) If you want to get a high score (script test), it is better to flush the data in the buffer in time. +The time taken for script presentation is relative, each time there will be a relatively fixed processing time. For example, your program used 1300ms to solve the sudoku problem, but the script preparation took 800ms. eventually, the script will show 2100ms. Also everyone's configuration and performance is different, resulting in different times, which means you only need to keep optimizing on your machine, not comparing it with others. Please be assured that the same environment will be used for the final scoring. -##### 3.2.2 Script Usage +脚本呈现所花费的时间是相对的,每次都会有一个相对固定的处理时间。 例如,您的程序使用1300ms来解决数独问题,但是脚本准备需要800ms。 最终,脚本将显示2100ms。 此外,每个人的配置和性能都是不同的,导致不同的时间,这意味着您只需要在您的机器上进行优化,而不需要与其他机器进行比较。 请放心,最终评分将使用相同的环境。 -```shell +(Very important) If you want to get a high score (script test), it is better to flush the data in the buffer in time. + +(非常重要)如果你想要得到一个高分(脚本测试),它是最好的刷新数据在缓冲区的时间。 + +3.2.2 Script Usage sudo ./Lab1.sh test_group answer_group -``` +Parameter explanation: + +​ The script takes two parameters + +​ Para1(For example: test_group ) : A file that create by yourself. This file is placed in the path of the different test files. For example, if the test file group contains: . /test1 . /test1000 two input test files, the structure is as follows: + +​ Para1(例如:test_group):由自己创建的文件。 该文件被放置在不同测试文件的路径中。 例如,测试文件组包含: ./ test1 ./test1000两个输入测试文件,结构如下: + +Sudoku + +​ Para2(For example: answer_group) : A file like parameter 1 but with the path to the answer to the test file. For example, if the test file group contains: . /test1 . /test1000 two input test files, the answer file group contains: . /answer1 . /answer1000 , and the structure is as follows: -The script takes two parameters, they are the 2 prepared files in 3.2.1. +​ Para2(例如:answer_group):一个类似于参数1的文件,但带有测试文件的答案的路径。 例如,测试文件组包含: ./ test1 ./test1000两个输入的测试文件,回答文件组包含: ./ answer1 ./answer1000,结构如下: -Note that this output below means that you are missing a line break at the end of your answer group, which will not be recognized. Of course, the path of your puzzle file should be in the same order as the answer path. +Sudoku -Sudoku +You can create your own test files and put in the combinations you want. + +Note that this output below means that you are missing a line break at the end of your test file, which will not be recognized. Of course, the path of your answer file should be in the same order as the test path. + +您可以创建自己的测试文件,并放入您想要的组合。 + +请注意,下面的输出意味着您在测试文件的末尾丢失了一个换行符,它将无法被识别。 当然,回答文件的路径应该与测试路径的顺序相同。 + +Sudoku An example: -Sudoku +Sudoku + +4. Lab submission +Please put all your code in folder Lab1 and write a Makefile so that we can compile your code in one single command make. The compiled runnable executable binary should be named sudoku_solve and located in folder Lab1. If you do not know how to write Makefile, you can find a simple example in Lab1/src/Sudoku. Please carefully following above rules so that TAs can automatically test your code!!! + +Please submit your lab program and performance test report following the guidance in the Overall Lab Instructions (../README.md) -## 4. Lab submission +请把你所有的代码放在Lab1文件夹中,然后写一个Makefile,这样我们就可以在一个命令make中编译你的代码。 编译后的可执行二进制文件应该命名为sudoku_solve,并位于Lab1文件夹中。 如果你不知道如何编写Makefile,你可以在Lab1/src/Sudoku中找到一个简单的例子。 请仔细遵守以上规则,以便助教能够自动测试你的代码!! -Please put all your code in folder `Lab1` and write a `Makefile` so that we **can compile your code in one single command** `make`. The compiled runnable executable binary should be named `sudoku_solve` and located in folder `Lab1`. If you do not know how to write `Makefile`, you can find a simple example in `Lab1/src/Sudoku`. Please carefully following above rules so that TAs can automatically test your code!!! +请按照实验总体说明 (../README.md)中的指导提交你们的实验计划和性能测试报告。 -Please submit your lab program and performance test report following the guidance in the [Overall Lab Instructions](../README.md) (`../README.md`) +5. Grading standards +You can get 38 points if you can: 1) finish all the requirements of the basic version, and 2) your performance test report has finished the two requirements described before. If you missed some parts, you will get part of the points depending how much you finished -## 5. Grading standards +如果可以,你可以得38分: 1)完成了基础版的所有要求,2)性能测试报告完成了之前描述的两个要求。 如果你错过了一些部分,你将得到部分的分数取决于你完成了多少 -1. You can get 38 points if you can: 1) finish all the requirements of the basic version, and 2) your performance test report has finished the two requirements described before. If you missed some parts, you will get part of the points depending how much you finished -2. You can get 40 points (full score) if you can: 1) finish all the requirements of the advanced version, and 2) your performance test report has finished the two requirements described before. If you missed some parts, you will get part of the points depending how much you finished. +You can get 40 points (full score) if you can: 1) finish all the requirements of the advanced version, and 2) your performance test report has finished the two requirements described before. If you missed some parts, you will get part of the points depending how much you finished. +如果可以,你可以得40分: 1)完成高级版本的所有要求,2)您的性能测试报告已完成前面描述的两个要求。 如果你错过了一些部分,你将得到部分的分数取决于你完成了多少。 diff --git a/Lab1/src/Sudoku/dancing_link/src/Makefile b/Lab1/src/Sudoku/dancing_link/src/Makefile new file mode 100755 index 0000000000000000000000000000000000000000..d7a4ff4623ee016b5ea2877e438654068ad2988d --- /dev/null +++ b/Lab1/src/Sudoku/dancing_link/src/Makefile @@ -0,0 +1,7 @@ +CXXFLAGS+=-O2 -ggdb -DDEBUG +CXXFLAGS+=-Wall -Wextra + +all: sudoku_solve + +sudoku_solve: main_multi.cc sudoku_dancing_links.cc + g++ -O2 -o $@ $^ diff --git a/Lab1/src/Sudoku/dancing_link/src/main_multi.cc b/Lab1/src/Sudoku/dancing_link/src/main_multi.cc new file mode 100755 index 0000000000000000000000000000000000000000..82b0f65cd0d272b7cfaab69c96733ecc563470a0 --- /dev/null +++ b/Lab1/src/Sudoku/dancing_link/src/main_multi.cc @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sudoku_dancing_multi.h" +using namespace std; + +vector> puzzle_array; //所有线程共用的一个数组,存储从文件中读到的数独题目 +pthread_mutex_t array_mutex = PTHREAD_MUTEX_INITIALIZER; //访问puzzle_array和current_index的锁 +pthread_cond_t work_available_cond = PTHREAD_COND_INITIALIZER; +int current_index =0; //标记当前puzzle_array中数组题目取到第几个了 + +queue filenameRead_queue; //存储文件名 +pthread_mutex_t filenameRead_mutex = PTHREAD_MUTEX_INITIALIZER; //访问filenameRead_queue的锁 + +pthread_cond_t output_cond = PTHREAD_COND_INITIALIZER; +int head_index =0; + +int64_t now() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000 + tv.tv_usec; +} + +//输入文件名 +void* filenameRead_thread(void* arg){ + string filename; + while(true){ + cin>>filename; + pthread_mutex_lock(&filenameRead_mutex); + // printf("输入"); + filenameRead_queue.push(filename); + pthread_mutex_unlock(&filenameRead_mutex); + } + return nullptr; +} + +//读取文件:1.读取文件名;2.写入数独数组 +void* read_file_thread(void* arg){ + while(true){ + string filename; + pthread_mutex_lock(&filenameRead_mutex); + if(!filenameRead_queue.empty()){ + filename = filenameRead_queue.front(); + filenameRead_queue.pop(); + // printf("读取文件名"); + } + pthread_mutex_unlock(&filenameRead_mutex); + + if(!filename.empty()){ + FILE* fp = fopen(filename.c_str(), "r"); + if(fp !=NULL){ + // printf("读取文件"); + char puzzle[128]; + while (fgets(puzzle, sizeof(puzzle), fp) != NULL) { //读一行,一行为一道数独题目 + if (strlen(puzzle) >= N) { + pthread_mutex_lock(&array_mutex); + puzzle_array.emplace_back(string(puzzle), false); //数独题读到全局共享数组中 + pthread_cond_signal(&work_available_cond); + pthread_mutex_unlock(&array_mutex); + } + } + fclose(fp); + } + } + } + return nullptr; +} + +//调用具体解数独方法的线程函数:1.修改数组;2.唤醒输出线程; 3.被唤醒 +void* solve_puzzles(void* arg){ + bool (*solve)(int*) = reinterpret_cast(arg); + while(true){ + vector> local_puzzles; + int start_index; + pthread_mutex_lock(&array_mutex); + while(current_index >= puzzle_array.size()){ + pthread_cond_wait(&work_available_cond, &array_mutex); + } + // printf("读取数独"); + start_index = current_index; + for(int i = 0; i < 10 && current_index < puzzle_array.size(); ++i){ + local_puzzles.push_back(puzzle_array[current_index]); + ++current_index; + } + pthread_mutex_unlock(&array_mutex); + if(local_puzzles.empty()){ + break; + } + + int board[N]; + for(int i = 0; i < local_puzzles.size(); ++i){ + // printf("解数独"); + string& puzzle = local_puzzles[i].first; + if(puzzle.length() >= N){ + for (int i = 0; i < N; ++i) { + board[i] = puzzle[i] - '0'; // 字符 '0' ~ '9' 转换成整数 0 ~ 9 + } + if(solve(board)){ + string result; + for(int j = 0; j < N; ++j){ + result += to_string(board[j]); + } + local_puzzles[i]=make_pair(result,true); + }else{ + printf("No:%s\n",puzzle.c_str()); + } + + } + pthread_mutex_lock(&array_mutex); + for(int i=0;i threads(num_cores); + pthread_create(&filenameRead_tid, nullptr, filenameRead_thread, nullptr); //处理读文件名的线程 + pthread_create(&read_tid, nullptr, read_file_thread, nullptr); //通过文件名打开文件,读到数独题目 + pthread_create(&output_tid, nullptr, output_thread, nullptr); + for(int i = 0; i < num_cores; ++i){ + pthread_create(&threads[i], nullptr, solve_puzzles, reinterpret_cast(solve_sudoku_dancing_links)); + } + + for(int i = 0; i < num_cores; ++i){ + pthread_join(threads[i], nullptr); + } + pthread_join(filenameRead_tid, nullptr); + pthread_join(read_tid, nullptr); + pthread_join(output_tid, nullptr); + + return 0; +} + diff --git a/Lab1/src/Sudoku/dancing_link/src/sudoku_dancing_links.cc b/Lab1/src/Sudoku/dancing_link/src/sudoku_dancing_links.cc new file mode 100755 index 0000000000000000000000000000000000000000..17e9bac68a46ce48046090a5a4f64b60ae2160f0 --- /dev/null +++ b/Lab1/src/Sudoku/dancing_link/src/sudoku_dancing_links.cc @@ -0,0 +1,259 @@ +#include +#include +#include +#include + +#include "sudoku_dancing_multi.h" +using namespace std; + +struct Node; +typedef Node Column; +struct Node +{ + Node* left; + Node* right; + Node* up; + Node* down; + Column* col; + int name; + int size; +}; + +const int kMaxNodes = 1 + 81 * 4 + 9 * 9 * 9 * 4; +const int kMaxColumns = 400; +const int kRow = 100, kCol = 200, kBox = 300; + + +struct Dance +{ + Column* root_; + int* inout_; + Column* columns_[400]; + vector stack_; + Node nodes_[kMaxNodes]; + int cur_node_; + + Column* new_column(int n = 0) + { + assert(cur_node_ < kMaxNodes); + Column* c = &nodes_[cur_node_++]; + memset(c, 0, sizeof(Column)); + c->left = c; + c->right = c; + c->up = c; + c->down = c; + c->col = c; + c->name = n; + return c; + } + + void append_column(int n) + { + assert(columns_[n] == NULL); + + Column* c = new_column(n); + put_left(root_, c); + columns_[n] = c; + } + + Node* new_row(int col) + { + assert(columns_[col] != NULL); + assert(cur_node_ < kMaxNodes); + + Node* r = &nodes_[cur_node_++]; + + //Node* r = new Node; + memset(r, 0, sizeof(Node)); + r->left = r; + r->right = r; + r->up = r; + r->down = r; + r->name = col; + r->col = columns_[col]; + put_up(r->col, r); + return r; + } + + int get_row_col(int row, int val) + { + return kRow+row*10+val; + } + + int get_col_col(int col, int val) + { + return kCol+col*10+val; + } + + int get_box_col(int box, int val) + { + return kBox+box*10+val; + } + + Dance(int inout[81]) : inout_(inout), cur_node_(0) + { + stack_.reserve(100); + + root_ = new_column(); + root_->left = root_->right = root_; + memset(columns_, 0, sizeof(columns_)); + + bool rows[N][10] = {false}; + bool cols[N][10] = {false}; + bool boxes[N][10] = {false}; + + for (int i = 0; i < N; ++i) { + int row = i / 9; + int col = i % 9; + int box = row/3*3 + col/3; + int val = inout[i]; + rows[row][val] = true; + cols[col][val] = true; + boxes[box][val] = true; + } + + for (int i = 0; i < N; ++i) { + if (inout[i] == 0) { + append_column(i); + } + } + + for (int i = 0; i < 9; ++i) { + for (int v = 1; v < 10; ++v) { + if (!rows[i][v]) + append_column(get_row_col(i, v)); + if (!cols[i][v]) + append_column(get_col_col(i, v)); + if (!boxes[i][v]) + append_column(get_box_col(i, v)); + } + } + + for (int i = 0; i < N; ++i) { + if (inout[i] == 0) { + int row = i / 9; + int col = i % 9; + int box = row/3*3 + col/3; + //int val = inout[i]; + for (int v = 1; v < 10; ++v) { + if (!(rows[row][v] || cols[col][v] || boxes[box][v])) { + Node* n0 = new_row(i); + Node* nr = new_row(get_row_col(row, v)); + Node* nc = new_row(get_col_col(col, v)); + Node* nb = new_row(get_box_col(box, v)); + put_left(n0, nr); + put_left(n0, nc); + put_left(n0, nb); + } + } + } + } + } + + Column* get_min_column() + { + Column* c = root_->right; + int min_size = c->size; + if (min_size > 1) { + for (Column* cc = c->right; cc != root_; cc = cc->right) { + if (min_size > cc->size) { + c = cc; + min_size = cc->size; + if (min_size <= 1) + break; + } + } + } + return c; + } + + void cover(Column* c) + { + c->right->left = c->left; + c->left->right = c->right; + for (Node* row = c->down; row != c; row = row->down) { + for (Node* j = row->right; j != row; j = j->right) { + j->down->up = j->up; + j->up->down = j->down; + j->col->size--; + } + } + } + + void uncover(Column* c) + { + for (Node* row = c->up; row != c; row = row->up) { + for (Node* j = row->left; j != row; j = j->left) { + j->col->size++; + j->down->up = j; + j->up->down = j; + } + } + c->right->left = c; + c->left->right = c; + } + + bool solve() + { + if (root_->left == root_) { + for (size_t i = 0; i < stack_.size(); ++i) { + Node* n = stack_[i]; + int cell = -1; + int val = -1; + while (cell == -1 || val == -1) { + if (n->name < 100) + cell = n->name; + else + val = n->name % 10; + n = n->right; + } + + //assert(cell != -1 && val != -1); + inout_[cell] = val; + } + return true; + } + + Column* const col = get_min_column(); + cover(col); + for (Node* row = col->down; row != col; row = row->down) { + stack_.push_back(row); + for (Node* j = row->right; j != row; j = j->right) { + cover(j->col); + } + if (solve()) { + return true; + } + stack_.pop_back(); + for (Node* j = row->left; j != row; j = j->left) { + uncover(j->col); + } + } + uncover(col); + return false; + } + + void put_left(Column* old, Column* nnew) + { + nnew->left = old->left; + nnew->right = old; + old->left->right = nnew; + old->left = nnew; + } + + void put_up(Column* old, Node* nnew) + { + nnew->up = old->up; + nnew->down = old; + old->up->down = nnew; + old->up = nnew; + old->size++; + nnew->col = old; + } +}; + +bool solve_sudoku_dancing_links(int* board) +{ + Dance d(board); + return d.solve(); +} diff --git a/Lab1/src/Sudoku/dancing_link/src/sudoku_dancing_multi.h b/Lab1/src/Sudoku/dancing_link/src/sudoku_dancing_multi.h new file mode 100755 index 0000000000000000000000000000000000000000..9bead270ff1107bda54c2dc43a5c732a7c49d37c --- /dev/null +++ b/Lab1/src/Sudoku/dancing_link/src/sudoku_dancing_multi.h @@ -0,0 +1,11 @@ +//防止头文件被重复包含 +#ifndef SUDOKU_MULTI_H +#define SUDOKU_MULTI_H + +const bool DEBUG_MODE = false; +//数独棋盘大小 +const int N = 81; + +bool solve_sudoku_dancing_links(int* board); + +#endif diff --git a/Lab1/src/Sudoku/dancing_link/src/sudoku_solve b/Lab1/src/Sudoku/dancing_link/src/sudoku_solve new file mode 100755 index 0000000000000000000000000000000000000000..cf8aa9288d6f69c455a0734a95e9f0a0d1740d5c Binary files /dev/null and b/Lab1/src/Sudoku/dancing_link/src/sudoku_solve differ diff --git a/Lab1/src/Sudoku/dancing_link/src/test1 b/Lab1/src/Sudoku/dancing_link/src/test1 new file mode 100755 index 0000000000000000000000000000000000000000..8d81622c7655023d357717ba2b70a6bf7782b683 --- /dev/null +++ b/Lab1/src/Sudoku/dancing_link/src/test1 @@ -0,0 +1 @@ +000000010400000000020000000000050407008000300001090000300400200050100000000806000 diff --git a/Lab1/src/Sudoku/dancing_link/src/test1000 b/Lab1/src/Sudoku/dancing_link/src/test1000 new file mode 100755 index 0000000000000000000000000000000000000000..c21f3fbe3af7889bec248ef2ea3264c5896d8fd3 --- /dev/null +++ b/Lab1/src/Sudoku/dancing_link/src/test1000 @@ -0,0 +1,1000 @@ +000000010400000000020000000000050407008000300001090000300400200050100000000806000 +000000010400000000020000000000050604008000300001090000300400200050100000000807000 +000000012000035000000600070700000300000400800100000000000120000080000040050000600 +000000012003600000000007000410020000000500300700000600280000040000300500000000000 +000000012008030000000000040120500000000004700060000000507000300000620000000100000 +000000012040050000000009000070600400000100000000000050000087500601000300200000000 +000000012050400000000000030700600400001000000000080000920000800000510700000003000 +000000012300000060000040000900000500000001070020000000000350400001400800060000000 +000000012400090000000000050070200000600000400000108000018000000000030700502000000 +000000012500008000000700000600120000700000450000030000030000800000500700020000000 +000000012700060000000000050080200000600000400000109000019000000000030800502000000 +000000012800040000000000060090200000700000400000501000015000000000030900602000000 +000000012980000000000600000100700080402000000000300600070000300050040000000010000 +000000013000030080070000000000206000030000900000010000600500204000400700100000000 +000000013000200000000000080000760200008000400010000000200000750600340000000008000 +000000013000500070000802000000400900107000000000000200890000050040000600000010000 +000000013000700060000508000000400800106000000000000200740000050020000400000010000 +000000013000700060000509000000400900106000000000000200740000050080000400000010000 +000000013000800070000502000000400900107000000000000200890000050040000600000010000 +000000013020500000000000000103000070000802000004000000000340500670000200000010000 +000000013040000080200060000609000400000800000000300000030100500000040706000000000 +000000013040000080200060000906000400000800000000300000030100500000040706000000000 +000000013040000090200070000607000400000300000000900000030100500000060807000000000 +000000013040000090200070000706000400000300000000900000030100500000060807000000000 +000000013200800000300000070000200600001000000040000000000401500680000200000070000 +000000013400200000600000000000460500010000007200500000000031000000000420080000000 +000000013400800000200000070000400900001000000060000000000501600380000200000070000 +000000014000000203800050000000207000031000000000000650600000700000140000000300000 +000000014000020000500000000010804000700000500000100000000050730004200000030000600 +000000014000708000000000000104005000000200830600000000500040000030000700000090001 +000000014008005000020000000000020705100000000000000800070000530600140000000200000 +000000014008005000020000000000020805100000000000000700070000530600140000000200000 +000000014008009000020000000000020805100000000000000700070000930600140000000200000 +000000014700000000000500000090014000050000720000600000000900805600000900100000000 +000000014790000000000200000000003605001000000000000200060000730200140000000800000 +000000014970000000000200000000003605001000000000000200060000730200140000000800000 +000000015000400070300060000800000200000104000400500000000023600010000000070000000 +000000015000400070400000000609000300000100800000700000500030200000060040010000000 +000000015000800070300000000408000300000100400000700000500040200000090060010000000 +000000015000800070400000000609000300000100800000700000500030200000060040010000000 +000000015000830000000000200023000800000001000080000000105040000000600720900000000 +000000015000830000000000200026000800000001000080000000105040000000300720900000000 +000000015000900070400000000608000300000100800000700000500030200000060040010000000 +000000015000900070400000000609000300000100800000700000500030200000060040010000000 +000000015000900080300000000704000300000100400000800000500040200000070060010000000 +000000015000900080400000000704000300000100900000800000500030200000070060010000000 +000000015020060000000000408003000900000100000000008000150400000000070300800000060 +000000015040080000000000300000040260500107000900000000300500000080000400000900000 +000000015300600000000000080600050200000001000000000040010200700000760300008000000 +000000015790000000000200000000008706001000000000000900070000830400150000000300000 +000000016000500040300070000900000200000408000700600000000023700040000000010000000 +000000016000708000000000050501200000300000800600000000040000200000053000080010000 +000000016000900080500000000405000300000100500000800000600040200000030070010000000 +000000016040005000000020000000600430200010000300000500000003700100800000002000000 +000000016070000040050200000400060300000005200000041000000900780100000000000000000 +000000016070000040050200000400060300000008200000041000000500790100000000000000000 +000000016200000000000300000601700002000900500400000000030000800000060040050040000 +000000016200080000009000000000420500010000000000000200000106030500000780000900000 +000000017090600000000000030400500200001000000000080000720000600000410500000003000 +000000017090600000000000050200000803000050400000001000600200300041070000000000000 +000000017090800000000000040007060300050000200000001000600300800401000000000050000 +000000017300080000000000000007100006000040300085000000200000840010700000000500000 +000000017600020000000000000153000000000080200007000000400301500020000600000700000 +000000018020500000000000000040000700600000500000041000000700260108300000400000000 +000000018050600000000000030400500200001000000000090000820000600000410700000003000 +000000018200400000000000070000008003000500200010000000502000600000040300000017000 +000000018320000000400000000008051000040000300000070000706000090000300700000200000 +000000018700040000000000030420000700000001000000300000500070200601800000040000000 +000000019000250000000000000091000030000400700030000000400000208200060500000001000 +000000019030050000000000020109000000000400700000870000000102000060000800500000300 +000000019030050000000000020109000000000400800000870000000102000060000700500000300 +000000019070000030200800000050600200001000000000200000000019500600000400000030000 +000000019300600000000000000600080500040000300000010000480000070000200400010900000 +000000019500600000000000000600080500040000300000010000380000040000200700010900000 +000000019500600000000000000600080500040000300000010000480000070000200400010900000 +000000019500800000000000000300070500040000300000010000470000060000200400010900000 +000000019800500000000000000300070500040000300000010000470000060000200400010900000 +000000021000030070040080000100207000050000400000000003200100000000040500000600000 +000000021000083000000040000500200070080000400030900000000060800100500000200000000 +000000021000083000000040000500200070080000400030900000000060800100700000200000000 +000000021000306000000800000400010600000700300200000000000090040530000000086000000 +000000021000407000000008000031060000000000750020000000500210000400000800000300000 +000000021000500030400600000000021000800000007500000600000400800010070000030000000 +000000021004090000070000030100203000500800000006000000200000600000060400030000000 +000000021005080000600000000000670300120000500400000000000201040003000000080000000 +000000021006800000000000070070021000020000400000005000500430600100000000000600000 +000000021030400000700000000100082000000000540000000000000560300290000000004700000 +000000021030600000000080000201000050500400000000370000700002000080000300000000600 +000000021040500000700000000100082000000000650000000000000610400320000000005700000 +000000021040500000800000000700092000000000650000000000000610400320000000005800000 +000000021040600000000000000201000050500800000000400300700020000060000800000300400 +000000021050030000000800000102000070700300000000540000600002000030000400000000500 +000000021060300000000708000100050040070000300000020000200040000000600800500000000 +000000021060500000000090000400002000070000300000600000102400000000030640800000000 +000000021060700000000000000402000000000600300500000700000340050080000600100002000 +000000021070030000000040000100205040030000800000100000200600000000070300600000000 +000000021070030000000090000100205040030000800000100000200600000000070300600000000 +000000021070300000000000000402000000000700300600000800000540060090000500100002000 +000000021070300000000408000100060050030000400000020000200050000000700800600000000 +000000021080300000000409000100060050030000400000020000200070000000800900500000000 +000000021090300000000000000402000000000700300600000700000540060080000500100002000 +000000021090300000000060000201000050500400000000970000600002000080000300000000900 +000000021090700000000000000000514000630000000000002000000600930001040000200000800 +000000021300050000000000000500630000010000080000000500704000600600200000000108000 +000000021300050000000000000500630000010000080000000900704000600600200000000108000 +000000021300050000000000000500830000010000090000000500704000600600200000000109000 +000000021300090000000000000500630000010000080000000500704000600600200000000108000 +000000021300090000000000000500630000010000080000000900704000600600200000000108000 +000000021300700000000000000060500300020000070000000800100040700500012000000006000 +000000021300800000000000000060500700020000040000000300100040800500012000000006000 +000000021300900000000000070200000400000060300000001000071040000000200508090000000 +000000021400300000000000000000010600080000300020007000600000470500120000000800000 +000000021400600000000000000000012800609000000000030000510000030000709600020000000 +000000021400600000000000000000012900706000000000030000510000030000807600020000000 +000000021430000000600000000201500000000006370000000000068000400000230000000070000 +000000021500040000000000070000300600000020500010000000600000203003107000000008000 +000000021500040000000600000031000080000070000020000000600300400405000700000200000 +000000021500400000000000000300000570600080000000010000010605000082000000000007400 +000000021500400000000800000021500000070000600000000030400000800300070000006020000 +000000021503000000600000000000104060700000500000200000000480300010070000200000000 +000000021600000030070900000000043700100000000000020000000600008002100000040000500 +000000021700060000490000000000070900003800000020000000960000800000302000000100000 +000000021700600000300500000000082000040010000500000000020040000000300700000000650 +000000021750000000000000000070000890000201000000400000030090500100030000400000600 +000000021800040000000000060090200000700000400000501000015000000000030900602000000 +000000021800400000009000000600570040300000800000020000070900400021000000000000000 +000000021800500000000060000030102000500000840000000000000780500620000000004000000 +000000021800600000000050000030102000500000840000000000000780500620000000004000000 +000000021800700000400005000023000060000800500010000000600000700000081000000030000 +000000023000500080000100000020000900000400100580000000600009500000020070001000000 +000000023000800010800400000032500000000000100070000000600070004100000500000003000 +000000023010040000500000000100000400000200080000803000000050160040000700003000000 +000000023010040000500000000100000400000200080000903000000050160040000700003000000 +000000023010040000500000000100000400000600090000203000000050170040000800003000000 +000000023010800000000000060300020000050000700000400000000507100002010000600000400 +000000023080000070400020000030002000000000401000060500100000600000807000000300000 +000000023080000070500090000030002000000000401000060500100000600000807000000300000 +000000023300010000000500060400000700000106000000200000092000100000040800060000000 +000000023400800000100000900050032000000000400000060000000401800030000050000900000 +000000023400800000100000900050032000000000400000070000000401800030000060000900000 +000000023480000000010000000503000060000010800000000000170000400000602000000300005 +000000023600010000000400000000080700502000000000000100080203000010000640000500000 +000000023600700000000000080000038500200000800000010000000200640003400000010000000 +000000023800000050000100000010600400507030000000000000300052000064000100000000000 +000000024000010000000000080107000900300800100000200000020400060500070300000000000 +000000024000010000000000080307000100100800500000200000020400060500070300000000000 +000000024000080010600005000000300700040700000010000000000040501300600000200000000 +000000024007000000006000000500090100000300600020000000940000050000607300000800000 +000000024010008000000070000600201500400000003000000000070000810500430000000000000 +000000024010300000060000000050000300000082000700000000400100500200000063008000000 +000000024010300000070000000060000300000029000800000000400100600200000075009000000 +000000024010300000070000000060000300000082000500000000400100600200000075008000000 +000000024100000000000600000000180700020000009030500000500070600004002000000000030 +000000024100000000000700000000560800020000009030100000600080700004002000000000030 +000000024100800000000000003000400500700000100000030000000510600002000050030007000 +000000024600800000100000000000040010070000300040600000520004000000000806000070000 +000000024700000060000900000004001000020050000000030700000400800300000500600200000 +000000024900700000000000000800000730000041000000000000002500800046000300010020000 +000000025000000070800000000600000103000070400000020000053100000020005000000600300 +000000025000800010400000000050000700000300600010000000600020400800007000000015000 +000000025000800010900000000050000700000300900010000000600020400800007000000015000 +000000025030006000000090000000740000600500000020000700000208300504000000000000100 +000000025050000040000100000207000000300000070000800600089000100000002700000040000 +000000025080000600000001000300400700000050008000000000000280400107000030000500000 +000000025190000000000600000006030700000000100002000000400205000060000340000800000 +000000026000080040000500000100600700300000080000020000000703100042000000000000500 +000000026000080040000500000100600700300000080000020000000903100042000000000000500 +000000026040700000000000001000900800400000500001000000000012050070000300300060000 +000000026080003000000070000100400800605200000007000300030000900000050000000600000 +000000026501000000000000000070206000300000150000800000020700000000000540000010300 +000000026800500000000000704300070100000040000000000030000300810040900000060000000 +000000026800700000000000005700030100000006500000020000026400000000000810030000000 +000000027000051000000000600504000100000200000300000000020740000060000039000000500 +000000027010900000500000060000300400600000050000000008049000100000026000000000300 +000000027010900000500000060000300400600000050000000008094000100000026000000000300 +000000027040800000000000001000400900600000500001000000000012050080000300300070000 +000000027300000040100000000000605100000100500040000000070020030008000600000040000 +000000027300000040100000000000605100000100500040000000070040030008000600000020000 +000000028000050000000040000708200000040000300000600000600801000030000450000000900 +000000028000070040000300000074000050000600300000001000630000100200040000000000600 +000000028000500060010000000506020000400000300000000100000100700000403000680000000 +000000028000800030100000000000070400080600000035000000700060100000000705000300000 +000000028030000050600000000100050604000062000000000700028000000000700300000100000 +000000028070009000000000003000302000040000500000000000800050100000040760300600000 +000000028300000070000100000000080030049000000050000600000604100000500400200000000 +000000029000306000000000008060000500053000000000020000000600150200070400900000000 +000000029000600070010000000507020000400000300000000100000100800000403000790000000 +000000029000730000000050080000600700082000000000000100400100600000002050100000000 +000000029000730000000400060203000400000100300600000000080050100000002000010000000 +000000029000730000000400060208000300000100500600000000070050100000002000010000000 +000000029000830000000400070203000600000100300700000000040050100000002000010000000 +000000029000830000000400070203000600000100300700000000080050100000002000010000000 +000000029300600000000080070800000600000021000000000100029000000000800030000400500 +000000029300700000000800040600000700000042000000000100049000000000010050000300600 +000000031000079000000000000013200000004000700000100000500040670280000000000300000 +000000031000407000000600000600300000407000000500080000030010000020000700000000450 +000000031000602000000700000007000600010080000400030000000500270140000000800000000 +000000031004020000080000000100300000000008200600000000020000740300510000000600000 +000000031004020000080000000600300000000008200100000000020000740300510000000600000 +000000031004020000090000000700300000000008200100000000050000840300610000000700000 +000000031005020000080000000700300000000008400100000000040000250300610000000700000 +000000031007020000080000000100300000000008200600000000020000740300510000000600000 +000000031007020000080000000600300000000008200100000000020000740300510000000600000 +000000031007020000080000000600300000000008200100000000040000720300510000000600000 +000000031008020000070000000600300000000008200100000000020000740300510000000600000 +000000031008020000090000000600300000000009200100000000040000720300510000000600000 +000000031008020000090000000700300000000009400100000000050000240300610000000700000 +000000031020500000000000000301070000000400200700000500070200600800010000000000080 +000000031020700000008500000000016200400030000050000000300000050000200700000040000 +000000031028000000000000000000208400730000060000500000160070000000400200300000000 +000000031040060000000009000060005200000300070500000000308100000000020400000000700 +000000031050060000000007000070004600000300050600000000403100000000020500000000800 +000000031050070000000009000070006400000300050600000000403100000000020500000000800 +000000031050080000000000000600307000040000500000100020100000800000050400003200000 +000000031060040000000000000002801400500300010000007000000050600730000000100000000 +000000031060200000000708000300050040070000200000010000100040000000600800500000000 +000000031060400000000000000500037000090000200000001000700840000000600490100000000 +000000031060500000000020000000460500300007000800000000000700080100003000020000600 +000000031080000070000920000401000000000200800300000000090000250000080600000001000 +000000031080040000070000000106300070300000000000080000540000800000600200000100000 +000000031080400000600000000000200840700600000100000000500073000090000200000010000 +000000031080600000000070000000700290500400000300000000020050800000031000400000000 +000000031200040000000000000031700080000020500400000000000803000500000200000100600 +000000031200070000000009000000301040600400000708000000000060200030500000000000700 +000000031200080000000400000031005060000720800000000000000603000400000200700000000 +000000031200700000400000000038000060000400300010000000000514000700000200000080000 +000000031280000000000000000003610000000004270000000000420000800500070400000300000 +000000031280000000500100000000037800600000200000040000030000040100500000000600000 +000000031400020000000007000000301050700500000206000000000080200030600000000000400 +000000031400020000000009000000301050600500000208000000000070200030600000000000400 +000000031400020000000009000000301050700500000204000000000080200030600000000000400 +000000031400020000000009000000301050700500000206000000000080200030600000000000400 +000000031400020000010500000000300060200006000800000000000700800060000200039000000 +000000031400070000208000000700000200000300000000900000630000090000580400000020000 +000000031500070000000006000700000560001400000020000700600000800030100000000200000 +000000031600008000000050000000370020580000000060000000200000600007100000000400800 +000000031600020000000070000050108000200000600000300070000040200030500000700000000 +000000031600200000000090000000080290310000000400000000049000500000603000000700000 +000000031600800000000000000030000850020010000000400000804000600006030000700005000 +000000031700020000000006000040100050030080000000000200600400900200005000000300000 +000000031700200000000480000000700800030000000060000000000039060520000400800000000 +000000031700200000040000000502700060000800700030000000000093000200000500000010000 +000000031740000000000000009000003460200000500000090000000570800030800000001000000 +000000031800020000200000000037100060010080500000000000500400800060300000000000000 +000000031800060000000000000600000470000100600500200000023500000000070800010000000 +000000031800900000000000040400000800000060200000001000031050000000200407090000000 +000000032000100000050000000040000800000310000000602000300000760000080500802000000 +000000032000100000060000000803000000000600900000007500000580070040000100200030000 +000000032010000000000300000309700000000060100800000400200000080000540000000016000 +000000032010040000000000000000307020084000000600000000000080104700100500300000000 +000000032010040000000000000000703020084000000600000000000080104700100500300000000 +000000032040000000900000000302700050000100800600000000070000100080060000000030006 +000000032480000000010000000503000060000010800000000000170000400000602000000300005 +000000034000100000000000060070000200005003000040050000000740100300000800600200000 +000000034000100007800000090980000200600040000000700000000009800007030000010000000 +000000034060200000000000070000960800301000000700800000070003000900000200000010000 +000000034080100000000000060000039000000040800001000000360200000400000700000700500 +000000034100000000000000050020050700043000000000010000900600800000400100000302000 +000000034500000010000070000405310000000000200100000000000600700087000000020400000 +000000034500900000000000000004700100060000200038000000200000507000036040000000000 +000000034600900000000000000004700100050000200038000000200000607000043050000000000 +000000034700005000000000010000087200000020500010000000200300060001400000000000900 +000000034800600000000100000605000100000040070200090000043000000000000201090000000 +000000035000020070000010000000240000800000600100000000020507000000300800070000100 +000000035040000080100000000007000200000085000600000000000400106030100700008000000 +000000035200100000080000000040000700000200040005003000300070006000040200000000100 +000000035490000000010000000603000070000010900000000000180000400000502000000300006 +000000036000000020800000000700000104000030500000020000064100000030006000000700400 +000000036000500040000700000000200705108000000600000000340060000050000200000010000 +000000036000500040000700000000200705108000000600000000340060000070000200000010000 +000000036007100000000040050405003000000700200000000100010200800300000000090000000 +000000036030000050200000000000060800700000400000053000000700210060900000001000000 +000000036040200000010000000000004019008000200600030000700050000000100800300000000 +000000036200030000500000001400070200010000000000000080308000400000501000000600000 +000000036200030000500000001700080200010000000000000080309000400000501000000600000 +000000036800010000000020000030602000000000190000500800100000900060000070000300000 +000000036800700000000000090090000001060000020000500400000039000004000800700000500 +000000036840000000000000020000203000010000700000600400000410050003000200600000000 +000000036900040000000000010000103000200000400000600050007500200000060800010000000 +000000037002000050010000000000200104000001600300400000700063000000000200000080000 +000000037004600000000000010078000200000007500000010000310000020000800600400000000 +000000037040600000000000010096000200000005800000010000107000050000400600300000000 +000000037060000040500000000100040502000083000000000600037000000000500100000200000 +000000037400200000000000000107000040000800200300500000000031000080000500060000400 +000000037500000040090000000000510200003000900060000000200000160000703000000800000 +000000037900040000000000010000103000200000400000700060006500200000070800010000000 +000000038000000710900400000000017000600000900000003000000650200003000060010000000 +000000038000009001000500020000460500800200000100000000040000600000021000700000000 +000000038000020000000090000800000200000600100007300000000701060290000500040000000 +000000038060020000007000050500400000000060700000000100100508000040000600000300000 +000000038090200000000000510740000600000003070000010000005600200003000000100000000 +000000038200050000000400010800000600000001000000200000041000500000620700030000000 +000000038200400000000070010800000500000001000000200000071000400000520600030000000 +000000038600001000000000050100200700800000004000750000025030000000000100030000000 +000000038700040000000000010000108000200000600000300040006500200000060700010000000 +000000039000070080000140000600000500200600000000003070000200600083000000000000100 +000000039000140000000060080000500200083000000000000100500200700000003060200000000 +000000039000140000000080070000500200037000000000000100500200600000003040200000000 +000000039000140000000080070000600200037000000000000100500200600000003040600000000 +000000039000600040800100000500000600000020070000004000000280700043000000000000100 +000000039000740000000050080000600700083000000000000100100200600000003050200000000 +000000039000740000000050080000600700083000000000000100100200600000003050600000000 +000000039500070000000000010000503000400000200000600000003000860000240700010000000 +000000039700400000003000010480000200000030700000001000040600500000000020000090000 +000000039700400000003000010680000200000030700000001000040600500000000020000090000 +000000039700400000003000010840000200000030700000001000080600500000000020000090000 +000000041000062000000000000000710030602000500500000000310400000000008200040000000 +000000041000700000300000000000045060700000300020010000000800200045000000601000000 +000000041000700000300000000000045060700000800020010000000900200045000000601000000 +000000041005080000600000000000670200410000500300000000000104030002000000080000000 +000000041007300000000000520000800300420000000500000007060004200000010000008000000 +000000041009300000000000520000800300420000000500000007060004200000010000008000000 +000000041020000050800000000000280700060030000001000000300000807000501600000000000 +000000041020060000800070000300400600000002000000100000000030700010500000005000030 +000000041020500000000000000000084060570000000000000200000120300804000000600700000 +000000041020500000000000000000094070580000000000000200000620300904000000700800000 +000000041020700000000000000400013000070000200600000000000270500103000060000800000 +000000041050080000000000000600107000030000500000400020400000800000050300001600000 +000000041050800000090000000000007020000041000000000503700260800100000000000300000 +000000041050900000070000000000008020000041000000000503800760900100000000000300000 +000000041060800000000300000200054070080000000000001000000630800700000200400000000 +000000041060900000070000000000008020000041000000000305800720600100000000000300000 +000000041070060000030000000400201050060000700000800000000050300100400000200000000 +000000041070200000000308000400060050020000300000010000100050000000700800600000000 +000000041080030000200000000500060700002000300400008000000500020010400000000000800 +000000041080070000030000000600201050070000800000900000000050300100400000200000000 +000000041090700000000080000000800290600500000400000000030060900000041000500000000 +000000041200500000000007000500000200000040600000036000034000000010000030000800500 +000000041200600000530000000700080300000041000000000060008300000000500200040000000 +000000041200700000000000006000300800090000500060040000700000230300060000000001000 +000000041300020000000500000015000000000070600080000000600000370200104000000800000 +000000041320000000500000000600300200004000080000500000200000300000081000000740000 +000000041500020000000800000018000000000030600090000000600000350700104000000900000 +000000041500300000200000000000260300010000060700500000080041000000080200000000000 +000000041500900000070600000000350600402000000800000000000040080090000300030000000 +000000041520000000000030000000070530100800000400000000600105000030000200000400000 +000000041600000000000800000500600200040000070000300000000071600002000300070040000 +000000041600300000000020000040100080000506000700000000300000500000070300010004000 +000000041630000000000800000010000070070030000000020500500104000200000600000700000 +000000041700050000200000000000801030650000700000400000081600000000020900000000000 +000000041700090000200000000030104000040200000008000500100050600000000080000000700 +000000041700600000200500000000081000030040000500000000010030000000200700000000650 +000000041800020000000000000040509000007000200000000800600000390200410000000700000 +000000041800050000200000000000701030650000200000400000071600000000080900000000000 +000000041800500000000000000200000860070140000000030000600008200000300500040000000 +000000041900300000000000000300200800000010060200000000067040000010050000000800200 +000000041900300000000000000300200900000010060200000000067040000010050000000800300 +000000041900500000000000000200000960080140000000030000600009700000300500040000000 +000000041900600000000200000000810300540000000002000000031040000700000600000000020 +000000041900700000000000000200000960080140000000030000600009700000300500040000000 +000000042000500080000001000000900300200000100400080000090060050010000700000800000 +000000042100700000000000080600300500040000020000100000000060105090040000000000300 +000000042100800000000000070600300500070000020000100000000060105090040000000000300 +000000042500090000000000000006100700000030800024000000390000000000004006000200050 +000000042600900000000000030500000800007600000020040000000508100034000000000000700 +000000042650000000000800000100000600000045000700002000000100780002030000040000000 +000000043000015000000200000000420000050000600000900000000008170403000000200000800 +000000043000015000000200000000420000090000500000800000000007160403000000200000700 +000000043000080050000001000700500600000304000100000000040200000000070100030000900 +000000043000800070000020000060500800000304000001000000370000200000010900400000000 +000000043010050000000000000000408030095000000700000000000090105800200600400000000 +000000043010050000000000000000804030095000000700000000000090105800200600400000000 +000000043050200000080009000060000800100030000000000000307510000000800200400000000 +000000043100200000000000000000600700030000200005080000270100000000030065900000000 +000000043200700000000000080600200500040000030000100000000060205090040000000000100 +000000043200800000000000070600200500070000030000100000000060205090040000000000100 +000000043500080000000000010000370500010000000000000200000104020005700000800000600 +000000043800050000000000010007600200000080700010000000000104020600000500000300000 +000000045000800020100000000005620000700000004000000700086000100000045000030000000 +000000045700200000000100000106000200000050060300080000054000000000000302080000000 +000000045800200000000100000106000200000050070300090000054000000000000302090000000 +000000046000070010060020000108000000000500300400000500030000200000108000000400000 +000000046000500010500000000709000300000100800000400000600030200000070050010000000 +000000046000500010500000000709000300000100800000400000600030200000090050010000000 +000000046000800010500000000709000300000100800000400000600030200000070050010000000 +000000046000800010500000000709000300000100800000400000600030200000090050010000000 +000000046005800000000000020160000300000300500020000000000267000309000000000040000 +000000046020000300001000000000001730600000008000000000030000210400680000000500000 +000000046020000700001000000000001830600000009000000000080000210400690000000500000 +000000046050010000000000000000408030017000000600000000000070102300200500400000000 +000000046100000000000000080000130200084005000000700000060084000300000100000200000 +000000046700010000000030000040603000000000190000800700100000900020000080000400000 +000000047010050000000000000000408030065000000700000000000060102300200500400000000 +000000047300500000000000010709000600000010000000000200000200705041008000030000000 +000000048600200000000700010000040060500000300002001000000350700010000000000000200 +000000049000050060000030000400900000700800000000000300503000100060000200000702000 +000000049700200000000800010000040070500000300002001000000360800010000000000000200 +000000051000036000000000000040500080200000600000001000000020340010400700600000000 +000000051000083000000040000600500020080000400030900000000070800500600000200000000 +000000051000203000000400000050080060094000000000000300302000600700000200000050000 +000000051000307000000008000021060000000000740050000000400150000300000800000200000 +000000051000307000000800000500010700000600300200000000000090020430000000087000000 +000000051000308000000100000090050040020000100000000000601700800400020000500000000 +000000051000308000000100000090050060020000100000000000601700800400020000500000000 +000000051000309000000100000080050040020000100000000000601700300400020000500000000 +000000051000309000000100000080050060020000100000000000601700300400020000500000000 +000000051000402000800070000200600400700000030000500000000030200016000000050000000 +000000051000402000800070000200600400700000080000500000000030200016000000050000000 +000000051000702000000400000050080030084000000000000700302000600700000200000050000 +000000051020060000700040000640000300000105080200000000001800000300000600000000000 +000000051020070000000000000000145000040000890000300000109500000000060200300000000 +000000051020400000000000000000390200500080000000000400040600700100050080000200000 +000000051020600000000000000000300780400900000100000000070005200600010000000040600 +000000051020600000000000000070000200300050000000040800501000030400008000000200600 +000000051030800000000000000000400830100700000200000000040006300700020000000010900 +000000051040006000000300000105030000000000820700000000620000400000750000000100000 +000000051040700000000000000000013700500020000060000400000600840100800000200000000 +000000051040700000000000000090000700000051000000060030000406200300000800506000000 +000000051040900000000300080107050000030000200000000000000209300605000000800000000 +000000051060007000000030000000006200700000030500100000014000600000850700000000000 +000000051060007000000030000000006200700000030500100000024000600000850700000000000 +000000051060020000000000000000145000040000780000300000108500000000060200300000000 +000000051060020000100700000000500030020030000040000000300000200000800400509000000 +000000051060400000000000000000380600500070000000000400040600300100050070000200000 +000000051060400000000000000000390600500080000000000400040600700100050080000200000 +000000051070030000800000000000501040030000600000800000500420000001000300000000700 +000000051080200000000000000930000800000014000000500000401000070000600200000380000 +000000051080400000000000000000031009507000000040000000000700460100200000300000800 +000000051090030000000000000070400620000501000000800000000070300504000000200000400 +000000051090700000000000000000400930100500000200000000080006300700010000000020700 +000000051200030000000000000000070620050400000000000300004501000600000830000700000 +000000051200060000000000000000080720050400000000000600004501000600000230000800000 +000000051200080000040030000017200000000000630000000400000507000600000300000100000 +000000051200600000000800000071050000040300200000000600000010040600000300800000000 +000000051200600000000800000071050000040300600000000200000010040600000300800000000 +000000051200800000400000000010057000300000200000060400057000060000200300000000000 +000000051260000000008600000000071020040050000000000300000300400500900000700000000 +000000051300020000000800000042000000000090600010000000600000390700501000000400000 +000000051300040000200000000056100000070600000000030800010500060400000300000000000 +000000051400030000000800000250100000300000740000006000000040300060007000010000000 +000000051400070000200000000037006400008000000000500000000020780510300000000000000 +000000051400200000000000000000406200050300000070000000000075030608000400000010000 +000000051400800000200000000010057000300000200000060400057000060000200300000000000 +000000051460000000080000000000050670001020000300000000050000400200300000000109000 +000000051600003000090040000012500000000007900400000000500000780000020000000100000 +000000051600030000000000000000504090802600000000001000000020800700000300050100000 +000000051600200000000000000000406200050300000070000000000075030408000600000010000 +000000051700200000003000000004058000000010600600000200010000080260000000000300000 +000000051700200000800000000054010030010030000000000200200700600030000000000000700 +000000051800020000300000000017600000000030200050000090400700800060500000000000000 +000000051800070000300000000040080700000400000005000000006501000030000870000000200 +000000051800070000300000000040080700000600000005000000006501000030000870000000200 +000000051800200000000000000040070300000051000090000000000309200507000060100000000 +000000051800200000400000000010095000000000840030000000000760300250000000000800000 +000000051800300000000000000520010000300000790000006000067000400000400300010000000 +000000051800700000300600000000012000090050000600000000010040000000300800000000760 +000000051803000000000000000250400000010000700000020300000506040007000200000100000 +000000051900200000000000000451060000000400380000000000240000700000003200000050000 +000000052000700040100000000010600000000030800024000000000200100000405000300000600 +000000052000700040100000000010600000000030800042000000000200100000405000300000600 +000000052003400000070000000030005600000020010000081000200000008000600700100000000 +000000052005400000070000000030005600000020010000081000200000008000600700100000000 +000000052009400000070000000030005600000020010000081000200000008000600700100000000 +000000052400060000000000010070200000600000400000108000018000000000030700502000000 +000000053000008010300400000000015020700000400006000000000720600010000000000000200 +000000053000400006080000000506000700000010400300000020010000200000305000000700000 +000000053160000000000000000400000607000305000000800000000024100003000020070010000 +000000053600700000000000020000039500200000800000010000000200640003400000010000000 +000000053700600000000000040024000000008050000000300000010040200600007000300000600 +000000053800060000000000070000200800000705000100000000072003000000610400050000000 +000000054000803000000000000105040000000200930600000000500007000000010002030000800 +000000054010700000200000000000056000030000700080000000600100300004000072500000000 +000000054010900000200000000000056000030000900070000000600100700004000082500000000 +000000054070300000200000000010000700000045000000208000000670100800000300500000000 +000000054100300000000000000000700300040000200006080000320100000000040076900000000 +000000054200070000000010000060000730005400000000000000710000200800300000000500009 +000000054300020000000000010003700200000080600010000000000105030600000800000400000 +000000054300800000000000010041000060030008000000900700905000800000010000000000200 +000000054700020000000010000060000730005400000000000000170000200200300000000500008 +000000054700030000000000000000400016380070000020000000000500800105000000006000300 +000000054900700000000000060006052000800000300000000700020300100040070000005000000 +000000056003800000400000000000062000000000410000000300000450100060100000720000000 +000000056080010000002000030000203000300600000010000900600700000000080400000000100 +000000057000040000000000003000307060800500400100000000000080100070000200030600000 +000000057000080010070020000301000000000600400500000600040000200000103000000500000 +000000059000130000000000000340000020050009000000800600800000307000054000000000100 +000000059700600000000300000059001000020040000000000130807000300000050000400000000 +000000061000027000000000000704000200000100040300000000510000700000048000090600000 +000000061000203000000700000005060400000002300100000000000540080320000000700000000 +000000061000320000500000000230000700000801040900000000001604000000030200000000000 +000000061000400080300000000000020540010000000800000000700800300005000200000603000 +000000061000704000000000000500400700602000050100000000000016000080020000030000900 +000000061000704000000000000500800700602000050100000000000016000090020000030000800 +000000061000800000400000000000300780160500000200000000030060000000020400080000300 +000000061000904000000000000500400700602000050100000000000016000080020000030000900 +000000061000904000000000000500700400102000050600000000000061000080020000030000700 +000000061000904000000000000500700400602000050100000000000016000080020000030000700 +000000061005700000020000000000430500100060000980000000600008010000500700000000000 +000000061009800000000000000004020500030000800000006000000700430160300000200000000 +000000061020500000000000000100064000050000200800000000000250300601000040000700000 +000000061030200000000000000106050040000700300500000000400300200080000700000010000 +000000061030400000000000000600300780105000000000900000200010000040000300000050400 +000000061040050000000007000070003500000100040500000000301600000000020800000000400 +000000061040300000000500090108060000030000200000000000000205300706000000900000000 +000000061040300000000500090108060000050000200000000000000205300706000000900000000 +000000061043000000000000000020008300600070050100000000700160000008000400000500000 +000000061050020000000000000000000250600400000000070300020000530400601000000800000 +000000061050030000000000000000000250600400000000050300020000730400601000000800000 +000000061050030000000000000680040700200600000000000500900106000000000380000200000 +000000061050090000000000000200000070000080500601000000000700320090000400000602000 +000000061050700000200009000000800300401000000600000000000060080030040000020000700 +000000061070005000400030000300000200000100070000800000001600000000070400500000300 +000000061070040000000000000102006000000080300500000000030000740600501000000200000 +000000061070500000000000000900460000050000200000000700601000030300200000000708000 +000000061070500000000400000603050000000200100000000040200006000000039000010000800 +000000061070800000500090000000600300302000000400000000000030040010002000060000900 +000000061200030000000000000000070240060500000000000300005601000300000820000700000 +000000061200030000400000000020801000500600700000000040081000000000070400003000000 +000000061200300000000000000000160000020040000800000300060000740000800200003500000 +000000061200500000800000000000200700037000000060400000100000200000038000000060040 +000000061200500000800000000000200700037000000060400000100000200000068000000030040 +000000061200700000000800000013060000050400200000000700000010050700000400800000000 +000000061200700000000800000013060000050400700000000200000010050700000400800000000 +000000061200800000000000000000402800063000000000700000000036200410000000000010050 +000000061300020000000700000017000000000080500090000000500000380600401000000900000 +000000061300700000090400000710080000000300400000000020000062000500000900000010000 +000000061300800000000000000500000400000014000000070800010620000000500390007000000 +000000061350000000400050000020000800000601000000700000000080200600400000007000010 +000000061400003000000700000010690000020000300000000000304000200000180050700000000 +000000061400030000000500000026000080000070000010000000500200300304000700000100000 +000000061400070000000090000000608200901000000200100000000050400060300000000000090 +000000061400070000020000000061500000000030740500000000005108000700000400000000000 +000000061400200000900000000067015030010070000000000400200800500030000000000000000 +000000061402000000030000000380000400000602000000100000006500000100000070000080300 +000000061403000000020000000308000400000602000000100000060500000100000070000080300 +000000061480000000000000000000520400000030000060000000530006070200000800000107000 +000000061500020000970000000061400000000050900000000080000806000300000500000700000 +000000061700020000000000000060530000010000200000000400000107030208000000400300000 +000000061700400000800000000000720400300000000000010000009800700010000500060000020 +000000061800007000000020000032100000000650800000000000000003720910400000000000000 +000000061890000000000000000000520400000030000060000000530006070200000800000107000 +000000061890000000000000000000520400000030000060000000530006070200000900000107000 +000000061900200000000400000070068030200000700000010000006050000000900200040000000 +000000062800300000000000050040200100060000040000000700001056000700000300000040000 +000000063000100000200000000050000100000400200009006000630090000000200740008000000 +000000063000500004080000000603000700000010500400000020010000200000406000000700000 +000000063020040000000001000040000210000370000000500400503600000000000700800000000 +000000063020040000000001000040000210000370000000500400803600000000000700500000000 +000000063800090000000000010005020400010000000000000200200600500000103070000400000 +000000064005800000000000020160000300000300500020000000000267000309000000000040000 +000000064300800000000000010041000070050008000000900500906000800000010000000000200 +000000064500080000000000010000305700010000040000070000708000200000600800000100000 +000000065000300000000010000000040170509000000000000800270500000010000300000906000 +000000065000710000040000000000053000080000200000000100003200700506000000100800000 +000000065040800000000000001006000800030000700000010000000700230400002000501000000 +000000065900200000000000000000900240053000000000000000060057000100006800000030900 +000000067003900000010000004600004000050010000000000100000800520007000300400000000 +000000067060200000000000040000860300401000000700900000070004000900000200000010000 +000000068030070000100000020070000450000208000000400000000030100200600000000000900 +000000068030070000400000020070000450000208000000100000000030100200600000000000900 +000000068030090000700000020010000350000208000000400000000030100200600000000000500 +000000068100000000000000030060030000000400100008000200400200500730000000000108000 +000000068350000000000010000100000500000800400009000000060205000000400300007000010 +000000068350000000000010000100000500000900400006000000070205000000400300008000010 +000000068900000002000400500041000000000035000050000000000800010300000700000100400 +000000069070000040050800000000507200300100000600000000000030008400060000000000500 +000000069800040000000010000000300800010000400650000000701000200000905000000600000 +000000071000040000600000000000705000200000600000100300087000050010300000000060400 +000000071000052000000000000000008540710400000300000000460070000005000200000300000 +000000071000208000000600000501000000000300200700000000030040600260000000000070050 +000000071000520000000000000000070080300001000204000000500600200000300600070004000 +000000071000580000000000000000031060200400000508000000070006000030000500000100200 +000000071000604000000000000500400600102000050700000000000071000080020000030000900 +000000071000604000000000000500800600102000050700000000000071000090020000030000800 +000000071000800000000300000040000300270000000000500800600070500008060000000010040 +000000071000904000000000000500400600102000050700000000000071000080020000030000900 +000000071002500000000000000780000030000420000000100000050007200004600500300000000 +000000071005020000040000000100300000000009400800000000060000950300710000000800000 +000000071006090000000000050102000000000060300050000000070504000800000600000200400 +000000071020400000500000000080000600000037000000010000000600240300500000109000000 +000000071020400000600000000080000200000037000000010000000200540300500000109000000 +000000071020600000000000000100073000060000200500000000000260400703000050000800000 +000000071020800000000403000700060050000200300900000000600070000080000400000050000 +000000071030020000000000000000000250600100000000080300020000530400601000000700000 +000000071040050000000600000000100600080000500000007003107000060000080200300000000 +000000071050003000040080000030000500200100000600000000000040300700000040100600000 +000000071050008000000000000060040030200170000000300600000002500401000000700000000 +000000071050080000000000000600103000020000890000400000000700200100040000403000000 +000000071050600000200009000000800300407000000100000000000010020030040000020000600 +000000071060005000000000000080000630400170000000200000907020000000003800000000500 +000000071060020000000030000700060300400000200100400000000105080020000000000700000 +000000071060020000000030000700060300400000200100400000000705080020000000000100000 +000000071060020000300000000050000260000108000000300000000430500108000000007000000 +000000071060030000000020000700060300400000200100400000000105080020000000000700000 +000000071060030000000020000700060300400000200100400000000705080020000000000100000 +000000071060300000500000000000040050007010000020000600000500900400600000801000000 +000000071060500000000000000005040600030000200000007000000800540107300000200000000 +000000071080300000000200000407020000000600800100000300500070040030000600000000000 +000000071080400000000500000100072000050000630000000000000380400207000000600000000 +000000071090800000000000000400300600701000050000902000060000300500070000000000900 +000000071200050000030060000701300000000000640800000000000107000040000500000002000 +000000071200300000860000000000500630004200000700000000000071000050000800000040000 +000000071200600000300000000000510007604000200000008000050000040000200600010000000 +000000071200900000000000000000600830071400000500000000640000200000050600000007000 +000000071300200000000000000000060300010030000004000000600000540000407200800100000 +000000071300200000000400000000078040200000300050010000400000500007060000000500000 +000000071300500000000000000000308500002600000070000000000070320800050000010040000 +000000071300500000600400000000072000080010000400000000070020000000300600000000540 +000000071300800000080000000005041000020000300000070000601000040000200600700000000 +000000071400030000000200000020700000000040300000000500000102060308000400500000000 +000000071400080000000000000000170050820000000300000000001703000600000800000500400 +000000071400500000600000003050037000200000800000010000000800040000400200010000000 +000000071400900000300500000000300450070060000000000900000072000080010000500000000 +000000071500020000000800000047000000000090600010000000600000250700103000000400000 +000000071500030000000600000600000800200400000000702000000080300041000000070000020 +000000071500400000300000000400306500010000060000200000080000200000017000000080000 +000000071580000000030900000407200000000000810060000000200000500000067000000010000 +000000071600040000000000000087500000000020900010000000300800600406000020000100000 +000000071600200000800000000070031040000600500200000000030070000000500600000000200 +000000071600200000900000000400650300010000080000400000070081000020000600000000000 +000000071600500000040000000502600030000900600070000000000013000800000900000070000 +000000071600500000200000000340010000000070620000000500000600300080400000010000000 +000000071600500000300400000000072000080010000400000000070020000000300600000000540 +000000071800020000300000000076500000000030200010000090400600800050100000000000000 +000000071800030000000000000670200000000090300000000500020701000500000830000400000 +000000071800040000000000000070200000030000800000090400000701030400500600900000000 +000000071800040000000000000670200000000090300000000400020701000300000840000500000 +000000071800300000400050000670000500000012000000400000002000050000800400010000000 +000000071900000060020000000004070000030000400000910000700600008000300200100000000 +000000071930000000000000000000620400000030000070000000650007080200000900000108000 +000000072000051000000000000000060180720300000400000000300200000000400600008000500 +000000072006800000000000050170000300000400800020000000000217000309000000000050000 +000000072010000000000060000000700510902000000400000000000510600300000009000807000 +000000072080500000010000000200097000000000100300000000703000060000180500000400000 +000000072080500000010000000200097000000000800600000000703000060000180500000400000 +000000072080600000010000000400097000000000800300000000703000040000180600000500000 +000000073200500000000000610003100000000900040800000700000086200010000000000030000 +000000074002800000000000003070530000600000010000000200540000600000071000700000000 +000000074010030000000000080000010520700600000400000000053000100000708000000000200 +000000074010030000000000080000010520700600000400000000053000100000807000000000200 +000000074150000000000000008010000230600048000000070000200500100000300000004000000 +000000074200050000000000001000104030500000600008700000000390800010000000000000200 +000000074500100000000000009800009500000040000000000010070200600000080300040700000 +000000075320000000000000008010000240600058000000070000200400100000300000005000000 +000000075400060000000000010002105000000700040600000300000390800010000000000000200 +000000075400060000000000010002105000000700040900000300000390800010000000000000200 +000000075400060000000000010003105000000700040600000300000390800010000000000000200 +000000075400060000000000010003105000000700040900000300000390800010000000000000200 +000000075620000000000000008010000240300058000000070000200400100000300000005000000 +000000076060200000000000050000860400501000000700900000030005000900000200000010000 +000000076400900000000000080008070000000200400090000300200000530000006001000080000 +000000078500200000000000600067000050080000020000300400300000102000070000000006000 +000000078500300000000000010400070200000018000030000000060400500000000430001000000 +000000078600000050000040000058000000000001300040000000300600100000250000000700400 +000000079030080000500000020080000560000209000000400000000030100200700000000000400 +000000079030080000500000020080000560000209000000400000000040100200700000000000400 +000000081000090030700004000000200600030800000010000000000010403500600000200000000 +000000081000090040700005000000300600040800000010000000000010504300600000200000000 +000000081000409000000200000060081000004000230000000000380070000200500900000000000 +000000081000602000300700000604000700000090010700000000500400200010080000000000000 +000000081020030000000000000000060320700450000100000000500708000060000200000100000 +000000081020040000000700000000050620300090000100000000040300200500008000000100000 +000000081020300000000000000109000040000200500800000000000580200070000300600010000 +000000081020300000040006000000600420801050000000000700000400200500080000000000000 +000000081020300000700000000040000700000018000000050000000600230500400000106000000 +000000081020500000000000000400031000700000200060000000000260500103000040000700000 +000000081020600000400000000090000200000038000000010000000500720300400000105000000 +000000081020700000000000000000900250800000030400000700600018000050000300000040000 +000000081020700000000403000100060050000200300500000000800010000040000700000050000 +000000081020700000000403000100060050000200300500000000800010000070000400000050000 +000000081020700000500000000060000200000038000000010000000600740200500000103000000 +000000081020700000500000000090000400000038000000010000000600240300500000106000000 +000000081030005000000000000500074600109000000000000000080000370600910000000200000 +000000081030005000000000000500074600901000000000000000080000370600910000000200000 +000000081030020000000700000000050620400090000100000000020400300500008000000100000 +000000081030020000000700000000050620400090000100000000060400300500008000000100000 +000000081030200000000000000108060040000700300600000000500300700090000200000010000 +000000081030200000000000000108060040000900300600000000500300700070000200000010000 +000000081030200000500000000000600230100400000700000000400070000000010800060000300 +000000081030500000000020000100007000000080500050000400600100070000403000800000000 +000000081030500000000020000100009000000080500050000400600100070000403000800000000 +000000081030600000000020000500007000000080600060000400100500070000403000800000000 +000000081030600000000020000700009000000080600060000400100500070000403000800000000 +000000081040300000020006000000600420801050000000000700000400200500080000000000000 +000000081050600000200009000000700300408000000100000000000010070030040000020000600 +000000081060020000300000000050000260000107000000300000000430500701000000008000000 +000000081060500000300000000500028000070000400000010000000600730002400000100000000 +000000081060500000700000000200600500008000020100300000040021000050000600000000000 +000000081060700000000200000040000600000083000000000020000502700308040000100000000 +000000081070600000300000000400018000030000500000020000000500760002400000100000000 +000000081070600000300000000400028000030000500000010000000500790002400000100000000 +000000081080000020300000000016000000000500600090200000000091000500000300400080000 +000000081090005000000000000070000630400810000000200000201060000000003500000000700 +000000081090005000000000000070000630400810000000200000201060000000003700000000500 +000000081090300000000200000708040000000600900100000300500080040030000600000000000 +000000081100060000070050000009000760000102000000800400000300500800000020000000000 +000000081200060000000000000048500000000020300010000000500000670000103000700400000 +000000081200060000000700000000408070630000000000100000004000600000050200018000000 +000000081200400000000000000000230700010000050008600000700000400090080000000050200 +000000081200500000030000000020406000001000070000200000008010000000030200700000400 +000000081200500000030000000020406000008000070000200000001080000000030200700000400 +000000081200600000000000000089010050000403200000000600400000700000250000000080000 +000000081200700000000000000000230700010000050008600000700000400030080000000050200 +000000081200700000000000000000230700010000050008600000700000400040080000000050200 +000000081200700000000000000000230700010000050008600000700000400090080000000050200 +000000081200700000000500000000080650400010000500000700060300000089000000000000400 +000000081200700000960000000000500630004200000800000000000081000050000900000040000 +000000081230000000040700000000600370005300000100000000400000200000058000000010000 +000000081250000000060700000000500670004200000100000000300000900000048000000010000 +000000081300020000000700000048000000000060200010000000600000350700504000000100000 +000000081300200000000074000200000560700010000000009000000800200014000000090000000 +000000081300600000090400000680070000000300400000000020000012000500000300000080000 +000000081360000000040700000500000300000021000000080000002000010000400600400300000 +000000081400300000300050000190000500000028000000600000082000050000400700000000000 +000000081400300000300050000190000500000028000000600000082000050000700400000000000 +000000081400300000300050000190000500000082000000600000082000050000400700000000000 +000000081400300000300050000190000500000082000000600000082000050000700400000000000 +000000081400300000300050000610000500000082000000700000002000050000600400080000000 +000000081400300000300050000680000500000012000000700000002000050000600400010000000 +000000081500400000073000000000028000060000300000010000000600740200500000100000000 +000000081600002000000700000500000360800100000000400000000060200047000000010030000 +000000081600030000000200000020800000000040300000000500000102070304000600500000000 +000000081600040000000230000400000050300700000000100000000050300010000200087000000 +000000081600070000000000000000801040702000000300400000200000700000060300080500000 +000000081600070000000000000000805040702000000300100000200000700000090300080500000 +000000081600200000000000000010089000503000200000000600000300570240000000080000000 +000000081600400000500700000012000000080090000000500000000010050030000600700000400 +000000081600500000040000000502700030000600700080000000000013000900000600000080000 +000000081690000000040300000508200000000000910070000000300000600000018000000070000 +000000081700050000020000000601200000080000040000090300300004000200000500000800000 +000000081700060000000000000400507000600000720000100000058200000000030200010000000 +000000081700200000200000000000510030050040000600000800000700900003006000010000000 +000000081700300000400050000610000500000082000000400000002000050000700400080000000 +000000081700400000000200000400000300005010000000090000010350000200000640000000700 +000000081700600000300500000000082000090010000500000000080040000000300700000000650 +000000081700600000500000000040081000000000290000030000000504700600200000080000000 +000000081900400000700600000082000000010050000000700000000080050030000900600000400 +000000082000031000000000000080420000400000100000500000601000300000200050700000600 +000000082000031000000000000080420000700000100000500000601000300000200050400000700 +000000082005060000010000000090302000000100500800000040600040000300000001000000300 +000000082040600000010000000200098000000000100300000000803000070000410600000500000 +000000082500006000000000090600000300000920000000000040000053100090600000008000700 +000000082500300000000000000300072000400000630000010000000800500081000000020000007 +000000082600400000000000000400072000500000430000010000000800600081000000020000007 +000000083000014000000200000000320000090000400000700000000006150308000000200000600 +000000083000030010070000000000204000030000600000010000200600405000500700100000000 +000000083020100000000000040000610200800000900004000000060300500100000070000008000 +000000083020700000000000040000610200800000900004000000060300100500000070000008000 +000000083040300000000500060300000400000700500208000000050060100000002000000080000 +000000083400020000000000510002300000700000600000100040000075200010000000000800000 +000000083500400000000100000000020700100000400000008000038600000020070000000000520 +000000083900100000000000020100009700020080000000000100005700400003000060080000000 +000000084000100000200000000000600130408000000050000000560000200000080007010030000 +000000084000510000000030000400000200300008000000600070000200403076000000000000100 +000000084050010000000000050000030620800200000400000000073000100000508000000000900 +000000084100600000000000000000040103030020000500000600048000020000701500000000000 +000000084600010000000000000500000106000800300070200000087000020000063500000000000 +000000084750000000000000009010000730600049000000080000200500100000300000004000000 +000000085004070000000000030100060700570000100030800000006200000000503000000000000 +000000085200030000000000030040010600058000000000700000700400100000500200000008000 +000000085760000000000000009010000640300059000000080000200400100000300000005000000 +000000086320000000000000009010000250700069000000080000200500400000300000006000000 +000000087004010000000000030100060500570000100030800000006200000000703000000000000 +000000087004050000000000030100060500570000100030800000006200000000703000000000000 +000000091000020000000400000507000200100900000860000000040000080090001000000070300 +000000091000030000000500000608000300200900000170000000050000020090001000000080400 +000000091002080000040700000050061400000090000300000000000300750900000000000200000 +000000091020400000000000000000380200700090000000000400040500600900010070000200000 +000000091020700000600000000080000500000039000000010000000600840300500000107000000 +000000091030600000000020000700008000000090600060000400100500080000403000900000000 +000000091060005000000000000080000630400910000000200000201070000000003500000000800 +000000091060005000000000000080000630400910000000200000201070000000003800000000500 +000000091060070000000000000005030760000000200100000000300100004082000000000409000 +000000091060070000000000000005030760000000300100000000300100004082000000000409000 +000000091070020000000004000000380000040000900000100000300000640000005700100800000 +000000091070080000000000000006040870000000300100000000400100005032000000000509000 +000000091080040000400000000000720500801000060900000000020000300000601000000900000 +000000091080200000000000000930000800000014000000500000104000070000600200000380000 +000000091080600000000030000000700260500400000100000000030050800000019000400000000 +000000091080600000000030000000700280500400000100000000030050800000019000400000000 +000000091200050000000000000500000240700800000060100000089400000000060300010000000 +000000091200400000030000000060507000009000080000200000001090000000030200800000400 +000000091200600000000000000040010600000039000070000200000400570300800000100000000 +000000091200800000600000000040091000000000250000030000000604800700500000090000000 +000000091300040000500600000007200600090000080000300000200000500000091000000080000 +000000091300200000000085000600000270800040000000001000000600500049000000010000000 +000000091400070000000000000700300000800000400000106000019500060000040700200000000 +000000091400070000000000000700300000800000400000106000019500060000040800200000000 +000000091400300000000000000000219000200000850000060000090000060000400700300000400 +000000091400300000300050000710000500000092000000600000092000050000400800000000000 +000000091400300000300050000790000500000012000000600000012000050000400800000000000 +000000091500080000200000000000720600010300000090000000640100000000000520000000800 +000000091500200000300000000080700040090000600000500000200060500010090000000003000 +000000091600300000070000000400000500000029000000010000000500680310000000020800000 +000000091600700000200000000700000010000600500000450000030081000040000600005000000 +000000091600700000800000000040091000000000250000030000000604800200500000090000000 +000000091600700000800000000040091000000000250000030000000604800700500000090000000 +000000091603000000500000000090100040000002300700000000300000700000410000000980000 +000000091630000000000000000019080000000020400000000600200600300000703050000400000 +000000091630000000000000000051080000000020400000000600200600300000703050000400000 +000000091630000000000000000091080000000020400000000600200600300000703050000400000 +000000091700000030000200000090010080005000600200000000080090000000600400000700200 +000000091700030000200500000600000200040900000000000000500008040090001000000020300 +000000091700030000200500000600000200040900000000000000500008040090001000000060300 +000000091700400000000030000000651000200000370000000000000800200054000000310000000 +000000091700400000000380000000500800029000000010000000600002000000060010500000300 +000000091700400000200000000500290000000080010040000600081000400000700300000000000 +000000091700800000200000000000510030020040000600000900000700600003006000010000000 +000000091700800000200000000000510030050040000600000900000700200003006000010000000 +000000091700800000200000000000510030050040000600000900000700800003006000010000000 +000000091700800000200000000000510030070040000600000900000700200003006000010000000 +000000091700800000600000000040091000000000250000030000000604700200500000090000000 +000000091800200000000400000060017030200000600000090000001050000000800200040000000 +000000091800200000200000000000510030050040000600000900000700800003006000010000000 +000000091800300000300050000470000500000092000000600000002000050000800400090000000 +000000091800700000200000000000510030090040000600000900000200800003006000010000000 +000000092010400000000000000030100400100060000000020007000500830209000000600000000 +000000092700000010000300000090020080005000600300000000010090000000600400000700300 +000000093000014000000200000000320000040000500000800000000007160309000000200000700 +000000093480000000010000000503000060000010800000000000170000400000902000000300005 +000000094000400070100000000208000600000750000000000100030060500047000000000002000 +000000094030090000000000060070000820200600000000004000000750300906000000000000100 +000000096200030000000000030050010700069000000000800000800400100000600200000009000 +000000097000050000000040000107200000040000300000900000600701000030000450000000800 +000000097300400000000000020600098100400007300000020000072000000000100000080000000 +000000100000300000900000000700100600200000090000500000008020040010006005050090000 +000000100000500000200000000035400000000010700080000200004000059600002000000070030 +000000100000500000200000000035400000000010700080000200004000059600070000000002030 +000000100000500000200000000035400000000010800070000200004000095600008000000020030 +000000100000500000200000000035400000000010800070000200004000095600020000000008030 +000000102000000340005080000360000000000090050010000000100403000007000600000100000 +000000102000300500000608000000400030200050000100000000000070200080010000030000060 +000000102000300500000708000000400070600050000100000000000040600070010000030000040 +000000102000300600000408000000500040200060000100000000000070200050010000040000030 +000000102000300600000709000000400030200050000100000000000080200040010000030000070 +000000102000300600000809000000400080200050000100000000000070200080010000030000060 +000000102000300700000409000000500040200060000100000000000080200090010000040000030 +000000102000300700000809000000500080200060000100000000000010600080040000030000070 +000000102030000400000700500080000030000015000000020000000300064201000000900000000 +000000102040700000300500000008001000600000070000020000002000600000600300010070000 +000000102080300000000000500000690080001000000500000000060000470000201000700050000 +000000102400050000000000900060070080001000000000300000000001460320000050000900000 +000000102500600000000000000023000700000405000010000300000170000000020080800000040 +000000102700050000000000800060070040001000000000300000000001460320000050000800000 +000000102700050000000000900060070080001000000000300000000001460320000050000900000 +000000102700400000000000800300000640400009000000010000012600000000500030090000000 +000000102900050000000000800040060070001000000000300000000001460320000050000800000 +000000102900050000000000800060070040001000000000300000000001460320000050000800000 +000000103000400500670000000000020070300000000001000000000063400007500000020000080 +000000103020090000000000400000025080010000000400000000300104000008000020000700600 +000000103020400000000670000070000400000001000000000070000240060301000500800000000 +000000103080020000000004500030000020000500070000100000100300600700080000005000000 +000000103800050000000000700060020040001000000000300000000001460420000050000700000 +000000103800600000200000700000406080010000000000700000008003000030010000400050000 +000000103900050000000000700060020040001000000000300000000001460820000050000700000 +000000103900050000000000800060020070001000000000300000000001460720000050000800000 +000000104000003600000050002503000000200600000000100080000070230010000000000400000 +000000104000010800600700000391000000080500000000200000506000070400080000000000000 +000000104000060000000050000200430000000107000600000800010500000070000040000000023 +000000104000080300040050000000200070300000600001004000870000050000300000000100000 +000000104000702000000000000460010000000500070100000000000380600027000030004000000 +000000104000802000000000000460070000000600080100000000000340700028000050009000000 +000000104080900000000000500000702080001000000500000000000530600020000030400010000 +000000104702000000000000000000705020300600000010000000200000630050014000000080000 +000000104800070000000000600700200000000104000030000080012000000000050030604000000 +000000104800090000000000600700200000000401000030000090012000000000050030604000000 +000000105000700400700200000000500080403000000061000000500000020040060000000010000 +000000105002000600030800000100000400000308000000200000570000030400060000000010000 +000000105002600000000902000300000090000070800000010000710000500000200040080000000 +000000105004070000000000300150300000000600080020000000000051200006000070800000000 +000000105030800000000000000000012000060000030000000700102000400500360000000700080 +000000105030800000000000600020030000500006000000000270601000004000200030000070000 +000000105200007000000030600009000400010500000000002030300000070000980000000100000 +000000105200800000000000300000071000000004800300050000000300026004000050010000000 +000000105300040000000000000000080720905600000000000040020000800000100030000509000 +000000105302000000000000000000206030710000000000300000400000820070015000000090000 +000000105802000000000000000000406030200300000010000000400000720060015000000090000 +000000105802000000000000000000406030400700000010000000300000720060015000000090000 +000000105802000000000000000000806020300700000010000000400000730060015000000090000 +000000105802000000000000000000806020400700000010000000200000730060015000000090000 +000000105802000000000000000000806030300700000010000000400000720060015000000090000 +000000106000025000300000000009100400000400000000000020520000080000630700000007000 +000000106020000500000082000010000200000040030000500000703000040400600000000001000 +000000106020070000800000500097000030000500040000100000000020780100600000000000000 +000000106020070000900000500078000030000500040000100000000020780100600000000000000 +000000106030070000400000500078000020000500040000100000000020780100600000000000000 +000000106030070000900000500078000020000500040000100000000020780100600000000000000 +000000106040700000000500300070000450600010000000000000000450020300000080100000000 +000000106040800000000500300070000450600010000000000000000480020300000090100000000 +000000106200005000000000800320000070000010000000800000071000400000023050000600000 +000000106302000000000000000000207030400800000010000000500000840070016000000090000 +000000106302000000000000000000507030500800000010000000200000840070016000000090000 +000000106390000000000000500000610200870000000000500000000407030001050000000000080 +000000106402000000000000000000207030500800000010000000300000840070016000000090000 +000000106402000000000000000000507030500800000010000000200000840070016000000090000 +000000106402000000000000000000507030500800000010000000300000840070016000000090000 +000000107000001300800040000500300000006000040200000000000200050010000200030700000 +000000107000001300800050000200300000006000050400000000000200040010000200030700000 +000000107000025000300000000004100600000400000000000020520000090000730800000008000 +000000107000500300000602000800000026600000040000010000410000700000200000030000000 +000000107000800300800200000000700090403000000061000000500000020090060000000010000 +000000107000800400200300000000700090504000000061000000300000020090060000000010000 +000000107000800400800300000000700090504000000061000000300000020090060000000010000 +000000107000902000000500600900000850000010000400000000007400020010000030060000000 +000000107020030000000000600000040020700600000100000000040200050008000300000105000 +000000107024000000000500600030000050000100400900000000000039020700000008001000000 +000000107040080000900000600028000030000600050000100000000020890100700000000000000 +000000107040080000900000600082000030000600050000100000000020890100700000000000000 +000000107090020000000000004000401500020003060000700000000090030400800000100000000 +000000107400200000080300000200000480000076000000000000567000000000400030001000000 +000000107400200000100000000098000050070000006000100000000095300000070400000000020 +000000107830000000000060400600200050000107000000000000071400000000050680000000000 +000000107900020000000000800000701500400000030000900000000340060008000020010000000 +000000108000008300700040000500300000006000040200000000000200050080000200030100000 +000000108000008300700050000200300000006000050400000000000200040080000200030100000 +000000108000407000000500300040000620000010000020000000701000050000200070300000000 +000000108000600400200300000000800090504000000071000000600000020090070000000010000 +000000108000605000000400300040000620000010000020000000106000050000200070300000000 +000000108009400000000300700600000040000020000000010000370005000010000200000600080 +000000108040200000000600000020400030700010500000000000100080000000000340000000026 +000000108050400000000200000020500030700010600000000000100080000000000350000000042 +000000108200300000600000000010054000000000020000008000000230040080000500700600000 +000000108200700000000000300500000090000038000020010000010000400000500020007600000 +000000108300060000000000500900000600000800020000401000085000001000030070040000000 +000000108400200000100000000089000050070000006000100000000075300000080400000000020 +000000108500040000000000700030050020001000000000200000000001360820000040000700000 +000000108500200000000000400900000050000340000000060200000605070041000000000000030 +000000108600200000000000400200000050000340000000070300000605020041000000000000030 +000000108600300000200000000010058000000000020000001000000230040080000900700600000 +000000108700400000000000000000038600400000070000010000000500064035200000010000000 +000000108900040000000000700030050060001000000000200000000001350820000040000700000 +000000108900040000000000700050060030001000000000200000000001350820000040000700000 +000000109000200300040070000070000080000300000000100000203000600000004050100080000 +000000109000400200000508000000300080100000040200000000060000730430000000000010000 +000000109000807000000500300040000620000010000080000000701000050000400070300000000 +000000109040200000030000400600405020100000000000700000000000870000019000000060000 +000000109200600000000050400000010500000700030300000000000802060014000000000000070 +000000109300400000000000200027006000000800500009000000510020000400000030000090000 +000000109400050000000020300000109000500007000000300000013000000080000040009000020 +000000109400050000090020000000401700060000000000700000000060020700300000801000000 +000000109700008000000000000360000080010590000000000020000140600205000000000900000 +000000109700400000000000000000039600400000070000010000000500084035200000010000000 +000000120000040700030007000057000008000410000000200000000000053400600000100000000 +000000120063000000000000000040000503100208000000700000500000080002600000000030400 +000000126000850000000000004000300700400001000105000000070000380000046000000000000 +000000126000950000000000004000300800400001000105000000030000790000046000000000000 +000000130000080005420000000600000020005010000000000400070402000000600200000000001 +000000130020400000000000000000600025700080000100000000000016700005200000040000300 +000000130040020000000000000000000026700900000100000000062050004000107300000800000 +000000130047000000050000000100302000000050007000000040800000200000603000000740000 +000000130200600000700500000040010300000200050010000000500000007000084000000030000 +000000130400070000800000000000506200700300004000100000000080076015000000000000000 +000000130800600000200500000040010300000200050010000000500000008000074000000030000 +000000135608000000000000040030400010000027000050000000200000706000000200000300000 +000000135608000000000000040050400010000076000030000000200000706000000200000300000 +000000135807000000000000040030400010000076000050000000200000706000000200000300000 +000000136087000000000000050000740900360000000000000000004080200600305000000000000 +000000140090020000000000000000107400950000000000400000001000302000090050800600000 +000000140090020000000600700401000000000580000300000000080000502000001030000400000 +000000140400000600000500000000305008200700000106000000050000083600010000000000000 +000000150080020000000000000000501400870000000000400000001000320000080007500600000 +000000150900700000000000030042000700001030000050000000200600800300400000000050000 +000000160000009500000040000041020000000300600080000000700000024300900000000000008 +000000160020700000000000900600010000000040002030000000100000470000300005800200000 +000000160040020000000009070300100000000000402600000000000630500029000000000800000 +000000160200040000000000708000530020007000050010000000300006400000107000000000000 +000000160200070000300000800000608900420000000000500000000010002008000050060000000 +000000160200070000300000800000608900420000000000500000000040002008000050060000000 +000000160800400000000000700000070600010030000200000050000208000076000000000500004 +000000170000004600000050000051020000000300700080000000700000025400900000000000008 +000000170020900000000000600600010000000040002030000000100000460000300005800200000 +000000170030040000000000600600100000000006030005000004000650200740000000000800000 +000000170040800000000000002000500048200070000100000000000010260080600000000000300 +000000175049600000000000000500000300100090000000420000020000049300001000000000000 +000000180000205000000003000010080000000600002003000000000040710600000300200500000 +000000180300500000000000020061000000000300400008000000710000300000086005000020000 +000000180300900000000000020068000000000300400001000000710000300000086005000020000 +000000190300400000000000020071000000000300500009000000810000400000097006000020000 +000000201000020500080004000000230000090000040000500000602100000500000300000000070 +000000201000080400300050000000204000500000070000600000004100002020000600000000030 +000000201000370000000000000430010000000002600080000070000800530001000020700000000 +000000201004030000000000000370000080600200000000500000540000600000070040002001000 +000000201005090000038000000120400000000030080700000000000000430000201000000600000 +000000201005090000038000000120400000000030080700000000000000530000201000000600000 +000000201009050000400700000600102000000000030000800000000040690710000000000030000 +000000201030070000000400800000050040801000000006000000200801000050000700000000090 +000000201040030000000006000600072000030000040000100500201800000000000730000000000 +000000201060400000003000000200070100500020000000000060100000500000308000000600040 +000000201070300000000000000060000030000205000000041000005780060100000400200000000 +000000201080050000000000000600201000000500740000300000000084050302000000100000000 +000000201080300000000000000060000030000205000000041000005780060100000400200000000 +000000201080400000000700000000540080302000000100000000500032600070000040000000000 +000000201090004000030000000000008530700000400100000000200670000000020800000100000 +000000201090030000000000004006000530300400000000100000000090080204000000170000000 +000000201090400000000300000170020000000008600000000050208000500000900040006000000 +000000201096000000000000500000090040200030000100000000070502000000006083000100000 +000000201500300000000070000000500030020004000076000000000000350000021000800000400 +000000201600300000700000000008540000020000030000600700010082000500000060000000000 +000000201730000000600040000000060030008000500200000000001200000000508000060000070 +000000201800000900000400000000610030270000000900000000090072000001000040000800000 +000000203006400000000000500100600070820000000000830000000059000050002000000000040 +000000203010700000000000000000023400090060000800000000000800019600900070200000000 +000000203080700000000000100005000040300010000000000600000407060100000080200500000 +000000203800600000000000700002000100040800000000300060000027040300000005000010000 +000000204000001000000080000020400500000030700000000080100200006806000010000700000 +000000204001000000050000000006500080200009000000000010000150700940000300000800000 +000000204050030000000000690000850010206000000900000000000206000130000000000400000 +000000204050700000680000000300000090000014000000020000201000000000800050000600700 +000000204100900000000000007670300000000100830040000000000025000500000090000040000 +000000204100900000000000008680700000000100730040000000000025000500000090000040000 diff --git a/README.md b/README.md index 6c4d0e8098108dd9c96df54d099c410afb3ce3f8..f3763cf007887a30302781a91bb0e6935a8d5763 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,83 @@ -# Cloud Computing: Overall Lab Instruction +Cloud Computing: Overall Lab Instruction +<!——这是包含湖南大学本科课程 CS06142“云计算技术”所有实验材料的仓库——> - +1. Overview +There are 4 labs in total in this course. All the materials of each lab are under folders Lab1-4 in this repo. Please clone the lab git repo onto your local computer, -## 1. Overview +git clone https://github.com/1989chenguo/CloudComputingLabs.git -There are **4 labs in total** in this course. All the materials of each lab are under folders Lab1-4 in this repo. Please clone the lab git repo onto your local computer, +and always track our latest lab materials using the following commands (should first enter the folder you have cloned from our lab repo) -`git clone https://github.com/1989chenguo/CloudComputingLabs.git` +git pull -and always track our latest lab materials using the following commands (should first enter the folder you have cloned from our lab repo) +You can find this overall lab instruction in README.md in the root folder. + +Please carefully read the overall lab instruction before you do anything. + +Also, please carefully read each lab's instruction (Lab1, Lab2, Lab3, Lab4) to get each lab's task, background, requirements, etc. + +本课程共有四堂实验课。 所有实验的资料都在这个代码仓库的 Lab1-4 文件夹下。 请克隆这个代码仓库到您的本地计算机上, -`git pull` +并始终使用以下命令跟踪我们最新的实验资料(应首先进入您从我们的实验仓库克隆的文件夹) -You can find this overall lab instruction in `README.md` in the root folder. +你可以在根目录下的 README.md 文档中找到这个完整的实验说明。 -Please **carefully read the overall lab instruction before you do anything**. +在你做任何事情之前,请仔细阅读整个实验说明。 -Also, please **carefully read each lab's instruction** ([Lab1](Lab1/README.md), [Lab2](Lab2/README.md), [Lab3](Lab3/README.md), [Lab4](Lab4/README.md)) to get each lab's task, background, requirements, etc. +同时,请仔细阅读各实验说明书(Lab1、Lab2、Lab3、Lab4),了解各实验的任务、背景、要求等。 -## 2. Group collaboration +2. Group collaboration +Each student should register your own github account. Group members should use git and github to collaborate. -Each student should register your own github account. Group members should use **git and github** to collaborate. +All the labs are done in the unit of group, i.e., a group only needs to submit one piece of code for each lab. However, each group member should make enough contribution to the lab. Teaching assistants will check the git commit history to evaluate each one’s contribution. -All the labs are done in the unit of group, i.e., a group only needs to submit one piece of code for each lab. However, each group member should make enough contribution to the lab. Teaching assistants will check the **git commit history** to evaluate each one’s contribution. +每个学生都应该注册自己的 github 账号。 小组成员应该使用git 和 github进行协作。 -## 3. Code submission +所有的实验都是以小组为单位完成的,即一个小组只需为每个实验提交一段代码。 但是,每个小组成员都应该为实验室做出足够的贡献。 教学助理将检查git 提交历史记录,以评估每个人的贡献。 +3. Code submission Each group should create a code repo for our course (create your own group's repo, do not push onto my course lab repo!). The group leader should send an email to TA telling us your group's lab git repo address. For example, https://github.com/group1/CloudComputingLabs.git` -**All the lab code should be submitted through pushing to your group's github code repo.** Teaching assistants will checkout your commit, and read and test your codes from the above repo address you provided us. The code of different lab should be in different folders, named Lab1/Lab2/Lab3/Lab4, respectively (following the same structure of this repo). Please note that your lab folder name should be exactly same as above (be careful about the first capital letter and no space before the number), otherwise your code may fail in our TAs' automatic testing scripts. All lab codes should be in the same course git repo of your group. +每个组应该为我们的课程创建一个代码仓库(创建自己组的仓库,不要推到我的课程实验仓库!) 组长应该给 TA 发邮件告诉我们你们组的实验代码仓库地址。 例如,https://github.com/group1/CloudComputingLabs.git -Please write a README.md to each lab code folder, briefly introducing how to run your lab code (including how to set the environment, provide the input, and explain the output, etc.). Keep the README short and clear! Also, your code should be well commented so that other people can understand without asking you. +All the lab code should be submitted through pushing to your group's github code repo. Teaching assistants will checkout your commit, and read and test your codes from the above repo address you provided us. The code of different lab should be in different folders, named Lab1/Lab2/Lab3/Lab4, respectively (following the same structure of this repo). Please note that your lab folder name should be exactly same as above (be careful about the first capital letter and no space before the number), otherwise your code may fail in our TAs' automatic testing scripts. All lab codes should be in the same course git repo of your group. -## 4. Environment requirement +**所有的实验代码应该通过推到你的小组的 github 代码仓库提交。 **助教将检查您的提交,并从您提供给我们的上述仓库地址阅读和测试您的代码。 不同 lab 的代码应该放在不同的文件夹中,分别命名为 Lab1/Lab2/Lab3/Lab4(与本次代码仓库的结构相同)。 请注意您的实验文件夹名称应该与上面的名称完全相同(注意第一个大写字母,数字前没有空格),否则您的代码可能会在我们的助教的自动测试脚本中失败。 所有的实验代码应该在同一课程的您的小组的代码仓库下。 -### 4.1 OS requirement +Please write a README.md to each lab code folder, briefly introducing how to run your lab code (including how to set the environment, provide the input, and explain the output, etc.). Keep the README short and clear! Also, your code should be well commented so that other people can understand without asking you. -All the labs should be tested and runnable on UNIX-like operating systems, such as Linux distributions (e.g., Ubuntu, CentOS) and MacOS. We highly recommend you to use Linux distributions such as Ubuntu. -If you only have windows PC or laptops, install a UNIX VM and do experiments on the VM. +请编写 README.md 文档到每个实验的代码文件夹下,简要介绍如何运行您的实验代码(包括如何设置环境,提供输入,并解释输出等)。 保持 README 的简短和清晰! 另外,你的代码应该有很好的注释,这样其他人不用问你也能理解。 -### 4.2 Programming language +4. Environment requirement +4.1 OS requirement +All the labs should be tested and runnable on UNIX-like operating systems, such as Linux distributions (e.g., Ubuntu, CentOS) and MacOS. We highly recommend you to use Linux distributions such as Ubuntu. If you only have windows PC or laptops, install a UNIX VM and do experiments on the VM. +所有的实验都应该在类 unix 的操作系统上进行测试和运行,例如 Linux 发行版(例如 Ubuntu, CentOS)和 MacOS。 我们强烈建议您使用 Linux 发行版,如 Ubuntu。 + +如果只有 windows PC 或笔记本电脑,请安装一台 UNIX 虚拟机,并在虚拟机上进行实验。 + +4.2 Programming language Any programming languages are permitted in all labs, such as C/C++, Java, Go, Python, Perl. But for performance consideration, we highly recommend you to use C/C++ or Go !!! -### 4.3 Try to only use standard API +任何编程语言都允许在所有的实验,如 C/ c++, Java, Go, Python, Perl。 但出于性能考虑,我们强烈建议您使用 C/C++或 Go !! -To make your program portable, try your best to only use standard & widely available functions and normal libraries (such as `glibc`, `C++ STLs` and some typical math libraries). All the labs should only use standard system API defined by POSIX specification or Linux man page specification. We prefer to use standard POSIX API, so your code can be easily runnable on various kind of UNIX-like systems (instead of only on Linux). +4.3 Try to only use standard API +To make your program portable, try your best to only use standard & widely available functions and normal libraries (such as glibc, C++ STLs and some typical math libraries). All the labs should only use standard system API defined by POSIX specification or Linux man page specification. We prefer to use standard POSIX API, so your code can be easily runnable on various kind of UNIX-like systems (instead of only on Linux). -## 5. Grading +为了使你的程序具有可移植性,尽量只使用标准的和广泛可用的函数和普通的库(如 ·glibc, c++ STLs和一些典型的数学库)。 所有的实验室应该只使用 POSIX 规范或 Linux 手册页规范定义的标准系统 API。 我们更喜欢使用标准的 POSIX API,这样您的代码就可以轻松地在各种类 unix 系统上运行(而不仅仅是在 Linux 上)。 -Grading details are specified in each lab's instruction document, please carefully read them [Lab1](Lab1/README.md), [Lab2](Lab2/README.md), [Lab3](Lab3/README.md), [Lab4](Lab4/README.md). +5. Grading +Grading details are specified in each lab's instruction document, please carefully read them Lab1, Lab2, Lab3, Lab4. Besides, we have the following 3 overall grading requirements applicable to all the 4 labs: -1. **DO NOT copy** others' code (either from the Internet or from your classmates), otherwise your group (every member and the leader) will got **zero point** in the lab. However, we encourage to communicate with other group and learn from each other. But do remember to write the code yourself and not copy. -2. **DO NOT miss the deadline**, otherwise your group (every member and the leader) points will be reduced accordingly. -3. Typically, your group (every member and the leader) will get same points in each lab, unless we find severely **unfair contribution** in the git commit history. In the overall grading, the leader will get some more points as bonus. +DO NOT copy others' code (either from the Internet or from your classmates), otherwise your group (every member and the leader) will got zero point in the lab. However, we encourage to communicate with other group and learn from each other. But do remember to write the code yourself and not copy. +DO NOT miss the deadline, otherwise your group (every member and the leader) points will be reduced accordingly. +Typically, your group (every member and the leader) will get same points in each lab, unless we find severely unfair contribution in the git commit history. In the overall grading, the leader will get some more points as bonus. +评分细则在各实验室说明书中有详细说明,请仔细阅读Lab1、Lab2、Lab3、Lab4。 + +此外,我们有以下 3 个整体评分要求,适用于所有 4 个实验: + +不要抄袭别人的代码(无论是网络还是同学的),否则你的小组(每个成员和领导)将在实验得到零分。 但是,我们鼓励与其他小组交流,互相学习。 但是一定要记住自己写代码,不要抄袭。 +请不要错过的截止时间,否则您的团队(每个成员和领导)的积分将会相应减少。 +通常情况下,你的团队(每个成员和领导)在每个实验都得到相同的分数,除非我们在 git 提交历史中发现严重的不公平贡献。 在整体评分中,领导者会得到更多的积分作为奖励。 \ No newline at end of file