Любой, кто в меру относится к низкоуровневой оптимизации кода, знает об опасностях ветвления, будь он реализован в виде операторов if, циклов или операторов выбора, поэтому возможность ошибочного прогнозирования ветвления - ужасная трата времени.
Простые проблемы могут быть решены намного лучше с помощью простой арифметики, так что давайте сделаем это.
Для следующих задач все переменные представляют собой 32-разрядные целые числа без знака, и единственным допустимым кодом являются операторы простого набора, включающие только следующие операторы:
+ addition
- subtraction
* multiplication
/ integer division, rounds down, division by 0 not allowed
% modulo
& binary and
| binary or
^ binary exclusive or
>> bitshift right
<< bitshift left
Logic operators, return 1 if the expression is true and 0 if it is false.
== equal
!= not equal
< less than
<= less than or equal
> greater than
>= greater than or equal
Set operator
=
Каждая строка должна состоять из идентификатора переменной, за которым следует оператор набора, за которым следует выражение.
Выражение может не содержать дополнительных операторов множества, но может содержать идентификаторы переменных, буквенные числа и круглые скобки.
Игра в гольф учитывает только количество операторов.
Пример:
myvar = ( ( ( foo + 5 ) * bar ) % 7 ) == 3
Имеет оценку 5 операторов.
Решение может включать столько переменных, сколько автор сочтет нужным.
Переменные, которые не были установлены, имеют значение 0
.
Переполнение и сгущенного допускаются, все отрицательные числа Underflow, так 3 - 5
это 4294967294
, даже как часть большего заявления.
Задача 1: Макс
Два значения A
и B
существуют в области видимости, чтобы RESULT
переменная содержала наибольшее из этих значений при завершении программы.
Задача 2: Медиана
Три значения, A
, B
и C
, существует в объеме, сделать RESULT
переменный содержат медиану тех значений , когда программа завершает свою работу .
Задача 3: Квадратный корень
Одно значение, A
существующее в области действия, заставляет RESULT
переменную содержать квадратный корень A
, округленный вниз, когда программа завершается.
Это нормально, чтобы опубликовать ответ только на один или два вопроса, для некоторых из вас просто будет трудно найти правильное решение.
источник
-
но~
может быть приятно (даже если я не знаю, для чего).0xFFFF_FFFF_FFFF_FFFF ^ x
и0 - x
. Как я мог забыть?!
является также довольно тривиально:x == 0
.Boole[a-b]
?Ответы:
Задача 3, 23 операции
Использование метода Ньютона, как и других решений, с более тактично выбранным начальным числом. Первый бит
A >> 16
удерживает верхнюю часть диапазона счастливым, второй - счастливуюA / ((A >> 13) + 511)
середину диапазона, а последний15
- нижнюю, а также предотвращает деление на ноль ошибок (15 - наибольшее возможное значение, которое позволяет0
правильно сходиться - делится пополам трижды минус коррекция равна нулю). Для входных значений225, 275625, 82137969, 2908768489
(и близлежащих значений) начальное начальное число является точным. Все граничные случаи (идеальные квадраты, идеальные квадраты + 1 и идеальные квадраты - 1) в диапазоне0 .. 2**32-1
были проверены и являются правильными.Несколько комментариев о правилах:
допускается переполнение и недополнение, все отрицательные числа недопустимы, поэтому 3 - 5 равно 4294967294, даже как часть более крупного оператора .
Этот последний бит оказывается чем-то вроде убийцы инноваций. Сначала я попытался найти решение, используя обобщенную форму метода Галлея , но понял, что оно недопустимо с учетом вышеуказанного ограничения. Итерация (применительно к квадратным корням) такова:
Эта итерация обладает хорошими качествами, которых нет у Ньютона. Он сходится кубически (а не квадратично), он сходится сверху или снизу (а не только сверху) и не так чувствителен к плохо выбранному семени (если итерация Ньютона обеспечит семя, которое является слишком низким, оно будет сильно перебить точку схождения, а затем нужно вернуться обратно вниз).
У метода Ньютона также есть проблема (по крайней мере, когда речь идет о целых числах), что он довольно часто достигает x, такого что A / x - x = 2 - в этом случае он будет сходиться к значению, которое на единицу больше, чем правильный целочисленный корень, который должен быть исправлен; Метод Галлея не нуждается в такой коррекции. Но, к сожалению, значение
3*A + x*x
часто будет больше, чем допустимое 32-разрядное целочисленное пространство.Существует ряд других обобщенных n- х корневых алгоритмов, но все они имеют одну и ту же характеристику:
и т. д. Большинство из них показывают кубическую или квадратичную сходимость. Последние четыре являются частью серии итераций, сходящихся к четвертой сходимости. Но на практике метод Ньютона даст вам то, что вам нужно, с меньшим количеством операций, если вам не нужно вычислять много сотен цифр.
источник
log(3)/log(2) ~= 1.585
итераций Ньютона.A = 0
- так что это на самом деле короче. Приблизительно 4294967295 , это был недосмотр: при 65536² ≡ 0 итерация исправления не может быть исправлена. Я посмотрю, смогу ли я найти альтернативу.65 (61) операций (5 + 13 + 47 (43))
Задача 1 - Макс (A, B)
Это очевидное решение. Вам нужно присваивание, вам нужно сравнение, вам нужно умножить сравнение на что-то, мультипликатор не может быть одной из переменных, а продукт не может быть результатом.
Задача 2 - Середина (A, B, C)
Это улучшение по сравнению с моим предыдущим 15-операционным решением, которое обусловило все три переменные - это спасло два вычитания, но оно ввело еще один тест центральности. Сам тест прост: элемент находится посередине, если только один из двух находится выше.
Задача 3 - sqrt (A)
Одиннадцать раундов приближения Ньютона. Волшебная постоянная 1024 уже побита WolframW (а 512 вызывает деление на ноль при a = 0 до того, как a = 2 ** 32 сходится), но если мы можем определить 0/0 как ноль, десять итераций будут работать с начальным значением из 512. Я признаю, что мое утверждение о десяти итерациях не совсем чисто, но я все еще претендую на них в скобках.
Я должен исследовать, если девять возможно, как бы то ни было.Решение WolframH состоит из девяти итераций.источник
(1024 + A/1024)/2 == (512 + A/2048)
(что, какX0 = 1024
, а затем запуск Ньютона).MOV RESULT, A; CMP A,B; CMOVA RESULT, B
;-)1: 5 операторов
Операторы 2: 13
3: 27 операторов
источник
Задача 3, 39 Операции
РЕДАКТИРОВАТЬ: изменена последняя строка; смотрите комментарии.
Это реализация метода Newthon. Проверено со всеми положительными квадратами, а также с положительными квадратами минус один, а также миллион случайных чисел в диапазоне от 0 до 2 ^ 32-1. На первый взгляд забавное начальное значение является коротким, для
(1022 + A/1022) / 2
которого требуется наименьшее количество итераций (я думаю), а также делает правильное значениеRESULT
forA=0
(что было бы не так1024
вместо1022
).источник