2008年3月30日 星期日

小考六(C) 題目

/* C Programming, Quiz 6C */
/*
小考六題目:完成一個C語言函數,getMinIndex。
函數輸入一個 二維陣列,輸出最小值的列索引值

函數輸入值:一個 二維陣列。
函數輸出值:一個 int。
題目輸入:如下列陣列
題目輸出:印出小值的列索引值。
*/

#define ROW 4
#define COL 12

int W[ROW][COL] = {{ 41, 467, 334, 500, 169, 724, 478, 358, 962, 464, 705, 145},
{281, 827, 961, 491, 995, 942, 827, 436, 391, 604, 902, 153},
{673, 386, 21, 745, 924, 72, 270, 829, 777, 573, 97, 512},
{313, 756, 321, 558, 646, 982, 481, 144, 196, 222, 129, 161}};

int main()
{
return 0;
}

解答下載
返回小考目錄
回到首頁

Problem 10018 Reverse and Add,反轉再相加

這題是有關palindrome(迴轉字)的計算。
將輸入的數字倒轉過來,例如1234變成4321。然後與原數相加,產生新的數字。在重複相加的結果,如果數值倒轉過來與原數字相同,則這個數字就叫做palindrome(迴轉字)。
這題要列印出某輸入數字算成palindrome所需的加法次數及這個palindrome。
下列C語言程式碼是解答的重點部份,digitNum是輸入值的位數,reverse是倒轉過來的新數字,剩下來程式部分如相加、及判斷結束的條件應該很容易就OK了。
digitNum = floor(log10(num)+1);
for (j=digitNum-1; j>=0; j--)
{
reverse += num%10 * (int)(pow(10,j)+0.001);
num /= 10;
}

p10018題目連結
回ACM題庫目錄
回首頁

2008年3月28日 星期五

如何學好C語言─陳泳叡

這篇文章是目前就讀實踐大學高雄校區資管系的同學的學習心得與建議,學C語言經過一些努力,必有所成,這位同學已成為程式高手,讀完這篇,預祝所有C語言初學者能有所體會。

liangk

----------------------------------------------

如何學好C語言─陳泳叡
很多人一開始C語言沒有學好,到了後來覺醒了,想要開始好好學習。上課時很認真聽,卻有聽沒有懂,後來又放棄了。學習C語言我覺得剛開始學的一個月是打基礎最重要的時候,建議每天摸索個1~2小時或更多。

在一開始,我的練習方法是每個範例都先照著打一次,一開始照著打一定會有打錯的地方,例如可能忘了打”;”,那這時候就可以對照著課本檢查一次,看是錯在哪裡。接著你可以試著去改變一些變數,要本著實驗的精神去玩它。

雖然老師小考時是可以Open Book的,但是我覺得課本裡很多該背的還是要去背(例如:如何設立變數,迴圈的應用,函數的應用‧‧‧),要是基本的東西沒背,考試的時候在那邊猛翻書,就算讓你翻到可以應用的範例好了,你也不見得會應用,而且老師出的小考考題是需要用到很多範例去組合的,試想腦袋裡一點東西都沒有,純粹靠翻課本找範例,這樣等你翻完課本我想大概也快要下課了吧!

學習C語言我覺得最主要的不是學習如何編寫程式碼,而是學習邏輯思考。寫程式都是要一步一步來的,要是一點邏輯概念都沒有,是很容易會忽略了某些條件而造成寫出來的程式不符合要求。

訓練邏輯我覺得梁老師一開始出的作業一,是最佳的訓練邏輯題目,如果是初學者一開始面對這個問題時,通常會覺得很痛苦,會覺得腦袋快轉不過來了,因此建議一開始先花一個禮拜的時間去想題目的邏輯和畫流程圖再花五天左右的時間去編寫程式碼(千萬不要到了要交作業的那禮拜才開始去動作業) ,流程圖對於初學者的幫助是很大的,能讓初學者省下很多的麻煩。

最後要告訴各位的是,作業一定要自己去寫,一開始一定會有很多地方都想不明白,當絞盡腦汁也無法解決問題的癥結在哪時,這時候就可以去問詢問老師,相信老師會本著熱誠的去教你,老師不會幫忙做作業但是他會說出你的作業的關鍵在哪裡,相信很快的問題一定可以迎刃而解,而且自我的水準也會有所提高。要是有空可以去老師的考古題網站去玩玩看那些題目,祝各位C語言都All Pass。

C++是一個奇跡,活著就是勇氣!C++是一段旅途,有磨礪就是人生!

電腦是死的,人是活的,希望大家是玩C語言,而不是被C語言玩。

資一甲,陳泳叡

2008年3月22日 星期六

C 程式設計作業六,陣列與字串之使用:解題

這題的C語言作業雖然是要做乘法,但是被乘數只有兩位數,所以,最簡單的作法是用加法來完成。也就是讀進來的第一個字串去累加,累加的次數由讀入的第二個數字決定。
完整的解答如下,我以add(prod, temp)函數呼叫來完成加法,使用addOn來處理進位。另外讀進來的數字字串最高位數是在str[0]的位置,所以轉成temp時要顛倒過來。digitNo是用來計算答案的位數,列印時前置的0才可以不用印出來。

#include <stdio.h>
#include <stdlib.h>

#define MSIZE 34

void multiply(int prod[], int multiplier[], int num);
void add(int prod[], int temp[]);
int main(void)
{
int prod[MSIZE], temp[MSIZE];
char str[MSIZE];
int i, num, digitNo;

while (1)
{
scanf("%s%d", str, &num);
if (!strcmp(str,"0") && num==0)
break;
for (i=0;i<MSIZE;i++)
{
prod[i]=0;
temp[i]=0;
}
for (i=strlen(str)-1;i>=0;i--)
temp[strlen(str)-i-1] = str[i]-48;
/*
for (i=strlen(str)-1;i>=0;i--)
printf("%d",temp[i]);
printf("\n");
*/
for (i=0;i<num;i++)
add(prod, temp);
digitNo = 0;
for (i=MSIZE-1;i>=0;i--)
if (prod[i]!=0)
{
digitNo = i;
break;
}
for (i=digitNo;i>=0;i--)
printf("%d",prod[i]);
printf("\n");
}


return 0;
}

void add(int prod[], int temp[])
{
int addOn=0, i;
for (i=0;i<MSIZE;i++)
{
prod[i] = prod[i]+temp[i] + addOn;
if (prod[i]>9)
{
prod[i] %= 10;
addOn = 1;
}
else
addOn = 0;
}
}

作業六題目
回到作業目錄
回到首頁

2008年3月19日 星期三

Problem 10019 Funny Encryption Method,有趣的密碼編碼

這個ACM題目看起來又臭又長,其實只有兩個重點,將一個數字N,看成10進位與16進位的數字,然後分別進行10進位轉換2進位,與16進位轉換2進位,然後將這兩個二進位的數字中的 1 進行加總,再分別列印出來。
這兩個要求在C語言中可以用 stdlib.h中的itoa()輕易解決。在Dev C++中,用itoa(N, X1, 2)可以求得二進位字串。但是,ACM的裁判系統找不到itao函數,而產生compile error,這段過程是很令人氣結的。

解決之道是我自己再寫一個函數:srt2bin(),將數字字串s,經過以base為底換算成十進位後,再轉換成二進位的字串。存在字串 b 中。數字字元與一般整數型態轉換,必須加減 48 。
void str2bin(char s[], char b[], int base)
{
int i, j, sum=0, prod, len=strlen(s);
char temp[20];
for (i=0;i<len;i++)
{
prod=1;
for (j=len-i-1;j>0;j--)
prod *= base;
sum += prod * (s[i]-48);
}
i = 0;
while (sum!=0)
{
b[i] = sum%2+48;
sum /= 2;
i++;
}
b[i] = '\0';
}

p10019題目連結
回ACM題庫目錄
回首頁

2008年3月14日 星期五

Problem 10035 Primary Arithmetic,小學算術

簡單的數學加法題目,非常適合C語言初學者,做為入門學習用。題目要求每次讀入兩個整數,求出兩數相加的過程中,產生了多少的進位。這種進位的數量可以用來決定這兩數相加的題目困難度。我想小學生的數學老師或許用的到吧。
程式的重點部份如下。雖然範例的數字是相同位數,可是真正的測試應該會有不同吧。迴圈中的兩個數字num1,num2每次都取出個位數,然後看addOne是否有產生進位的情形,有就記錄起來。迴圈的執行在兩個數都為0時停止。
        while (num1!=0 || num2!=0)
{
d1 = num1 % 10;
d2 = num2 % 10;
num1 /= 10;
num2 /= 10;
addOne = (d1+d2+addOne)/10;
if (addOne==1)
count++;
}

p10035題目連結
回ACM題庫目錄
回首頁

2008年3月12日 星期三

Problem 10038 Jolly Jumpers,計算數列差

這個題目說的不是很明白,文中說明Jolly jumper是一個數列序列,內容包含了1到n-1之間的每一個數,可是題目所舉例之相鄰數字差的絕對值為連續的 3 2 1,所以會誤解說是不是要按大小排列,其實,題目中的Jolly jumper所指的1到n-1 之數列是要求,每一個數字都要有,但不用按序排,可以是任何排列。只是範例恰巧由大到小(八成是故意的)。
下列附上程式的重點內容,我用了一個整數陣列來存放這些差值,每個差值出現一次,就在該陣列的相關位置累進 1,算完後,只要看看這個陣列的每個值,如果都是 1,那就是Jolly,只要有 1 以外的數字,就不是Jolly。
for (i=0;i<seqNum-1;i++)
{
scanf("%d",&x2);
if (x1>x2)
diff = x1-x2;
else
diff = x2-x1;
x1 = x2;
if (0<diff && diff<seqNum)
n[diff]++;
else
{
isJolly = 0;
}
}

p10038題目連結
回ACM題庫目錄
回首頁

2008年3月9日 星期日

Problem 494 Kindergarten Counting Game,幼稚園算字遊戲

這題就像完成Office Word中計算字數的功能,這裡算的是英文字,所以只用ASCII值來判斷讀進來的字母是否為A-Z或a-z,只要是,就處於文字狀態,否則處於間隔狀態。只要狀態改變且進入文字狀態,wordCount就累進 1。重點程式碼如下
if ((str[i]>=65&&str[i]<=90) || (str[i]>=97&&str[i]<=122))
isLetter = 1;
else
isLetter = 0;
if (status != isLetter)
{
if (isLetter==1)
wordCount++;
status = isLetter;
}

p494題目連結
回ACM題庫目錄
回首頁

2008年3月7日 星期五

Problem 488 Triangle Wave,三角波形

這個題目非常適合初學 for 迴圈練習,難易程度比考試系列中的期末考(C)期末考(D)還簡單,用到四個 for 迴圈,就解決了。
重點程式碼如下所示:
        scanf("%d%d", &, &freq);
for (j=0; j<freq; j++)
{
if (first)
first=0;
else
printf("\n");

for (k=1;k<=amp;k++)
{
for (n=1;n<=k;n++)
printf("%d", k);
printf("\n");
}
for (k=amp-1;k>=1;k--)
{
for (n=1;n<=k;n++)
printf("%d", k);
printf("\n");
}
}

紅色部分是處理最後一行不列印換行的方法,也就是在一開始先決定不印,此後一律進行換行列印。
p488題目連結
回ACM題庫目錄
回首頁

2008年3月6日 星期四

Problem 913 Joana and the Odd Numbers,喬安娜與奇數

這是一個初學者練習解題的好機會,這個可愛的喬安娜愛玩奇數,所以排列了奇數如下:

1
3 5 7
9 11 13 15 17
19 21 23 25 27 29 31

全部都是奇數,每一列的數量也是奇數,題目要求將最後面的三個數字相加後印出。
如果你要自己練習,請先不要看下面的解題經過。

解題過程:
行數  數字數量(n)  最後的值
1 1 (1) x 2 - 1
2 3 (1+3) x 2 - 1
3 5 (1+3+5) x 2 - 1
4 7 (1+3+5+7) x 2 - 1
5 9 (1+3+5+7+9) x 2 - 1
...
(n+1)/2 n (1+3+...+n) x 2 - 1

所以最後的值,可以直接用公式 1+3+...+n = ((1+n)*(n+1)/2)/2
(上底為1,下底為n,高為(n+1)/2)
經過簡化:最後值的公式是(n+1)*(n+1)/2 -1
最後三個數字和為:((n+1)*(n+1)/2-3)*3
所以程式的重點如下:
    while (scanf("%d", &n)!=EOF)
{
a = (((long long)(n+1)/2)*((n+1)/2)*2-3)*3;
printf("%lld\n", a);
}


a 必須宣告為 long long
做這一題時,我的Dev C++無法列印出正確的 long long答案,找了很多說法,我採用了其中的一個說法,那就是,你的電腦印不出來,不代表ACM線上裁判系統也印不出來,所以,上傳後,居然就過了。呵呵。
913題目連結
回ACM題庫目錄
回首頁