【问题标题】:Having a hard time creating a function that displays all different combinations of n numbers (0<n<10)by ascending order很难创建一个按升序显示 n 个数字 (0<n<10) 的所有不同组合的函数
【发布时间】:2021-09-15 20:14:03
【问题描述】:

我很难找到它的基本逻辑。我知道递归会有所帮助,但我不知道如何处理它。我的困难在于在基本情况下处理发送/打印数组。我所做的一切都只能迭代最后一个数字,不知道如何处理其他数字。

如果 n 为 2:

$&gt;./a.out | cat -e

01, 02, 03, ..., 09, 12, ..., 79, 89$

如果 n 是 3,事情会变得更难:

012, 013, 014, ..., 123, 124, ..., 134, 135,... 234, ..., 789$

我的代码远没有工作

#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>

void    ft_putchar(char c)
{
    write(1, &c, 1);
}

bool is_consecutive(int arr[], int n)
{
    int last_value = 9;
    if ( n <= 0 )
        return false;
    while ( --n ) {
        if ( arr[n] != last_value-- )
            return false;
    }
    return true;
}

void    ft_print_screen(int *t, int size)
{
        int i;
    
    i = 0;
        while (i < size)
    {
                ft_putchar(t[i] + '0');
        i++;
    }
        if (is_consecutive(t, size) != true)
        {
            ft_putchar(',');
            ft_putchar(' ');
        }
}

void    ft_print_combn(int n)
{
        int i;
        int tab[n];

        i = 0;
        if (n == 1)
                while (i < 10)
        {
                        ft_putchar(i + '0');
            i++;
        }
        while (i < n)
    {
                tab[i] = 0;
        i++;
    }
        while (tab[0] <= (10 - n) && n > 1)
        {
                ft_print_screen(tab, n);
                tab[n - 1]++;
                i = n;
                while (i && n > 1)
                {
                        i--;
                        if (tab[i] > 9)
                        {
                                tab[i - 1]++;
                                tab[i] = 0;
                        }
                }
        }
}

void main(int argc, char *argv[])
{
    int x = atoi(argv[1]);
    ft_print_combn(x);
}

【问题讨论】:

  • 首先,澄清问题。您的标题表明目标是创建“所有”组合,但您显示了两个数字组合的部分列表和三个数字组合的单独部分列表。该函数是否需要列出所有组合或仅列出具有固定数量数字的组合?如果它必须列出所有组合,那么升序是什么? 09 是在 012 之前还是之后?
  • 第二,一旦你弄明白了,忘掉C代码,想想一个算法来遍历所有的组合。向自己描述该算法。
  • 为什么使用write 来生成输出,而不是printfputchar&lt;stdio.h&gt; 的任何其他缓冲输出函数?您通常不必直接使用readwrite
  • @TomKarzes 因为它将由自动评分系统进行评估
  • 你可以在 StackOverflow 上搜索“[c] generate combination”来找到很多解决这个问题的问题。其中应该有一些适合你需要的。

标签: c logic combinations


【解决方案1】:

这是一个您应该能够适应您的需求的解决方案。代码被条件化为使用 stdio 或裸 write 调用。只需将 USE_STDIO 的定义更改为 #define USE_STDIO 0 以使其使用裸 write 调用(或简单地删除条件化)。

请注意,我使用int 而不是size_t 作为字符串长度,因为它们永远不会大于字符集大小(即10),但如果您愿意,当然可以使用size_t

#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

#define USE_STDIO   1

void my_write(int len, char buf[len])
{
#if USE_STDIO
    printf("%.*s", len, buf);
#else
    write(1, buf, len);
#endif
}

void my_write_s(char *buf)
{
    my_write(strlen(buf), buf);
}

void show(bool first, int len, char buf[len])
{
    if (! first) {
        my_write_s(", ");
    }
    my_write(len, buf);
}

void end(void)
{
    my_write_s("$\n");
}

void gen_combs2(bool first, char *buf, int off, int m, char chars[m], int n)
{
    if (n == 0) {
        show(first, off, buf);
        return;
    }

    for (int i = 0; i < m + 1 - n ; i++) {
        buf[off] = chars[i];
        gen_combs2(first, buf, off + 1, m - i - 1, chars + i + 1, n - 1);
        first = false;
    }
}

void gen_combs(char *chars, int n)
{
    int m = strlen(chars);
    char buf[n];

    gen_combs2(true, buf, 0, m, chars, n);
    end();
}

int main(void)
{
    gen_combs("0123456789", 1);
    gen_combs("0123456789", 2);
    gen_combs("0123456789", 3);

    return 0;
}

【讨论】:

  • 关于:int m = strlen(chars); 这将导致编译器输出警告,因为函数:strlen() 返回 size_t,而不是 int
  • @user3629249 不,不会。您可以将整数类型分配给较小的整数类型而不会发出警告。我确实编译了它。试试吧。在这种情况下,它会将其隐式转换为 int。我放弃了演员阵容,因为它没有必要。我在顶部解释说我没有使用size_t,因为它没有必要。
猜你喜欢
  • 2015-08-22
  • 2018-02-25
  • 2013-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多