Codegolf — Задача «Заполнить Сетку»

  • Автор темы Sergey Luzhnov
  • Обновлено
  • 18, Oct 2024
  • #1

Задача с простыми правилами, но нетривиальными алгоритмами. :-)

Задача

Возьмите ввод в виде целых чисел, разделенных пробелами:

 
 
 
  384  159 1472
1174  499  342

457 1357  201
 

Где N — длина стороны двумерной квадратной матрицы, заполненной уникальный числа (целые числа) между A и B включительно. Для каждой строки и столбца этой матрицы сумма всегда одна и та же: S. (Другими словами, матрица представляет собой полумагический квадрат).

Примечание:

Все числа положительные. Исключением является A, который может быть равен 0.

Примеры

Для

8 1 300 500

действительным решением было бы

codegolf -

Для

3 1 10000 2015

действительным решением было бы

codegolf -

Выход

Вывод должен представлять собой таблицу ASCII. Пример первого примера выше:

N A B S

Целые числа, выровненные по правому краю, дополненные пробелами. Ширина каждого столбца равна ширине наибольшего целого числа в этом столбце.

Подсчет очков

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

#код-гольф #код-гольф #математика #сетка

Sergey Luzhnov


Рег
22 Oct, 2020

Тем
74

Постов
194

Баллов
574
  • 26, Oct 2024
  • #2

CJam, 119 91 байт

 
 
 
 
 S;§f⁵ - Helper link. Takes a matrix M and outputs if it's semi-magic to S
S     - Column sums of M

§   - Row sums of M

;    - Concatenate

f⁵ - Keep only S

r/œ!²}s€ÇÞṪG - Main link. Takes [A, B] on the left and N on the right
r/           - Reduce [A, B] by range, yielding [A, A+1, ..., B-1, B]

}       - To N:

²        -   Square

œ!         - Generate all permutations of range(A, B) of length N²

€     - Over each:

s      -   Slice into NxN matrices

ÇÞ   - Sort the matrices by the helper link

ṪG - Take the last and format as a grid
 

Это доказуемо правильный, недетерминированный подход.

На моем рабочем столе второй тестовый пример обычно завершается менее чем за 10 минут.

Первое дело заканчивается мгновенно. Попробуйте онлайн в CJam-переводчик.

Пробный запуск

S

Идея

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

  • Вместо псевдослучайной генерации квадрата длины стороны Н, мы генерируем квадраты с длиной стороны Н-1, добавьте один столбец, чтобы сформировать Н × (Н-1) прямоугольник, строки которого имеют сумму С, затем один ряд, чтобы сформировать квадрат с длиной стороны Н чьи столбцы имеют сумму С.

    Поскольку сумма элементов всех столбцов будет равна НС и сумма элементов первого Н-1 строки это (Н-1)С, последняя строка также будет иметь сумму С.

    Однако этот процесс может сгенерировать недопустимую матрицу, поскольку нет гарантии, что все элементы последней строки и столбца будут уникальными или попадут в диапазон [А...Б].

  • Выбор квадрата уникальных целых чисел в [А...Б] и длина стороны Н-1 равномерно и случайным образом заняло бы слишком много времени. Нам каким-то образом приходится расставлять приоритеты среди квадратов, у которых с большей вероятностью получится правильный квадрат с длиной стороны. Н после применения процесса, подробно описанного в предыдущем пункте.

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

    Для каждого я в [А...Б], мы псевдослучайно выбираем число с плавающей запятой между 0 и (Я - С/Н)2 + 1 и сортируем элементы [А...Б] по выбранным поплавкам. Мы держим первое Н2 числа и расположите их в порядке чтения в квадрате.

    Предполагая совершенно равномерное распределение всех действительных чисел между 0 и (Я - С/Н)2 + 1 на каждом этапе все квадраты имеют ненулевую вероятность выбора, а это означает, что процесс в конечном итоге завершится.

Код

N ||answer||

Желе, 19 18 байт

A, B

Попробуйте онлайн!

Принимает ввод через командную строку в форме S;§f⁵ r/œ!²}s€ÇÞṪG q~ e# Read all input from STDIN and evaluate it. :M; e# Save "S" in M and discard it from the stack. ),>:R; e# Transform "A B" into [A ... B], save in R and discard. (:L e# Save "N - 1" in L and keep it on the stack. { e# If L is non-zero: { e# Do: R{ e# For each I in R: ML)d/ e# Compute M/Double(L+1). -Y# e# Subtract the result from I and square the difference. )mr e# Add 1 and pick a non-negative Double below the result. }$ e# Sort the values of I according to the picks. L/ e# Split the shuffled R into chunks of length L. L< e# Keep only the first L chunks. 2{ e# Do twice: { e# For each row of the L x L array. M1$ e# Push M and a copy of the row. :+- e# Add the integers of the row and subtract their sum from M. + e# Append the difference to the row. }% e# z e# Transpose rows and columns. }* e# :U:+ e# Save the result in U and concatenate its rows. __O| e# Push two copies. Deduplicate the second copy. =R* e# Push R if all elements are unique, an empty array otherwise. - e# Remove the result's elements from U's elements. }g e# If the resulting array is non-empty, repeat the loop. U{ e# For each row in U: :s e# Convert its integers into strings. _:, e# Copy and replace each string with its length. :e> e# Compute the maximum length. f{ e# For each integer, push the maximum length; then Se[ e# Left-pad the integer with spaces to that length. } e# }% e# z e# Transpose rows with columns. Sf*N* e# Join columns by spaces, rows by linefeeds. }M? e# Else, push M. $ cjam grid.cjam <<< '8 1 300 500' 77 66 37 47 56 46 86 85 63 102 70 72 49 54 81 9 62 69 58 57 71 17 48 118 64 65 67 87 53 44 80 40 73 60 55 89 51 76 84 12 68 59 28 78 74 38 50 105 61 75 52 43 125 83 42 19 32 4 133 27 21 142 29 112 . Outputs the lexicographic ally first grid that fits

-1 байт благодаря Джонатан Аллан!

С одной стороны, это коротко. С другой стороны, это невероятно неэффективно. Это порождает

$$\frac {(B-A+1)!} {(B-A-N^2+1)!}$$

\$N\times N\$ квадратов для проверки. Например, если \$A = 1, B = 9, N = 3\$ (пример в TIO), это создаёт матрицы \$362880\$ \$3\times3\$ для проверки на полумагию. Для второго тестового примера генерируется 243427020732724848691170301000009788596908895057539171134817782742659530443034291592046861179091424965386457564. 096330026488754281163364761600000000000000000 \$8\times8\$ матрицы.

При наличии достаточного количества времени и памяти это будет работать с любым вводом. Однако на моем компьютере не хватает памяти для второго тестового примера через 5 минут.

Как это работает

q~:M;),>:R;(:L{{R{ML)d/-Y#)mr}$L/L<2{{M1$:+-+}%z}*:U:+__O|=R*-}gU{:s_:,:e>f{Se[}}%zSf*N*}M?
 

Ilya055


Рег
30 Jan, 2008

Тем
70

Постов
200

Баллов
580
Тем
403,760
Комментарии
400,028
Опыт
2,418,908

Интересно