Умножьте два числа


21

Входные данные: два десятичных целых числа. Они могут быть переданы коду при стандартном вводе в качестве аргументов программы или функции или в виде списка.

Вывод: их произведение в виде десятичного целого числа. Например, ввод 5 16приведет к выводу 80.

Ограничения: пожалуйста, никаких стандартных лазеек. Это , ответ в самом низком количестве выигранных байтов.

Примечания: Макет, украденный из моего более раннего испытания, Добавьте два числа .

Тестовые случаи:

1 2   -> 2
4 5   -> 20
7 9   -> 63
-2 8  -> -16
8 -9  -> -72
-8 -9 -> 72
0 8   -> 0
0 -8  -> 0
8 0   -> 0
-8 0  -> 0
0 0   -> 0

Или как CSV:

a,b,c
1,2,2
4,5,20
7,9,63
-2,8,-16
8,-9,-72
-8,-9,72
0,8,0
0,-8,0
8,0,0
-8,0,0
0,0,0

Leaderboard


4
@FlipTack Предполагается, что сложение и умножение так же просто на любом языке, и я не знаю, правда ли это на самом деле.
фатализировать

16
Я не думаю, что было бы справедливо разрешить задачу «добавить два числа», но закрыть ее. Несмотря на то, что это очень тривиально в большинстве языков программирования, это все еще актуальная задача. Если это слишком широко, то задача «добавить два числа» также должна быть слишком широкой.
Мего

32
Любой может свободно оценивать тривиальные вызовы, если они им не нравятся, но это вполне допустимый и тематический вызов, и он далеко не «слишком широк» (во всяком случае, вы можете назвать тривиальный вызов слишком узким). Я снова открываю это. Тем не менее, если кто-то чувствует, что тривиальные проблемы оскорбляют их интеллект, я призываю их искать языки, которые делают задачу менее тривиальной.
Мартин Эндер

16
Уо следующий: вычтите два числа!
Steenbergh

7
@wat Не оставляя без дна ствол, не так ли?
Гарет

Ответы:


39

Brachylog V1, 05AB1E, J, K, Underload, MATL, Forth, PigeonScript, Stacked, Implicit, Jolf, Clojure, Braingolf, 8-й, Common Lisp, Julia, Pyt, Appleseed, Stax, Reality, постоянный ток 1 байт

*

Вы можете редактировать этот ответ, чтобы добавить другие языки, для которых *правильный ответ.


Полигот, 05AB1E и 5 других языков.
Волшебная урна осьминога

13
Я отредактировал Underload в этом. Это , возможно, самый интересный из них, потому что Underload вовсе не есть метод 1 байт делать вычитание, деление или сложение.


Это не действует в Pyth. Pyth не принимает неявные данные, как это.
Исаак

Добавлена ​​Джулия, например*(5,16)
gggg

32

C (GCC), 13 байтов

Не работает на всех реализациях, но это нормально.

f(a,b){a*=b;}

Попробуйте это на TIO!


6
Подождите, это должно как-то вернуться a? Я не понимаю ...
Эрик Outgolfer

2
Объяснение того, как это работает, было бы полезно. ( aявляется локальной переменной стека для f()- почему возвращается ее значение?). +1, кстати - очень умное злоупотребление ABI.
Цифровая травма

6
@EriktheOutgolfer returnКлючевое слово просто помещает повторение аргумента в регистр EAX. В этом случае сгенерированный исполняемый файл выполняет вычисления a*bв этом регистре, поэтому returnничего не делает.
Деннис

7
Эй, это был мой трюк! codegolf.stackexchange.com/a/106067/18535 :-)
GB

12
Так рад видеть C на вершине на этот раз! На самом деле вы можете сбрить около 9 байтов, просто заменив f(a,b){a*=b;}часть на, 1##&а затем просто изменив язык на Mathematica.
Альберт Реншоу

21

Битник , 888 байт

k I
j k ZZZZX z
xw k C vp yQ KD xw z j k ZZZZX z
j k ZZZD z xw bZ ZX
k XX z qs xw vp xw xw vp xw vp vp vp k I Xj ZZD hd
xw yQ K k ZZZZX xo exx
qs yQ XA xw xw xw xw z xw bZ K
xw xw k I
j k ZZZZX z
xw k C vp yQ XA hd k I z j k ZZZZX z
j xw k A vp bZ ZX
k ZZZZX z qs xw vp xw xw vp xw vp vp vp k I Xj ZZD hd
xw yQ K k ZZZZX xo exx
qs yQ F k ZZZZK xo
vp
xw xw z qs xw bZ X xw k I z xw Xj K
qs xw bZ KA vp qs xw Xj C hd
qs z xw xw xw xw z qs
xw xw xw xw z qs k I qs k I z xw Xj ZC
qs bZ ZZZX qs xw yQ C hd xw
k I vp qs k I qs
xw Xj ZZC hd hd z Kz ZZD
k I z xw xw xw xw z qs k I qs k I Xj ZZZZF
z
xw xw z qs xw bZ X xw k I z xw Xj K
qs xw bZ KA vp qs xw Xj C hd
z qs xw
xw xw z qs xw bZ X xw k I z xw Xj K
qs xw bZ KA vp qs xw Xj C hd
z vp
xw xw z qs
xw xw z qs
k I qs
xw bZ ZZX k I z qs k I vp
xw k ZA z yQ ZA hd qs k I vp qs k I Xj ZZKD
qs xw Xj ZZK
hd qs xw Xj ZZZZ hd
k ZZZZKD vp xo xw Xj K

Попробуйте онлайн!

Я использую интерпретатор C, потому что интерпретатор Python в TIO раздражающе выполняет адрес, если не выполнено условие перехода назад. Простой обходной путь для интерпретатора Python - добавить несколько nops, чтобы сделать адрес nop. Я считаю, что ни один не является правильным

                                   C       Python  My interpretation
IP after skiping N words           IP+N+1  IP+N+2  IP+N+2
IP after skiping back N words      IP-N    IP-N+1  IP-N+2
IP after not skiping N words       IP+2    IP+2    IP+2
IP after not skiping back N words  IP+2    IP+1    IP+2

Входные данные должны быть двумя целыми числами, разделенными пробелом, без завершающих строк.

Этот ответ теоретически работает для всех целых чисел, если каждая ячейка может хранить произвольно большое значение, не ограниченное 0 - 255. Но оно переполняется, если | A | + | B | > 22. И он работает очень медленно, если | A | + | B | > 6. Таким образом, существует не так много случаев, которые вы можете на самом деле протестировать, и решение if-else для этих случаев может быть еще короче.

Идея состоит в том, чтобы вычислить треугольные числа T (N) = N (N + 1) / 2, уменьшив значение до 0 и суммируя все промежуточные значения. Тогда мы можем получить ответ A * B = T (A + B) - T (A) - T (B).

Но сложно вычислить все 3 значения. Он делает это, сначала вычисляя T (A + B) - A, оставляя копию A в стеке для последующего добавления обратно и используя вход B. Затем рекурсивно находят наибольшее треугольное число, меньшее, чем то, которое является T ( A + B-1) за исключением нулевых особых случаев. Мы можем получить обратно B = T (A + B) - A - T (A + B-1) и вычислить T (B) оттуда.

Число N является треугольным числом, если оно равно наибольшему треугольному числу, меньшему, чем N, плюс число неотрицательных треугольных чисел, меньших, чем N. Это выполняется в O (2 ^ (T (A + B) -A)) и самая медленная часть в программе.

k I                                         Push 1
j k ZZZZKAAA z                              Input and decrement by 48.
xw k AAA vp yQ (input_a_loop)               If the character was '-':
xw z j k ZZZZKAAA z                           Replace with 0 and input another.
input_a_loop:
j k ZZZAA z xw bZ (input_a_end)             Input and break if it is a space.
k ZKA z qs xw vp xw xw vp xw vp vp vp       Otherwise multiply the previous
                                              value by 10 and add.
k I Xj (input_a_loop)                       Continue the loop.
input_a_end: hd                             Discard the space.
xw yQ (check_sign) k ZZZZKAAA xo exx        If A=0, print 0 and exit.
                                            Stack: ?, A_is_positive, A
check_sign:
qs yQ (check_sign_else)                     If A is positive... or not,
xw xw xw xw z xw bZ (check_sign_end)          in either cases, push 2 copies
check_sign_else: xw xw k I                    of A and the negated flag back
check_sign_end:                               as a constant.
                                            Stack: A, A, A, A_is_negative
j k ZZZZKAAA z                              Similar for B.
xw k AAA vp yQ (input_b_loop)               If the character was '-':
hd k I z j k ZZZZKAAA z                       Decrement the flag and input another.
input_b_loop:
j xw k A vp bZ (input_b_end)                EOF is checked instead of a space.
k ZZZZKAAA z qs xw vp xw xw vp xw vp vp vp
k I Xj (input_b_loop)
input_b_end: hd
xw yQ (output_sign) k ZZZZKAAA xo exx       If B=0, print 0 and exit.
                                            Stack: A, A, A, A*B_is_negative, B
output_sign:
qs yQ (output_sign_end) k ZZZZK xo          If negative, output '-'.
output_sign_end:

vp                                          Add.        Stack: A, A, A+B
xw xw z qs                                  Insert a 0. Stack: A, A, 0, A+B.
xw bZ { xw k I z xw Xj }                    Copy and decrement while nonzero.
                                            Stack: A, A, 0, A+B, A+B-1, ..., 0
qs xw bZ { vp qs xw Xj } hd                 Add while the second value in the
                                              stack is nonzero.
                                            Stack: A, A, T(A+B)
qs z xw xw xw xw z qs                       Stack: A, C0=T(A+B)-A, C0, F0=0, C0

expand_loop:
xw xw xw xw z qs k I qs                     Stack: A, C0, C0, F0=0,
                                              ..., [P=C, P, S=0, F=1], C
dec_expand: k I z xw Xj (expand_loop)       Decrement and continue if nonzero.
                                            Stack: [P=1, P, S, F], C=0
                                            The last number 0 is assumed to
                                              be a triangular number.
test: qs bZ (extract_end)                   If F=0, break.
qs xw yQ (test_not_first) hd xw             If S=0, it's the first triangular
                                              number below previous C. Set S=C.
test_not_first: k I vp qs k I qs            S+=1 and restore F=1.
xw Xj (dec_expand)                          If C!=0, recursively expand from C-1.
hd hd z Kz (test)                           If S=P, P is a triangular number,
                                              return to the previous level.
k I z xw xw xw xw z qs k I qs               Otherwise, decrement P and try again.
k I Xj (dec_expand)
extract_end:                                Stack: A, C0, C0, T(A+B-1)

z                                           Subtract and get B.
xw xw z qs xw bZ { xw k I z xw Xj }         Computes T(B).
qs xw bZ { vp qs xw Xj } hd
                                            Stack: A, C0, T(B)
z qs xw                                     Stack: C0-T(B), A, A

xw xw z qs xw bZ { xw k I z xw Xj }         Computes T(A).
qs xw bZ { vp qs xw Xj } hd
z vp                                        Get A*B=(C0-T(B))+(A-T(A))
xw xw z qs                                  Stack: 0, X=A*B

divide: xw xw z qs                          Stack: 0, ..., Y=0, X
subtract: k I qs                            Stack: 0, ..., Y, Z=1, X
xw bZ {                                     While X!=0:
k I z qs k I vp                               X-=1, Z+=1.
xw k ZA z yQ (not_ten)                        But if Z=11:
hd qs k I vp qs k I Xj (subtract)               Y+=1, reset Z and restart the loop.
not_ten: qs xw Xj }
hd qs xw Xj (divide)                        Put Z under Y and make Y the new X,
                                              continue the loop if X!=0.
hd                                          Discard X.

print_loop:
k ZZZZKAA vp xo xw Xj (print_loop)          Add each cell by 47 and print.

Ого. Просто ... воу. Я положил награду, вы получите ее через 7 дней.
NieDzejkob

19

Mathematica, 4 байта

1##&

Пример использования: 1##&[7,9]возврат 63. Действительно, эта же функция умножает любое количество аргументов любого типа вместе.

Как знают программисты Mathematica, это работает, потому что ##относится ко всей последовательности аргументов функции, а конкатенация в Mathematica (часто) представляет умножение; так 1##относится к (1 раз) произведение всех аргументов функции. Это &просто сокращение от Functionкоманды, которая определяет чистую (безымянную) функцию.

Внутри другого кода общий символ *действует как умножение. Так же как и пробел, который 7 9интерпретируется как 7*9(действительно, текущая версия Mathematica для REPL фактически отображает такие пробелы как знаки умножения!). Еще лучше, однако, если Mathematica может определить, где начинается один токен, а другой заканчивается, тогда для оператора умножения вообще не требуется никаких байтов: 5yавтоматически интерпретируется как 5*y, и 3.14Log[9]как 3.14*Log[9].


Что делает ##&недействительным?
Линн

##&возвращает свой список аргументов в виде объекта 'Sequence' - подходит для подключения к другим функциям, которые принимают несколько аргументов. В этом контексте ##&ничего не делает со своим списком аргументов; мы хотим, чтобы этот список был умножен вместе.
Грег Мартин

19

Retina , 38 37 31 байт

Абсолютно новый подход, старый ниже.

M!`-
*\)`-¶-

.* 
$*_
_
$'$*_
_

Попробуйте онлайн!

объяснение

Сначала мы имеем дело со знаком:

M!`-

сопоставляет все -в строке и возвращает их через новую строку

*\)`-¶-

(со следующей пустой строкой)
*\)означает, что результат этого и предыдущих этапов должен быть напечатан без новой строки, а затем строка возвращается к тому, что было раньше (входная строка). Оставшаяся часть удаляет два, -разделенных новой строкой.

Затем мы конвертируем первое число в одинарное:

.* 
$*_

(в конце первой строки есть пробел). В _этом случае мы используем нашу унарную цифру, потому что стандартная цифра 1может присутствовать во втором числе, и это будет конфликтовать позже.

Теперь перейдем к фактическому умножению:

_
$'$*_

Каждый _заменяется унарным представлением всего, что следует за ним (все еще используя _в качестве унарной цифры). Поскольку преобразование в унарное число игнорирует нецифровые символы, это будет повторять унарное представление второго числа для раз «первого числа». Второе число останется в десятичном представлении в конце строки.

В конце, с одним _мы возвращаем число _в строке, которое будет результатом умножения.


Предыдущий ответ: (предупреждение: выводит пустую строку, когда она должна выводиться 0)

Retina ,  45  42 41 байт

Давай сыграем в игру! Умножьте относительные числа на язык, в котором нет арифметических операторов и ограничена поддержка только натуральных чисел ... Звучит смешно :)

O^`^|-
--

\d+
$*
1(?=1* (1*))?
$1
1+
$.&

объяснение

Первые три строки имеют дело со знаком:

O^`^|-

Это сортирует Oи затем переворачивает ^все строки, соответствующие регулярному выражению ^|-. На практике это соответствует пустой строке в начале и возможному знаку минус перед вторым числом, и переупорядочивает их, помещая пустую строку вместо минуса. После этого все -находятся в начале строки, и пару из них можно легко удалить с помощью следующих двух строк.

После этого мы используем встроенную функцию для преобразования чисел в унарное представление, а затем происходит фактическое умножение:

1(?=1* (1*))?
$1

Мы подбираем любой 1и заменяем каждый из них 1после следующего пробела. Каждая цифра первого числа будет заменена полным вторым номером, а каждая цифра второго номера будет заменена пустой строкой.

Последняя часть снова является встроенной для преобразования обратно из унарного в десятичное.

Попробуйте онлайн!


2
Хотелось бы, чтобы я подавал заявку каждый раз, когда вы играете в гольф, отличная работа!
Kritixi Lithos

Вау, этот новый подход удивителен. Я думаю, что вы выиграли. :) (И это еще больше убеждает меня в том, что символ по умолчанию для $*должен быть _.)
Мартин Эндер

Кстати, вот решение только для ASCII с тем же количеством байтов, если вы предпочитаете это: tio.run/nexus/retina#U9VwT/…
Martin Ender

1
Забавный факт: по- видимому, я разобрался в уловке смешивания одного унарного и одного десятичного оператора в какой-то момент.
Мартин Эндер

1
Я попытался обновить это до Retina 1.0, и благодаря новым ограничениям и новому оператору повторения, теперь ему нужно всего 23 байта: tio.run/##K0otycxLNPyvpxqj4Z7wX8vOR9dQxyBBl0tPW4dLiyueS0UdSP7/… ... вы можете даже умножить однозначное число на положительное число этап сейчас ( .+,(.+)до $.($1**), но это на самом деле больше байтов здесь.
Мартин Эндер

18

Царапина , 1 байт

введите описание изображения здесь

Использование: Поместите числа в обе стороны *знака

Примечание. Поскольку Scratch - это визуальный язык, я не мог понять, сколько байт он потребляет, пока @ mbomb007 не обратил внимание на метод подсчета байтов для скретча.



@ mbomb007 Спасибо за ваш комментарий!
rahnema1

15

Brain-Flak , 56 байт

([({}<([({})<>])<>>)<>]){({}[()]<(({})<({}{})>)>)<>}{}{}

Это должно быть выполнено как полная программа, так как она не чистая, а входные данные должны быть единственными элементами в любом стеке.

Попробуйте онлайн!


Пояснение: (вызовите входы x и y)

Часть 1:

([({}<([({})<>])<>>)<>])

([                    ]) # Push negative x on top of:
      ([      ])         # negative y. After...
  ({}<            >)     # pushing x and...
        ({})             # y...
            <>  <>  <>   # on the other stack (and come back)

На данный момент у нас есть [x, y] в одном стеке и [-x, -y] в другом.

Часть 2:

{({}[()]<(({})<({}{})>)>)<>}{}{}
{                          }     # Loop until x (or -x) is 0
 ({}[()]<              >)        # Decrement x
         (({})<      >)          # Hold onto y
               ({}{})            # Add y and the number under it (initially 0)
                         <>      # Switch stacks
                            {}{} # Pop x and y leaving the sum

1
Вот Это Да! Определенно самый впечатляющий ответ на данный момент
DJMcMayhem

@DJMcMayhem И (немного измененный) он превосходит тот, что в вики, на 18 байт
Райли

Есть ли у вас доступ на запись к вики о мозге? Я хотел бы загрузить более короткую версию.
DJMcMayhem

@DJMcMayhem У меня нет доступа. Я разместил более короткий в чате Brain-Flak, если вы хотите посмотреть и загрузить его.
Райли

Я знаю, это было какое-то время, но у вас есть соревнование ;)
Wheat Wizard

11

JavaScript (ES6), 9 байт

ES6 имеет специальную функцию для 32-разрядных целых чисел, которая быстрее, чем более общий *оператор.

Math.imul

Кстати, это так же долго, как:

a=>b=>a*b

Отлично, теперь я знаю Math.imul, спасибо!
Чау Гианг

9

Brain-Flak , 56 54 52 байта

2 байта сохранены благодаря ошибке, пойманной Нитродоном

({}(<()>)<>)({<([{}({}())])><>([{}]([{}]))<>}<{}{}>)

Попробуйте онлайн!

Стек чистая версия, 62 60 байт

({}(<()>)(<>))({<([{}({}())])><>([{}]([{}]))<>}<{}{}<>{}{}>)

Попробуйте онлайн!

объяснение

Это объяснение является скорее объяснением задействованного алгоритма и не учитывает фактический код. Предполагается, что вы знаете, как умело читать Brain-Flak. Если вам нужна помощь в понимании кода или алгоритма, я буду рад отредактировать или ответить, если вы оставите комментарий.

Это немного странно и использует какую-то странную математику, которая едва работает. Первым делом я сделал цикл, который всегда заканчивался бы за O (n) шагов. Обычный способ сделать это - положить n и -n в разные стеки и добавлять по одному в каждый, пока один не достигнет нуля, однако я сделал это немного страннее. В моем методе я помещаю счетчик под входом, и на каждом шаге я увеличиваю счетчик, добавляя его к n и меняя знак n .

Давайте пройдемся по примеру. Скажи п = 7

7  -8   6  -9   5 -10   4 -11   3 -12   2 -13   1 -14   0
0   1   2   3   4   5   6   7   8   9  10  11  12  13  14

Я не буду доказывать это здесь, но это всегда завершится для любого ввода и сделает это за 2n шагов. Фактически, он завершится за 2n шагов, если n положительно, и 2n-1 шагов, если n отрицательно. Вы можете проверить это здесь .

Теперь у нас есть около 2n шагов в нашем цикле, как мы умножаем на n ? Ну, здесь есть немного математической магии. Вот что мы делаем: мы создаем аккумулятор, на каждом шаге процесса мы добавляем второй вход ( m ) к аккумулятору и переворачиваем знак их обоих, затем мы помещаем сумму по всем возникающим циклам, это продукт.

С какой стати это так?

Хорошо, давайте рассмотрим пример, и, надеюсь, это станет ясно. В этом примере мы умножаем 5 на 3 , я покажу только важные значения

total       -> 0  -5   5 -10  10 -15  15
accumulator -> 0  -5  10 -15  20 -25  30
m           -> 5  -5   5  -5   5  -5   5

Надеюсь, механизм здесь очевиден. Мы перебираем все кратные m в порядке их абсолютных значений. Вы обратите внимание на то , что 2n - й член всегда т * п и член , прежде чем всегда -m * п . Это делает так, чтобы наш цикл идеально соответствовал желаемым результатам. Немного счастливого совпадения;)


8

Дьялог АПЛ , 1 байт

× занимает один номер слева, а другой справа

×... или даже несколько чисел слева или справа или с обеих сторон

×/ умножает все числа в списке

×/¨ умножает пары в данном списке

×/∊ умножает все числа в массиве

Это относится ко всем арифметическим функциям, массивам всех размеров и рангов и числам всех типов данных.


8

R, 3 байта

'*'

Это функция, которая принимает ровно два аргумента. Беги как'*'(a,b) .

Смотрите также, prodчто делает то же самое, но может принимать произвольное количество аргументов.


Это правильное выражение само по себе? Если нет, его необходимо отправить как '*'.

@ ais523 Ах, ты прав, само по себе это неверное выражение. Я отредактировал пост, чтобы уточнить. Благодарность!
rturnbull

4
Для downvoters: это было исправлено.
Rɪᴋᴇʀ


8

Гексагония , 9 байт

?{?/*!@'/

Попробуйте онлайн!

Это на самом деле довольно просто. Вот развернутая версия:

  ? { ?
 / * ! @
' / . . .
 . . . .
  . . .

/Просто перенаправить поток управления на вторую линию , чтобы сохранить байты на трети. Это сводит код к этой линейной программе:

?{?'*!@

Этот линейный код сам по себе был бы правильным решением, если бы ввод был ограничен строго положительными числами, но из-за возможности неположительных результатов это не гарантировано завершается.

Программа использует три края памяти в форме Y:

A   B
 \ /
  |
  C

Указатель памяти начинается с края, Aуказывающего на центр.

?   Read first input into edge A.
{   Move forward to edge B.
?   Read second input into edge B.
'   Move backward to edge C.
*   Multiply edges A and B and store the result in C.
!   Print the result.
@   Terminate the program.

Я выполнил поиск методом перебора 7-байтовых решений (то есть тех, которые соответствуют длине стороны 2), и если я не ошибся (или есть решение «занят-бобер-у», выполнение которого занимает много времени, что я сомневаюсь) тогда 7-байтовое решение не существует. Возможно, существует 8-байтовое решение (например, путем повторного использования ?или использования только одной команды перенаправления вместо двух /), но это выходит за рамки того, что может сделать мой поиск методом перебора, и я пока не нашел его вручную.


7

Пит , 16 байтов

5bpiaibpikibptai

Онлайн переводчик доступен здесь.

объяснение

Для запуска вставьте приведенный выше код в текстовое поле с правой стороны связанной страницы. Ниже приведено графическое представление этого кода с размером кода 31. Сетка предназначена для удобства чтения и может мешать традиционным интерпретаторам Piet.
Код выполняется линейно слева направо, проходя вдоль верхней части изображения до первого зеленого блока, где поток программы перемещается в средний ряд кодов. Белый одинокий белый кодел необходим для выполнения программы. Его можно заменить кодеком любого цвета, кроме зеленого или темно-синего, но я выбрал белый для удобства чтения.

Визуализация кода

Instruction    Δ Hue    Δ Lightness    Stack
-----------    -----    -----------    -----
In (Number)    4        2              m
In (Number)    4        2              n, m
Multiply       1        2              m*n
Out (Number)   5        1              [Empty]
[Exit]         [N/A]    [N/A]          [Empty]

Если вы считаете, что текст не является наилучшим способом представления программы Piet или у вас есть проблема с размером байтов в программах Piet в целом, пожалуйста, сообщите свое мнение в обсуждении мета .


7

BitCycle -U , 68 байт

  >    > v
 ?+ >  +
Bv ?^ v ~
 \  v<CB~\v
 Cv  ^  <\/
^ <@=!   <
0A^

Попробуйте онлайн!

Умножение двух чисел не является тривиальной проблемой в BitCycle, особенно когда нужно обрабатывать знаки! Это моя вторая попытка; первый (по сути, тот же алгоритм, другой макет) был 81 байт, так что вполне возможно, что этот тоже можно сократить.

Программа принимает два числа в качестве аргументов командной строки и выводит на стандартный вывод. Этот -Uфлаг предназначен для преобразования десятичных чисел в унарные со знаком, поскольку BitCycle знает только 0 и 1.

объяснение

Это объяснение предполагает, что вы понимаете основы BitCycle (см. Esolangs или readme GitHub). Я основываю свои объяснения по этому ungolfed версии, видели здесь вычислительном -2раз 3:

Умножение со знаком в BitCycle

обзор

Унарные числа со знаком состоят из знака ( 0для неположительного, пустого для положительного), за которым следует величина (число 1s, равное абсолютному значению числа). Чтобы умножить два из них, нам нужно XOR знаков (вывести a, 0если точно один из них 0, или ничего, если оба или ни один из них ), а затем умножить величины (и вывести столько 1s). Мы добьемся умножения путем повторного сложения.

Биты знака

Исходя из двух источников ?, мы отделили знаки от величин +. 0s (знаковые биты) поворачиваются влево и направлены вдоль верхнего ряда, в то время как 1s (величины) поворачиваются направо и оказываются в двух Bколлекторах.

Раздел, который обрабатывает знаки, выглядит следующим образом:

  v

  \  v
> \  /

! <

Если оба числа неположительны, два 0бита приходят сверху v. Первый отражается сверху \, отправляется на юг и отражается от /. Между тем, второй бит проходит через деактивированную верхнюю часть \и отражается от нижней \. Два бита проходят друг через друга, проходят прямо через деактивированные разделители в нижнем ряду и уходят с игрового поля.

Если только одно из чисел неположительно, оно 0приходит сверху. Он прыгает вокруг всех трех сплиттеров и в конечном итоге снова направляется на север, пока не достигнет vи снова отправится на юг. На этот раз он проходит через деактивированные сплиттеры и достигает <, который отправляет его в раковину !.

Петли для хранения величин

Величина первого числа уходит в Bколлектор в этом разделе:

B v
  \
  C v
^   <

0 A ^

Перед тем, как Bколлектор открывается, он Aвыпускает сингл, 0который был помещен в него, который затем идет в конец очереди B. Мы будем использовать его в качестве значения флага, чтобы завершить цикл, когда все 1биты Bисчезнут.

Каждый раз, когда Bколлекторы открываются, \разветвитель снимает первый бит с очереди и отправляет его в логику обработки посередине. Остальные биты входят в C, и когда Cколлекторы открываются, они отправляются обратно B.

Величина второго числа уходит в Bколлектор в этом разделе:

v   ~
C B ~
    <

Когда Bколлекторы открываются, биты уходят в нижний дупнег ~. Исходные 1биты поворачиваются направо и отправляются на запад в логику обработки в середине. Отрицаемые копии 0поворачиваются налево и сразу же попадают в другого дупнега. Здесь 0s поворачивают направо и уходят с игрового поля, в то время как (теперь вдвойне) отрицают 1s поворот налево и отправляются в C. Когда Cоткрывается, они возвращаются в B.

Повторное сложение

Центральная логика обработки - это часть:

   v
   v


@  =  !

Биты из обеих петель (одна с западной стороны и все с восточной стороны) отправляются на юг в коммутатор =. Время должно быть настроено так, чтобы бит из западного цикла получался первым. Если это 1, переключатель переключается на }, отправляя следующие биты на восток в приемник !для вывода. Как только все 1s ушли, мы получаем 0, который меняет переключатель на {. Это отправляет следующие биты в @, который завершает программу. Короче говоря, мы выводим (унарную) величину второго числа столько раз, сколько 1s в (унарной) величине первого числа.



6

Java 8, 10 9 байт

a->b->a*b

Попробуй это здесь.

Java 7, 31 байт

int c(int a,int b){return a*b;}

Попробуй это здесь.

Как полная программа ( 99 90 байт) :

interface M{static void main(String[]a){System.out.print(new Long(a[0])*new Long(a[1]));}}

Попробуй это здесь.


2
В вашей полной программе есть опечатка, о которой стоит *рассказать +.
corvus_192

Вам не нужны круглые скобки a,bв лямбда-выражении.
FlipTack


5

TI-Basic, 2 байта

Очень просто.

prod(Ans


2
По мнению кого? Эта ссылка показывает семь голосов
Timtech

1
@Timtech это было не во время комментария, но оно было опубликовано в чате, поэтому просто
Blue

Хорошо, спасибо за отзыв @muddyfish
Timtech

5

PHP, 21 байт

<?=$argv[1]*$argv[2];

принимает входные данные из аргументов командной строки. Также работает с поплавками.


5

Сетчатка , 39 35 байт

Спасибо Лео за то, что он позволил мне использовать его идею, которая в итоге сэкономила 4 байта.

[^-]

*\)`--

.+
$*
\G1
_
_|1+
$'
1

Ввод разделен переводом строки.

Попробуйте онлайн! (Разделенный пробелами набор тестов для удобства.)

объяснение

Первые два этапа выводят знак минус, если ровно один из двух входов является отрицательным. Они делают это без фактического изменения ввода. Это делается путем группировки их на втором этапе )и превращения их в пробный запуск *. \Вариант на втором этапе печати предотвращает заднюю подачу листа.

[^-]

Сначала мы удаляем все, кроме знаков минус.

*\)`--

Затем мы отменяем знаки минус, если их осталось два.

.+
$*

Теперь мы конвертируем каждую строку в унарное представление ее абсолютного значения. Это избавит от знака минус, потому что $*только ищет первое неотрицательное число в матче (т.е. он не знает о знаках минус и игнорирует их).

\G1
_

Первая строка конвертируется в _путем сопоставления отдельных 1s до тех пор, пока они соседствуют с предыдущим соответствием (следовательно, мы не можем сопоставить 1s во второй строке, потому что перевод строки разрывает эту цепочку).

_|1+
$'

Это выполняет фактическое умножение. Мы заменяем каждую _(в первой строке), а также всю вторую строку всем после этого совпадения. Поэтому _совпадения будут включать в себя всю вторую строку (умножая ее на число 0s в первой строке), и вторая строка будет удалена, поскольку после этого совпадения ничего нет. Конечно, результат также будет включать в себя некоторое количество мусора в виде _s и перевода строки, но это не будет иметь значения.

1

Мы заканчиваем простым подсчетом числа 1s в результате.


5

MATLAB, 5 4 байта

@dot

dotпринимает скалярное произведение двух векторов одинаковой длины. Если мы будем кормить его двумя скалярами, он просто умножит два числа.

prodпринимает произведение значений во всех строках каждого столбца матрицы. Если матрица одномерна (т. Е. Вектор), то она действует вдоль не-одиночного измерения, беря произведение всех элементов в векторе.

dotна один байт короче, чем на prodодин байт короче, чем еще более очевидный встроенный times.

Назовите это так:

@dot
ans(3,4)
ans = 
   12

4

PigeonScript , 1 байт

*

Объяснение:
*смотрит в стек, чтобы увидеть, есть ли там что-нибудь. Если нет, он запрашивает ввод и умножает входы вместе


5
Это должно быть добавлено здесь вместо
mbomb007

4

Perl 6 , 4 байта

&[*]

Это обычный оператор инфиксного умножения *, выраженный в виде обычной функции. В качестве бонуса, если дано одно число, оно возвращает это число, а если не дано ни одного числа, оно возвращает 1мультипликативную идентичность.



4

> <>, 5 байт

i|;n*

Принимает ввод как символ ascii, выводит число.

Объяснение:

i                        | Get input.
 |                       | Mirror: Change the pointer's direction.
i                        | Get input again.
    *                    | Loop around to the right side. Multiply
   n                     | Print the value on the stack, as a number
  ;                      | End the program

Вы могли бы также сделать

ii*n;

Но я чувствую , что мое решение waaay прохладнее.

Другая возможность - сбросить точку с запятой, что приведет к отскоку указателя от зеркала, выполнению команды print и выдаче ошибки, поскольку стек пуст.


4

Машинный код Intel 8080 , MITS Altair 8800 , 28 байт

Это реализует двоичное умножение на процессоре Intel 8080 (c. 1974), который не имел инструкций умножения или деления. Входы - это 8-битные значения, а произведение - это 16-битное значение, возвращаемое в BCпаре регистров.

Вот машинный код вместе с пошаговыми инструкциями для загрузки программы в Altair 8800 с помощью переключателей на передней панели.

Step    Switches 0-7    Control Switch  Instruction Comment
1                       RESET
2       00 001 110      DEPOSIT         MVI  C, 5   Load multiplier into C
3       00 000 101      DEPOSIT NEXT                value is 5
4       00 010 110      DEPOSIT NEXT    MVI  D, 16  Load multiplicand into D
5       00 010 000      DEPOSIT NEXT                value is 16
6       00 000 110      DEPOSIT NEXT    MVI  B, 0   clear B register (high byte of result)
7       00 000 000      DEPOSIT NEXT
8       00 011 110      DEPOSIT NEXT    MVI  E, 9   set loop counter E multiplier size
9       00 001 001      DEPOSIT NEXT                (8 bits + 1 since loop ends in middle)
10      01 111 001      DEPOSIT NEXT    MOV  A, C   move multiplier into A for shift
11      00 011 111      DEPOSIT NEXT    RAR         shift right-most bit to CF
12      01 001 111      DEPOSIT NEXT    MOV  C, A   move back into C
13      00 011 101      DEPOSIT NEXT    DCR  E      decrement loop counter
14      11 001 010      DEPOSIT NEXT    JZ   19 00  loop until E=0, then go to step 27
15      00 011 001      DEPOSIT NEXT
16      00 000 000      DEPOSIT NEXT
17      01 111 000      DEPOSIT NEXT    MOV  A, B   move sum high byte into A
18      11 010 010      DEPOSIT NEXT    JNC  14 00  add if right-most bit of 
19      00 010 100      DEPOSIT NEXT                multiplier is 1, else go to 22
20      00 000 000      DEPOSIT NEXT
21      10 000 010      DEPOSIT NEXT    ADD  D      add shifted sums
22      00 011 111      DEPOSIT NEXT    RAR         shift right new multiplier/sum
23      01 000 111      DEPOSIT NEXT    MOV  B, A   move back into B
24      11 000 011      DEPOSIT NEXT    JMP  08 00  go to step 10
25      00 001 000      DEPOSIT NEXT
26      00 000 000      DEPOSIT NEXT
27      11 010 011      DEPOSIT NEXT    OUT  255    display contents of A on data panel
28      11 111 111      DEPOSIT NEXT
30      01 110 110      DEPOSIT NEXT    HLT         Halt CPU
31                      RESET                       Reset program counter to beginning
32                      RUN
33                      STOP

Попробуйте онлайн!

Если вы все правильно ввели, на панели состояния машины в симуляторе содержимое вашей оперативной памяти будет выглядеть так:

0000    0e 05 16 10 06 00 1e 09 79 1f 4f 1d ca 19 00 78 
0010    d2 14 00 82 1f 47 c3 08 00 d3 ff 76

вход

Множитель в Cрегистре и умножение на D. В наличии у Altair нет, STDINпоэтому ввод осуществляется только с помощью переключателей на передней панели.

Выход

Результат отображается на индикаторе D7- D0(верхний правый ряд) в двоичном виде.

5 x 16 = 80 (0101 0000)

введите описание изображения здесь

4 x 5 = 20 (0001 0100)

введите описание изображения здесь

7 x 9 = 63 (0011 1111)

введите описание изображения здесь

8 x -9 = -72 (1011 1000)

введите описание изображения здесь

Примечание о совместимости: это также должно работать на IMSAI 8080 , хотя в настоящее время не проверено.


3

C #, 10 байт

a=>b=>a*b;

Это просто умножение.


Ты подтолкнул меня на это!
TheLethalCoder

Как работает => =>? Я ожидаю (a, b) => a * b;
Карра

1
@Carra Работает, что это лямбда-выражение возвращает делегат, который возвращает результат, поэтому вы называете это так, если вы называете эту лямбду f: f (a) (b).
Хорват Давид



3

Clojure, 1 байт

*

: P В качестве бонуса это работает на любое количество аргументов:

[(*)
 (* 2)
 (* 2 3)
 (* 2 3 4)
 (* 2 3 4 5)] => [1 2 6 24 120]

Интересно, что вы можете легко получить его исходный код:

(source *)
(defn *
  "Returns the product of nums. (*) returns 1. Does not auto-promote
  longs, will throw on overflow. See also: *'"
  {:inline (nary-inline 'multiply 'unchecked_multiply)
   :inline-arities >1?
   :added "1.2"}
  ([] 1)
  ([x] (cast Number x))
  ([x y] (. clojure.lang.Numbers (multiply x y)))
  ([x y & more]
     (reduce1 * (* x y) more)))

3

Owk , 11 байт

λx.λy.x*y

Это может быть назначено на функцию как это:

multiply:λx.λy.x*y

и называется так:

result<multiply(a,b)

Это не работает? Пожалуйста, объясните голос доу.
Конор О'Брайен

Я не был отрицателем, но я думаю, что могу догадаться, что произошло: это очень тривиальный вопрос (и, следовательно, очень сильно недооцененный, но со многими отклонениями, отменяющими это), и, вероятно, привлечет людей, которые понизят тривиальные вопросы. Этот ответ также довольно тривиален, и вполне вероятно, что некоторые из людей, которые понижают тривиальные вопросы, также любят понижать тривиальные ответы. (Лично я предпочитаю оставлять тривиальные ответы на 0, поэтому я не
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.