C找到周边三角形的所有可能边

时间:2017-02-04 02:26:12

标签: c

我继续得到c的负数,b只打印23,a就像它应该循环。当我把它放到外围时,至少输出加起来为24。我觉得我只是接近一些愚蠢的逻辑错误。 我的代码如下。

编写程序以查找具有整数边长度和用户的所有三角形 指定的周长。你的程序应该找到所有三元组a,b和c,其中a + b + c是用户指定的周长值。

  1 #include <stdio.h>
  2 
  3 int main() {
  4     int p, a, b, c;
  5     printf("Enter a perimeter: ");
  6     scanf("%d", &p);
  7 
  8     printf("Triangles with a perimeter: " " %d\n", p);
  9 
 10     for(a = 1; a < p; a++) {
 11         for(b = a;  b < p; b++)
 12             c = p - (a + b);
 13             b = p - (a + c);
 14             a = p - (b + c);
 15 
 16             printf("%d, %d, %d\n",a,b,c);
 17 
 18 }
 19     return 0;
 20 }

我认为这更像是一个面试问题,而不是一个初学者问题。

2 个答案:

答案 0 :(得分:5)

原始代码中存在一些错误。一些与三角形为三角形的原因有关,有些是基本逻辑出错。

for (a = 1; a < p; a++)错误,因为三角形的一边不能超过周长的一半。即使在周长的一半,也会产生2条线,而不是三角形。

for (b = 1; b < (p - a); b++)错误,因为a+b将小于开头的一半。

c根据pab的值计算。

c = p - (a + b);

计算ba

的重点是什么?
b = p - (a + c);
a = p - (b + c);

正如Jonathan Leffler指出的那样,代码应该只打印唯一的三角形。这可以通过在a<=b && b<=c语句之前添加条件printf来轻松完成。

感谢@JonathanLeffler花时间调试这个简短的代码。发现一个错误导致代码由于b被初始化为更高的值而跳过某些输出,以及内部for循环条件过早地终止循环。

这是代码的更正版本。

#include <stdio.h>
int main() {
    int p, a, b, c;
    printf("Enter a perimeter: ");
    scanf("%d", &p);

    printf("Triangles with a perimeter: " " %d\n", p);

    for (a = 1; 2*a < p; a++) {
        for (b = 1; a+b < p; b++)
            if ((p-2*a) > 0 && (p-2*b) > 0 && (2*a+2*b-p) > 0) {
                c = p - (a + b);
                if(a<=b && b<=c)
                    printf("%d, %d, %d\n", a ,b, c);
            }
    }
    return 0;
}

现在让我们试一试。

Enter a perimeter: 6
Triangles with a perimeter:  6
2, 2, 2

那是对的。周长6的三角形只有1种可能的组合。 1, 1, 4单位长边不会是三角形,除非您愿意弯曲4单位长的边。

Enter a perimeter: 12
Triangles with a perimeter:  12
2, 5, 5
3, 4, 5
4, 4, 4

答案 1 :(得分:1)

输出中的重复信息

当前接受的answer alvits会产生大量重复输出,其中组合是相同组合边的排列。我修改了代码以打印3到29周边的所有三角形,并在打印操作之前添加了建议条件if (a <= b && b <= c)

tp17.c

警告:代码不正确。

#include <stdio.h>

int main(void)
{
    int p, a, b, c;
    // printf("Enter a perimeter: ");
    // scanf("%d", &p);
    for (p = 3; p < 30; p++)
    {
        printf("Triangles with perimeter: %d\n", p);

        for (a = 1; 2 * a < p; a++)
        {
            for (b = (p - a) / 2; (p - 2 * a) > 0 && (p - 2 * b) > 0 && (2 * a + 2 * b - p) > 0; b++)
            {
                c = p - (a + b);
                if (a <= b && b <= c)
                    printf("%d, %d, %d\n", a, b, c);
            }
        }
    }
    return 0;
}

结果if (a <=b && b <= c)之前的条件printf()旨在确保您只生成一次长度的每个组合。我注意到,例如,p = 12,您得到:(2, 5, 5)(3, 4, 5)(4, 4, 4)作为输出。我错过的是使用p = 11,添加条件省略了(3, 5, 3)(因为代码不会生成(3, 3, 5),原因就是躲避我)。因此,条件不够好 - 它确实消除了大量重复条目(好),但也抛出了一些不重复的条目(坏)。

因此,代码应该消除条件,这会使程序产生大量冗余输出,使输出比较变得非常复杂。

tp13.c

我还创建了一个密切相关的程序,从同一个基础开始:

#include <stdio.h>

int main(void)
{
    for (int p = 3; p < 30; p++)
    {
        printf("Triangles with perimeter: %d\n", p);
        for (int a = 1; a <= p / 2; a++)
        {
            for (int b = 1; b + a < p; b++)
            {
                int c = p - (a + b);
                if (a + b <= c || a + c <= b || b + c <= a)
                    continue;
                if (a <= b && b <= c)
                    printf("%d, %d, %d\n", a, b, c);
            }
        }
    }
    return 0;
}

输出比较

比较diff -utp13输出的tp17输出的一部分是:

 Triangles with perimeter: 11
 1, 5, 5
 2, 4, 5
-3, 3, 5
+2, 5, 4
 3, 4, 4
+3, 5, 3
+4, 3, 4
+4, 4, 3
+4, 5, 2
+5, 3, 3
+5, 4, 2
+5, 5, 1
 Triangles with perimeter: 12
 2, 5, 5
 3, 4, 5
+3, 5, 4
 4, 4, 4
+4, 5, 3
+5, 3, 4
+5, 4, 3
+5, 5, 2
 Triangles with perimeter: 13

查看周长为12的结果,显然tp17只生成不同的排列。但是,查看周长为11的结果会显示tp17生成(3, 5, 3)(5, 3, 3)但不生成(3, 3, 5),而tp13会生成(3, 3, 5),而不是其他两个排列。但是,显示的输出片段中tp17输出中的所有其他额外行都是其他行的排列。

需要不同的输出格式

上面的输出格式不适合自动比较,因此我修改了输出以打印周边,然后按非递减顺序列出三个边。因此,我将代码添加到tp17.c,以便在打印前将边排序为非递减顺序。对于三个元素,可能有更简单的方法,但这可行。

tp47.c

/* SO 4203-5818 - Calculate all triangles with given perimeter */
#include <stdio.h>
#include <stdlib.h>

static int int_cmp(const void *va, const void *vb)
{
    int a = *(int *)va;
    int b = *(int *)vb;
    return (a > b) - (a < b);
}

int main(void)
{
    int p, a, b, c;
    for (p = 3; p < 30; p++)
    {
        for (a = 1; 2 * a < p; a++)
        {
            for (b = (p - a) / 2; (p - 2 * a) > 0 && (p - 2 * b) > 0 && (2 * a + 2 * b - p) > 0; b++)
            {
                c = p - (a + b);
                {
                int d[] = { a, b, c };
                qsort(d, 3, sizeof(d[0]), int_cmp);
                printf("%d: %d, %d, %d\n", p, d[0], d[1], d[2]);
                }
            }
        }
    }
    return 0;
}

tp43.c

/* SO 4203-5818 - Calculate all triangles with given perimeter */

#include <stdio.h>

int main(void)
{
    for (int p = 3; p < 30; p++)
    {
        for (int a = 1; a <= p / 2; a++)
        {
            for (int b = 1; b + a < p; b++)
            {
                int c = p - (a + b);
                if (a + b <= c || a + c <= b || b + c <= a)
                    continue;
                if (a <= b && b <= c)
                    printf("%d: %d, %d, %d\n", p, a, b, c);
            }
        }
    }
    return 0;
}

(除了打印,这与tp13.c相同。)

比较

现在可以对输出进行排序和比较。 -u的{​​{1}}选项是多余的,但却是对称的。

tp43

因此,唯一的输出是相同的,但是当你计算差异时,$ tp43 | sort -u -k1n -k2n -k3n -k4n > tp43.out $ tp47 | sort -u -k1n -k2n -k3n -k4n > tp47.out $ diff tp43.out tp47.out $ 的输出中有390个额外的行:

tp47

仅供记录,文件$ tp43 | sort -k1n -k2n -k3n -k4n > tp43-all.out $ tp47 | sort -k1n -k2n -k3n -k4n > tp47-all.out $ diff tp43-all.out tp47-all.out | diffcount deleted 0, inserted 390 $ wc -l tp4?.out tp4?-all.out 206 tp43.out 206 tp47.out 206 tp43-all.out 596 tp47-all.out 1214 total $ tp43.outtp47.out相同。他们的内容是:

tp43-all.out