NTUEE113HW 板


LINE

就是呢 王凡班的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
1F:→ cktigeryang:Dev-C++內建就是用gcc來編譯的,跟在linux下是一樣的 05/02 17:05
2F:→ cktigeryang:只是平台不一樣而已(如果只用standard函式庫的話) 05/02 17:07
3F:→ Helicoid:是哦 我都傻傻拿到系工作站compile...XD 05/02 17:20
4F:推 victoret:有神快拜啊!!! 05/02 18:29
5F:推 xup65p4:強者 05/02 19:07
6F:推 schimtag168:快收 05/02 21:27
7F:推 LouisJC:大公無私阿~~ 05/03 11:50
8F:推 johnjohnlin:#1BpV8-fs (Linux) 這好像有講到結尾換行問題的說 05/04 17:07
9F:→ Helicoid:哦 真的耶~ 感謝樓上~ 05/05 06:25
10F:推 tomap41017:真的太感動了XD 05/05 22:14







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:iOS站內搜尋

TOP