Проблема может быть разделена на две задачи: (1) найти все подпоследовательности массива цифр и (2) упаковать и распаковать целые числа на цифры.
Рассмотрим подпоследовательности массива {a, b, c}
. Вы можете сгенерировать их, пройдя через массив слева направо и следуя двум путям: один, где вы включаете текущий элемент в подпоследовательность, и тот, где вы этого не делаете.
Это приводит к рекурсивной подход тат можно представить в виде дерева:
{}
/ \
{} {a}
/ \ / \
{} {b} {a} {ab}
/\ / \ / \ / \
{} {c} {b} {bc} {a} {ac} {ab} {abc}
Когда мы ветвь слева, мы пропустить текущий элемент и когда мы идем вправо, мы включаем элемент. Сами элементы - это глубина дерева: На первом уровне мы обрабатываем элемент a
, на следующем b
и на последнем c
.
Нижняя строка имеет все подпоследовательности. Это включает в себя пустую последовательность и полную последовательность, которую вы не хотите. Но давайте включим их сейчас. (Массивы в нижнем ряду обычно называются power set, что является хорошим термином для поиска в Интернете.)
Я упоминал рекурсию, которая влечет за собой рекурсивные функции и функции.
Таким образом, нам нужно решить проблему другим способом. Давайте повернем дерево на бок. Черточка означает, что элемент был пропущен. Запись на праве использует другое обозначение: 0
означает, что элемент был пропущен, 1
означает, что элемент был включен:
- - - 000
- - c 001
- b - 010
- b c 011
a - - 100
a - c 101
a b - 110
a b c 111
Я надеюсь, что коды на праве выглядеть знакомыми, потому что, как вы считаете от 000
к 111
в двоичный файл. Это хороший способ перечислить наши элементы. Теперь нам нужно определить, какие биты установлены в каждом номере.
Самый правый бит устанавливается, когда число нечетное. Мы можем узнать о других битах путем многократного деления числа на два, которые в двоичном формате являются сдвигом вправо, отбрасывая самый правый бит.
Теперь, как извлечь цифры из исходного номера? Это число является десятичным числом; он находится в базе 10. Мы можем использовать тот же подход, что и для поиска битов в двоичном числе, потому что биты 0 и 1 являются двоичными цифрами.
Начало с номером. Последняя цифра является результатом взятия остатка после деления на 10. Затем разделите число на десять, пока оно не станет равным нулю. Этот код дает цифры справа налево. Так же и код для поиска битов, что означает, что мы можем определить, установлен ли бит и какая цифра печататься в одном цикле, всегда беря самый правый бит, и если он установлен, напечатайте самую правую цифру исходного номера.
Пустые и полные подпоследовательности являются первым и последним элементами перечисления. Если вы не хотите их, пропустите их.
Это оставляет проблему дублированных подпоследовательностей, если цифра имеет повторяющиеся цифры. Я не вижу простого решения, кроме предложения user3629249, чтобы создать подпоследовательность в любом случае и позже проверить, была ли она уже напечатана.
Простой способ сделать это - сохранить массив подпоследовательностей. Этот массив имеет max
записей. После того, как вы заполнили этот массив, отсортируйте его и распечатайте, но пропустите записи, которые соответствуют предыдущей записи.
Вот пример реализации, который использует массив цифр, так что исходный номер не нужно разлагать каждый раз. Она использует функцию сортировки qsort
из <stdlib.h>
, который требует функции сортировки:
#include <stdlib.h>
#include <stdio.h>
#define NUM 412131
typedef unsigned int uint;
int uintcmp(const void *pa, const void *pb)
{
const uint *a = pa;
const uint *b = pb;
return (*a > *b) - (*a < *b);
}
int main(void)
{
uint digit[20]; // array of digits
size_t ndigit = 0; // length of array
uint num = NUM;
uint max = 1;
size_t i;
while (num) {
digit[ndigit++] = num % 10;
num /= 10;
max *= 2;
}
uint res[max]; // array of subsequences
for (i = 0; i < max; i++) {
uint mask = i; // mask for bit detection
uint j = ndigit; // index into digit array
uint s = 0;
while (j--) {
if (mask % 2) s = s*10 + digit[j];
mask /= 2;
}
res[i] = s;
}
qsort(res, max, sizeof(*res), uintcmp);
for (i = 1; i < max - 1; i++) {
if (res[i] != res[i - 1]) printf("%u\n", res[i]);
}
return 0;
}
_and без использования functions_ - Что так плохо о функциях? При правильном использовании они могут сделать код более понятным. –
'max = max-2' добавление точки с запятой устраняет ошибку компилятора, если это то, что вы считаете« эффективным ». – Downvoter
ничего себе, простите, я сделал изменения и забыл. – riegour