Вы обучаете класс студентов интересным предпочтениям относительно того, как устроены их стулья. У них есть 3 очень специфических требования к расположению стульев:
Большинство из них расположены в прямоугольнике, даже если некоторые стулья пустуют.
Должно быть как можно меньше пустых стульев.
Они должны быть как можно более квадратными. Прямоугольность определяется расстоянием между шириной и высотой прямоугольника, чем ниже, тем лучше. Например, прямоугольник
4x7
имеет квадратность 3.
Чтобы быть более конкретным, «оценка» договоренности - это расстояние между шириной и высотой плюс количество стульев, которые опустели бы.
Давайте возьмем пример. Допустим, у вас 13 учеников. Вы можете расположить стулья любым из следующих способов:
1x13
2x7
3x5
4x4
1x13
не очень квадратный На самом деле, 1 и 13 разнесены на 12, поэтому мы даем этому расположению 12 баллов. У него также 0 пустых стульев, поэтому мы добавляем 0 баллов, что дает этому расположению 12 баллов. Не так уж и здорово.
2x7
конечно лучше. 2 и 7 разнесены только на 5, поэтому мы даем этому расположению 5 баллов. Однако, если вы на самом деле расположите 2 ряда по семь стульев, это займет 14 стульев, то есть один стул будет пустым. Таким образом, мы добавляем одно очко, давая этой договоренности оценку 6.
Мы могли бы также сделать 3x5
. 3 и 5 - 2, так что +2 балла. Это займет 15 стульев, то есть у нас будет два дополнительных стула, так что еще +2 балла, для оценки 4.
Последний вариант 4x4
. 4 и 4 - 0, поэтому мы даем это +0 баллов. 4x4 занимает 16 стульев, так что 3 стула пустуют, что дает общий балл 3. Это оптимальное решение.
В случае галстука оптимальным решением будет решение с менее пустыми стульями.
Соревнование
Вы должны написать программу или функцию, которая принимает целое число и выводит оптимальное расположение стульев для такого количества студентов. IO может быть в любом разумном формате. Вот пример вывода для любого количества студентов от 1 до 100:
1: (1, 1)
2: (1, 2)
3: (2, 2)
4: (2, 2)
5: (2, 3)
6: (2, 3)
7: (3, 3)
8: (3, 3)
9: (3, 3)
10: (2, 5)
11: (3, 4)
12: (3, 4)
13: (4, 4)
14: (4, 4)
15: (4, 4)
16: (4, 4)
17: (3, 6)
18: (3, 6)
19: (4, 5)
20: (4, 5)
21: (3, 7)
22: (5, 5)
23: (5, 5)
24: (5, 5)
25: (5, 5)
26: (4, 7)
27: (4, 7)
28: (4, 7)
29: (5, 6)
30: (5, 6)
31: (4, 8)
32: (4, 8)
33: (6, 6)
34: (6, 6)
35: (6, 6)
36: (6, 6)
37: (5, 8)
38: (5, 8)
39: (5, 8)
40: (5, 8)
41: (6, 7)
42: (6, 7)
43: (5, 9)
44: (5, 9)
45: (5, 9)
46: (7, 7)
47: (7, 7)
48: (7, 7)
49: (7, 7)
50: (5, 10)
51: (6, 9)
52: (6, 9)
53: (6, 9)
54: (6, 9)
55: (7, 8)
56: (7, 8)
57: (6, 10)
58: (6, 10)
59: (6, 10)
60: (6, 10)
61: (8, 8)
62: (8, 8)
63: (8, 8)
64: (8, 8)
65: (6, 11)
66: (6, 11)
67: (7, 10)
68: (7, 10)
69: (7, 10)
70: (7, 10)
71: (8, 9)
72: (8, 9)
73: (7, 11)
74: (7, 11)
75: (7, 11)
76: (7, 11)
77: (7, 11)
78: (9, 9)
79: (9, 9)
80: (9, 9)
81: (9, 9)
82: (7, 12)
83: (7, 12)
84: (7, 12)
85: (8, 11)
86: (8, 11)
87: (8, 11)
88: (8, 11)
89: (9, 10)
90: (9, 10)
91: (7, 13)
92: (8, 12)
93: (8, 12)
94: (8, 12)
95: (8, 12)
96: (8, 12)
97: (10, 10)
98: (10, 10)
99: (10, 10)
100: (10, 10)
Как обычно, это код-гольф, поэтому применяются стандартные лазейки, и победитель - самый короткий ответ в байтах.
Ответы:
Желе ,
161514 байтПопробуйте онлайн! или проверьте все контрольные примеры .
Как это устроено
источник
Python 2, 68 байт
Эквивалент более «очевидного»:
источник
range(-n,0)
, как я делаю в своем ответе . Тестирование.Haskell, 65 байт
Пример использования:
map f [1..5]
->[(1,1),(1,2),(2,2),(2,2),(2,3)]
.Проходит внешний цикл
a
от1
доx
(х -> количество студентов) и внутренний циклb
от1
доa
. Сохраняет все(b,a)
гдеa*b>=x
и строит пары,((arrangement points,seats left), (b,a))
которые следуют лексикографическому порядку, нам нужно найти минимум. Примечание:a
всегда больше чемb
, поэтому нам не нужнаabs
прямоугольность. Не нужно вычитатьx
из балла «осталось мест», потому что имеет значение только относительный порядок. Наконец мы удаляем пару очков сsnd
.источник
a*b
(количество свободных мест) - это разрыв связи, если основной счет равен. Напримерn=43
: а)a=7, b=7
, оценка:(49,49)
б)a=9, b=5
, оценка:(49,45)
. Главный счет равен, решает тай-брейк, б) побеждает.a*b
, сами числа,(b,a)
которые я должен носить с собой, в любом случае действуют как прерыватель связи и дают те же результаты (по крайней мере)n=1..300
. Продукт маленький, если один из факторов (здесьb
) маленький. Но пока у меня нет формальных доказательств, я не хочу использовать этот факт. Посмотрим, найду ли я его.Рубин, 64 байта
Лямбада, которая принимает число людей в качестве аргумента и возвращает массив с шириной и высотой оптимального решения.
источник
w*h
второй элемент в вашем массиве? Я не думаю, что это что-то особенно меняет, когда вы звоните,min
потому что вы сводите к минимуму на счету, как первый элемент.In case of a tie, the optimal solution is the one with less empty chairs
MATL , 18 байт
Попробуйте онлайн!
объяснение
источник
Javascript, 98 байт
Мой первый код гольф, поэтому я все равно публикую!
Первоначально my
o
был пустым объектом, и я проверил,o.a
пусто ли это, поэтому это был особый случай в первом раунде. Но я нашел трюк 1/0 в ответе edc65, чтобы инициализировать переменную в бесконечность.источник
Pyth,
242221 байтИзменить : в ключе сортировки, я понимаю, что нет необходимости находить количество пустых стульев. Это эквивалентно общему количеству стульев. Это спасло мне 2 байта.
Попробуйте онлайн!
источник
Matlab
(174) (146)121Трюк 1: я добавил сумму в
1-1/length*width
качестве подсчета очковТрюк 2: я рассчитал
number_students/length
ceiled для ширины прямоугольника,верхняя граница - квадрат, но тоже CeiledЯ уверен, что это может быть дальше в гольфе ...
попытайся
Изменить: ссылается на замечания @StewieGriffin.
Изменить 2:
1
иn
константы не нужно добавлять их в общий счет.Редактировать 3: тест на производительность.
источник
unique
Python 2, 64 байта
Это объединение ответа @ Lynn's Python (откуда я взял
max(...)[1:]
трюк) и алгоритма из моего ответа Джулии (что позволяет немного более короткую реализацию).Проверьте это на Ideone .
источник
Юлия,
6159555352 байтаПопробуйте онлайн!
Как это устроено
Код эквивалентен следующей версии без заглавных букв с
cld
разделением потолка.Чтобы найти оптимальное расположение, явно достаточно изучить пары [i, j] , где 1 ≤ i ≤ n и j = ⌈n / i⌉ .
Оценка для такой договоренности составляет | j - i | + (ij - n) , где второе слагаемое - количество пустых стульев. Вместо фактических баллов мы можем сравнивать баллы, дополненные константой, например, ij + | j - i | + 1 .
Достаточно рассмотреть пары [i, j], где i ≤ j, поскольку схемы [i, j] и [j, i] одинаково верны. Мы имеем дело со строго нисходящими парами, устанавливая вместо этого j = max (⌈n / i⌉, i) , что гарантирует, что j ≥ i, и даст субоптимальный результат, если ⌈n / i⌉ <i .
Поскольку j - i ≥ 0 , имеем ij + | j - i | + 1 = ij + j - i + 1 = (i + 1) × (j - 1) , который может быть вычислен в меньшем количестве байтов кода.
Наконец,
indmin
/indmax
дает индекс m (и, следовательно, значение i ) оптимального расположения, который равен m на ⌈n / m⌉ . Связи разрываются при первом появлении, которое соответствует наименьшему значению i , следовательно, наибольшему значению j - i и, следовательно, наименьшему значению ij - n (пустые стулья).источник
JavaScript (ES6) 74
78Изменить, сохранив временный результат в виде массива вместо 2 переменных, заимствованных из ответа Тихта
Меньше гольфа
Тестовое задание
источник
PHP, 129 байт
Ungolfed:
источник
PHP, 104 байта
Алгоритм, решающий эту проблему, прост и, вероятно, используется другими ответами на языках, похожих на PHP (JavaScript, fe):
n
достаточно большой (гдеn
входное значение); оценка расположения, вычисленная на первой итерации (1, n
), равна(n-1)+0
;1
иn
; рассчитать минимальную высоту какceil(n/width)
, вычислите оценку расположения, используя формулу, представленную в вопросе (то естьabs(width - height) + (width * height - n)
); если результат лучше, чем предыдущий лучший результат, запомните ширину, высоту и новый лучший результат; используйте связиwidth * height - n
для текущей договоренности и предыдущей наилучшей договоренности, чтобы обнаружить новую наилучшую договоренность;После игры в гольф этот алгоритм производит что-то вроде этого (обернуто здесь для удобства чтения):
Использует 137 байт. (при размещении в одной строке), и это далеко от 104 байтов, объявленных в заголовке. Код, вероятно, может быть сокращен еще на 2-3 байта, но большой источник улучшений находится где-то еще: в деталях алгоритма.
Пересмотренный алгоритм:
Есть несколько мест, где алгоритм может быть улучшен путем удаления ненужного кода.
1
до$n
; для скорости width ($i
) должна выполнять итерации между1
и,floor(sqrt($n))
но это делает код еще длиннее, а не сокращает его; но если ширина не превышаетsqrt($n)
, минимальная высота ($j
) всегда будет больше чемsqrt($n)
(их произведение должно быть как минимум$n
);$i <= $j
(width <= height) в качестве условия завершения цикла; таким образом, ширина будет повторяться от1
до,floor(sqrt($n))
а высота получит значения, начинающиеся с$n
и понижающиесяceil(sqrt($n))
(не обязательно все);abs(width - height)
всегдаheight - width
($j-$i
); 5 байтов сохранены таким образом;$n
используется при подсчете очков (количество незанятых местwidth * height - n
), но это не нужно; оценка не должна отображаться, она рассчитывается только для сравнения договоренностей; удаляя- n
из формулы оценки, мы сохраняем еще 3 байта (код PHP-$n
), ничего не теряя;height - width + width * height
($j-$i+$i*$j
);height - width
часть оценки уменьшается на каждом шаге;||$c==$s&&$i*$j<$w*$h
- много байтов);-$n
формулы оценки, оценка для первой договоренности (1x$n
) равна$n-1+1*$n
(т.е.2*$n-1
); начальное значение best score ($s
) может быть любым значением, большим или равным2*$n
; первая итерация имеет лучший результат, и она становится наилучшей схемой, позволяющей алгоритму работать без проблем инициализации.Новый код ( 104 байта ) после применения описанных выше улучшений:
Это обернуто здесь для удобочитаемости. Добавьте код выше с маркером PHP
<?php
(технически он не является частью кода), поместите его в файл (скажемarrange-your-chairs.php
) и запустите с целым числом, большим нуля в качестве аргумента. Он будет отображать ширину и высоту вычисляемого расположения, разделенные запятой:Другое решение (116 байт)
Другое решение, которое использует другой алгоритм:
Это помещает все комбинации по крайней мере
$n
мест в ассоциативный список; ключ - текстовое представление соглашения, значение - оценка соглашения. Затем он сортирует список (по возрастанию по значению) и получает ключ первой записи.Еще один (115 байт)
Это PHP-версия ответа @ Neil (JavaScript / ES6, 85 байт).
Есть некоторые заметные различия из-за особенностей каждого языка:
n
(неопределенных) значений, а затем использует его ключи для итерации от0
доn-1
; он увеличиваетi
(d=(n+i++)/i|0
), чтобы сделать итерацию от1
доn
; решение PHP не нужно увеличивать; он используетrange()
для генерации массива, а затем использует сгенерированные значения (1
дляn
) для итерации;(n+i)/i
затем преобразует значение в целое число, используя,|0
чтобы получить наименьшее целое число больше, чемn/i
; ответ PHP решает эту проблему легко с помощью функции PHPceil()
; JavaScript также предоставляет,Math.ceil()
но он использует на 5 байт больше, чем решение, найденное Нилом;array_map()
которая чем-то похожа на JS,Array.map()
но здесь она не помогает; его синтаксис многословен,foreach
производит более короткий код; хотя он больше, чем код JS;||
невозможно в PHP, поскольку в нем отсутствует оператор запятой; Я перевелa||b||c
вif(!a&&!b)c
тогда, потому чтоa
иb
являются сравнениями, я отрицал их операторы (заменены<
на>=
); это также производит больший код, чем версия JS;$
.Развернутые версии всех решений и наборов тестов можно найти на Github .
источник
JavaSCript (ES6), 83 байта
источник
m
чтобы компенсировать.Юлия, 87
Я думаю, что это один шаг в направлении к поиску волшебной функции для проблемы:
Это смотрит только на пары
(i, j=(i+n)/(i+1))
или(i, j+1)
источник
n
нигде не определяете , и вы, кажется, не принимаете входные данные.n
качестве входных данных Нужно было бы обернуть это вn->...
. Приятно, что ты смог заставить это работать.Oracle SQL 11.2, 173 байта
Un-golfed
источник
Q 58 байт
Lamba, которая вычисляет минимальную стоимость для данного значения (x) и возвращает последовательность из двух значений (ширина, высота)
Добавление имени к этой лямбде требует двух других символов (например, f: {..} вместо {..})
Тестовое задание
где {..} лямбда Читайте как «применяет лямбду к каждому значению 1 + первые 100 дюймов» (другими словами, к каждому значению 1..100)
Формирует
объяснение
Вложенная lamdba
{((b<a)?1b)#+(b:-_-x%a;a:1+!x)}
генерирует все пары кандидатов (widht, высота) для x стульев как две последовательности (w1 w2 w3 ..; h1 h2 h3 ..) (ширины и высоты). Читайте слева направо, но оценивает справа налевоa:1+!x
генерирует значения 1..x и присваивает эту последовательность-_-
является отрицанием пола отрицанием, и реализует ceil (ceil не является примитивом языка)b:-_-x%a
применяет ceil к каждому значению x, деленному на любой элемент im a, и присваивает результирующую последовательность b. Другими словами, каждый элемент x делится на 1.x+(b;a)
возвращает последовательность, состоящую из seq a и seq b, затем переворачивает ее (в результате получается последовательность пар, в которой i-pair содержит элемент i из a и элемент i из b)b<a
сравнивает элемент за элементом из b и a и генерирует последовательность логических значений (true = 1b для каждого индекса, где b [i]s?x
возвращает первую позицию элемента x в последовательности s. С(b<a)?1b
Мы ищем 1b (истинное значение) в последовательности, полученной в результате сравнения b и a, и получаем первую позицию, где bn#s
берет n первых n элементов из последовательностей. Мы хотим отбросить дублирующиеся пары, поэтому мы останавливаемся, когда первый элемент пары <второй элемент (например, рассмотрим 13,1, но не 1,13).Как побочный эффект, каждая пара получающейся последовательности имеет уменьшающееся расстояние между a и b (например, (13 1; 7 2; 5 3; 4 4)
Пара кандидатов, сгенерированная вложенной лямбдой, присваивается c. Затем мы переворачиваем c (снова получаем b, a) и применяем к этому аргументу две функции:
*/
умножаем на и-/
вычитаем на. Результатом(-/;*/)@\:+c
является разница и произведение каждой пары.+/
суммируется, и рассчитывается окончательная стоимость. Стоимость каждого патир назначается на д& / является минимальным значением, поэтому
&/
d является минимальной стоимостью. С помощьюd?&/d
мы находим первое вхождение минимальной стоимости в d, а с помощью c @ .. мы получаем пару в этой позиции. Поскольку каждая пара имеет уменьшающееся расстояние между a и n, первый найденный минимум имеет максимальное расстояние между другими минимальными парами, поэтому мы правильно применяем правило связиисточник