Проблема:
Выбирая язык, напишите кратчайшую функцию, которая возвращает пол квадратного корня 64-разрядного целого числа без знака.
Тестовые случаи:
Ваша функция должна работать правильно для всех входов, но вот несколько, которые помогают проиллюстрировать идею:
INPUT ⟶ OUTPUT
0 ⟶ 0
1 ⟶ 1
2 ⟶ 1
3 ⟶ 1
4 ⟶ 2
8 ⟶ 2
9 ⟶ 3
15 ⟶ 3
16 ⟶ 4
65535 ⟶ 255
65536 ⟶ 256
18446744073709551615 ⟶ 4294967295
Правила:
- Вы можете назвать свою функцию как угодно. (Безымянные, анонимные или лямбда-функции в порядке, если они так или иначе могут вызываться.)
- В этом испытании важнее всего количество символов, но важно и время выполнения. Я уверен, что вы могли бы итеративно сканировать ответ в течение O (√n) времени с очень небольшим количеством символов, но время O (log (n)) было бы действительно лучше (то есть, предполагая, что входное значение n, не битовая длина п).
- Возможно, вы захотите реализовать функцию с использованием чисто целочисленной и / или логической арифметики. Однако, если вы действительно хотите использовать вычисления с плавающей запятой, это нормально, если вы не вызываете библиотечные функции. Таким образом, просто говорить
return (n>0)?(uint32_t)sqrtl(n):-1;
в C запрещено, даже если это даст правильный результат. Если вы используете арифметику с плавающей точкой, вы можете использовать*
,/
,+
,-
и возведение в степень (например,**
или ,^
если это встроенный оператор в выбранном вами языке, но только экспоненцирование полномочий не менее 1 ). Это ограничение состоит в том, чтобы предотвратить «мошенничество» путем вызоваsqrt()
или варианта или повышения значения до степени ½. - Если вы используете операции с плавающей точкой (см. # 3), вам не требуется, чтобы возвращаемый тип был целочисленным; только то, что возвращаемое значение является целым числом, например, floor (sqrt (n)), и может содержать любое 32-разрядное значение без знака.
- Если вы используете C / C ++, вы можете предположить существование беззнаковых 64-битных и 32-битных целочисленных типов, например,
uint64_t
иuint32_t
как определено вstdint.h
. В противном случае просто убедитесь, что ваш целочисленный тип может содержать любое 64-разрядное целое число без знака. - Если ваш язык не поддерживает 64-битные целые числа (например, Brainfuck, по-видимому, поддерживает только 8-битные целые числа), приложите все усилия и укажите ограничение в заголовке вашего ответа. Тем не менее, если вы сможете понять, как кодировать 64-разрядное целое число и правильно получить квадратный корень из него, используя 8-разрядную примитивную арифметику, тогда вам больше сил!
- Веселитесь и будьте креативны!
code-golf
math
arithmetic
Тодд Леман
источник
источник
O(log_2 n) === O(log_4 n)
.log_4(n) = log_2(n) / log_2(2) = log_2(n) / 2
Ответы:
CJam, 17 (или 10) байт
Попробуйте онлайн , проверив контрольные примеры:
Он не пройдет последний тестовый случай из-за проблем с округлением, но, поскольку в CJam
18446744073709551615
нет Integer (это Big Integer ), мы все еще хороши, верно?Если нет, следующий (и чуть более длинный) код исправит эти ошибки:
Больше не самое короткое решение, но faaast .
Как это устроено
источник
<.@%~^&1.5
. Могу ли я опубликовать это как отдельный ответ (поскольку это в основном ваш точный порт)?4294967295
и4294967296
выглядел очень похожим ...Хаскелл,
2826Я считаю, что это самая короткая запись из всех языков, не предназначенных для игры в гольф.
Называет функцию
s
с параметромa
и возвращает один минус первое число, квадрат которого больше чемa
. Работает невероятно медленно (O (sqrt n), может быть?).источник
[...]!!0
) короче головы?Golfscript, 17 символов
Я мог назвать свою функцию так, как мне нравится, но я решил не называть ее вообще. Добавьте два символа к имени, добавьте три к имени и не оставляйте его в стеке, вычтите один символ, если полная программа в порядке.
Эта мерзость выполняется не в логарифмическом времени в значении ввода, а не в O (sqrt n) времени, для получения результата требуется колоссальное линейное количество времени. Это также занимает столько места. Абсолютно ужасно. Но ... это код-гольф.
Алгоритм:
источник
Pyth , 14 символов
Предоставляет именованную функцию s, которая вычисляет квадратный корень путем фильтрации списка от 0 до n для квадрата, большего, чем вход, а затем печатает последнее такое число. Не использует возведения в степень или плавает.
Пример использования:
источник
Сетчатка (не конкурирующая - язык новее, чем вызов), 43
Работая над этим ответом , мне пришло в голову, что аналогичный метод может быть использован для вычисления целых квадратных корней с помощью сетчатки:
Это основывается на том факте, что совершенные квадраты могут быть выражены как
1+3+5+7+...
и, как следствие, число членов в этом выражении является квадратным корнем.Попробуйте онлайн. (Добавлена первая строка, позволяющая запускать несколько тестовых случаев.)
Очевидно, что из-за десятичного преобразования в унарное это будет работать только для относительно небольших входных данных.
источник
Perl, 133 символа
Не самый короткий, но использует алгоритм «цифра за цифрой» для обработки ввода любого размера и выполняется за время O (log n). Свободно преобразует между числами, как строки и числа, как числа. Поскольку наибольший возможный продукт на сегодняшний день - это корень с квадратом одной цифры, он должен иметь возможность получить квадратный корень из примерно 120-битных или около того чисел в 64-битной системе.
Распакованный, то есть:
источник
if length%2
вместоif(length)%2
? Это сбрило бы 1 персонажа. Кроме того, это будет работать, чтобы сказать$y=$z,$d=$_ if
вместо($y,$d)=($z,$_)if
? Я думаю, что это сбрило бы еще 3 персонажа.for
цикл следующим образом:$a<($z=$_*(20*$r+$_))or$y=$z,$d=$_ for(1..9);
%2
), но остальные действительны. Я поработаю с ними.for
не нуждается в скобках; добавив, что к вашим предложениям мне всего 6 символов. Благодарность!Матлаб (56) / Октава (55)
Он работает с квадратным корнем, используя метод с фиксированной точкой. Он сходится максимум за 36 шагов (для аргумента 2 ^ 64-1) и затем проверяет, является ли он нижним из «возможных» целочисленных корней. Поскольку он всегда использует 36 итераций, он имеет время выполнения O (1) = P
Предполагается, что аргумент будет uint64.
MatLab:
Октав:
источник
Рубин - 36 символов
источник
while
цикл заканчивается точно, когда g сходится к полу (√n), который является желаемым значением. Вы видите случай, когда это не будет правдой?Python (39)
Естественный рекурсивный подход. Подсчитывает потенциальные квадратные корни, пока их квадрат не станет слишком высоким, а затем уменьшится на 1. Используйте Stackless Python, если вы беспокоитесь о превышении глубины стека.
and/or
Идиомы эквивалентно тройном оператора какEdit: я могу вместо этого получить 25 символов путем использования правила «вы можете использовать
*
,/
,+
,-
, и возведение в степень (например,**
или ,^
если это встроенный оператор в выбранном вами языке, но только экспоненцирование полномочий не менее 1). " (Правка: видимо, Денис уже нашел и использовал этот трюк.)Я использую оператор целочисленного деления
//
Python 3 для округления вниз. К сожалению, я трачу много символов на случай,n=0
чтобы не дать ошибку деления на 0. Если бы не это, я мог бы сделать 18 символовВ правилах также не говорилось, что функция должна быть названа (в зависимости от того, как вы интерпретируете «Вы можете назвать свою функцию как угодно»), но если это так, это еще два символа.
источник
C99 (58 знаков)
Это пример ответа, который я бы не посчитал хорошим, хотя он интересен мне с точки зрения гольф-кода, потому что он настолько извращен, и я просто подумал, что было бы интересно добавить в него микс:
Оригинал: 64 символа
Причина, по которой этот код ужасен, заключается в том, что он выполняется за время O (√n), а не за O (log (n)). (Где n - входное значение.)
Редактировать: 63 персонажа
Изменение
r-1
к--r
и примыкающий егоreturn
:Редактировать: 62 персонажа
Перемещение приращения цикла внутрь условной части цикла (примечание: это имеет негарантированное поведение, поскольку порядок операций относительно оператора preincrement зависит от компилятора):
Изменить: 60 символов
Добавление,
typedef
чтобы скрытьuint64_t
(кредит пользователю technosaurus за это предложение).Изменить: 58 символов
Теперь требуется, чтобы второй параметр передавался как 0 при вызове функции, например,
r(n,0)
вместо justr(n)
. Хорошо, на данный момент я не могу понять, как это сжимать дальше ... кого-нибудь?источник
uint64_t s(uint64_t n){for(uint64_t r=n;--n>r/n;);return n;}
.--n
когдаn==0
будет -1, а это беззнаковые значения, поэтому -1 будет 2⁶⁴ – 1.#define Z uint64_t
... или typedef спасет паруn/++r/r
имеет неопределенное поведение ....Гольфскрипт - 14 символов
Найти наименьшее число
i
меньше, чем входn
для которогоn < i*i
. Возвращениеi - 1
.Т.е.
[0..n-1].first(i => n < i*i) - 1
Объяснение для тех, кто также не знает Golfscript, для примера вызова с вводом
5
:источник
1
вероятно, занимает два символа.Haskell,
147138134128 байтНе самый короткий код в мире, но он работает на O (log n) и на числах произвольного размера:
Это выполняет бинарный поиск диапазона [0..n], чтобы найти наилучшее нижнее приближение к sqrt (n). Вот негольфированная версия:
Редактировать: Сохранение двух байтов путем замены предложений «иначе» на «0 <1» в качестве более короткой версии «True» и еще нескольких путем вставки g * g.
Кроме того, если вы довольны O (sqrt (n)), вы можете просто сделать
для 35 символов, но что это весело?
Редактировать 2: Я только что понял, что, поскольку пары сортируются по порядку словаря, вместо того, чтобы делать min2Cycle. Карта FST, я могу просто сделать FST. min2Cycle. В загаданном коде это означает замену f $ map fst на fst $ f, экономя еще 4 байта.
Редактировать 3: Сохранено еще шесть байтов благодаря гордому хакеллеру!
источник
JavaScript
918886: оптимизирован для скоростиJavaScript 46: не оптимизирован для скорости
Вот JSFiddle: http://jsfiddle.net/rmadhuram/1Lnjuo4k/
источник
function s(n){for(a=1;++a*a<n;);return a}
С 95
97Редактировать Typedef, предложенный @Michaelangelo
Это должно быть более или менее простой реализацией алгоритма Герона. Единственная изюминка - вычисление среднего значения во избежание переполнения целых чисел: a = (m + n) / 2 не работает для двухзначных чисел.
источник
C #
646255Так как это код-гольф (а я плохо разбираюсь в математике), а время выполнения - всего лишь совет, я сделал наивный подход, который работает в линейном времени:
( тест на dotnetfiddle )
Конечно, это ужасно медленно для больших входов.
источник
return i-1
наreturn--i
?i*i<=a
гарантируется ли целочисленная арифметика обычного типа? (Я не знаком с C #.) Если это так, и если C # допускает неявное целочисленное преобразование в логическое значение, как это делает C, то вы можете сохранить еще один символ, изменив его наa/i/i
.Decimal
более высокое максимальное значение и точность), чтобы избежать переполнения, поскольку результат умножения потенциально может пройти на шаг впередUInt64.MaxValue
. Но C # в любом случае не имеет неявных преобразований в Boolean. Я должен быть в состоянии изменить,return
хотя, спасибо. Я сделаю это, когда вернусь к компьютеру.Clojure - 51 или 55 байтов
Проверяет все числа от n до 0, давая первое где
x^2 <= n
. Время выполненияO(n - sqrt n)
Без имени:
Названный:
Пример:
источник
Befunge 93 - 48 байт или 38 символов
Попробуйте это здесь.
источник
Кобра - 62
Партия - 74
источник
Haskell,
535049 символов, O (log n)Это решение реализует метод Ньютона-Рафсона, хотя он ищет целые числа, а не числа с плавающей точкой. вики: http://en.wikipedia.org/wiki/Newton%27s_method
сложность, кажется, о O (log n), но есть ли доказательства этого? Пожалуйста, ответьте в комментариях.
источник
\g->div(n+g^2)$2*g
экономит 7 байт.J (10)
Очень, очень, очень вдохновленный ответом @Dennis :
И немного дольше, но с лучшей производительностью (я подозреваю):
floor(halve under log)
Для выполнения вводятся отступные части:
источник
APL - 12 символов, 19 байтов
пример использования:
возвращает 4
Тестовый вектор
возвращается
1 1 1 1 2 2 3 3 4 255 256 4294967296
Попробуйте онлайн
Большое спасибо : пользователь "ssdecontrol" за алгоритм
источник
0
→1
! Используя Dyalog APL , вы можете установить⎕DIV←1
(который многие используют по умолчанию) для получения правильного результата.C99 (108 символов)
Вот мое собственное решение в C99, которое адаптировано из алгоритма в статье в Википедии . Я уверен, что это может быть возможно сделать намного лучше, чем это на других языках.
Golfed:
Частично гольф
Ungolfed:
источник
a
, используйтеn
.n
так, чтобы непосредственно перед возвратом я мог сделать утверждение (не показано), что r ^ 2 <= n <(r + 1) ^ 2. Если это утверждение опущено, его необходимо сохранитьn
без изменений.const
в разглаженную версию.JavaScript
7381 (для соответствия требованиям 64-битных чисел)n=prompt();g=n/3;do{G=g,g=(n/g+g)/2}while(1E-9<Math.abs(G-g))alert(Math.floor(g))
Реализация алгоритма Герона Александрийского ...
источник
|0
влияет на 32-битные, тогдаMath.floor
как более эффективен на 64-битных ... Я обновил свой код, мне пришлось взять дополнительные 8 символов, чтобы сделать это ...Powershell (52), ограниченный Int32 (от -2 147 483 648 до 2 147 483 647)
Я сейчас кричу о Powershell, пытаясь заставить работать последний тестовый пример, но независимо от того, что я делаю, Powershell использует переменную конвейера $ _ в качестве Int32, и сейчас я не могу найти способ обойти это.
Так что я пока ограничу свой ответ. Если я найду лучший способ обработки uint64s, я буду редактировать. (Кстати, последний тестовый пример слишком велик для обычного типа Powershell Int64!)
Вот несколько тестовых случаев (с дополнительным выводом, который я использовал для отслеживания времени)
Я не знаю своих O (), но это кажется довольно драматичным скачком.
источник
Предостережение: с 2011 года R не имел встроенной поддержки 64-битных целых чисел, как я предполагал. Эти ответы могут быть недействительными по этой технической причине, но опять же R сильно изменился за последние 3 года.
R 85
Используя метод Ньютона:
который сходится квадратично. +2 символа для назначения функции переменной для бенчмаркинга:
Р, 37
Грубая сила:
И тот же чек:
Р, 30
Дешево / блестящий экспоненцирование трюк :
что также происходит очень быстро (хотя и не так быстро, как встроенный):
источник
С, 38
Перевод моего четвертого представления. Медленно, но верно. O (√n). Протестировано на OS X (64 бит).
источник
постоянный ток, 50 байтов
Разместил и объяснил:
источник
C
139137136 байтМоя первая попытка в коде гольф. Похоже, что это самый короткий C, который соответствует «эффективному» требованию, поскольку он выполняется во
O(log n)
времени, используя только сложение и сдвиги битов. Хотя я уверен, что это может быть еще короче ...Он должен прекрасно работать и для больших целочисленных значений, пока
a=32
деталь изменяется наa=NUMBITS/2
.источник
(t++)
а не простоt++
в заданииr
?a--+1
как способ избежать написанияa-- != UINT64_C(-1)
. Ты где-нибудь научился этому трюку или сам придумал?C - 50 (61 без глобального)
Он использует глобальные переменные в качестве параметра и возвращаемого значения для экономии места.
Нет глобальной версии:
источник
C ++ 125
источник
x+=(d<0)-0.5;
... сохранить еще 5 символов?main
это функция, но она не вызывается изнутри программы, такой какf(y)
было бы.)while((d=x*x-y)>0.5)
вместоwhile((d=(x*x-y))>0.5)
. Сохраняет еще 2 персонажа. :)