как создать массив различных целых чисел - PullRequest
0 голосов
/ 21 апреля 2019

Я пытался создать массив совершенно разных случайных целых чисел, 25 из них от 1 до 75. застряли в бесконечном цикле. очень признателен за помощь!

Я пытался искать решения, но я либо не понимал их, либо просто не нашел ничего подходящего моему уровню. Кстати, я убедился, что я использовал srand (время (NULL));

for (i = 0; i < 25; i++)
    {
        while (k != 1)
        {
            arr[i] = rand() % 75 + 1;
            for (j = 0; j < 25; j++)
            {
                if (arr[i] == arr[j])
                {
                    k++;
                }
            }
        }
        k = 0;
    }

весь код:

/*********************************
* Class: MAGSHIMIM C2            *
* Week:                          *
* Name:                          *
* Credits:                       *
**********************************/

#include <stdio.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main(void)
{
    srand(time(NULL));
    int i = 0;
    int j = 0;
    int k = 0;
    int arr[25] = { 0 };
    for (i = 0; i < 25; i++)
    {
        while (k != 1)
        {
            arr[i] = rand() % 75 + 1;
            for (j = 0; j < 25; j++)
            {
                if (arr[i] == arr[j])
                {
                    k++;
                }
            }
        }
        k = 0;
    }
    for (i = 0; i < 25; i++)
    {
        printf("%d", arr[i]);
    }
    getchar();
    return 0;
}

expecetd: отличный массив, но у меня бесконечный цикл.

Ответы [ 5 ]

1 голос
/ 21 апреля 2019

Один из способов сделать это состоит в том, чтобы создать пул или пакет чисел в необходимом диапазоне и выбрать их. Это не намного сложнее, чем повторная проверка, чтобы узнать, было ли уже выбрано число, и более эффективно. Ваша измененная программа сейчас:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define ARRLEN  25          // how many to pick
#define NUMBERS 75          // range of available numbers
#if NUMBERS < ARRLEN        // precaution
    #error Impossible job!
#endif

int cmp(const void *a, const void *b)
// optional, for qsort
{
    return *(int *)a - *(int *)b;
}

int main(void)
{
    int arr[ARRLEN];                    // final array
    int bag[NUMBERS];                   // bag of available numbers
    int avail = NUMBERS;                // size of bag available
    srand((unsigned)time(NULL));

    // prepare the bag of available numbers
    for(int i = 0; i < NUMBERS; i++) {
        bag[i] = i + 1;
    }

    // fill the array with values from the bag
    for(int i = 0; i < ARRLEN; i++) {
        int index = rand() % avail;     // random index into array
        arr[i] = bag[index];            // take that number

        avail--;
        bag[index] = bag[avail];        // replace with the one from the top
    }

    // just to check, sort the array, can be deleted
    qsort(arr, ARRLEN, sizeof arr[0], cmp);

    // output the result
    for (int i = 0; i < ARRLEN; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    getchar();
    return 0;
}

Я отсортировал массив, чтобы было легче увидеть, есть ли дубликаты. Эта строка qsort и функция cmp могут быть удалены.

Вывод программы из трех запусков

6 7 8 9 12 16 17 19 21 27 31 35 43 46 47 50 51 53 59 64 65 66 70 71 72
2 6 7 14 17 23 24 25 30 31 32 34 36 37 45 58 59 61 65 68 69 71 73 74 75
5 10 13 18 20 21 25 30 34 36 39 40 41 43 49 50 54 58 60 63 64 66 67 72 75
0 голосов
/ 22 апреля 2019

Еще одно небольшое изменение подхода bag Weather Vane - это не подготовка пакета всех доступных чисел, а просто объявление массива с максимальным числом элементов, равным диапазону принятых чисел, инициализированных всем нулем(например, int arr[75] = {0}; в этом случае).Нет необходимости заполнять массив, вы просто будете увеличивать элемент на 1 каждый раз, когда это число используется при заполнении вашего массива.

Чтобы убедиться, что вы используете только уникальное число, вы проверяете, является ли соответствующий элемент массива нулевым, если это так, используйте это число и увеличивайте его.Если оно не равно нулю, вы знаете, что число было использовано - сгенерируйте другое и попробуйте снова.

Например, с числом целых чисел для массива 25 и максимальным значением любого целого числа75, вы можете сделать;:

#define NINT 25
#define MAXI 75
...
    int arr[NINT],
        seen[MAXI] = {0};
    ...
    for (int i = 0; i < NINT; i++) {    /* for each needed element */
        int tmp = rand() % MAXI + 1;    /* generate a random in range */
        while (seen[tmp-1])             /* has been seen/used yet? */
            tmp = rand() % MAXI + 1;    /* if so, generate another */
        seen[tmp-1]++;                  /* incement element */
        arr[i] = tmp;                   /* assign unique value to arr */
    }

( примечание: seen индексы отображаются как tmp-1 для сопоставления с действительными индексами 0-74, в то время как числа генерируютсядля tmp будет 1-75 с использованием rand() % MAXI + 1. Вы можете использовать любой диапазон, необходимый для этого типа отображения. Использование диапазона чисел от 1000001 - 1000075 все равно потребует только 75-элементный массив seen.)

Чтобы вывести числа, используемые по порядку, вам просто нужно вывести индекс, соответствующий каждому ненулевому элементу массива seen (+1 для отображения обратно в диапазон значений 1-75)Например,

    for (int i = 0; i < MAXI; i++)
        if (seen[i])
            printf (" %d", i + 1);
    putchar ('\n');

Сложив все это в кратком примере, вы можете сделать:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define NINT 25
#define MAXI 75

int main (void) {

    int arr[NINT],
        seen[MAXI] = {0};
    srand (time(NULL));

    for (int i = 0; i < NINT; i++) {    /* for each needed element */
        int tmp = rand() % MAXI + 1;    /* generate a random in range */
        while (seen[tmp-1])             /* has been seen/used yet? */
            tmp = rand() % MAXI + 1;    /* if so, generate another */
        seen[tmp-1]++;                  /* incement element */
        arr[i] = tmp;                   /* assign unique value to arr */
    }

    puts ("array:");
    for (int i = 0; i < NINT; i++) {
        if (i && i % 5 == 0)
            putchar ('\n');
        printf (" %2d", arr[i]);
    }

    puts ("\n\nused:");
    for (int i = 0; i < MAXI; i++)
        if (seen[i])
            printf (" %d", i + 1);
    putchar ('\n');
}

( note: очевидно, размер видимого массива будет ограничендо доступного размера стека, так что если ваш диапазон необходимых чиселпревышает объем памяти, доступный для seen, объявленного с типом автоматического хранения , вам нужно будет сделать seen массивом с типом выделенного хранилища ).

Пример использования / Вывод

$ ./bin/randarr25-75
array:
  1 18 70 26 75
 29 31 58 22  9
  5 13  3 25 35
 40 48 44 57 56
 60 50 71 67 43

used:
 1 3 5 9 13 18 22 25 26 29 31 35 40 43 44 48 50 56 57 58 60 67 70 71 75

Используете ли вы сумку или массив для отслеживания увиденных чисел, результаты одинаковы.Никто не лучше другого.Добавьте их обоих в свой C-toolbox.

0 голосов
/ 21 апреля 2019
int *fillint(int *arr, size_t size)
{
    int added = 0;
    int pos = 0
    while(pos != size)
    {
        int rv;
        do
        {
            added = 1;
            rv = rand();

            for(size_t index = 0; index < pos; index++)
            {
                if(arr[index] == rv)
                {
                    added = 0;
                    break;
                }
            }
        }while(!added)
        arr[pos++] = rv;
    }
    return arr;
}
0 голосов
/ 21 апреля 2019

Во внутреннем цикле for, который для j, повторяется до j Кроме того, инициализируйте значение k равным нулю каждый раз, когда вы проверяете предыдущие вхождения, это делает код более легким для чтения.

Если было обнаружено одно вхождение, просто прервите его, чтобы алгоритм работал быстрее, даже если он имеет значение только для больших значений.

Примерно так:

for (i = 0; i < 25; i++)
{
    k = 1;
    while (k != 0)
    {
        arr[i] = rand() % 75 + 1;
        k = 0; 

        for (j = 0; j < i; j++)
        {
            if (arr[i] == arr[j])
            {
                k++;
                break;
            }
        }
    }
}
0 голосов
/ 21 апреля 2019

... но у меня есть бесконечный цикл.

просто замените

    while (k != 1)
    {
        arr[i] = rand() % 75 + 1;
        for (j = 0; j < 25; j++) {
          ...
        }
    }
    k = 0;

от

do
{
  k = 0;
  arr[i] = rand() % 75 + 1;
  for (j = 0; j < 25; j++) {
     ...
  }
} while (k != 1);

Обратите внимание, что также бесполезно проверять просмотр всего массива, включая записи, не заданные случайным значением, поэтому может быть:

do
{
  k = 0;
  arr[i] = rand() % 75 + 1;
  for (j = 0; j < i; j++)
  {
    if (arr[i] == arr[j])
    {
      k++;
    }
  }
} while (k != 0);

потому что теперь j не может значения i , тест равен (k != 0), а не (k != 1)

или лучше, потому что когда найдено идентичное значение, нет оснований продолжать

do
{
  arr[i] = rand() % 75 + 1;
  for (j = 0; j < i; j++)
  {
    if (arr[i] == arr[j])
      break;
  }
} while (j != i);

Чтобы хорошо видеть значения, также добавьте пробел между ними и добавьте последний перевод строки:

for (i = 0; i < 25; i++)
{
    printf("%d ", arr[i]);
}
putchar('\n');

ПОСЛЕ этих изменений, компиляции и выполнения:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall r.c
pi@raspberrypi:/tmp $ ./a.out
74 60 16 65 54 19 55 45 41 24 39 59 66 36 27 22 68 49 29 14 28 5 71 56 72 

pi@raspberrypi:/tmp $ ./a.out
16 34 62 29 74 41 3 43 69 17 61 22 28 59 7 65 5 46 60 20 66 14 49 54 45 

pi@raspberrypi:/tmp $ 

редактировать

Реализация проста, но может потребоваться время, чтобы найти еще не использованное значение таким образом, и чем больше диапазон допустимых значений будет ближе к числу значений для возврата, тем выше будет необходимое время. Так что это решение хорошо, когда есть несколько значений для возврата по сравнению с диапазоном допустимых значений.

В отношении интересного предложения Weather Vane все наоборот: число вызовов rand равно только числу возвращаемых значений, но чем больше диапазон допустимых значений, тем больше массив bag велик, что может привести к переполнению памяти.

Вероятно, для 25 значений от 1 до 75 решение Weather Vane лучше ... даже моему предложению требуется всего 0,001 сек на моем Raspberry Pi, так что почти ничего

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...