Цель
Генерируйте ( N
) случайные отрезки одинаковой длины ( l
), проверьте, пересекают ли они равноотстоящие ( t
) параллельные линии.
моделирование
Что мы моделируем? Игла Буффона . Разгладьте песок в своей песочнице, нарисуйте набор параллельных линий, расположенных на равных расстояниях (назовите расстояние между ними t
). Возьмите прямую палку длины l
и бросьте ее N
в песочницу. Пусть будет количество пересечений линии c
. Тогда Pi = (2 * l * n) / (t * c)
!
Как мы моделируем это?
- Принять вход
N,t,l
- Со
N, t, l
всеми положительными целыми числами - Делайте следующее
N
время:- Генерация равномерно случайной целочисленной координаты
x,y
- С
1 <= x, y <= 10^6
x,y
является центром отрезка длиныl
- Генерация равномерно случайного целого числа
a
- С
1 <= a <= 180
- Позвольте
P
быть точкой, где отрезок будет пересекать ось X - Тогда
a
угол(x,y), P, (inf,0)
- Генерация равномерно случайной целочисленной координаты
- Подсчитайте количество
c
отрезков, которые пересекают линиюx = i*t
для любого целого числаi
- Возвращение
(2 * l * N) / (t * c)
Спецификация
- вход
- Гибкость, принимать входные данные любым из стандартных способов (например, параметр функции, STDIN) и в любом стандартном формате (например, String, Binary)
- Вывод
- Гибкость, вывод на печать любым из стандартных способов (например, возврат, печать)
- Пробел, конечный и ведущий пробел приемлем
- Точность, укажите не менее 4 знаков после запятой (т.е.
3.1416
)
- счет
- Самый короткий код выигрывает!
Тестовые случаи
Ваш результат может не совпадать с этим из-за случайного шанса. Но в среднем вы должны получить примерно такую точность для заданного значения N, t, l
.
Input (N,t,l) -> Output
----------- ------
10,10,5 -> ?.????
10,100,50 -> ?.????
1000,1000,600 -> 3.????
10000,1000,700 -> 3.1???
100000,1000,700 -> 3.14??
TL; DR
Эти проблемы представляют собой симуляции алгоритмов, которые требуют только природы и вашего мозга (и, возможно, некоторых ресурсов многократного использования) для приближения Pi. Если вам действительно нужен Пи во время апокалипсиса зомби, эти методы не тратят патроны ! Всего девять задач .
a
быть создано другим методом, если оно однородно? (думая о 2Dt > l
? Два решения ниже делают это предположение, которое немного упрощает проверку на пересечение.Ответы:
R,
1131007570686765596357 байтКак статистический, функциональный язык программирования, неудивительно, что R достаточно хорошо подходит для такого рода задач. Тот факт, что большинство функций может принимать векторизованный ввод, действительно полезен для этой проблемы, поскольку вместо циклического
N
повторения мы просто передаем векторы размераN
. Спасибо @Billywob за некоторые предложения, которые приводят к сокращению 4 байтов. Большое спасибо @Primo за терпеливое объяснение, как мой код не работал в тех случаяхt > l
, когда это исправлено.Попробуйте онлайн!
Пример вывода:
объяснение
Проблема сводится к тому, чтобы определить, находятся ли два
x
значения стрелки по обе стороны параллельной линии. Это имеет несколько важных последствий:y
-значения не имеют значенияx
оси не имеет значения, только положение относительно ближайших параллельных линий.По сути, это задача в одномерном пространстве, где мы генерируем линию с длиной в [0,
l
] (уголa
определяет эту длину), а затем мы проверяем, во сколько раз эта длина превышаетt
. Грубый алгоритм тогда:x1
значения из [0, 1000000]. Поскольку параллельные линии встречаются в каждойt
точке вдольx
оси-осей, относительноеx
положение являетсяx
модулемt
.a
.x2
позицию на основеa
.x1+x2
вписываетсяt
, то есть взять слово(x1+x2)/t
.Выборка
N
чисел в [0, 1e6] по модулюt
эквивалентна простой выборкеN
чисел в [0,t
]. Поскольку(x1+x2)/t
эквивалентноx1/t + x2/t
, первый шаг становится выборкой из [0,t
] /t
, то есть [0, 1]. К счастью для нас, это диапазон по умолчанию дляrunif
функции R , которая возвращаетN
действительные числа от 0 до 1 из равномерного распределения.Мы повторяем этот шаг, чтобы сформировать
a
угол наклона иглы.Эти числа интерпретируются как пол оборота (то
.5
есть 90 градусов). (ОП просит градусов от 1 до 180, но в комментариях это уточнить , что любой метод, допускается , если это так , или более точным.) Для углаθ
,sin(θ)
дает нам расстояние по оси х между концами иглы. (Обычно вы используете косинус для чего-то подобного; но в нашем случае мы рассматриваем уголθ
как относительный относительно оси y, а не оси x (то есть значение 0 градусов увеличивается , а не справа ), и поэтому мы используем синус, который в основном сдвигает числа по фазам.) Умноженное наl
это дает намx
местоположение конца иглы.Теперь мы делим на
t
и добавляемx1
значение. Это дает то(x1+x2)/t
, насколько далеко выступает иглаx1
, с точки зрения количества параллельных линий. Чтобы получить целое число пересеченных линий, мы беремfloor
.Мы вычисляем сумму, давая нам счет
c
того, сколько линий пересекают иглы.Остальная часть кода просто реализует формулу для аппроксимации пи, то есть
(2*l*N)/(t*c)
. Мы экономим несколько байтов в скобках, используя тот факт, что(2*l*N)/(t*c) == 2*l*N/t/c
:И все это заключено в анонимную функцию:
источник
(2*l*N) => 2*l*N
?(2*l*N)/(t*c) = 2*l*N/t/c
вы можете сохранить еще два байта, пропустив скобки и в последней части.Perl, 97 байт
Считая Шебанг как единое, ввод берется из стандартного ввода, разделенное пробелами. Если бы допускались нецелые случайные значения, это могло бы быть несколько короче.
Я взял одну свободу, приблизив π / 180 к 71/4068 , что с точностью до 1,48 · 10 -9 .
Образец использования
Более или менее математически эквивалентные замены
Предполагая, что координата x представляет крайнюю левую точку иглы, а не ее середину, как указано в описании проблемы:
89 байт
Проблема указывает, что
x
выборка должна быть случайным целым числом. Если спроецировать межстрочный интервал на разрыв одного, это оставит нас значение формыn/t
с0 <= n < t
, не обязательно однородным, еслиt
не равномерно разделить1e6
. Предполагая, что равномерное распределение, тем не менее, приемлемо:76 байт
Обратите внимание, что, поскольку
rand
всегда будет меньше единицы (и, следовательно, обрезается до нуля), в начале диапазона это необязательно:70 байт
Предполагая, что угол наклона иглы не должен быть целым градусом, а только равномерно случайным:
59 байт
Предполагая, что угол может быть любым равномерным распределением:
52 байта
Выше приведено математически правильное моделирование иглы Буффона. Тем не менее, на данный момент я думаю, что большинство людей согласятся, что это на самом деле не тот вопрос, о котором спрашивают.
Действительно толкаю это
Мы могли бы просто отбросить половину тестовых случаев, когда вторая конечная точка находится слева от первой (вместо их замены):
47 байт
Обратите внимание, что значения
t
иl
несущественны для результатов эксперимента. Мы могли бы просто игнорировать их (неявно предполагая, что они равны):28 байт
Очевидно, что он неконкурентный, но вы должны признать, что он обладает определенной элегантностью.
источник
Python 2, 141 байт
бесстыдный порт грохота, уже пропускающий,
y
потому что совершенно не нужен.Проблема только в том, что пи уже известен в программе.
Вот он (играбельный) с неизвестным пи и без тригонометрических функций
x,y
вg
только для направления.источник
from random import randint;from math import cos,pi
. Сбойt < l
, например1000000,1000,70000
.