var QUESTION_ID=106182,OVERRIDE_USER=8478;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>
Jawaban:
Brachylog V1, 05AB1E, J, K, Underload, MATL, Forth, PigeonScript, Stacked, Implisit, Jolf, Clojure, Braingolf, 8, Common Lisp, Julia, Pyt, Appleseed, Stax, Reality, dc 1 byte
Anda dapat mengedit jawaban ini untuk menambahkan bahasa lain yang
*
merupakan jawaban yang valid.sumber
*(5,16)
C (GCC), 13 byte
Tidak berfungsi pada semua implementasi, tapi tidak apa-apa.
Cobalah di TIO!
sumber
a
? Saya tidak mengerti ...a
adalah variabel stack lokal untukf()
- mengapa nilainya dikembalikan?) +1, btw - penyalahgunaan ABI yang sangat pintar.return
kunci hanya menempatkan redult dari argumennya dalam register EAX. Dalam hal ini, executable yang dihasilkan melakukan perhitungana*b
dalam register itu, jadireturn
tidak melakukan apa-apa.f(a,b){a*=b;}
bagian dengan1##&
dan kemudian hanya mengubah bahasa Anda ke Mathematica.Beatnik , 888 byte
Cobalah online!
Saya menggunakan juru bahasa C karena juru bahasa Python di TIO secara tidak sengaja mengeksekusi alamat jika kondisi untuk melompat mundur tidak terpenuhi. Solusi yang mudah untuk juru bahasa Python adalah menambahkan beberapa nops untuk membuat alamat nop. Saya percaya tidak ada yang benar:
Input harus berupa dua bilangan bulat yang dipisahkan oleh spasi, tanpa tertinggal baris baru.
Jawaban ini bekerja secara teori untuk semua bilangan bulat, jika setiap sel dapat menyimpan nilai besar yang sewenang-wenang, tidak terbatas pada 0 - 255. Tetapi ia meluap jika | A | + | B | > 22. Dan itu berjalan sangat lambat jika | A | + | B | > 6. Jadi tidak banyak kasus yang dapat Anda uji dan solusi jika-untuk kasus-kasus tersebut mungkin lebih pendek.
Idenya adalah untuk menghitung angka segitiga T (N) = N (N + 1) / 2 dengan menurunkan nilai menjadi 0 dan menjumlahkan semua nilai perantara. Maka kita bisa mendapatkan jawaban A * B = T (A + B) - T (A) - T (B).
Tetapi sulit untuk menghitung semua 3 nilai. Ini dilakukan dengan terlebih dahulu menghitung T (A + B) - A, meninggalkan salinan A di tumpukan untuk ditambahkan kembali nanti, dan menggunakan input B. Kemudian secara rekursif menemukan bilangan segitiga terbesar lebih kecil dari itu, yaitu T ( A + B-1) kecuali untuk nol kasus khusus. Kita bisa mendapatkan kembali B = T (A + B) - A - T (A + B-1) dan menghitung T (B) dari sana.
Angka N adalah angka segitiga jika sama dengan angka segitiga terbesar lebih kecil dari N, ditambah jumlah angka segitiga non-negatif lebih kecil dari N. Ini berjalan dalam O (2 ^ (T (A + B) -A)) dan merupakan bagian paling lambat dalam program ini.
sumber
Mathematica, 4 byte
Contoh penggunaan:
1##&[7,9]
pengembalian63
. Memang, fungsi yang sama ini mengalikan sejumlah argumen dari jenis apa pun secara bersamaan.Seperti diketahui codegolfers Mathematica, ini bekerja karena
##
mengacu pada seluruh rangkaian argumen untuk suatu fungsi, dan gabungan dalam Mathematica (sering) mewakili multiplikasi; jadi1##
mengacu pada (1 kali) produk dari semua argumen fungsi. Ini&
hanya kependekan dariFunction
perintah yang mendefinisikan fungsi murni (tanpa nama).Di dalam kode lain, simbol umum
*
berfungsi sebagai perkalian. Begitu juga spasi, sehingga7 9
ditafsirkan sebagai7*9
(memang, versi REPL saat ini dari Mathematica benar-benar menampilkan ruang seperti tanda-tanda perkalian!). Bahkan lebih baik, jika Mathematica dapat mengetahui di mana satu token dimulai dan yang lainnya berakhir, maka tidak ada byte sama sekali yang diperlukan untuk operator perkalian:5y
secara otomatis diartikan sebagai5*y
, dan3.14Log[9]
sebagai3.14*Log[9]
.sumber
##&
tidak valid?##&
mengembalikan daftar argumennya sebagai objek 'Urutan' - cocok untuk menghubungkan ke fungsi lain yang mengambil banyak argumen. Dalam konteks ini,##&
tidak melakukan apa pun pada daftar argumennya; kami ingin daftar itu dikalikan bersama.Retina ,
383731 bytePendekatan yang sama sekali baru, yang lama di bawah ini.
Cobalah online!
Penjelasan
Pertama, kita berurusan dengan tanda:
cocok dengan semua
-
dalam string dan mengembalikannya dipisahkan oleh baris baru(dengan baris kosong berikut)
*\)
berarti hasil dari ini dan tahap sebelumnya harus dicetak tanpa baris baru, dan kemudian string dikembalikan ke apa sebelumnya (string input). Bagian yang tersisa menghapus dua-
dipisahkan oleh baris baru.Lalu kami mengonversi angka pertama menjadi unary:
(ada spasi di akhir baris pertama). Kami menggunakan
_
sebagai digit unary kami dalam hal ini, karena digit standar1
dapat hadir di angka kedua, dan ini akan bertentangan nanti.Sekarang kita sampai pada perkalian yang sebenarnya:
Masing
_
- masing digantikan oleh representasi unary dari semua yang mengikutinya (masih menggunakan_
sebagai digit unary). Karena konversi ke unary mengabaikan karakter non-digit, ini akan mengulangi representasi unary dari angka kedua untuk kali "angka pertama". Angka kedua akan tetap dalam representasi desimal di akhir string.Pada akhirnya, dengan satu
_
kita mengembalikan jumlah_
dalam string, yang akan menjadi hasil dari perkalian.Jawaban sebelumnya: (peringatan: mengeluarkan string kosong ketika seharusnya menampilkan
0
)Retina ,
454241 byteAyo main game! Gandakan angka relatif dengan bahasa yang tidak memiliki operator aritmatika dan dukungan terbatas hanya untuk bilangan alami ... Kedengarannya lucu :)
Penjelasan
Tiga baris pertama berhubungan dengan tanda:
Ini memilah
O
dan kemudian membalik^
semua string yang cocok dengan regex^|-
. Dalam prakteknya ini cocok dengan string kosong di awal, dan tanda minus akhirnya sebelum nomor kedua, dan mengatur ulang mereka menempatkan string kosong di tempat minus. Setelah ini, semua-
berada di awal string, dan sepasang dari mereka dapat dihapus dengan mudah dengan dua baris berikutnya.Setelah itu, kami menggunakan builtin untuk mengonversi angka menjadi representasi unary, dan kemudian muncul perkalian yang sebenarnya:
Kami cocok dengan siapa saja
1
, dan gantikan mereka masing-masing dengan semua1
setelah ruang berikut. Setiap digit angka pertama akan diganti dengan angka kedua penuh, sedangkan setiap digit angka kedua akan digantikan oleh string kosong.Bagian terakhir lagi-lagi adalah builtin untuk mengkonversi kembali dari unary ke desimal.
Cobalah online!
sumber
$*
seharusnya_
.).+,(.+)
ke$.($1**
) tapi itu sebenarnya lebih banyak byte di sini.Gores , 1 byte
Penggunaan: Tempatkan angka di kedua sisi
*
tandaCatatan: Karena Scratch adalah bahasa visual saya tidak bisa mengetahui berapa banyak byte yang dikonsumsi sampai @ mbomb007 mencatat saya tentang metode untuk menghitung byte awal
sumber
Brain-Flak , 56 byte
Ini harus dijalankan sebagai program lengkap karena tidak menumpuk bersih dan input harus menjadi satu-satunya elemen dalam tumpukan.
Cobalah online!
Penjelasan: (panggil input x dan y)
Bagian 1:
Pada titik ini kita memiliki [x, y] pada satu tumpukan dan [-x, -y] pada yang lain.
Bagian 2:
sumber
JavaScript (ES6), 9 byte
ES6 memiliki fungsi khusus untuk bilangan bulat 32-bit, lebih cepat dari
*
operator yang lebih umum .Kebetulan, ini hanya selama:
sumber
Brain-Flak ,
565452 byte2 byte disimpan berkat kesalahan yang ditangkap oleh Nitrodon
Cobalah online!
Stack versi bersih,
6260 byteCobalah online!
Penjelasan
Penjelasan ini lebih merupakan penjelasan dari algoritma yang terlibat dan tidak menyertakan kode yang sebenarnya. Diasumsikan bahwa Anda tahu cara membaca Brain-Flak dengan mahir. Jika Anda perlu bantuan memahami kode atau algoritme, saya akan senang mengedit atau merespons jika Anda meninggalkan komentar.
Ini sedikit aneh dan menggunakan beberapa matematika aneh yang baru saja berhasil. Hal pertama yang saya lakukan adalah membuat loop yang selalu berakhir pada langkah O (n) . Cara normal untuk melakukan ini adalah dengan meletakkan n dan -n pada tumpukan yang berlawanan dan menambahkan satu ke masing-masing sampai satu mencapai nol, namun saya melakukannya dengan cara yang agak asing. Dalam metode saya, saya meletakkan penghitung di bawah input dan setiap langkah saya menambah penghitung menambahkannya ke n dan membalik tanda n .
Mari kita telusuri contoh. Katakan n = 7
Saya tidak akan membuktikannya di sini, tetapi ini akan selalu berakhir untuk input apa pun dan akan melakukannya dalam sekitar 2n langkah. Bahkan itu akan berakhir dalam langkah 2n jika n positif dan langkah 2n-1 jika n negatif. Anda dapat mengujinya di sini .
Sekarang kita memiliki sekitar 2n langkah dalam loop kita bagaimana kita mengalikan dengan n ? Nah di sini ada beberapa keajaiban matematika. Inilah yang kami lakukan: Kami membuat akumulator, setiap langkah dari proses kami menambahkan input kedua ( m ) ke akumulator dan membalik tanda keduanya, kami kemudian mendorong total pada semua loop yang terjadi, ini adalah produk.
Kenapa bisa begitu?
Baiklah mari kita telusuri contoh dan mudah-mudahan itu akan menjadi jelas. Dalam contoh ini kita mengalikan 5 dengan 3 , saya hanya akan menunjukkan nilai-nilai penting
Semoga mekanismenya jelas di sini. Kami sedang melangkah melalui semua kelipatan m dalam urutan nilai absolutnya. Anda kemudian pemberitahuan bahwa 2n th jangka selalu m * n dan istilah sebelum selalu * -m n . Ini membuatnya sehingga perulangan kita sejajar dengan hasil yang kita inginkan. Sedikit kebetulan yang menyenangkan;)
sumber
Dyalog APL , 1 byte
×
mengambil satu nomor di sebelah kiri, dan satu di sebelah kanan×
... atau bahkan beberapa nomor di kiri atau di kanan atau di kedua sisi×/
multiplies all numbers in a list×/¨
multiplies the pairs in a given list×/∊
mulitplies all numbers in an arrayThis applies to all arithmetic functions, arrays of all sizes and ranks, and numbers of all datatypes.
sumber
R, 3 bytes
This is a function which takes exactly two arguments. Run as
'*'(a,b)
.See also
prod
which does the same thing but can take an arbitrary number of arguments.sumber
'*'
.ArnoldC, 152 bytes
Try it online!
sumber
Hexagony, 9 bytes
Try it online!
This is actually fairly straightforward. Here is the unfolded version:
The
/
just redirect the control flow to the second line to save bytes on the third. That reduces the code to this linear program:This linear code on its own would actually be a valid solution if the input was limited to strictly positive numbers, but due to the possibility of non-positive results, this isn't guaranteed to terminate.
The program makes use of three memory edges in a Y-shape:
The memory pointer starts on edge
A
pointing towards the centre.I ran a brute force search for 7-byte solutions (i.e. those that fit into side-length 2), and if I didn't make a mistake (or there's a busy-beaver-y solution that takes a long time to complete, which I doubt) then a 7-byte solution doesn't exist. There might be an 8-byte solution (e.g. by reusing the
?
or using only one redirection command instead of two/
), but that's beyond what my brute force search can do, and I haven't found one by hand yet.sumber
Piet, 16 bytes
Online interpreter available here.
Explanation
To run, paste the code above in the text box on the right side of the linked page. Below is a graphical representation of this code with codel size 31. The grid is for readability and may interfere with traditional Piet interpreters.
The code runs linearly from left to right, going along the top of the image until the first green block, where program flow moves to the middle row of codels. The white lone white codel is necessary for program flow. It could be replaced with a codel of any color other than green or dark blue, but I have chosen white for readability.
If you think that text is not the best way to represent a Piet program or have an issue with the byte size of Piet programs in general, please let your opinion be known in the discussion on meta.
sumber
BitCycle
-U
, 68 bytesTry it online!
Multiplying two numbers is not a trivial problem in BitCycle, especially when signs need to be handled! This is my second attempt; the first one (essentially same algorithm, different layout) was 81 bytes, so it's quite possible this one could be shortened too.
The program takes the two numbers as command-line arguments and outputs to stdout. The
-U
flag is to convert the decimal numbers to signed unary, since BitCycle knows only of 0's and 1's.Explanation
This explanation assumes you understand the basics of BitCycle (see Esolangs or the GitHub readme). I'll base my explanation on this ungolfed version, seen here computing
-2
times3
:Overview
Signed unary numbers consist of the sign (
0
for nonpositive, empty for positive) followed by the magnitude (a number of1
s equal to the number's absolute value). To multiply two of them, we need to XOR the signs (output a0
if exactly one of them is0
, or nothing if both or neither are) and then multiply the magnitudes (and output that many1
s). We'll achieve the multiplication by repeated addition.Sign bits
Starting from the two sources
?
, we split off the signs from the magnitudes using+
.0
s (sign bits) turn left and are directed along the top row, while1
s (magnitudes) turn right and end up in the twoB
collectors.The section that handles the signs looks like this:
If both numbers are nonpositive, two
0
bits come in from the topv
. The first one reflects off the top\
, is sent southward, and reflects off the/
. Meanwhile, the second bit passes through the deactivated top\
and reflects off the bottom\
. The two bits pass each other, go straight through the now-deactivated splitters on the bottom row, and go off the playfield.If only one of the numbers is nonpositive, one
0
comes in from the top. It bounces around all three splitters and ends up going northward again, until it hits thev
and is once more sent south. This time, it passes through the deactivated splitters and reaches the<
, which sends it into the sink!
.Loops to store the magnitudes
The magnitude of the first number goes into the
B
collector in this section:Before the
B
collector opens, theA
collector releases the single0
that was placed in it, which then goes onto the end of the queue inB
. We'll use it as a flag value to terminate the loop when all the1
bits inB
are gone.Each time the
B
collectors open, the\
splitter peels off the first bit from the queue and sends it to the processing logic in the middle. The rest of the bits go intoC
, and when theC
collectors open, they are sent back intoB
.The magnitude of the second number goes into the
B
collector in this section:When the
B
collectors open, the bits go into the bottom dupneg~
. The original1
bits turn right and are sent west into the processing logic in the middle. The negated copies (0
s) turn left and immediately hit another dupneg. Here the0
s turn right and go off the playfield, while the (now doubly) negated1
s turn left and are sent intoC
. WhenC
opens, they go back intoB
.Repeated addition
The central processing logic is this part:
Bits from both loops (one from the western side, and everything from the eastern side) are sent south into the switch
=
. The timing has to be set up so that the bit from the western loop gets there first. If it is a1
, the switch changes to}
, sending the following bits eastward into the sink!
to be output. Once all the1
s are gone, we get the0
, which changes the switch to{
. This sends the following bits into the@
, which terminates the program. In short, we output the (unary) magnitude of the second number as many times as there are1
s in the (unary) magnitude of the first number.sumber
Python 3, 11 bytes
Try it online!
Also works for integers under
2**32
in Python 2.sumber
Java 8,
109 bytesTry it here.
Java 7, 31 bytes
Try it here.
As full program (
9990 bytes):Try it here.
sumber
*
instaed of+
.a,b
in the lambda expression.Pyth, 2 bytes
Try it here!
Pyth's automatic evaluation gets in the way here. To get around it, I'm using explicit evaluation for one of the arguments
sumber
TI-Basic, 2 bytes
Very straightforward.
sumber
Ans
is not an allowed I/O method.PHP, 21 bytes
takes input from command line arguments. Also works with floats.
sumber
Retina,
3935 bytesThanks to Leo for letting me use an idea of his that ended up saving 4 bytes.
Input is linefeed-separated.
Try it online! (Space-separated test suite for convenience.)
Explanation
The first two stages print a minus sign if exactly one of the two inputs is negative. They do this without actually changing the input. This is done by grouping them in the second stage with
)
and turning them into a dry-run with*
. The\
option on the second stage prevents printing a trailing linefeed.First, we remove everything except the minus signs.
Then we cancel the minus signs if there are two of them left.
Now we convert each line to the unary representation of its absolute value. This will get rid of the minus sign because
$*
only looks for the first non-negative number in the match (i.e. it doesn't know about minus signs and ignores them).The first line is converted to
_
, by matching individual1
s as long as their adjacent to the previous match (hence, we can't match the1
s on the second line, because the linefeed breaks this chain).This performs the actual multiplication. We replace each
_
(on the first line) as well as the entire second line everything after that match. The_
matches will therefore include the entire second line (multiplying it by the number of0
s in the first line), and the second line will be removed because there is nothing after that match. Of course the result will also include some junk in the form of_
s and linefeeds, but that won't matter.We finish by simply counting the number of
1
s in the result.sumber
MATLAB,
54 bytesdot
takes the dot product of two vectors of equal length. If we feed it with two scalars, it will simply multiply the two numbers.prod
takes the product of the values in all rows of each column of a matrix. If the matrix is one-dimensional (i.e. a vector), then it acts along the non-singleton dimension, taking the product of all elements in the vector.dot
is one byte shorter thanprod
which is one byte shorter than the even more obvious builtintimes
.Call it as such:
sumber
PigeonScript, 1 byte
Explanation:
*
looks to the stack to see if there is anything there. If not, it prompts for input and multiplies the inputs togethersumber
Perl 6, 4 bytes
This is just the ordinary infix multiplication operator
*
, expressed as an ordinary function. As a bonus, if given one number it returns that number, and if given no numbers it returns1
, the multiplicative identity.sumber
*×*
><>, 5 Bytes
Takes input as an ascii character, outputs a number.
Explanation:
You could also do
But I feel my solution is waaay cooler.
Another possibility is dropping the semicolon, which would result in the pointer bouncing off the mirror, hitting the print command, and throwing an error since the stack is empty.
sumber
Intel 8080 machine code, MITS Altair 8800, 28 bytes
This implements binary multiplication on the Intel 8080 CPU (c. 1974) which did not have multiplication or division instructions. Inputs are 8-bit values and the product is a 16-bit value returned in the
BC
register pair.Here is the machine code along with step-by-step instructions to load the program into an Altair 8800 using the front panel switches.
Try it online!
If you've entered it all correctly, on the machine state drawer in the simulator your RAM contents will look like:
Input
Multiplier in
C
register, and multiplicand intoD
. The stock Altair has noSTDIN
so input is by front panel switches only.Output
The result is displayed on the
D7
-D0
lights (top right row) in binary.5 x 16 = 80 (0101 0000)
4 x 5 = 20 (0001 0100)
7 x 9 = 63 (0011 1111)
8 x -9 = -72 (1011 1000)
Compatibility note: this should also run on the IMSAI 8080, though currently untested.
sumber
C#, 10 bytes
It's just a simply multiplication.
sumber
Jelly, 1 byte
Try it online!
Obligatory Jelly submission.
sumber
Clojure, 1 byte
:P As a bonus this works on any number of arguments:
Interestingly you can easily get its source code:
sumber
Owk, 11 bytes
This can be assigned to a function like this:
and called like this:
sumber