程式技巧實做範例:卡布列克常数 (Kaprekar Constant)

Home Home
引用 | 編輯 a7811311622
2013-06-09 16:35
樓主
推文 x1
久違的教學文呢…

這次解釋的是不論是SMA還是其他高階語言都會用到的一些技巧…
那這次的的範例是從某處看到後引起好奇而寫的…
題目的規則:
給定一個整數,你必須以下列的方式產生出另一個整數:
1. 將該數的每一個位數由大到小排列。
2. 將該數的每一個位數由小到大排列。
3. 將上述第一步驟所得的數減掉第二步驟所得的數,產生另一個數。
4. 重複上述步驟,直到出現重複的數字為止。
並輸出該數值所產生出"執行次數"。

範例:
Input:
1234

Output:
4321
1234
4321 - 1234 = 3087
8730 -   378 = 8352
8532 - 2358 = 6174
7641 - 1467 = 6174
最後輸出的數值:4
以上的規則是來自黑洞數
至於數學什麼的身為過期的大學生早就忘記那是什麼啦…

好啦…雖然這好像也是個重點…姑且無視…
這個題目的規則用到的技巧有三個(大概):

1在陣列中比較數值大小並取得最大最小值的陣列位置
2將陣列中的數值重新排列,每個人的排法可能會有差異,我是用「不重複的隨機亂數」這寫法
3當執行次數只有一次時讓未知的執行次數用迴圈跑出來

然後這教學的重點…程式碼:
故意寫成CS版的…某些學生以為撿到現成的程式想偷懶複製貼上的話…這樣不行喔~╱/( ◕‿‿◕ )\╲
複製程式
public plugin_init()
{
    register_plugin("Kaprekar constant", "1.0", "MyChat:a7811311622")
    register_concmd("Kaprekar_constant", "kaprekar_constant") // 註冊控制台指令
}

public kaprekar_constant(id)
{
    new text[100], text_1[100], text_2[100], text_3[100]
    new i, j, k, num
    read_argv(1, text, sizeof text - 1) // 讀取輸入的數值
    
    if (!(3 <= strlen(text) <= 4)) return PLUGIN_HANDLED; // 卡布列克常數三位數和四位數的黑洞數只有一個,才列入程式考量
    
    while (!equal(text, text_3)) // 只要第一步驟減掉第二步驟的數和原本的數一樣就終結迴圈
    {
        num++ // 計數
        if (strlen(text_3)) copy(text, charsmax(text), text_3) // 第三步驟有算出來數才執行第四步驟
        
        copy(text_1, charsmax(text_1), text) // 最初的數複製給第一步驟的數
        copy(text_2, charsmax(text_2), text) // 最初的數複製給第二步驟的數
        
        // 個人比較懶,不想每個位數都要計算,所以比大小我就直接拿字元的ASCII碼比大小
        // '0' = 48、'1' = 49、'2' = 50......'9' = 57
        for (i = 0; i < strlen(text_1); i++) // 從大排到小
        {
            new max = 0 // ASCII碼最小從0開始
            for (j = i; j < strlen(text_1); j++) // 掃描一遍每位的數字大小,從中比較並取得最大的數
            {
                if (text_1[j] > max)
                {
                    max = text_1[j] // 這裡的max是用來記憶最大的數值是多少
                    k = j // 記憶最大數的陣列位置
                }
            }
            // 掃描過後將最大數的位置和最前面數字的位置交換,這寫法常見於「不重複的隨機亂數」
            max = text_1[k] // 這裡的max不再是比大小,只是單純的暫存數,不想又宣告一個 temp 嘛…
            text_1[k] = text_1[i]
            text_1[i] = max // 如果沒用暫存數記憶的話,這時的text_1[k]已經是text_1[i]了,程式就不記得text_1[k]的數是多少了
            // i = 0 時我將數字中最大的數和最左邊(最高位數)的數交換了,接下來的 j = i 在比較時就不會比較到上一個最大數
            // 例如範例 1234 這時便成 4231,第二層迴圈因為 j = i 會取掃描 231 來比大小,i = 1 時就變成 4321
        }
        // 打了好多字…懶的打…同上…(<ゝω・)
        for (i = 0; i < strlen(text_2); i++)
        {
            new min = 255 // 比大小時「最大」的數總是給最小的…「最小」的數反而給最大的…
            for (j = i; j < strlen(text_2); j++)
            {
                if (text_2[j] < min)
                {
                    min = text_2[j]
                    k = j
                }
            }
            min = text_2[k]
            text_2[k] = text_2[i]
            text_2[i] = min
        }
        num_to_str(str_to_num(text_1) - str_to_num(text_2), text_3, charsmax(text_3)) // 第三步驟
        console_print(id, "%s %s %s %s %d", text, text_1, text_2, text_3, num) // 輸出所有的數和目前跑了幾次迴圈
    }
    
    return PLUGIN_HANDLED;
}
結果:


反正這教學跟現在€$◎無關…不覺得會被盜…
雖然和CS也無關就是了…

獻花 x0
引用 | 編輯 弒血
2013-06-09 17:11
1樓
  
a78大~ 我只能說 佩服到底
想不到 過程居然要這麼高難

獻花 x1
引用 | 編輯 Marchillus
2013-06-12 17:49
2樓
  
這個   根本要IQ高於150才能理解0-0

獻花 x0
引用 | 編輯 弒血
2013-06-12 22:21
3樓
  
下面是引用 ffgh478tw 於 2013-06-12 17:49 發表的 Re:]: 到引言文
這個   根本要IQ高於150才能理解0-0



光是看到 字串的排列 與應用 就讓人 頭暈


話說 a78大 IQ > 150 ? 

獻花 x0
引用 | 編輯 a7811311622
2013-06-12 22:53
4樓
  
正常人類 IQ >= 140 就已經是天才了…
如果我的 IQ 有 140 早就被國家抓去為國家服務而不會在這發廢文了…

獻花 x0
引用 | 編輯 弒血
2013-06-13 00:09
5樓
  
下面是引用 a7811311622 於 2013-06-12 22:53 發表的 : 到引言文
正常人類 IQ >= 140 就已經是天才了…
如果我的 IQ 有 140 早就被國家抓去為國家服務而不會在這發廢文了…



話也不能這麼講


有很多高手 都躲在暗處 做一些 意想不到的事情


搞不好 在研究 超人類的事

獻花 x0
引用 | 編輯 a23107971a
2013-06-14 17:24
6樓
  
又是程式碼的東西= =
但這些東西部都有一定的規則只要懂這些規則就能大略理解了....
但本人只是個超新手 表情

獻花 x0
引用 | 編輯 ofgm4521
2013-06-23 10:59
7樓
  
謝謝OwO 表情

獻花 x0
引用 | 編輯 zxzyman
2014-04-04 19:55
8樓
  
我上程式設計約5堂...

雖然只學到毛的部位

不過我以學習的心態   完整的閱讀2次        ~(應該沒有人會看第二次)




老實說我看不懂                  (一定有人會說: 阿你看無,是在看蝦米)

但能知道內容約是不斷的定義 讓它會運算 

(像您內容說,不想打太多字,所以用公式的方式處理)


我看到最下面 第三部導出時 有一種豁然開朗的感覺

一夕之間複雜的文字 變成會自動運算   這是我覺得最有趣的地方~

獻花 x0