Вызов
Оригами (складная бумага) - это творческий вид искусства. Насколько я знаю, мастер оригами предпочитает квадратную бумагу. Начнем с начала - конвертируем прямоугольную бумагу в квадратную.
Таким образом, бумага делится на квадраты. Мы удаляем самый большой квадрат, который разделяет один более короткий край с текущей формой, шаг за шагом (см. Рисунок ниже). И если оставшаяся часть после одного шага меньше или равна 0.001 * (area of the original paper)
, бумага не может быть разделена дальше. Возможно, что в конце концов ничего не останется.
Ваша задача - подсчитать, сколько квадратов сделано в процессе. Квадрат на последнем шаге, который не позволяет разделить бумагу, засчитывается в результат.
Пример (бумага 1.350
ширины / высоты), вывод 10:
Вход и выход
Ввод: отношение ширины к высоте для прямоугольной бумаги, один десятичный знак (или целое число без точки) от 1.002
до 1.999
с минимальным шагом 0.001
. Вы также можете использовать любой другой разумный формат, описывающий соотношение. Просто упомяните это в своем ответе.
Вывод: квадратное число, одно целое число.
Пример ввода / вывода
Формат отображения используется для поддержания чистоты страницы, в то время как ваш код не должен поддерживать ввод списка или быть функцией отображения.
1.002 => 251
1.003 => 223
1.004 => 189
1.005 => 161
1.006 => 140
1.007 => 124
1.008 => 111
1.009 => 100
Спасибо @LuisMendo, вот график ответов.
замечания
- Это код-гольф, поэтому выигрывает самый короткий код
- Обратите внимание на стандартные лазейки
- Вы можете сами решать, что делать с вводом и выводом, но они должны следовать стандартным ограничениям.
Кстати...
- Прокомментируйте, если у вас есть что-то неясное по поводу проблемы
- Лично я бы предложил, чтобы ваш ответ содержал объяснение, если вы используете язык игры в гольф
- Спасибо @GregMartin, прочитайте его ответ для хорошего математического объяснения проблемы.
Пример кода
Вот незакрашенная версия кода C ++:
#include <iostream>
#include <utility>
int f (double m)
{
double n = 1, k = 0.001;
int cnt = 0;
k *= m; // the target minimum size
while(m*n >= k)
{
m -= n; // extract a square
if(n > m)
std::swap(n, m); // keep m > n
++ cnt;
}
return cnt;
}
int main()
{
double p;
std::cin >> p;
std::cout << f(p);
return 0;
}
Все вычисления, относящиеся к примеру кода, требуют точности 6 десятичных цифр, которая покрыта float
.
Ответы:
MATL , 19 байт
Входные данные представляют собой массив с двумя числами, определяющими исходное соотношение, например
[1, 1.009]
. (Не обязательно, чтобы числа были отсортированы или чтобы одно из них было 1.)Попробуйте онлайн!
объяснение
источник
Haskell ,
71 70 65 63 62 61 5856 байтСпасибо @xnor за некоторые гениальные улучшения!
Попробуйте онлайн!
источник
m==n
в конце может быть,1>0
потому что это единственная оставшаяся возможность. Или, может быть, дела могут быть переставлены, чтобы связать здесь.n>m
расширен доn>=m
и написана первая проверкаe>m*n*1000
, это должно дать1
равенство.(n#m)e|e>n*m*1e3=0|n<m=m#n$e|d<-n-m=(d#m)e+1;n!m=n#m$n*m
d<-n-m
какotherwise
действительно опрятно !!!JavaScript (ES6),
5958 байтТестовое задание
Показать фрагмент кода
источник
Mathematica, не конкурирующий (21 байт)
Этот ответ не конкурирует, потому что он не отвечает на фактически заданный вопрос! Но он действительно отвечает на вариант вопроса и дает повод для выделения интересной математики.
Символьная функция, принимающая положительное рациональное число в качестве входных данных (числитель и знаменатель которых представляют размеры оригинальной статьи) и возвращающая положительное целое число. Например,
Tr@*ContinuedFraction[1350/1000]
возвращает10
. (ContinuedFraction
действует по-разному для чисел с плавающей точкой из-за проблем с точностью, поэтому в качестве входных данных в этом контексте требуется рациональное число.)Интересная интерпретация геометрической процедуры, описанной в задаче (многократное отрезание квадратов от прямоугольника), заключается в том, что это реализация евклидова алгоритма для нахождения наибольших общих делителей! Рассмотрим пример в самом вопросе с соотношением
1.35
, который можно смоделировать, имея лист бумаги с размерами (1350, 1000). Каждый раз, когда квадрат обрезается, меньшее число вычитается из большего числа; поэтому получающиеся прямоугольники в этом примере имеют размеры (350, 1000), затем (350 650), затем (350 300), затем (50 300), затем (50 250) и (50 200) и (50 150) и (50 100) и (50, 50), а также (50,0), как только мы заберем у себя последний квадрат. Именно так работает евклидов алгоритм (по модулю разницы между делением и повторным вычитанием), и мы действительно видим, что 50 - это действительно GCD из 1350 и 1000.Как правило, в евклидовом алгоритме каждый отслеживает эти промежуточные измерения и отбрасывает количество вычитаний; Тем не менее, можно поочередно записать, сколько раз мы вычитали одно число из другого, прежде чем разница станет слишком маленькой, и мы должны изменить то, что мы вычитаем. Этот метод записи является именно непрерывной дробью рационального числа. (Непрерывные дроби иррациональных чисел, которые никогда не заканчиваются, также очень крутые, но здесь они не актуальны.) Например, в примере 1350/1000 мы вычитали 1000
1
раз, затем 3502
раз, затем 3001
раз, затем 506
раз; следовательно, продолжающаяся дробь 1350/1000 есть{1,2,1,6}
. Математически мы переписали 1350/1000 как1
+ 1 / (2
+ 1 / (1
+ 1 /)6
)), который вы можете проверить.Так что для этой проблемы, если вы не останавливаетесь, когда квадраты становятся меньше, чем определенное пороговое значение, а просто подсчитываете все конечное число квадратов до того, как оно остановится, тогда общее количество квадратов равно общему количеству вычитаний, то есть сумма всех целых чисел в непрерывной дроби - и это именно то, что
Tr@*ContinuedFraction
вычисляет композиция функций ! (Для данного примера 1.35, он получает ответ, который желает OP, потому что последний квадрат достаточно велик, чтобы были подсчитаны все квадраты. НоTr@*ContinuedFraction[1001/1000]
, например, дает1001
, так как он учитывает один огромный квадрат и все 1000 из маленьких квадратов 1x1000 .)источник
Mathematica,
6453 байтаИмперативное (в стиле C) решение точно такой же длины:
источник
C (GCC / Clang),
6159 байтВвод двух целых чисел (ширина и высота) без точки, например
f(1999,1000)
.Я надеюсь, что кто-то может сохранить один байт, вставив C в 58-байтовый клуб. ;)
источник
m-=n
C 59 байт
Попробуй онлайн
Входные данные представляют собой целое число, которое представляет собой отношение ширины к высоте в тысячных долях (например, 1002 для 1,002: 1).
Неуправляемая версия
источник