2024年度「プログラミング言語1」「プログラミング言語演習」のページ

練習問題

2024年6月20日出題

  1. 三角形の内接円と辺の接点を結ぶ三角形をジェルゴンヌ三角形と呼ぶ。

    ジェルゴンヌ三角形

    三角形 ABC のジェルゴンヌ三角形を ABC とおくと、位置ベクトルに関して以下の関係が成り立つ。 { A = a + b c 2 a B + a b + c 2 a C B = a + b c 2 b A + a + b + c 2 b C C = a b + c 2 c A + a + b + c 2 c B ただし、 a=|BC| b=|CA| c=|AB|

    • 三角形の頂点の座標を入力してそのジェルゴンヌ三角形のジェルゴンヌ三角形の頂点の座標を出力するプログラムを、以下のように書いた。

      ジェルゴンヌ三角形のジェルゴンヌ三角形

      #include <stdio.h>
      #include <math.h>
      
      int
      main()
      {
      	double	xA, yA, xB, yB, xC, yC;
      	double	xA1, yA1, xB1, yB1, xC1, yC1;
      	double	xA2, yA2, xB2, yB2, xC2, yC2;
      	double	a, b, c, sa, sb, sc;
      	double	a1, b1, c1, sa1, sb1, sc1;
      
      	scanf("%lf%lf%lf%lf%lf%lf", &xA, &yA, &xB, &yB, &xC, &yC);
      	a = hypot(xB - xC, yB - yC);
      	b = hypot(xC - xA, yC - yA);
      	c = hypot(xA - xB, yA - yB);
      	sa = (b + c - a) / 2;
      	sb = (c + a - b) / 2;
      	sc = (a + b - c) / 2;
      	xA1 = fma(xB, sc, xC * sb) / a;
      	yA1 = fma(yB, sc, yC * sb) / a;
      	xB1 = fma(xC, sa, xA * sc) / b;
      	yB1 = fma(yC, sa, yA * sc) / b;
      	xC1 = fma(xA, sb, xB * sa) / c;
      	yC1 = fma(yA, sb, yB * sa) / c;
      	a1 = hypot(xB1 - xC1, yB1 - yC1);
      	b1 = hypot(xC1 - xA1, yC1 - yA1);
      	c1 = hypot(xA1 - xB1, yA1 - yB1);
      	sa1 = (b1 + c1 - a1) / 2;
      	sb1 = (c1 + a1 - b1) / 2;
      	sc1 = (a1 + b1 - c1) / 2;
      	xA2 = fma(xB1, sc1, xC1 * sb1) / a1;
      	yA2 = fma(yB1, sc1, yC1 * sb1) / a1;
      	xB2 = fma(xC1, sa1, xA1 * sc1) / b1;
      	yB2 = fma(yC1, sa1, yA1 * sc1) / b1;
      	xC2 = fma(xA1, sb1, xB1 * sa1) / c1;
      	yC2 = fma(yA1, sb1, yB1 * sa1) / c1;
      	printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n", xA2, yA2, xB2, yB2, xC2, yC2);
      	return 0;
      }

    • main関数だけですべての処理を行っていて見通しが悪いので、三角形の頂点の座標からそのジェルゴンヌ三角形の頂点の座標を計算する関数gergonne_triangleを使う形に改良した。


      #include <stdio.h>
      #include <math.h>
      
      void
      gergonne_triangle(double, double, double, double, double, double, double *, double *, double *, double *, double *, double *);
      
      void
      gergonne_triangle(
      	double xA, double yA, double xB, double yB, double xC, double yC,
      	double *pA, double *qA, double *pB, double *qB, double *pC, double *qC)
      {
      	double	a, b, c, sa, sb, sc;
      	double	xA1, yA1, xB1, yB1, xC1, yC1;
      
      	a = hypot(xB - xC, yB - yC);
      	b = hypot(xC - xA, yC - yA);
      	c = hypot(xA - xB, yA - yB);
      	sa = (b + c - a) / 2;
      	sb = (c + a - b) / 2;
      	sc = (a + b - c) / 2;
      	xA1 = fma(xB, sc, xC * sb) / a;
      	yA1 = fma(yB, sc, yC * sb) / a;
      	xB1 = fma(xC, sa, xA * sc) / b;
      	yB1 = fma(yC, sa, yA * sc) / b;
      	xC1 = fma(xA, sb, xB * sa) / c;
      	yC1 = fma(yA, sb, yB * sa) / c;
      	*pA = xA1;
      	*qA = yA1;
      	*pB = xB1;
      	*qB = yB1;
      	*pC = xC1;
      	*qC = yC1;
      }
      
      int
      main()
      {
      	double	xA, yA, xB, yB, xC, yC;
      	double	xA1, yA1, xB1, yB1, xC1, yC1;
      	double	xA2, yA2, xB2, yB2, xC2, yC2;
      
      	scanf("%lf%lf%lf%lf%lf%lf", &xA, &yA, &xB, &yB, &xC, &yC);
      	gergonne_triangle(xA, yA, xB, yB, xC, yC, &xA1, &yA1, &xB1, &yB1, &xC1, &yC1);
      	gergonne_triangle(xA1, yA1, xB1, yB1, xC1, yC1, &xA2, &yA2, &xB2, &yB2, &xC2, &yC2);
      	printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n", xA2, yA2, xB2, yB2, xC2, yC2);
      	return 0;
      }
      

    引数を12個も取る関数は使いづらいので、構造体を使ってさらに見通しを良くしたい。

    (動作確認をしたい方は、上の見通しの悪いプログラムも動かして自分の描いたプロと結果を比較すると良い)

    1. 以下に書き足す形でプログラムを完成させよ。


      #include <stdio.h>
      #include <math.h>
      
      struct point {
      	double	x, y;  /*  x : x座標, y : y座標  */
      };
      
      struct triangle {
      	struct point	A, B, C;  /*  A : 頂点A, B : 頂点B, C : 頂点C  */
      };
      
      struct triangle	gergonne_triangle(struct triangle);
      
      /*
       *	関数 gergonne_triangle の定義が必要
       */
      
      int
      main()
      {
      	struct triangle	t, t1, t2;
      
      	scanf("%lf%lf%lf%lf%lf%lf", &t.A.x, &t.A.y, &t.B.x, &t.B.y, &t.C.x, &t.C.y);
      	t1 = gergonne_triangle(t);
      	t2 = gergonne_triangle(t1);
      	printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n", t2.A.x, t2.A.y, t2.B.x, t2.B.y, t2.C.x, t2.C.y);
      	return 0;
      }

    2. 以下に書き足す形でプログラムを完成させよ。


      #include <stdio.h>
      #include <math.h>
      
      struct point {
      	double	x, y;  /*  x : x座標, y : y座標  */
      };
      
      struct triangle {
      	struct point	A, B, C;  /*  A : 頂点A, B : 頂点B, C : 頂点C  */
      };
      
      void	gergonne_triangle(const struct triangle *, struct triangle *);
      
      /*
       *	関数 gergonne_triangle の定義が必要
       */
      
      int
      main()
      {
      	struct triangle	t, t1, t2;
      
      	scanf("%lf%lf%lf%lf%lf%lf", &t.A.x, &t.A.y, &t.B.x, &t.B.y, &t.C.x, &t.C.y);
      	gergonne_triangle(&t, &t1);
      	gergonne_triangle(&t1, &t2);
      	printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n", t2.A.x, t2.A.y, t2.B.x, t2.B.y, t2.C.x, t2.C.y);
      	return 0;
      }

    3. 以下に書き足す形でプログラムを完成させよ。


      #include <stdio.h>
      #include <math.h>
      
      struct point {
      	double	coordinates[2];  /*  coordinates[0] : x座標, coordinates[1] : y座標  */
      };
      
      struct triangle {
      	struct point	vertices[3];  /*  vertices[0] : 頂点A, vertices[1] : 頂点B, vertices[2] : 頂点C  */
      };
      
      struct triangle	gergonne_triangle(struct triangle);
      
      /*
       *	関数 gergonne_triangle の定義が必要
       */
      
      int
      main()
      {
      	struct triangle	t[3];
      
      	scanf("%lf%lf%lf%lf%lf%lf",
                       &t[0].vertices[0].coordinates[0], &t[0].vertices[0].coordinates[1],
                       &t[0].vertices[1].coordinates[0], &t[0].vertices[1].coordinates[1],
                       &t[0].vertices[2].coordinates[0], &t[0].vertices[2].coordinates[1]);
      	t[1] = gergonne_triangle(t[0]);
      	t[2] = gergonne_triangle(t[1]);
      	printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n",
                      t[2].vertices[0].coordinates[0], t[2].vertices[0].coordinates[1],
                      t[2].vertices[1].coordinates[0], t[2].vertices[1].coordinates[1],
                      t[2].vertices[2].coordinates[0], t[2].vertices[2].coordinates[1]);
      	return 0;
      }

    4. 以下に書き足す形でプログラムを完成させよ。


      #include <stdio.h>
      #include <math.h>
      
      struct point {
      	double	coordinates[2];  /*  coordinates[0] : x座標, coordinates[1] : y座標  */
      };
      
      struct triangle {
      	struct point	vertices[3];  /*  vertices[0] : 頂点A, vertices[1] : 頂点B, vertices[2] : 頂点C  */
      };
      
      void	gergonne_triangle(const struct triangle *, struct triangle *);
      
      /*
       *	関数 gergonne_triangle の定義が必要
       */
      
      int
      main()
      {
      	struct triangle	t[3];
      
      	scanf("%lf%lf%lf%lf%lf%lf",
                       &t[0].vertices[0].coordinates[0], &t[0].vertices[0].coordinates[1],
                       &t[0].vertices[1].coordinates[0], &t[0].vertices[1].coordinates[1],
                       &t[0].vertices[2].coordinates[0], &t[0].vertices[2].coordinates[1]);
      	gergonne_triangle(&t[0], &t[1]);
      	gergonne_triangle(&t[1], &t[2]);
      	printf("%15.10f %15.10f %15.10f %15.10f %15.10f %15.10f\n",
                      t[2].vertices[0].coordinates[0], t[2].vertices[0].coordinates[1],
                      t[2].vertices[1].coordinates[0], t[2].vertices[1].coordinates[1],
                      t[2].vertices[2].coordinates[0], t[2].vertices[2].coordinates[1]);
      	return 0;
      }


奈良女子大学生活環境学部文化情報学科生活情報通信科学コース