Разбить число на байты и проверить их последовательность

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Дано беззнаковое целое x. sizeof(x) строго меньше 256. Требуется проверить следующее утверждение: если разобрать число на байты, то они по разу примут все значения от ноля до sizeof(x)-1. Например, если sizeof(x) равно 8, то требуется проверить утверждение: x состоит из байтов, равных: 0, 1, 2, 3, 4, 5, 6 и 7. При этом порядок байтов значения не имеет.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
somewhere
Сообщения: 1858
Зарегистрирован: 31 авг 2006, 17:14
Откуда: 71 RUS
Контактная информация:

я бы подсказал, но мне противопоказан комп ;)
It's a long way to the top if you wanna rock'n'roll
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Ну Ваш вариант угадать не сложно: написать функцию поиска в числе байта с заданным значением и функцию поиска в числе байта с заданным значением, начиная от заданной позиции байта, перебрать циклом байты числа, при этом найти максимальное из их значений и каждое значение поискать в числе обеими функциями. Иначе два костыля не получаются.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Ну изъясняешься ты конечно. Голову сломал, пока прочёл. Особенно последний ответ...

Как хранится число? Как массив байтов?

Код: Выделить всё

unsinged char number[255];
Просто для таких больших чисел встроенного типа нет.

Самое простое - это отсортировать байты по не убыванию qsort'ом, затем однократно пройти увеличивая счётчик и сравнивая его с текущим байтом. Если все сравнения были успешны, значит говорим да, иначе - говорим нет. Количество действий N*log(N) + 2*N + С. Итого сложность алгоритма O(N) = N*log(N). Думаю, улучшить это значение без дополнительной памяти уже не получится.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
somewhere
Сообщения: 1858
Зарегистрирован: 31 авг 2006, 17:14
Откуда: 71 RUS
Контактная информация:

Можно улучшить со сложностью N, т.е. однопроходно, но это в личке =)
It's a long way to the top if you wanna rock'n'roll
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Romeo писал(а):Как хранится число? Как массив байтов?
Нет конечно.
Romeo писал(а):Просто для таких больших чисел встроенного типа нет.
Восемь жалких байт - это уже большое число?
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

Romeo писал(а):Количество действий N*log(N) + 2*N + С. Итого сложность алгоритма O(N) = N*log(N).
У меня уже получилось 3N шагов цикла в худшем случае и N+1 в лучшем.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Хорошо, тогда однопроходный алгоритм, но с дополнительной памятью размера N. Решай сам, что тебе важнее: память или скорость. Я бы поставил на второе.

Код: Выделить всё

#include <iostream>

// Checks whether array contains consecutive values from 0 to nSize-1 in arbitrary order.
bool ContainsConsecutiveValues(unsigned char arrNumbers[], unsigned int nSize)
{
   bool arrExists[nSize];
   for (int i = 0; i < nSize; arrExists[i++] = false);

   for (unsigned int i = 0; i < nSize; ++i)
   {
      // Value is not in range [0..nSize-1]
      if (arrNumbers[i] >= nSize) return false;

      if (arrExists[arrNumbers[i]])
      {
         // Repetition of the value
         return false;
      }
      else
      {
         // Marking the value as met
         arrExists[arrNumbers[i]] = true;
      }
   }

   // If we are here, then all the checks are OK, so return true
   return true;
}

int main()
{
   unsigned char arrNumbers[] = { 1, 0, 3, 2 };
   std::cout << (ContainsConsecutiveValues(arrNumbers, sizeof(arrNumbers)) ? "Yes" : "No") << std::endl;
   return 0;
}
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Аватара пользователя
Сионист
Сообщения: 1211
Зарегистрирован: 31 мар 2014, 06:18

В каком месте сказано, что число на байты уже разобрано? Я даже не использую тот факт, что байты одной переменной хранятся подряд. Они так хранятся, но это не используется.
Писать можно на чём угодно, но зачем же так себя ограничивать? Пиши на c.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Я поэтому и спросил, первым делом, как они хранятся. А ты так и не ответил на тот вопрос. И даже сейчас ответа не дал.

Если они гарантированно хранятся подряд (а было бы странно, если бы они не подряд хранились), то просто кастишь память к unsigned char* и используешь готовую функцию.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить