[計概] 王凡班的project 有一點點想法

看板NTUEE113HW作者 (螺旋麵)時間14年前 (2010/05/02 16:45), 編輯推噓6(604)
留言10則, 8人參與, 最新討論串1/1
就是呢 王凡班的project不是要用redlib來寫嗎 然後它的用法還真的是頗有趣... 我個人看了滿久之後 大概理解出個大概了 底下這個是教授給我們的資料中 解一個9x9的數獨的code 我加了一些可有可無的註解 如果有興趣又不嫌我嘴炮的 就看看唄~ sudoku.c ---------------------------------------- /* 這個是為了讓這個程式比較好懂,所做的一些註解。當然,我的希望只是讓 它比較好懂,所以如果我表達能力不佳或者其它因素,讓你覺得不是很有幫 助的話,就不要看吧,畢竟我也只是推想出它可能的意思而已。也因為這個 原因,裡面很多地方可能都有錯,所以請各位選擇性的採信唄:) 另外一個想說的是,這是用C寫出來的,所以有很多跟C++很像的地方,可是 有些地方又會有很大差別,所以自行小心唄~~不過除了印東西的時候,不用 cout而用fprintf(輸出的地方, "要印的字串",變數)外,基本上其它不會太 麻煩(吧)。有關語法的可以去GOOGLE找,找printf這個函數來看應該會有幫 助。 另外,裡面很多地方是有關圖論的部份,至於圖的性質也不是很容易說的 (因為要畫圖才能解釋),所以如果覺得不太好懂的話,那就多討論吧~~ 最後我個人建議大家,不要用Dev-Cpp 來寫程式。既然最後是要在linux上 compile的,那麼用 Dev-Cpp寫也不會比用記事本好... 私心推薦Notepad++ 好用~真的~ 2010/05/02,by Helicoid */ //這兩行是寫C的時候很重要的 //就當作習慣的直接加上去唄 #include <stdio.h> #include <stdlib.h> //下兩行順序不能對調,不然會有滿滿的錯誤 #include "redlib.h" #include "redlib.e" char *s[9][9]; int count_print = 0; //redgram是一個資料型別,而這三行的意思等於是 //redgram slot_constraint(redgram d, int i, int j) 其實只是個函數 redgram slot_constraint(d, i, j) redgram d; int i, j; { // 宣告有的沒的 int value, h, k, nc, ac, gs; redgram conj; //value從1到9,h從0到8,來看它要做什麼 for(value =1; value <= 9; value++) { for (h = 0; h < 9; h++){ if (h != i) { //底下這個式子是因為,在9x9的數獨裡,同一行當然不能同時是某個數字啦~ //例如說,當value=3時,第i列j行和 第h列j行是不能同時等於3的 //所以畫一個圖表示要避開這種事 conj = red_diagram("~(%s==%d && %s==%d)", s[i][j], value, s[h][j], value ); //底下可以暫時不看,反正就是跟輸出有關的東西 //倒是有一點值得注意,RED_OUT這個東西似乎跟輸出有關 //它的意義大家想想吧(我不知道XD) if ((++count_print) < 100 &&(gs=red_diagram_size(d, &nc, &ac))<30){ fprintf(RED_OUT, "\nMutual exclusion to value:%1d at %s and %s:\nconstraint:\n", value, s[i][j], s[h][j] ); red_print_line(conj); fprintf(RED_OUT, "\n"); red_print_diagram(conj); fprintf(RED_OUT, "input diagram:\n"); red_print_line(d); fprintf(RED_OUT, "\n"); red_print_diagram(d); } //下面這行是重點!!表示把剛剛的"同一行不能同時是某個數字" //這點加到原本的redgram中,而且是AND //(因為正確的圖形要同時滿足所有的限制!) d = red_and(d, conj); //再來也可以暫時不要看 if (count_print < 100 && gs < 30) { fprintf(RED_OUT, "result diagram:\n"); red_print_line(d); fprintf(RED_OUT, "\n"); red_print_diagram(d); } /* fprintf(RED_OUT,"%s && %s, after one conjunction.\n",s[i][j],s[h][j]); red_print_graph(d); fprintf(RED_OUT, "\n"); fflush(RED_OUT); */ //接下來的概念完全一樣,就是說如果同在一個3x3的小正方形內 //那麼數字不能同時等於某個value //稍微看一下,畫出一個數獨的形狀再比一比,應該比較好理解 if ((h/3) == (i/3)) { for (k = 0; k < 9; k++) { if ((k/3)==(j/3) && (k!=j)) { d = red_and(d, red_diagram("~(%s==%d && %s==%d)", s[i][j], value, s[h][k], value ) ); /* fprintf(RED_OUT,"%s && %s, after one conjunction.\n",s[i][j],s[h][k]); red_print_graph(d); fprintf(RED_OUT, "\n"); fflush(RED_OUT); */ } } } } //一樣的概念第三次出現(也是最後一次了) //同樣的一列裡面,任兩格是不能同時為相同的數字的~ if (h != j) { d = red_and(d, red_diagram("~(%s==%d && %s==%d)", s[i][j], value, s[i][h], value ) ); /* fprintf(RED_OUT, "%s && %s, after one conjunction.\n", s[i][j], s[i][h]); red_print_graph(d); fprintf(RED_OUT, "\n"); fflush(RED_OUT); */ } } } //複習一下剛剛做了什麼事 //就是,一個正常的數獨的限制條件 //1.一行裡面有1~9<=>任何兩格數字不同 //2.一列裡面有1~9<=>任何兩格數字不同 //3.一個3x3小方格裡面有1~9<=>任何兩格數字不同 //重點是都用到了red_and這個函數,他是這個程式的主角 //接下來的我是用猜的啦...不太確定 //把d在堆疊的號碼找出來,然後標記一下不要被清掉 h = red_push(d); //清掉用過的垃圾圖表(狡兔死走狗烹的道理吧...) red_garbage_collect(RED_GARBAGE_SILENT); //把d給擠出來(?) red_pop(h); //傳回加了料之後的圖表d return(d); } /* slot_constraint() */ //以上slot_constraint函數告一段落 //這兩行只是定義了東西而已 #define FLAG_MULTIPLE 1 #define FLAG_SINGLE 0 //以下為main函數 main(argc, argv) int argc; char **argv; { //宣告有的沒的 char a, *start, *condition, *p; redgram sol, cube; int i, j, k, u, v, h, m, c[9][9], lb[9][9], ub[9][9], flag; char stop[30]; FILE *datafile; //argc是用終端機(類似cmd)的時候,輸入的變數數目 //例如說,當我們打"程式名 輸入檔名"時,argc就會是2 //然後argv[0]="程式名" argv[1]="輸入檔名" //所以... 就會有底下的兩個if if (argc < 2) { printf("Input file for sudoko not specified!\n"); exit(0); } datafile = fopen(argv[1], "r"); if (datafile == NULL) { printf("Can't open the data file of sudoko!! \n"); exit(0); } //一些REDLIB所需的架構 //RED_input_file("sample.d"); red_begin_session(RED_SYSTEM_UNTIMED, "sudoku", 2); red_begin_declaration(); /* each process for a row on the board. */ //REDLIB所用的變數要有個名子,所以就跑個for跑出一大堆名子 //(因為REDLIB跟C的變數是不一樣的,所以光是給名子就有點麻煩) //後面的 red_declare_variable, //(我覺得)是宣告d00,d01,d02,...,d87,d88都是1到9的離散變數 //(因為數獨上面不會有7.4或者 2π之類的東東吧) for (i = 0; i < 9; i++) { for (j = 0; j < 9; j++) { s[i][j] = malloc(4); sprintf(s[i][j], "d%1d%1d", i, j); red_declare_variable(RED_TYPE_DISCRETE, 1, 9, "%s", s[i][j]); } } //REDLIB所需的架構 red_end_declaration(RED_NO_REFINED_GLOBAL_INVARIANCE); /* How to access a variable ? */ //RED_print_variables(); //RED_print_xtions(); //RED_verify(); /* Declaration of the 81 slot variable indices as a 9X9 arrays. * Note this is not for the array of slot variable values. * This is only for the slot variable indices. */ do { /* After the completion of the loop, sol should be the MBDD+CRD * that records the solutions to your input board specification. * Initially, we set sol to TRUE. */ //sol是整個程式的主要圖表,一開始我們讓它恆真(總不能一開始就錯了吧...) sol = red_true(); /* Please fill in the code here to calculate the solution for * the given sudoko puzzle. * The details of the main processing body, that you should fill in, include: 1. Read in the values of those given slots on the board and construct the logic formula with the REDLIB procedures. 2. Iteratively restrict the formula you got in step 1 with all the sudoko rules. Now start filling in the main processing body in the following. |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV */ for (i = 0; i < 9; i++){ for (j = 0; j < 9; j++){ //讀取數字(不過用char的方式存 ) //讀到換行就丟了再讀 a = getc(datafile); if (a == '\n') a = getc(datafile); //把讀到的字元換成字串 sprintf(stop, "%c\0", a); //把字串換成數字,用atoi這個有趣函數 c[i][j] = atoi(stop); if (c[i][j] != 0) { //如果讀到非零值,就要加上"某位置=讀到的某數"這個限制條件 //一樣,用到的是red_and sol = red_and(sol, red_diagram("%s==%d", s[i][j], c[i][j])); //把這個東西拿去做前面的函數 sol = slot_constraint(sol, i, j); } } } //因為我們可以發現,不管那格的數字是不是被決定了 //它都應該要拿去做slot_constraint //所以我們對漏網之魚拿去做 slot_constraint //(個人認為(純猜測)如此安排是效率因素) for(i = 0; i < 9; i++) { for(j = 0; j < 9; j++) { if (c[i][j] == 0) sol = slot_constraint(sol, i, j); } } /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| After the main processing body of the loop, * we are now ready to print out the solution board specification. * We do this in two ways. * In the first way, we print the board as a 9X9 char array. * We do this by first invoking the depth-first traversing procedure * red_process_DFS() for MBDD+CRD. * For each node in the MBDD+CRD, red_process_DFS() process the * node with procedure max_rec() and each arc of the node with * procedure arc_noop(). * * In the second way, we print the MBDD+CRD of sol as a single-line * Boolean formula. */ /* red_print_diagram(sol); */ //似乎是要算總解數的樣子 //(小聲說)但是這個算到的數字跟印出來的都不一樣...這條函數似乎... i = red_diagram_discrete_model_count(sol); //印出來唄 switch (i) { case 0: fprintf(RED_OUT, "\nNo solutions!\n"); break; case 1: fprintf(RED_OUT, "\nOnly 1 solution\n"); break; default: fprintf(RED_OUT, "\nTotal %1d solutions!\n", i); break; } //接下來的我不太懂... //不過,可以理解為就是純粹的印出吧 //既然是印出,參數改一改要印出別的東西應該也是可行的 cube = red_first_cube(sol); for (; cube != red_false(); cube = red_next_cube(sol)) { fprintf(RED_OUT, "\n\nOne solution:\n"); flag = FLAG_SINGLE; for (i = 0; i < 9; i++) { for (j = 0; j < 9; j++) { red_get_cube_discrete_value( cube, s[i][j], &(lb[i][j]), &(ub[i][j]) ); if (lb[i][j] < ub[i][j]) flag = FLAG_MULTIPLE; fprintf(RED_OUT, "%1d", lb[i][j]); } fprintf(RED_OUT, "\n"); } if (flag != FLAG_MULTIPLE) continue; fprintf(RED_OUT, "\n\nOne more solution:\n"); for (i = 0; i < 9; i++) { for (j = 0; j < 9; j++) { fprintf(RED_OUT, "%1d", ub[i][j]); } fprintf(RED_OUT, "\n"); } fprintf(RED_OUT, "\n"); } fprintf(RED_OUT, "\n-----------------------------------------------\n"); // red_print_line(sol); // fprintf(RED_OUT, "\nsolution diagram:\n"); // red_print_diagram(sol); break; } //如果先前抓到檔案結束之類的,會跳出吧 //不過說實在的我不清楚這整個do while的運作方式 while( strcmp(fgets(stop, 30, datafile), "end") != 0 && strcmp(fgets(stop, 30, datafile), "END") != 0 ); //結束了~收個尾,記得關檔 red_end_session(); fclose(datafile); } /* main() */ //一個滿奇怪的地方是,記得最最後面留一行空行 //不然用linux來compile的時候會有意見(不要問我為什麼) --------------------------------------------- 大概是這樣吧 我把它修剪成剛好貼在一般看B的寬度了 覺得在這邊看不清楚的人(應該是每個人吧= =) 把它複製到文字編輯器裡 不然就... http://www.badongo.com/file/22378576 裡面有.c檔~ 嗯嗯 後來我(以為)有寫出教授要的code啦 放了幾個輸入檔還沒有錯(只是跑很慢,慢到差點以為系計中電腦當了) 那就祝王凡班的各位都寫出來唄~ 我該回去寫普物報告了@@ -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.112.241.41

05/02 17:05, , 1F
Dev-C++內建就是用gcc來編譯的,跟在linux下是一樣的
05/02 17:05, 1F

05/02 17:07, , 2F
只是平台不一樣而已(如果只用standard函式庫的話)
05/02 17:07, 2F

05/02 17:20, , 3F
是哦 我都傻傻拿到系工作站compile...XD
05/02 17:20, 3F

05/02 18:29, , 4F
有神快拜啊!!!
05/02 18:29, 4F

05/02 19:07, , 5F
強者
05/02 19:07, 5F

05/02 21:27, , 6F
快收精華區
05/02 21:27, 6F

05/03 11:50, , 7F
大公無私阿~~
05/03 11:50, 7F

05/04 17:07, , 8F
#1BpV8-fs (Linux) 這好像有講到結尾換行問題的說
05/04 17:07, 8F

05/05 06:25, , 9F
哦 真的耶~ 感謝樓上~
05/05 06:25, 9F

05/05 22:14, , 10F
真的太感動了XD
05/05 22:14, 10F
文章代碼(AID): #1BtJkGxI (NTUEE113HW)