Этот вопрос вдохновлен этим ответом . По совпадению я использовал Эфиопское Умножение, когда я был ребенком, но никогда не знал название метода до недавнего времени.
Эфиопское умножение - это метод умножения целых чисел с использованием только сложения, удвоения и деления пополам.
Метод:
- Возьмите два числа, которые нужно умножить, и запишите их в верхней части двух столбцов.
- В левом столбце несколько раз делите пополам последнее число, отбрасывая все остатки, и записывайте результат ниже последнего в том же столбце, пока не напишите значение 1.
- В правом столбце несколько раз удвойте последнее число и напишите результат ниже. остановка, когда вы добавляете результат в той же строке, где в левом столбце отображается 1.
- Изучите созданную таблицу и откажитесь от любой строки, в которой значение в левом столбце является четным. Суммируйте значения в правом столбце, которые остались, чтобы получить результат умножения исходных двух чисел вместе.
Например: 17 х 34
17 34
Половина первого столбца:
17 34
8
4
2
1
Удвоение второго столбца:
17 34
8 68
4 136
2 272
1 544
В зачеркнутых строках, чья первая ячейка четная, мы сделаем это, заключив эти числа справа в квадратные скобки:
17 34
8 [68]
4 [136]
2 [272]
1 544
Суммируйте оставшиеся числа в правом столбце:
17 34
8 [68]
4 [136]
2 [272]
1 544
=====
578
Таким образом, 17, умноженное на 34, по эфиопскому методу равно 578.
Задание:
Гольф-код, который принимает два числа от 1 до 1000 и выполняет ту же схему и алгоритм, отображая продукт ниже.
Метод ввода: однако вы выбираете ...
Пример ввода:
19 427
Результирующий вывод:
19 427
9 854
4 [1708]
2 [3416]
1 6832
======
8113
Пожалуйста, обратите внимание на выравнивание цифр. Это наиболее важно в макете. Также обратите внимание, что двойная линия, обозначенная знаками равенства, должна быть на два символа длиннее общего ответа и должна быть выровнена по центру.
тестирование
Как вы будете это тестировать? Предоставляя прогон вашей программы, используя два числа. Эти числа могут быть извлечены из вашего идентификационного номера пользователя (это можно получить, наведя курсор на свой аватар в верхнем окне). Возьмите ваш номер и возьмите последние три цифры, это будет номер B, возьмите все остальное, что будет впереди, это будет номер A. Затем проверьте на A раз B.
Пример тестирования:
Мой идентификационный номер пользователя 8555, поэтому мои номера 8 и 555. Таким образом, мой вывод должен выглядеть следующим образом:
8 [555]
4 [1110]
2 [2220]
1 4440
======
4440
Ограничения:
Не допускается использование собственных операторов умножения, кроме как при использовании «удвоения», как указано в алгоритме. Другими словами, если вы используете оператор типа *, он может использоваться только для умножения только на 2.
Записи, которые не придерживаются этого, не будут рассматриваться, и пользователя будут сопровождать из помещения с картонной коробкой, полной их вещей. Каждая запись будет иметь код плюс тест, основанный на вашем идентификационном номере.
Это код гольф. Наименьшее количество байтов получит приз, славу и восхищение своих пэров ... (И, может быть, Ламборджини ... Я сказал "возможно"!)
*
илиx
), но невозможно определить, используется ли умножение или нет. За исключением этой части, задача интересная.Ответы:
Древесный уголь , 91 байт
Попробуйте онлайн!Ссылка на подробную версию кода. Объяснение:
Устанавливает
t
в пустой список иs
в0
. (u
уже по умолчанию пустой список.)Вводит два числа.
Повторяется пока
q
ненулевое.Заверните
q
в отступ и добавьте его в списокt
.Оберните
h
в дополнение или в[]
зависимости от того,q
является ли нечетным, и добавьте его в списокu
.Добавьте
h
кs
еслиq
нечетно.Целочисленное деление
q
на 2.Добавьте
h
к себе.Добавьте в список подходящую строку
=
знаковu
.Добавьте дополненную сумму
s
в списокu
.Повернуть список
t
на 180 ° и распечатайте его вверх ногами, выровняв его по правому краю.Переместите курсор так, чтобы при
u
выравнивании по правому краю его верхний левый угол совпал с только что достигнутым верхним правым углом, и напечатайте выравнивание поu
правому краю.источник
Python 2 ,
203202187133 байтаПопробуйте онлайн!
Если я могу использовать
*
для умножения строк ('='*R
) и в качестве «селектора» (b*(a%2)
вместо[0,b][a%2]
), я получаю:118 байт
Попробуйте онлайн!
Объяснение:
источник
Java (OpenJDK 8) ,
353316267214210 байтПопробуйте онлайн!
источник
(a,b)->{int g=0;for(;a>0;g+=a%2*b,a/=2,b*=2)System.out.printf("%1$8d%2$10s\n",a,a%2<1?"["+b+"]":" "+b+" ");System.out.printf("%1$19s%2$18s","".valueOf(new char[(int)Math.log10(g)+3]).replace("\0","=")+"\n",g+" ");}
a%2*b
приятно, спасибоMathematica, 264 байта
вход
выход
источник
s=Quotient[s,2]
:)Perl 5 , 157 байт
155 байт кода + 2 флага командной строки (
-nl
)Попробуйте онлайн!
источник
JavaScript 2017, 221 байт
В основном проблема форматирования вывода
Меньше гольфа
Тестовое задание
источник
C, C ++,
319313301299 байт-8 байт благодаря Захари
Большое спасибо
printf
магии, которую я только что узнал за 60 минут между изменениямиC ++ оптимизации, заменить заголовок
stdio.h
наcstdio
и сstring.h
помощьюcstring
, сохраняет 2 байтаКомпиляция с MSVC требует добавить
#pragma warning(disable:4996)
для использованияsprintf
Тестирование с моим PPCG ID:
72 х 535 =>
Он соблюдает правила, цифры выровнены, а знаки равенства всегда будут на 2 знака больше, чем окончательное число. Пример с 17 x 34 =>
источник
#define O printf("%*d %c%*d%c\n",5,a,a%2?' ':'[',9,b,a%2?' ':']');
иvoid m(int a,int b){int r=0,i=0;O while(a>1){r+=a%2*b;a/=2;b*=2;O}r+=b;char t[20],p[20];memset(t,0,20);memset(p,0,20);sprintf(t,"%d",r);for(;i<strlen(t)+2;++i)p[i]='=';printf("%*c%*s\n%*d",5,' ',12,p,16,r);}
%
и*
одинаковы, поэтомуr+=a%2*b
должно работать.[Bash],
144142140131128 байтЛучшее уважение к отображению, обратите внимание, что в конце есть пробел
Первый ответ
источник
Haskell , 305 байт
Попробуйте онлайн!
!
Оператор создает два списка,?
вычисляет произведение.%
и#
используются для макета ASCII.источник
C
205201190183156150143 байтаЭто скомпилирует с предупреждениями как C89, и я не верю, что это действительный C99, но в итоге он оказывается меньше, чем версия HatsuPointerKun, так как он сохраняет байты, пропуская
#include
, не используя динамические длины для printf, поскольку они не нужны, & с помощьюlog10()
для вычисления количества=
необходимых:Как мой номер
64586
, я использовал эту тестовую программу для расчета64 * 586
:И это выводит:
редактировать
сохранено 4 байта по правилу "implicit int"
редактировать 2
сохранил 11 байтов, изменив
do...while()
цикл и переместив printf в цикл из макроса. Также должен работать правильно, еслиa=1
.редактировать 3
сохранил 7 байтов и сделал код работать правильно.
редактировать 4
Сохранено 26 байт с некоторыми хитростями при печати.
редактировать 5
сэкономил 6 байтов, свернув дополнительные отступы в 1 число.
редактировать 6
сохранено 7 байт с помощью трюка printf с тернарным оператором и без объявления неиспользуемой переменной
источник
Excel VBA, 183 байта
Функция анонимного непосредственного окна VBE, которая принимает данные из диапазона
[A1:B1]
и выводит их на консоль.Ungolfed
Выход
источник