] > Answer

解答集

目次

第1回

演習1-1

演習1-2

演習1-3


/* testf.c */
#include <stdio.h>
int combination(int n,int m);
main(){
  int in1[]={0,1,1,5,-1};
  int in2[]={0,0,1,2,-1};
  int out[]={1,1,1,10,-1};
  int i,result;

  for(i=0;in1[i]!=-1;i++){
    result=combination(in1[i],in2[i]);
    printf("combination(%d,%d)=%d: ",in1[i],in2[i],result);
    if(out[i]==result){
      printf("Ok\n");
    }else{
      printf("NG\n");
    }
  }
}

第2回

演習2-1

  1. # define EOF (-1)
  2. extern int getchar (void);
  3. extern int printf (__const char *__restrict __format, ...);

演習2-2

演習2-3

演習2-4

第3回

演習3-1


1
2
1
2
2
0
2

第4回

演習4-1

演習4-2

低速版


#include <stdio.h>
int fibo(int n){
  if(n==0){ return 1; }
  if(n==1){ return 1; }
  return fibo(n-1)+fibo(n-2);
}
main(){
  printf("%d\n",fibo(45));
}

高速版


#include <stdio.h>
#include <stdlib.h>
#define N 100
int a[N]={0};
int fibo(int n){
  if(n>=N){fprintf(stderr,"Overflow at %d\n",n);exit(2);}
  if(a[n]>0){ return a[n];}
  if(n==0){ return 1; }
  if(n==1){ return 1; }
  a[n]=fibo(n-1)+fibo(n-2);
  return a[n];
}
main(){
  printf("%d\n",fibo(45));
}

演習4-3

低速版


#include <stdio.h>
int ack(int n, int m){
  if(n==0){return m+1;}
  if(m==0){return ack(n-1,1);}
  return ack(n-1, ack(n,m-1));
}
main(){
  int i;
  for(i=0;i<=4; i++){
    printf("ack(%d,1)=%d\n",i,ack(i,1));
  }
}

高速版


#include <stdio.h>
#include <stdlib.h>
#define MAX 100000
int a[5][MAX]={0};
int ack(int n, int m){
  if(m>=MAX){fprintf(stderr,"Overflow! m=%d\n",m);exit(2);}
  if(a[n][m]!=0){return a[n][m];}
  if(n==0){a[n][m]=m+1;}
  else if(m==0){a[n][m]= ack(n-1,1);}
  else {a[n][m]=ack(n-1, ack(n,m-1));}
  return a[n][m];
}
main(){
  int i;
  for(i=0;i<=4; i++){
    printf("ack(%d,1)=%d\n",i,ack(i,1));
  }
}

演習4-4


#include >stdio.h>
hanoi(int n, char x, char y, char z){
  if(n==1){
    printf("move 1 from %c to %c\n",x,y);
    return;
  }else{
    hanoi(n-1,x,z,y);
    printf("move %d from %c to %c\n",n,x,y);
    hanoi(n-1,z,y,x);
    return ;
  }
}
main(){
  hanoi(4,'a','b','c');
}

演習4-5


void Turtle::home(int xsize, int ysize){
  x=(double)_x;
  y=(double)_y;
  angle=0.0;
}
void Turtle::forward(int n){
  double dx,dy;
  dx=n*cos(angle*3.141592/180);
  dy=n*sin(angle*3.141592/180);
  line(x,y,x+=dx,y+=dy);
}
void Turtle::turn(double dangle){
  angle += dangle;
}
void Turtle::skip(int n){
  double dx,dy;
  dx=n*cos(angle*3.141592/180);
  dy=n*sin(angle*3.141592/180);
  x+=dx;
  y+=dy;
}

演習4-6

tree.cpp
  1. box.cpp を tree() の前にコピーする。
  2. box.h を読み込む部分を tree.h にする。
  3. tree のプロトタイプを作る。
  4. case WM_PAINT の部分を tree を呼ぶようにする。

したがって、 tree.cpp は次のようになる。


#include <Windows.h>
#include "box.h"
#include "turtle.h"
void tree(Turtle &t, int length);
BOOL CALLBACK box( HWND, UINT, WPARAM, LPARAM );
int x_size, y_size;

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
  DialogBox( hInstance, "DLG_DATA", HWND_DESKTOP, (DLGPROC)box ) ;
  return 0;
}

BOOL CALLBACK box( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
  static HWND hwnd_gr;

  switch(msg){
  case WM_INITDIALOG:{
    HDC hdc = GetDC(hwnd);
    TEXTMETRIC tm;
    GetTextMetrics(hdc, &tm);
    ReleaseDC(hwnd, hdc);
    y_size = (int) (YSIZE/8.0*(float)tm.tmHeight);
    x_size = (int) (XSIZE/4.0*(float)tm.tmAveCharWidth);
    return TRUE;
  }
  case WM_PAINT:{
    Turtle t(hwnd);
    t.home(x.size/2,y_size/2);
    tree(t,50);
    return True;
  }
  case WM_COMMAND:
    switch(LOWORD(wp)){
    case IDCANCEL:
      EndDialog( hwnd, -1);
      return TRUE;
    }
  }
  return FALSE;
}
void tree(Turtle &t, int length){
  if(length < 1){
    t.turn(180);
    return;
  }
  t.forward(length);
  t.turn(30); tree(t, length/2);
  t.turn(120); tree(t, length/2);
  t.turn(30); t.skip(length);
  return;
}
tree.h
box.h を単純にコピーする。
tree.rc
box.rc をコピーして、box という単語を tree に置き換える(二箇所)。
Makefile
TARGET=treeにする。

演習4-7

後日書きます

第5回

演習5-1

演習5-2

演習5-3

演習5-4

stack.h


typedef struct st {
  char *string;
  struct st *pointer;
} stack;
int empty();
int push(char * x);
char * pop();

stack.c


#include <stdio.h>
#include "stack.h"
stack *stackpointer=NULL;
int empty(){
  return stackpointer==NULL;
}
int push(char * x){
  stack *next=(stack *) malloc(sizeof(stack));
  if(next!=NULL){ /* メモリが確保できないと NULL が返される */
    next->string = x;
    next->pointer=stackpointer;
    stackpointer=next;
    return 1;
  }else{
    return 0;
  }
}
char * pop(){
  char * x=stackpointer->string;
  stack *p=stackpointer;
  stackpointer=p->pointer;
  free(p);
  return x;
}

parser.c


#include <stdio.h>
#include <string.h>
#include "stack.h"

void error(int i){
  fprintf(stderr,"error %d\n",i);
  exit(i);
}
main(){
  int flag=0;
  int l;
  char buffer[50];
  char c;
  char *p,*q;
  while((c=getchar())!=EOF){
    if(flag){  /* flag==1 タグ内解析中 */
      if((c==' ')||(c=='>')){/* 要素名終了 */
	*p='\0';
	flag=0;
	if(buffer[0]=='/'){ /* 終了タグ処理 */
	  if(empty()){error(1);}/* 開始タグ無し */
	  else{
	    q=pop();
	      printf("%s popped\n",q);
	    if(strcmp(q,buffer+1)!=0){
	      error(2); /* 不一致 */
	    }else{
	      free(q);/* Ok */
	    }
	  }
	}else{
	  /* 開始タグ処理(プッシュ) */
	  l=strlen(buffer);
	  if((q=(char *)malloc((l+1)*sizeof(char)))!=NULL){;
            strcpy(q,buffer);
	    push(q);
	    printf("%s pushed\n",q);
	  }else{
	    error(4);
          }
	}
      }else{ /* タグの要素名の採集 */
	*p++=c;
      }
    }else{ /* flag==0 タグの外 */
      if(c=='<'){
	p=buffer;
	flag=1;
      }
    }
  }
  if(empty()){
    printf("Ok.\n");
  }else{
    error(3);
  }
}

Makefile


TARGET = parser
$(TARGET):	parser.o stack.o
	$(CC) -o $@ $^
stack.o:	stack.h
parser.o:	stack.h

test0.xml(Ok)


<body>
<h1>解答集</h1>
<h2>目次</h2>
<ul>
<li><a href="#1">第1回</a></li>
<li><a href="#2">第2回</a></li>
<li><a href="#3">第3回</a></li>
<li><a href="#4">第4回</a></li>
<li><a href="#5">第5回</a></li>
</ul>
</body>

test1.xml(error 1)


<h1>解答集</h1>
<h2>目次</h2>
<ul>
<li><a href="#1">第1回</a></li>
<li><a href="#2">第2回</a></li>
<li><a href="#3">第3回</a></li>
<li><a href="#4">第4回</a></li>
<li><a href="#5">第5回</a></li>
</ul>
</body>

test2.xml(error 2)


<body>
<h1>解答集</h1>
<h2>目次</h2>
<ul>
<li><a href="#1">第1回</a></li>
<li><a href="#2">第2回</a></li>
<li><a href="#3">第3回</li></a>
<li><a href="#4">第4回</a></li>
<li><a href="#5">第5回</a></li>
</ul>
</body>

test3.xml(error 3)


<body>
<h1>解答集</h1>
<h2>目次</h2>
<ul>
<li><a href="#1">第1回</a></li>
<li><a href="#2">第2回</a></li>
<li><a href="#3">第3回</a></li>
<li><a href="#4">第4回</a></li>
<li><a href="#5">第5回</a></li>
</ul>

error 4 はメモリーオーバーなのでテストデータは作らず

演習5-5


#include <stdio.h>
typedef struct st {
  int num;
  struct st *pointer;
} stack;
stack *stackpointer=NULL;
int empty(){
  return stackpointer==NULL;
}
int push(int x){
  stack *next=(stack *) malloc(sizeof(stack));
  if(next!=NULL){ /* メモリが確保できないと NULL が返される */
    next->num = x;
    next->pointer=stackpointer;
    stackpointer=next;
    return 1;
  }else{
    return 0;
  }
}
int pop(){
  int x=stackpointer->num;
  stack *p=stackpointer;
  stackpointer=p->pointer;
  free(p);
  return x;
}
main(){
  char *p;
  char first;
  int i;
  int x,y;
  char *formula[] ={"2","3","*","4","5","*","+",NULL};
  for(i=0; formula[i]!=NULL; i++){
    first=*(formula[i]);
    switch(first){
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
      push(atoi(formula[i]));
      break;
    case '+':
      y=pop();
      x=pop();
      push(x+y);
      break;
    case '*':
      y=pop();
      x=pop();
      push(x*y);
      break;
    }
  }
  printf("%d\n",pop());
}

第6回

演習6-1

14種類

演習6-2

解答作成中

演習6-3

n 頂点の場合、他の n-1 頂点とそれぞれ結ぶには、 n 個の中から 2 個取り 出す場合の数になるので、 n n-1 2

演習6-4

n 頂点それぞれについて、 m 個の頂点と辺を結ぶので、 mn。


坂本直志 <sakamoto@c.dendai.ac.jp>
東京電機大学工学部情報通信工学科