Сортировка списка в несколько вертикальных столбцов

import предназначен для импорта модулей кода. Чтобы прочитать файл и распечатать его, было бы что-то вроде:

f = open('somefile.txt','r')
print(f.read())

Я бы настоятельно рекомендовал прочитать / посмотреть учебник.

6
задан Kevin Fairchild 14 November 2008 в 19:27
поделиться

3 ответа

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

То, что мой код делает ниже, создает матрицу. Мы пишем матрицу сверху донизу и затем слева направо (и прекращаем заполнять что-либо кроме первой строки, когда у нас заканчиваются элементы для заполнения всех столбцов первой строки). Затем мы читаем его в другом порядке, слева направо и от начала до конца. В основном то, что мы делаем здесь, транспонирует матрицу, путем записи этого в одном порядке, но читает его в другом порядке. Перемещение матрицы является очень элементарной математической операцией (много 3D работ программирования при помощи матричных вычислений, и перемещение является на самом деле простой операцией). Прием - то, как мы первоначально заполняем матрицу. Для проверки мы можем заполнить первый столбец в любом случае, независимо от количества требуемых столбцов и размера массива, мы должны прекратить заполнять матрицу в нормальном порядке, если мы заканчиваемся элементы и резервируем все элементы, перенесенные для первой строки. Это произведет вывод, который Вы предложили в своем комментарии.

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

int Columns;
char * Array[] = {"A", "B", "C", "D", "E", "F", "G"};

int main (
    int argc,
    char ** argv
) {
    // Lets thest this with all Column sizes from 1 to 7
    for (Columns = 1; Columns <= 7; Columns++) {

        printf("Output when Columns is set to %d\n", Columns);

        // This is hacky C for quickly get the number of entries
        // in a static array, where size is known at compile time
        int arraySize = sizeof(Array) / sizeof(Array[0]);

        // How many rows we will have
        int rows = arraySize / Columns;

        // Below code is the same as (arraySize % Columns != 0), but
        // it's almost always faster
        if (Columns * rows != arraySize) {
            // We might have lost one row by implicit rounding
            // performed for integer division
            rows++;
        }

        // Now we create a matrix large enough for rows * Columns
        // references. Note that this array could be larger than arraySize!
        char ** matrix = malloc(sizeof(char *) * rows * Columns);

        // Something you only need in C, C# and Java do this automatically:
        // Set all elements in the matrix to NULL(null) references
        memset(matrix, 0, sizeof(char *) * rows * Columns );

        // We fill up the matrix from top to bottom and then from
        // left to right; the order how we fill it up is very important
        int matrixX;
        int matrixY;
        int index = 0;
        for (matrixX = 0; matrixX < Columns; matrixX++) {
            for (matrixY = 0; matrixY < rows; matrixY++) {
                // In case we just have enough elements left to only
                // fill up the first row of the matrix and we are not
                // in this first row, do nothing.
                if (arraySize + matrixX + 1 - (index + Columns) == 0 &&
                        matrixY != 0) {
                    continue;
                }

                // We just copy the next element normally
                matrix[matrixY + matrixX * rows] = Array[index];
                index++;
                //arraySize--;
            }
        }

        // Print the matrix exactly like you'd expect a matrix to be
        // printed to screen, that is from left to right and top to bottom;
        // Note: That is not the order how we have written it,
        // watch the order of the for-loops!
        for (matrixY = 0; matrixY < rows; matrixY++) {
            for (matrixX = 0; matrixX < Columns; matrixX++) {
                // Skip over unset references
                if (matrix[matrixY + matrixX * rows] == NULL)
                    continue;

                printf("%s", matrix[matrixY + matrixX * rows]);
            }
            // Next row in output
            printf("\n");
        }
        printf("\n");

        // Free up unused memory
        free(matrix);
    }   
    return 0;
}

Вывод

Output when Columns is set to 1
A
B
C
D
E
F
G

Output when Columns is set to 2
AE
BF
CG
D

Output when Columns is set to 3
ADG
BE
CF

Output when Columns is set to 4
ACEG
BDF

Output when Columns is set to 5
ACEFG
BD

Output when Columns is set to 6
ACDEFG
B

Output when Columns is set to 7
ABCDEFG

Этот код C должен быть легким к порту к PHP, C#, Java, и т.д., нет никакого большого включенного волшебства, таким образом, это является в значительной степени универсальным, портативным и межплатформенным.


Одна важная вещь я должен добавить:

Этот код откажет, если Вы обнулите Столбцы (деление на нуль, я не проверяю на тот), но какой смысл 0 столбцов имели бы? И это также откажет, если у Вас будет больше столбцов, чем элементы в массиве, я не проверяю на это также. Можно легко проверить на любое право после того, как Вы получили arraySize:

if (Columns <= 0) {
   // Having no column make no sense, we need at least one!
   Columns = 1;
} else if (Columns > arraySize) {
   // We can't have more columns than elements in the array!
   Columns = arraySize;
}

Далее необходимо также проверить на arraySize быть 0, в этом случае можно немедленно выскочить функции, как в этом случае нет абсолютно ничего, чтобы сделать для функции :) Добавление этих проверок должно заставить код качать тело.

Наличие ПУСТЫХ Элементов в Массиве будет работать, BTW, в этом случае в получающемся выводе нет никаких дыр. ПУСТЫЕ элементы просто пропускаются как не присутствование. Например, позволяет использованию

char * Array[] = {"A", "B", "C", "D", "E", NULL, "F", "G", "H", "I"};

Вывод будет

ADFI
BEG
CH

для Столбцов == 4. Если Вы хотите дыры, необходимо создать элемент дыры.

char hole = 0;
char * Array[] = {"A", "B", &hole, "C", "D", "E", &hole, "F", "G", "H", "I"};

и измените рисование, кодируют немного

    for (matrixY = 0; matrixY < rows; matrixY++) {
        for (matrixX = 0; matrixX < Columns; matrixX++) {
            // Skip over unset references
            if (matrix[matrixY + matrixX * rows] == NULL)
                continue;

            if (matrix[matrixY + matrixX * rows] == &hole) {
                printf(" ");
            } else {
                printf("%s", matrix[matrixY + matrixX * rows]);
            }
        }
        // Next row in output
        printf("\n");
    }
    printf("\n");

Выходные образцы:

Output when Columns is set to 2
A 
BF
 G
CH
DI
E

Output when Columns is set to 3
ADG
BEH
  I
CF

Output when Columns is set to 4
AC H
BDFI
 EG
6
ответ дан 10 December 2019 в 02:55
поделиться

Это похоже на присвоения домашней работы так или иначе

array<String^>^  sArray = {"A", "B", "C", "D", "E", "F", "G"};
double Columns = 4;
double dRowCount = Convert::ToDouble(sArray->Length) / Columns;
int rowCount = (int) Math::Ceiling(dRowCount);
int i = 0;
int shift = 0;
int printed = 0;
while (printed < sArray->Length){
    while (i < sArray->Length){
        if (i % rowCount == shift){
            Console::Write(sArray[i]);
            printed++;
        }
        i++;
    }
    Console::Write("\n");
    i = 0;
    shift++;
}
1
ответ дан 10 December 2019 в 02:55
поделиться

Маленькое ОБНОВЛЕНИЕ:

Алгоритм, который я использую здесь, является измененным, который Вы использовали бы для рисования изображений. Я симулирую записи массива, чтобы быть пиксельными данными изображения, и затем я крашу изображение слева направо (1. LtoR) и сверху донизу (2. TtoB), однако, данные изображения хранятся сверху донизу (1. TtoB) и затем слева направо (2. LtoR); IOW в другом порядке. Так как изображение не может иметь дыр, это - причина, почему это не будет работать с 5 или 6 столбцами. С 4 столбцами вывод

ACEG
BDF

Как изображение это похоже на это

OOOO
OOO.

Причем O является пикселем изображения и. будучи неопределенным пикселем (недостающий). Недостающие могут только быть в конце изображения, не посреди него. Это означает, что могло также быть похожим на это

OOO
OO.
OO.
OO.

Все недостающие пиксели всегда в конце, если Вы читаете сначала сверху донизу и затем слева направо, потому что в этом случае все недостающие пиксели следуют непосредственно друг за другом в конце. Если бы я прочитал схему TtoB и затем LtoR, то это должно читать как этот "Пиксель, Пиксель, Пиксель, Пиксель..., Пиксель, Пропавшие без вести, Пропавшие без вести, Пропавшие без вести..., Пропавшие без вести", это никогда не могло бы читать "Пиксель, Пропавших без вести, Пиксель" или "Пропавшие без вести, Пиксель, Пропавшие без вести". Все пиксели вместе, и все missings, также.

С 5 столбцами, как комментарий предполагает, он должен быть похожим на это

ACEFG
BD

Однако как изображение это было бы похоже на это

OOOOO
OO...

И это не позволяется алгоритмом. Если я считал его TtoB и затем LtoR, это будет читать: "Пиксель, Пиксель, Пиксель, Пиксель, Пиксель, Пропавшие без вести, Пиксель, Пропавшие без вести, Пиксель, Пропавшие без вести". И как указано выше, это не позволяется алгоритмом. Таким образом, этот простой пиксельный подход рисования не нарисует как много столбцов согласно просьбе, если рисование, которое много столбцов приводят к дырам в изображении. В этом случае это просто заполнит дыры, однако, это заставит меньше столбцов быть оттянутым.

Позвольте мне думать о решении, которое будет всегда красить требуемые числа пикселей (в отдельном ответе).


Вы не должны перестраивать данные в памяти для этого вообще. Просто распечатайте его в желаемом порядке.

Некоторый Код C (я делаю его чрезвычайно подробный, таким образом, все понимают то, что я делаю так. Конечно, это может быть намного более компактно):

int Columns = 4;
char * Array[] = {"A", "B", "C", "D", "E", "F", "G"};

int main (
    int argc,
    char ** argv
) {
    // This is hacky C for quickly get the number of entries
    // in a static array, where size is known at compile time
    int arraySize = sizeof(Array) / sizeof(Array[0]);

    // How many rows are we going to paint?
    int rowsToPaint = (arraySize / Columns) + 1;

    int col;
    int row;

    for (row = 0; row < rowsToPaint; row++) {
        for (col = 0; col < Columns; col++) {
            int index = col * rowsToPaint + row;

            if (index >= arraySize) {
                // Out of bounds
                continue;
            }

            printf("%s", Array[index]);
        }
        printf("\n"); // next row
    }
    printf("\n");
    return 0;
}

Примечание: Это хорошо работает со значением 8 (таким образом, все красится в одной строке), и значения 4, и ниже (хорошо работает с 3, 2 и 1), но она не может работать с 5. Это не отказ алгоритма, это - отказ ограничивания.

ACEFG
BD

Ограничение говорит, что столбцы прочитаны от начала до конца для получения исправленных отсортированных данных. Но выше "EFG" отсортирован, и это не от начала до конца, это слева направо. Таким образом этот алгоритм имеет проблему. Используя Столбцы = 3 будет работать

ADG
BE
CF

Используя два будет работать также

AE
BF
CG
D

И каждый поместит все в один столбец.

2
ответ дан 10 December 2019 в 02:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: