Pomnóż dwie liczby


21

Dane wejściowe: dwie liczby całkowite dziesiętne. Można je podać kodowi na standardowym wejściu, jako argumenty programu lub funkcji lub jako listę.

Wyjście: ich produkt jako liczba całkowita dziesiętna. Na przykład wejście 5 16doprowadziłoby do wyniku 80.

Ograniczenia: Brak standardowych luk. To jest , odpowiedź w najmniejszej ilości bajtów wygrywa.

Uwagi: Układ skradziony z mojego wcześniejszego wyzwania, Dodaj dwie liczby .

Przypadki testowe:

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

Lub jako 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

Tabela liderów


4
@FlipTack Zakłada się, że dodawanie i mnożenie jest tak łatwe w każdym języku, co nie wiem, czy to prawda.
Fatalize

16
Nie sądzę, aby dozwolone było wyzwanie „dodaj dwie liczby”, ale zamknij to. Mimo że w większości języków programowania jest to bardzo trywialne, wciąż stanowi ważne wyzwanie. Jeśli jest to zbyt szerokie, wyzwanie „dodaj dwie liczby” musi być również zbyt szerokie.
Mego

32
Każdy może zlekceważyć trywialne wyzwania, jeśli mu się nie podoba, ale jest to całkowicie poprawne i tematyczne wyzwanie i nigdzie nie jest zbyt „zbyt szerokie” (jeśli cokolwiek, można nazwać trywialne wyzwanie zbyt wąskim). Ponownie to otwieram. To powiedziawszy, jeśli ktoś uważa, że ​​trywialne wyzwania obrażają jego inteligencję, zachęcam go do poszukiwania języków, które czynią to zadanie mniej trywialnym.
Martin Ender

16
Uo dalej: odejmij dwie liczby!
steenbergh

7
@wat Nie pozostawiając nieskurczonego dna beczki, co?
Gareth,

Odpowiedzi:


39

Brachylog V1, 05AB1E, J, K, Underload, MATL, Forth, PigeonScript, Stacked, Implicit, Jolf, Clojure, Braingolf, 8th, Common Lisp, Julia, Pyt, Appleseed, Stax, Reality, dc 1 bajt

*

Możesz edytować tę odpowiedź, aby dodać inne języki, dla których *jest poprawna odpowiedź.


Polygot, 05AB1E i podobne 5 innych języków.
Magic Octopus Urn

13
Zmontowałem w tym Underload. Jest to być może najbardziej interesujący z nich, ponieważ Niedociążenie nie ma 1-bajtowej metody dokonywania odejmowania, dzielenia lub dodawania.


To nie jest poprawne w Pyth. Pyth nie przyjmuje takich danych niejawnych.
isaacg,

Dodano Julię, np.*(5,16)
gggg

32

C (GCC), 13 bajtów

Nie działa na wszystkich implementacjach, ale jest OK.

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

Wypróbuj na TIO!


6
Zaraz, czy to ma jakoś powrócić a? Nie rozumiem ...
Erik the Outgolfer

2
Pomocne byłoby wyjaśnienie, jak to działa. ( ajest zmienną stosu lokalnego do f()- dlaczego zwracana jest jej wartość?). +1, btw - bardzo sprytne nadużycie ABI.
Cyfrowa trauma

6
@EriktheOutgolfer Słowo returnkluczowe po prostu umieszcza redult swojego argumentu w rejestrze EAX. W tym przypadku wygenerowany plik wykonywalny dokonuje obliczeń a*bw tym rejestrze, więc returnnic nie robi.
Dennis

7
Hej, to była moja sztuczka! codegolf.stackexchange.com/a/106067/18535 :-)
GB

12
Cieszę się, że raz widziałem C na górze! Możesz ogolić około 9 bajtów, po prostu zamieniając f(a,b){a*=b;}część na, 1##&a następnie zmieniając język na Mathematica.
Albert Renshaw

21

Beatnik , 888 bajtów

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

Wypróbuj online!

Używam interpretera C, ponieważ interpreter Pythona na TIO irytująco wykonuje adres, jeśli warunek skoku do tyłu nie jest spełniony. Prostym obejściem dla interpretera Pythona jest wypełnienie niektórych pól zerowych, aby adres stał się pusty. Uważam, że żadne z nich nie jest poprawne:

                                   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

Dane wejściowe powinny składać się z dwóch liczb całkowitych oddzielonych spacją, bez końcowych znaków nowej linii.

Ta odpowiedź działa teoretycznie dla wszystkich liczb całkowitych, jeśli każda komórka może przechowywać dowolnie dużą wartość, nieograniczoną do 0 - 255. Ale przepełnia się, jeśli | A | + | B | > 22. I działa bardzo wolno, jeśli | A | + | B | > 6. Tak więc nie ma wielu przypadków, które można przetestować, a rozwiązanie if-else dla tych przypadków może być jeszcze krótsze.

Chodzi o obliczenie liczb trójkątnych T (N) = N (N + 1) / 2 poprzez zmniejszenie wartości do 0 i zsumowanie wszystkich wartości pośrednich. Wtedy możemy uzyskać odpowiedź A * B = T (A + B) - T (A) - T (B).

Jednak obliczenie wszystkich 3 wartości jest trudne. Robi to najpierw obliczając T (A + B) - A, pozostawiając kopię A na stosie, aby dodać później, i wykorzystując dane wejściowe B. Następnie rekurencyjnie znajdź największą trójkątną liczbę mniejszą niż ta, którą jest T ( A + B-1) z wyjątkiem zerowych przypadków specjalnych. Możemy odzyskać B = T (A + B) - A - T (A + B-1) i obliczyć T (B) stamtąd.

Liczba N jest liczbą trójkątną, jeżeli jest równa największej liczbie trójkątnej mniejszej niż N, plus liczba nieujemnych liczb trójkątnych mniejsza niż N. Działa to w O (2 ^ (T (A + B) -A)) i jest najwolniejszą częścią programu.

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.

Łał Po prostu ... łał. Umieściłem nagrodę, dostaniesz ją w ciągu 7 dni.
NieDzejkob

19

Mathematica, 4 bajty

1##&

Przykładowe użycie: 1##&[7,9]zwraca 63. Rzeczywiście, ta sama funkcja zwielokrotnia dowolną liczbę argumentów dowolnego typu razem.

Jak wiedzą kodegolfiści Mathematica, działa to, ponieważ ##odnosi się do całej sekwencji argumentów funkcji, a konkatenacja w Mathematica (często) reprezentuje mnożenie; 1##odnosi się zatem do (1 razy) iloczynu wszystkich argumentów funkcji. &Jest tylko krótki dla Functionkomendy, która definiuje czystego funkcji (bez nazwy).

Wewnątrz innego kodu wspólny symbol *działa jak mnożenie. Podobnie spacja, więc 7 9jest to interpretowane jako 7*9(w rzeczywistości, obecna wersja REPL Mathematica faktycznie wyświetla takie spacje, jak znaki mnożenia!). Co więcej, jeśli Mathematica może stwierdzić, gdzie zaczyna się jeden token, a drugi kończy, wówczas operator mnożenia wcale nie potrzebuje bajtów: 5yjest automatycznie interpretowany jako 5*yi 3.14Log[9]jako 3.14*Log[9].


Co czyni ##&nieważnym?
Lynn,

##&zwraca listę argumentów jako obiekt „Sekwencja” - odpowiedni do podłączenia do innych funkcji, które pobierają wiele argumentów. W tym kontekście ##&nic nie robi z listą argumentów; chcemy, aby ta lista została pomnożona razem.
Greg Martin,

19

Retina , 38 37 31 bajtów

Całkowicie nowe podejście, stare jest poniżej.

M!`-
*\)`-¶-

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

Wypróbuj online!

Wyjaśnienie

Najpierw zajmujemy się znakiem:

M!`-

dopasowuje wszystkie -w ciągu i zwraca je rozdzielone znakami nowej linii

*\)`-¶-

(z następną pustą linią)
*\)oznacza, że ​​wynik tego i poprzednich etapów powinien zostać wydrukowany bez nowej linii, a następnie ciąg znaków powrócił do poprzedniego stanu (ciąg wejściowy). Pozostała część usuwa dwa -oddzielone znakiem nowej linii.

Następnie przekształcamy pierwszą liczbę na unarną:

.* 
$*_

(na końcu pierwszego wiersza jest spacja). _W tym przypadku używamy jako naszej jednoznacznej cyfry, ponieważ standardowa cyfra 1może występować w drugim numerze, a to spowodowałoby konflikt później.

Teraz dochodzimy do faktycznego pomnożenia:

_
$'$*_

Każdy z nich _jest zastępowany przez jednoargumentową reprezentację wszystkiego, co następuje po nim (nadal _jako cyfra jedności). Ponieważ konwersja na jednoargumentowe ignoruje znaki niecyfrowe, powtórzy to jednoargumentową reprezentację drugiej liczby po raz pierwszy. Druga liczba pozostanie w postaci dziesiętnej na końcu łańcucha.

Na koniec za pomocą jednego _zwracamy liczbę _w ciągu, która będzie wynikiem pomnożenia.


Poprzednia odpowiedź: (ostrzeżenie: wyświetla pusty ciąg znaków, gdy powinien wypisać 0)

Siatkówka ,  45  42 41 bajtów

Zagrajmy w grę! Pomnóż liczby względne przez język, w którym nie ma operatorów arytmetycznych i ograniczone wsparcie tylko dla liczb naturalnych ... Brzmi zabawnie :)

O^`^|-
--

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

Wyjaśnienie

Pierwsze trzy linie dotyczą znaku:

O^`^|-

Sortuje, Oa następnie odwraca ^wszystkie ciągi pasujące do wyrażenia regularnego ^|-. W praktyce powoduje to dopasowanie pustego łańcucha na początku i ewentualnego znaku minus przed drugą liczbą, a także porządkuje je, umieszczając pusty ciąg w miejscu znaku minus. Następnie wszystkie -znajdują się na początku łańcucha, a parę z nich można łatwo usunąć za pomocą dwóch następnych linii.

Następnie używamy wbudowanego narzędzia do konwertowania liczb na jednoargumentową reprezentację, a następnie następuje faktyczne pomnożenie:

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

Dopasowujemy dowolne 1i zastępujemy każdą z nich 1następującą spacją. Każda cyfra pierwszego numeru zostanie zastąpiona pełnym drugim numerem, a każda cyfra drugiego numeru zostanie zastąpiona pustym ciągiem.

Ostatnia część jest ponownie wbudowanym narzędziem do konwersji z jedności na dziesiętne.

Wypróbuj online!


2
Chciałbym móc głosować za każdym razem, gdy grasz w golfa, niezła robota!
Kritixi Lithos

Wow, to nowe podejście jest niesamowite. Myślę, że wygrałeś. :) (I jeszcze bardziej przekonuje mnie, że domyślna postać $*powinna być _.)
Martin Ender

Przy okazji, oto rozwiązanie tylko dla ASCII o tej samej liczbie bajtów, na wypadek, gdybyś wolał: tio.run/nexus/retina#U9VwT/…
Martin Ender

1
Ciekawostka: najwidoczniej wymyśliłem sztuczkę polegającą na samodzielnym wymieszaniu jednego operatora jedno- i dziesiętnego.
Martin Ender

1
Próbowałem zaktualizować to do Retina 1.0, a dzięki nowym limitom i nowemu operatorowi powtarzania potrzebuje teraz tylko 23 bajtów: tio.run/##K0otycxLNPyvpxqj4Z7wX8vOR9dQxyBBl0tPW4dLiyueS0UdSP7/… ... można nawet pomnożyć liczby dodatnie w liczbie dodatniej etap teraz ( .+,(.+)do $.($1**), ale tutaj jest więcej bajtów.
Martin Ender


15

Brain-Flak , 56 bajtów

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

To musi być uruchomione jako pełny program, ponieważ nie jest on czysty w stosach, a dane wejściowe muszą być jedynymi elementami w każdym stosie.

Wypróbuj online!


Objaśnienie: (wywołaj dane wejściowe x i y)

Część 1:

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

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

W tym momencie mamy [x, y] na jednym stosie i [-x, -y] na drugim.

Część 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
Łał! Zdecydowanie najbardziej imponująca jak dotąd odpowiedź
DJMcMayhem

@DJMcMayhem I (nieco zmodyfikowany) bije ten na wiki o 18 bajtów
Riley

Czy masz dostęp do zapisu w wiki typu brain-flak? Chciałbym przesłać krótszą wersję.
DJMcMayhem

@DJMcMayhem Nie mam dostępu. Krótszy z nich opublikowałem na czacie Brain-Flak, jeśli chcesz rzucić okiem i załadować go.
Riley

Wiem, że minęło trochę czasu, ale masz trochę konkurencji ;)
Wheat Wizard

11

JavaScript (ES6), 9 bajtów

ES6 ma dedykowaną funkcję dla 32-bitowych liczb całkowitych, szybciej niż bardziej ogólny *operator.

Math.imul

Nawiasem mówiąc, jest to tak długo, jak:

a=>b=>a*b

Wspaniale, teraz znam Math.imul, dziękuję!
chau giang

9

Brain-Flak , 56 54 52 bajtów

2 bajty zapisane dzięki błędowi wyłapanemu przez Nitrodon

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

Wypróbuj online!

Wersja czystego stosu, 62 60 bajtów

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

Wypróbuj online!

Wyjaśnienie

To wyjaśnienie jest raczej wyjaśnieniem stosowanego algorytmu i pomija rzeczywisty kod. Zakłada się, że umiesz biegle czytać Brain-Flak. Jeśli potrzebujesz pomocy w zrozumieniu kodu lub algorytmu, chętnie edytuję lub odpowiadam, jeśli zostawisz komentarz.

Jest to trochę dziwne i wykorzystuje dziwną matematykę, która ledwo się sprawdza. Pierwszą rzeczą, którą zrobiłem, było utworzenie pętli, która zawsze kończyłaby się w krokach O (n) . Normalnym sposobem na to jest umieszczenie n i -n na przeciwnych stosach i dodawanie po jednym do każdego, aż osiągnie zero, jednak zrobiłem to w nieco dziwniejszy sposób. W mojej metodzie umieszczam licznik pod wejściem i na każdym kroku zwiększam licznik, dodając go do n i odwracając znak n .

Przejdźmy przez przykład. Powiedz 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

Nie udowodnię tego tutaj, ale to zawsze kończy się dla dowolnego wejścia i zrobi to w około 2n krokach. W rzeczywistości zakończy się w krokach 2n, jeśli n jest dodatnie, i kroków 2n-1, jeśli n jest ujemne. Możesz to przetestować tutaj .

Teraz mamy około 2n kroków w naszej pętli, w jaki sposób pomnożymy przez n ? Cóż, oto magia matematyki. Oto, co robimy: tworzymy akumulator, na każdym etapie procesu dodajemy drugie wejście ( m ) do akumulatora i odwracamy znak obu z nich, a następnie przesuwamy sumę nad wszystkimi występującymi pętlami, jest to produkt.

Dlaczego, u licha, tak jest?

Cóż, przejdźmy przez przykład i mam nadzieję, że stanie się jasny. W tym przykładzie mnożymy 5 przez 3 , pokażę tylko ważne wartości

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

Mam nadzieję, że mechanizm jest tutaj widoczny. Przechodzimy przez wszystkie wielokrotności m w kolejności ich wartości bezwzględnych. Będziesz wówczas zawiadomienie, że 2n th termin jest zawsze m * n a termin przed zawsze -m * n . To sprawia, że ​​nasza pętla idealnie pokrywa się z oczekiwanymi wynikami. Trochę szczęśliwego zbiegu okoliczności;)



8

R, 3 bajty

'*'

Jest to funkcja, która przyjmuje dokładnie dwa argumenty. Uruchom jako '*'(a,b).

Zobacz także, prodktóry robi to samo, ale może przyjąć dowolną liczbę argumentów.


Czy to samo w sobie jest prawidłowym wyrażeniem? Jeśli nie, należy go przesłać jako '*'.

@ ais523 Ach, masz rację, nie jest to samo w sobie prawidłowe wyrażenie. Zredagowałem post, aby wyjaśnić. Dzięki!
rturnbull

4
Do downvoters: Zostało to naprawione.
Rɪᴋᴇʀ

8

ArnoldC , 152 bajty

HEY CHRISTMAS TREE c
YOU SET US UP 0
GET TO THE CHOPPER c
HERE IS MY INVITATION a
YOU'RE FIRED b
ENOUGH TALK
TALK TO THE HAND c
YOU HAVE BEEN TERMINATED

Wypróbuj online!


1
+1 ENOUGH TALK (nowa linia) ROZMOWA DO RĘKI
MilkyWay90

8

Sześciokąt , 9 bajtów

?{?/*!@'/

Wypróbuj online!

Jest to w rzeczywistości dość proste. Oto rozwinięta wersja:

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

/Tylko przekierować przepływ sterowania do drugiej linii, aby zapisać bajty na trzecią. To redukuje kod do tego programu liniowego:

?{?'*!@

Sam ten liniowy kod byłby faktycznie poprawnym rozwiązaniem, gdyby dane wejściowe były ograniczone do liczb ściśle dodatnich, ale ze względu na możliwość uzyskania dodatnich wyników nie gwarantuje się zakończenia.

Program wykorzystuje trzy krawędzie pamięci w kształcie litery Y:

A   B
 \ /
  |
  C

Wskaźnik pamięci zaczyna się od krawędzi Awskazującej w kierunku środka.

?   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.

Przeprowadziłem wyszukiwanie brutalnej siły dla rozwiązań 7-bajtowych (tj. Pasujących do długości 2), a jeśli nie popełniłem błędu (lub istnieje rozwiązanie typu zajęty bóbr, które zajmuje dużo czasu, co wątpię) to rozwiązanie 7-bajtowe nie istnieje. Może istnieć rozwiązanie 8-bajtowe (np. Przez ponowne użycie ?lub użycie tylko jednego polecenia przekierowania zamiast dwóch /), ale to jest więcej niż to, co może zrobić moje wyszukiwanie z użyciem siły i nie znalazłem jeszcze ręcznie.


7

Piet , 16 bajtów

5bpiaibpikibptai

Tłumacz online dostępny tutaj.

Wyjaśnienie

Aby uruchomić, wklej powyższy kod w polu tekstowym po prawej stronie połączonej strony. Poniżej znajduje się graficzna reprezentacja tego kodu z rozmiarem kodu 31. Siatka ma na celu czytelność i może zakłócać tradycyjne interpretery Piet.
Kod działa liniowo od lewej do prawej, idąc wzdłuż górnej krawędzi obrazu, aż do pierwszego zielonego bloku, w którym przepływ programu przechodzi do środkowego rzędu kodeli. Biały samotny biały kod jest niezbędny do przebiegu programu. Można go zastąpić kodem dowolnego koloru innego niż zielony lub ciemnoniebieski, ale dla czytelności wybrałem biel.

Wizualizacja kodu

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]

Jeśli uważasz, że tekst nie jest najlepszym sposobem reprezentacji programu Piet lub masz problem z rozmiarem bajtów programów Piet w ogólności, daj znać swoją opinię w dyskusji na temat meta .


7

BitCycle -U , 68 bajtów

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

Wypróbuj online!

Pomnożenie dwóch liczb nie jest trywialnym problemem w BitCycle, szczególnie gdy znaki muszą być obsługiwane! To moja druga próba; pierwszy (zasadniczo ten sam algorytm, inny układ) miał 81 bajtów, więc całkiem możliwe, że ten też można skrócić.

Program przyjmuje dwie liczby jako argumenty wiersza poleceń i dane wyjściowe na standardowe wyjście. -UFlaga jest do konwersji liczb dziesiętnych do podpisał jednoskładnikowa , ponieważ BitCycle wie tylko 0 i 1 roku.

Wyjaśnienie

To wyjaśnienie zakłada, że ​​rozumiesz podstawy BitCycle (zobacz Esolangs lub readme GitHub). Będę opierać moje wyjaśnienie tego ungolfed wersji widziane tutaj obliczeniowej -2razy 3:

Podpisane mnożenie w BitCycle

Przegląd

Podpisane liczby jednoargumentowe składają się ze znaku (0 przypadku liczby niepozytywnej, pustej w przypadku wartości dodatniej), po której następuje wielkość (liczba 1s równa wartości bezwzględnej liczby). Aby pomnożyć dwa z nich, musimy XOR znaki (wypisać a, 0jeśli dokładnie jeden z nich jest 0lub nic, jeśli oba lub oba nie są), a następnie pomnożyć wielkości (i wypisać tyle 1s). Pomnożymy przez wielokrotne dodawanie.

Podpisuj bity

Zaczynając od dwóch źródeł ?, oddzielamy znaki od wielkości za pomocą+ . 0s (bity znakowe) skręcają w lewo i są skierowane wzdłuż górnego rzędu, podczas gdy 1s (wielkości) skręcają w prawo i kończą się na dwóchB kolektorach.

Sekcja, która obsługuje znaki, wygląda następująco:

  v

  \  v
> \  /

! <

Jeśli obie liczby nie są dodatnie, dwa 0bity pochodzą od góry v. Pierwszy odbija się od szczytu \, jest wysyłany na południe i odbija się od/ . Tymczasem drugi bit przechodzi przez zdezaktywowaną górę \i odbija się od dołu \. Dwa bity mijają się, idą prosto przez dezaktywowane teraz rozdzielacze w dolnym rzędzie i schodzą z pola gry.

Jeśli tylko jedna z liczb nie jest dodatnia, jedna 0pochodzi z góry. Odbija się od wszystkich trzech splitterów i kończy ponownie na północ, dopóki nie trafiv i znów zostaje wysłany na południe. Tym razem przechodzi przez dezaktywowane rozgałęźniki i dociera do <, który wysyła go do zlewu !.

Pętle do przechowywania wielkości

Wielkość pierwszej liczby trafia do Bkolektora w tej sekcji:

B v
  \
  C v
^   <

0 A ^

Zanim Bkolektor się otworzy, Akolektor zwalnia singiel, 0który został w nim umieszczony, a następnie trafia na koniec kolejki B. Użyjemy go jako wartości flagi do zakończenia pętli, gdy znikną wszystkie 1bity B.

Za każdym razem, gdy Botwierają się kolektory, \rozdzielacz odrywa pierwszy bit z kolejki i wysyła go do logiki przetwarzania w środku. Reszta bitów wchodzi C, a kiedy Ckolektory się otwierają, zostają odesłane z powrotem B.

Wielkość drugiej liczby trafia do Bkolektora w tej sekcji:

v   ~
C B ~
    <

Po Botwarciu kolektorów bity trafiają do dolnego dupneg ~. Oryginalne 1bity skręcają w prawo i są wysyłane na zachód do logiki przetwarzania na środku. Negowane kopie 0skręcają w lewo i natychmiast uderzają w kolejny dupneg. Tutaj 0s skręca w prawo i schodzi z pola gry, a (teraz podwójnie) negowane 1s skręca w lewo i zostaje wysłany C. Po Cotwarciu wracają do B.

Powtarzane dodawanie

Centralną logiką przetwarzania jest ta część:

   v
   v


@  =  !

Bity z obu pętli (jedna od strony zachodniej i wszystko od strony wschodniej) są wysyłane na południe do przełącznika =. Czas należy ustawić tak, aby bit z zachodniej pętli dotarł tam pierwszy. Jeśli jest to 1, przełącznik zmienia się na }, wysyłając następujące bity na wschód do zlewu w !celu wysłania . Gdy wszystkie 1s znikną, otrzymamy 0, co zmienia przełącznik na {. To wysyła następujące bity do @, który kończy program. Krótko mówiąc, wypisujemy (jednoargumentową) wielkość drugiej liczby tyle razy, ile jest 1wartości (jednej) wielkości pierwszej liczby.






5

PHP, 21 bajtów

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

pobiera dane wejściowe z argumentów wiersza poleceń. Działa również z pływakami.


5

Siatkówka oka , 39 35 bajtów

Dzięki Leo za umożliwienie mi wykorzystania jego pomysłu, który ostatecznie pozwolił mi zaoszczędzić 4 bajty.

[^-]

*\)`--

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

Wejście jest oddzielone od linii.

Wypróbuj online!(Dla wygody zestaw testów oddzielony spacjami).

Wyjaśnienie

Pierwsze dwa etapy wypisują znak minus, jeśli dokładnie jedno z dwóch sygnałów wejściowych jest ujemne. Robią to bez faktycznej zmiany danych wejściowych. Odbywa się to poprzez grupowanie ich w drugim etapie )i przekształcanie ich w suchą próbę z *. \Opcję na drugiej zapobiega etap drukowania spływu wysuwu.

[^-]

Najpierw usuwamy wszystko oprócz znaków minus.

*\)`--

Następnie anulujemy znaki minus, jeśli pozostały dwa z nich.

.+
$*

Teraz przekształcamy każdą linię w jednoargumentową reprezentację jej wartości bezwzględnej. Pozbędzie się znaku minus, ponieważ $*szuka tylko pierwszej nieujemnej liczby w dopasowaniu (tzn. Nie wie o znakach minus i ignoruje je).

\G1
_

Pierwsza linia jest konwertowana na _, dopasowując poszczególne 1s tak długo, jak sąsiadują z poprzednim dopasowaniem (stąd nie możemy dopasować 1s na drugim wierszu, ponieważ wysuw linii przerywa ten łańcuch).

_|1+
$'

Wykonuje to rzeczywiste mnożenie. Zastępujemy każdą _(w pierwszej linii), a także całą drugą linię wszystko po tym meczu. Te _mecze będą zatem obejmować całą drugą linię (pomnożenie jej przez liczbę 0sekund w pierwszej linii), a druga linia zostanie usunięty, ponieważ nie ma nic po tym meczu. Oczywiście wynik będzie również zawierał śmieci w postaci _s i linii, ale to nie będzie miało znaczenia.

1

Kończymy, po prostu licząc liczbę 1s w wyniku.


5

MATLAB, 5 4 bajtów

@dot

dotprzyjmuje iloczyn kropkowy dwóch wektorów o równej długości. Jeśli karmimy go dwoma skalarami, po prostu pomnoży te dwie liczby.

prodprzyjmuje iloczyn wartości we wszystkich wierszach każdej kolumny macierzy. Jeśli macierz jest jednowymiarowa (tj. Wektor), wówczas działa wzdłuż wymiaru nie singletonu, przyjmując iloczyn wszystkich elementów w wektorze.

dotjest o jeden bajt krótszy niż o prodjeden bajt krótszy niż nawet bardziej oczywiste wbudowanetimes .

Nazwij to tak:

@dot
ans(3,4)
ans = 
   12


4

Perl 6 , 4 bajty

&[*]

Jest to zwykły operator mnożenia infix *, wyrażony jako zwykła funkcja. Jako bonus, jeśli podana zostanie jedna liczba, zwróci tę liczbę, a jeśli nie otrzyma żadnej liczby, zwróci 1tożsamość multiplikatywną.


Alternatywne rozwiązanie 4 bajtów UTF-8:*×*
nwellnhof

4

> <>, 5 bajtów

i|;n*

Pobiera dane wejściowe jako znak ascii, wypisuje liczbę.

Wyjaśnienie:

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

Ty też możesz to zrobić

ii*n;

Ale czuję, że moje rozwiązanie jest znacznie fajniejsze.

Inną możliwością jest upuszczenie średnika, co spowodowałoby odbicie wskaźnika od lustra, naciśnięcie polecenia drukowania i wygenerowanie błędu, ponieważ stos jest pusty.


4

Kod maszynowy Intel 8080 , MITS Altair 8800 , 28 bajtów

To implementuje binarne mnożenie w procesorze Intel 8080 (ok. 1974), który nie miał instrukcji mnożenia ani dzielenia. Wejściami są wartości 8-bitowe, a iloczyn 16-bitowy jest zwracany w BCparze rejestrów.

Oto kod maszynowy wraz z instrukcjami krok po kroku, jak załadować program do Altair 8800 za pomocą przełączników na panelu przednim.

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

Wypróbuj online!

Jeśli wprowadziłeś to wszystko poprawnie, w szufladzie stanu maszyny w symulatorze zawartość pamięci RAM będzie wyglądać następująco:

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

Wkład

Mnożnik w Crejestrze i multiplikacja na D. Standardowy Altair nie ma, STDINwięc dane wejściowe są dokonywane tylko za pomocą przełączników na panelu przednim.

Wydajność

Wynik jest wyświetlany na lampkach D7- D0(prawy górny rząd) w formacie binarnym.

5 x 16 = 80 (0101 0000)

wprowadź opis zdjęcia tutaj

4 x 5 = 20 (0001 0100)

wprowadź opis zdjęcia tutaj

7 x 9 = 63 (0011 1111)

wprowadź opis zdjęcia tutaj

8 x -9 = -72 (1011 1000)

wprowadź opis zdjęcia tutaj

Uwaga dotycząca zgodności: ta funkcja powinna również działać na IMSAI 8080 , choć obecnie nie była testowana.


3

C #, 10 bajtów

a=>b=>a*b;

To tylko pomnożenie.


Pobiłeś mnie do tego!
TheLethalCoder

Jak działa => =>? Oczekiwałbym (a, b) => a * b;
Carra,

1
@Carra Działa, że ​​to wyrażenie lambda zwraca delegata, który zwraca wynik, więc nazywamy to w ten sposób, jeśli wywołasz to lambda f: f (a) (b).
Horváth Dávid

Byłaby to forma
curry


3

Clojure, 1 bajt

*

: P Jako bonus działa na dowolnej liczbie argumentów:

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

Co ciekawe, możesz łatwo uzyskać jego kod źródłowy:

(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 bajtów

λx.λy.x*y

Można to przypisać do funkcji takiej jak ta:

multiply:λx.λy.x*y

i nazwał tak:

result<multiply(a,b)

Czy to nie działa? Proszę wyjaśnić głosowanie łania.
Conor O'Brien

Nie byłem zwolennikiem, ale myślę, że mogę zgadnąć, co się stało: jest to bardzo trywialne pytanie (a zatem bardzo mocno przegłosowane, ale z wieloma opiniami anulującymi to) i prawdopodobnie przyciągnie ludzi, którzy głosują na trywialne pytania. Ta odpowiedź jest również dość trywialna i prawdopodobne jest, że niektórzy ludzie, którzy głosują za trywialnymi pytaniami, lubią też głosować za trywialnymi odpowiedziami. (Osobiście wolę pozostawić trywialne odpowiedzi na 0, więc nie głosuję w żaden sposób w tej sprawie.)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.