Принцип голубиной дыры гласит, что
Если N элементов помещено в M блоков с N > M , то хотя бы один блок должен содержать более одного элемента.
Для многих этот принцип имеет особый статус по сравнению с другими математическими высказываниями. Как писал EW Dijkstra ,
Он окружен какой-то мистикой. Доказательства его использования часто рассматриваются как нечто особенное, что-то особенно гениальное.
Соревнование
Цель этой задачи состоит в том, чтобы проиллюстрировать принцип «голубиных отверстий» с использованием художественных представлений ASCII. В частности:
- Возьмите в качестве входных данных
N
(количество элементов) иM
(количество блоков), сN
неотрицательным иM
положительным.N
может быть меньше, чемM
(даже если принцип не применяется в этом случае). - Произвольно выберите одно из возможных назначений предметов для ящиков. Каждое назначение должно иметь ненулевую вероятность быть выбранным.
Создайте ASCII художественное представление задания следующим образом:
- Есть
M
строки, каждая из которых соответствует коробке. - Каждая строка начинается с непробельного символа, такого как
|
. - За этим символом следует другой непробельный символ, например
#
, повторяемый столько раз, сколько в этом поле есть элементов.
- Есть
Рассмотрим, например N = 8
, M = 5
. Если выбранная распайка элементов для ящиков 4
, 1
, 0
, 3
, 0
, то представление
|####
|#
|
|###
|
Другой прогон (приводящий к другому назначению) одной и той же программы может дать
|#
|##
|#
|#
|###
Существует некоторая гибкость в отношении представления; увидеть ниже.
Особые правила
Код должен теоретически работать при любых значениях в N
и M
. На практике это может быть ограничено размером памяти или типом данных.
Поскольку наблюдения выходных данных недостаточно для определения того, все ли присвоения имеют ненулевую вероятность , каждое представление должно объяснять, как код достигает этого, если не очевидно.
Допустимы следующие варианты представления:
- Любая пара разных непробельных символов может быть выбрана. Они должны быть согласованы при выполнении программ.
- Повороты представления на 90 градусов допустимы. Опять же, выбор должен быть последовательным.
- Трейлинг или пробел допускается.
В качестве примера с другим форматом представления, для N = 15
, M = 6
результаты двух выполнений программы может быть
VVVVVV
@@@@@@
@@ @@@
@ @@
@
или
VVVVV
@@@ @
@@@ @
@ @ @
@ @ @
@
Кроме того, N = 5
, M = 7
может дать, используя другой вариант представления,
*
* * * *
UUUUUUU
или
*** **
UUUUUUU
или
*
* *
* *
UUUUUUU
Обратите внимание, что принцип не применим в этом случае, потому что N
< M
.
Основные правила
Программы или функции разрешены на любом языке программирования . Стандартные лазейки запрещены.
Вклад может быть сделан любым разумным способом ; и с любым форматом, таким как массив из двух чисел или двух разных строк.
Средство вывода и формат также являются гибкими. Например, выходные данные могут быть списком строк или строкой с символами новой строки; возвращается как выходной аргумент функции или отображается в STDOUT. В последнем случае не нужно беспокоиться о переносе строк, вызванном ограниченной шириной экрана.
Самый короткий код в байтах побеждает.
Ответы:
Желе ,
98 байтЭто диадическая ссылка, которая принимает M в качестве левого и N в качестве правого аргумента. Выходные данные - это массив целых чисел, где 0 представляет голубей, а 1 - дырки.
Попробуйте онлайн!
Как это работает
источник
Mathematica, 68 байт
Неименованная функция, которая принимает два целочисленных аргумента: количество блоков, а затем количество элементов.
Сначала он вычисляет все возможные разбиения
N+M
в точноM
положительные части, а затем вычитает1
из каждого разбиения. Это дает нам все возможные разбиенияN
наM
неотрицательные части (которыеIntegerPartitions
не сгенерируют иначе). Затем выберите случайный раздел и перемешайте его. Это гарантирует, что разрешены все возможные заказанные разделы с нулями. Наконец, преобразуйте каждую ячейку раздела в выходную строку, увеличив 10 до соответствующей мощности (так, чтобы каждая строка стала1000...
сk
нулями). Пример вывода может выглядеть так:источник
PadRight
что не дополняетM
нули, еслиN
<M
.PadRight
отсутствие возможности сделать это намного дольше.PadRight
будетIntegerPartitions[#,{#2},0~Range~#]
.Python 2,
7786 байтСоздает число в [0, n], печатает столько элементов и вычитает его из n. Это делает это m раз.
Это делает очень маловероятным, что что-либо дойдет до последней рамки, но вопрос только в том, чтобы каждый вывод был возможен , не одинаково вероятен .
источник
Пакет, 164 байта
Я думаю, что 7 последовательных
%
признаков могут стать новым личным лучшим! Примечание: это создает странный вывод, если он когда-либо назначит более 9 элементов в один блок; если это проблема, то для 180 байтов:Да, это всего 28
%
секунд на второй строке.источник
C, 102 байта
Принимает ввод на стандартный ввод, например:
Не будет генерировать каждый выход с равной вероятностью, но способен генерировать все возможные комбинации.
Сломать:
Полагается, что GCC обрабатывает неопределенное поведение
%0s
- обычно%0
будет заполнять нулями целое число или число с плавающей запятой, но он может только дополнять (никогда не обрезать), поэтому невозможно напечатать пробел. Но поведение для строк не определено, и GCC решил сделать это с нулевым заполнением таким же образом, так что это нулевое заполнение пустой строки, чтобы иметь возможность записать ноль или более0
s.источник
a(b,c){...}
вместоmain
иscanf
.Python 2,
102999790 байтm-1
раз, выбрал случайное количествоx
между0
иn
включительно и вычесть его из n. Затем распечатайте1
и'0'*x
.Наконец, распечатайте
1
и остальные0
с. Совсем нет равных шансов, но возможны все конфигурации.(Повторно использованный код из неправильного ответа Python.)
источник
Haskell,
11494 байтаНемного подхода грубой силы: генерирует бесконечный список случайных чисел, берет n чисел начала списка, суммирует их и проверяет, равны ли они m. Если нет, уберите первый элемент из списка и повторите.
Попробуйте онлайн!
Примечание: 73 байта без импорта
РЕДАКТИРОВАТЬ: Сохранено несколько байтов с помощью трюка 10 ^ ( Попробуйте новую версию онлайн! )
источник
REXX, 74 байта
Выход (8 5):
Выход (8 5):
источник
С
175138 байтСпасибо @Dave за сохранение 37 байт!
Попробуйте онлайн!
источник
calloc
даст вам 0-инициализированную память (не нужно устанавливать все 0 самостоятельно),strchr
может найти конец строки, запятая может связывать операции, избегая необходимости{}
, иx[0] == *x
. Также будьте осторожны; у васmalloc
недостаточно памяти, если все предметы находятся в одной коробке.AHK, 66 байт
Я следовал тому же принципу, что и orlp , используя случайные числа от 0 до N, а затем вычитал его из N. К сожалению, я не смог сохранить байты, используя 10 ^ r из-за способа работы функции Send. Увы и неудачно. Вот некоторые выводы для n = 8, m = 5:
источник
CJam,
303121 байтВвод двух чисел
n m
в стеке. Используется1
для символа столбца и0
для повторного символа.Объяснение:
источник
Рёда , 79 байт
Попробуйте онлайн!
Это создает массив нулей и увеличивает их в случайных местах.
источник
PHP, 100 байт
Сломать :
Выходы для
m=7
иn=5
:Первое исполнение:
Второе исполнение:
Попробуйте онлайн!
источник
[,$m,$n]=$argv;
из PHP 7.1, чтобы сохранить несколько символов. Вы можете заменить\n
фактический разрыв строки, чтобы сохранить 1 байт. Вы можете использовать,for(;$m-->0;)$a[rand(0,$n-1)].=a;
чтобы сохранить разрывы,$m
и точку с запятой.[,$m,$n]=$argv;$a=array_fill(0,$n,z);for(;$m-->0;)$a[rand()%$n].=a;echo join("\n",$a);
85 байт[,$m,$n]=$argv;for(;$m--;)${rand()%$n}.=a;for(;$n--;)echo"z${$n}\n";
67 байт.[,$m,$n]=$argv;
на других кодах-гольфах, но не смог заставить ее работать ни в моей среде разработки, ни на eval.inJavaScript, 105 байт
Попробуйте онлайн!
Из-за метода назначения строк это будет иметь тенденцию размещать больше по направлению к низу, хотя есть небольшая вероятность того, что верх получит некоторые.
источник
Рубин, 52 байта
Создает анонимную функцию, которая принимает два целых числа в качестве аргументов и возвращает массив строк:
источник
Python 2, 81 байт
Возвращает список строк.
источник
Javascript (ES7), 75 байт
Я подумал, что у меня хватит ума придумать идею 10 способностей только для того, чтобы понять, что большинство ответов уже используют это.
источник
AWK, 78 байт
Принимает 2 аргумента, сначала количество элементов, затем количество блоков. Начинается с заполнения генератора случайных чисел, поэтому каждый прогон отличается. Затем просто строит строки в массиве, пример использования:
источник
MATLAB,
10394 байтаС форматированием
Пример вывода
Существуют завершающие пробелы, поскольку каждая запись массива отображается с вкладкой между ними, но это должно быть приемлемым согласно спецификациям.
Это кажется мне очень упрощенной реализацией, поэтому я уверен, что это можно улучшить.
Спасибо @Luis Mendo за предложения.
источник
d=@(p)disp(char([1,~(1:p)]+48));for i=1:m-1;p=randi([0,n]);d(p);n=n-p;end;d(n)
a=
. В этом случае вы не можете сделать это в принципе, потому что анонимные функции не могут содержать циклы. Но вы могли бы использовать хитрость, чтобы положить все вeval('...')
. Кстати, это обычно считается уродливой и плохой практикой в Matlab, но здесь нам нравятся злоупотребления языками :-)Октава ,
6254 байтаАнонимная функция, которая принимает два числа и выводит двумерный массив символов
>
для блоков и*
объектов. Все результаты одинаково вероятны.Попробуйте онлайн!
источник
TI-Basic,
6362 байтаЭтот критерий значительно облегчил написание этой программы.
Пример ввода / вывода:
Объяснение:
источник
MATLAB,
736458 байтОбновление # 3
Кажется, мне нужна сортировка, поскольку в противном случае я получаю отрицательные целые числа. Я заменил
disp(sprintf(...))
наfprintf(...)
сейчас, поэтому ответ остается 58 байтов.Обновление # 2:
Я понял, что мне не нужно сортировать массив, и фактически сортировка фактически уменьшит среднее число чисел в массиве. Поэтому я удалил
sort(...)
часть. Обратите внимание, что вывод остается прежним, поэтому я не обновляю «пример вывода».Наконец-то приближаемся к октавскому ответу Луиса! : D
Обновление # 1:
Вместо преобразования в строку, я просто отображаю числа напрямую. Я мог бы уменьшить до 58 байт, удалив
disp(...)
, но тогда я получаю дополнительныеans =
с помощью только sprintf, и не знаю, приемлемо ли это.Исходный код:
Благодаря некоторым предложениям Луиса я избавился от этой петли в своем предыдущем ответе . Теперь я сначала создаю вертикальный массив
m
случайных чисел, складывающихся вn
(diff([0;sort(randi(n,m-1,1));n])
), затем использую их как показатели степени 10, преобразую их в строку, выравниваю их по левому краю и показываю их.Я мог бы технически избавиться от disp (...), чтобы сохранить еще 6 байтов, но затем напечатал «ans», который может нарушать спецификации. Также может быть способ изменить их на строковые и выровнять по левому краю, чтобы получить желаемый конечный формат, поэтому я открыт для предложений.
Образец вывода:
Примечание : здесь я изменил свою функцию на анонимную, основываясь на предложениях. В примере вывода я назначил это
a
для демонстрации. Я надеюсь, что это не нарушает спецификации, но если это так, пожалуйста, дайте мне знать, и я изменю это.источник
m
случайных целых чисел, которые составляют вn
целом, так как я застрял на этой части в течение долгого времени .. (Тем не менее не могу добавить более 2 ссылок в моих ответах, поэтому включение его в комментарии)С накоплением , 29 байт
Попробуйте онлайн!
Ведет себя путем построения массива
M
синглетонов, содержащего'|'
, а затем добавляющего'#'
в произвольно выбранный массивN
раз.источник
randin
использует алгоритм Фишера-Йейтса внутренне. (Это тот же алгоритм, который в ответе CJam использует FWIW)Python 2 ,
80 95 8988 байтПопробуйте онлайн!
источник
Древесный уголь , 19 байт
Попробуйте онлайн! Ссылка на подробную версию кода. Объяснение:
источник