- Feature Articles
 - CodeSOD
 - Error'd
 - 
                
                    
Forums
 - 
                Other Articles
                
- Random Article
 - Other Series
 - Alex's Soapbox
 - Announcements
 - Best of…
 - Best of Email
 - Best of the Sidebar
 - Bring Your Own Code
 - Coded Smorgasbord
 - Mandatory Fun Day
 - Off Topic
 - Representative Line
 - News Roundup
 - Editor's Soapbox
 - Software on the Rocks
 - Souvenir Potpourri
 - Sponsor Post
 - Tales from the Interview
 - The Daily WTF: Live
 - Virtudyne
 
 
            
Admin
This is, of course, a one- or two-liner (depending how long you like your lines) in Haskell and probably most other functional languages:
-- Just for neatness; without this, ((`div` 2) *** (* 2)) can be -- written (\(a, b) -> (a `div` 2, b * 2)) import Control.Arrow ((***)) rus n m = sum . map snd . filter ((/= 0) . (`mod` 2) . fst) . takeWhile ((> 0) . fst) $ iterate ((`div` 2) *** (* 2)) (n, m)Or adding some labels for clarity:
rus n m = sum . rightColumn . filter hasOddRight . takeWhile nonZeroLeft $ makeColumns (n, m) where rightColumn = map snd hasOddRight = (/= 0) . (`mod` 2) . fst makeColumns = iterate multiplyAndDivide multiplyAndDivide = ((`div` 2) *** (* 2)) nonZeroLeft = ((> 0) . fst)Admin
oops the last 2 lines are busted (great idea to refactor just before posting :-)
rsum([M, N} | P], S) -> rsum(P, S + case M rem 2 of 0 -> 0; 1 -> N end).Admin
Not the shortest or simplest bit of code, but a pretty elegant way of mirroring the Russian Peasant method, as opposed to looking more like binary multiplication.
Python:
def multiply(a, b): def pairs(): nonlocal a, b while a: yield a, b a //= 2 b *= 2 return sum(j for (i, j) in pairs() if i % 2)Admin
I'm sure this is lost in the haze:
int peasant(int x, int y) { int result = 0; do { result += (x % 2) * y; x /= 2; y *= 2; } while(x > 0); return result; }Didn't bother with bitshifting. Looking at the generated assembly is an interesting excersize.
Admin
I feel daring today and throw this in untested. thx for spoiler alert i did it in a text editor before scrolling down to comment. =)
// russian multiply // the usual limitations on result size apply int ru_mul(int fac0,int fac1) { int prod=0; do { prod+=(fac0&1)*fac1; fac1<<=1; } while (fac0>>=1); return prod; }
Admin
the wtf is of course that my spaces got eaten... =)
Admin
echo "In soviet russia, multiplication does YOU!"
Admin
nah, the real wtf is: ye shouldnae do sucha thing that i did there: late night surfing on coding sites while not sober. speaking of test-driven development, hihi! i inadvertedly coded for unsingeds... take brians solution!
Admin
using Microsoft.VisualStudio.TestTools.UnitTesting; namespace RussianPeasantMultiplication { ///
    /// The biggest WTF, of course, is there are tests!
    ///  
    [TestClass]
    public class Multiply_numbers
    {
        [TestMethod]
        public void Multiply_some_numbers()
        {
            Assert.AreEqual(18*23, WtfPeasantCalculator.Multiply(18, 23));
            Assert.AreEqual(0*1, WtfPeasantCalculator.Multiply(0, 1));
            Assert.AreEqual(1*0, WtfPeasantCalculator.Multiply(1, 0));
            Assert.AreEqual(11*13, WtfPeasantCalculator.Multiply(11, 13));
        }
        [TestMethod]
        public void Multiply_with_cryptic_version()
        {
            Assert.AreEqual(18*23, CrypticPeasantCalculator.Multiply(18, 23));
        }
    }
    /// 
    /// What kind of entry would it be, if the expected code quality wasn't posted?
    ///  
    internal static class CrypticPeasantCalculator
    {
        public static long Multiply(int a, int b)
        {
            return a < 1 ? 0 : (a%2 != 0 ? b : 0) + Multiply(a/2, b*2);
        }
    }
    /// 
    /// Another WTF is to actually try to write readable, understandable code.
    ///  
    internal static class WtfPeasantCalculator
    {
        public static long Multiply(int a, int b)
        {
            if (ThereIsNothingLeftToAccumulate(a)) return 0;
            return ValueToAccumulate(a, b) + FollowingAccumulatedValues(a, b);
        }
        private static bool ThereIsNothingLeftToAccumulate(int a)
        {
            return a < 1;
        }
        private static int ValueToAccumulate(int a, int b)
        {
            return IsOddNumber(a) ? b : 0;
        }
        private static bool IsOddNumber(int number)
        {
            return number%2 != 0;
        }
        private static long FollowingAccumulatedValues(int a, int b)
        {
            return Multiply(a/2, b*2);
        }
    }
}
Admin
def russianpeasants(x, y): print 'Useless waste of time. Any idiot could write this.' def multiply(x, y): if x < 0 and y < 0: x = -x; y = -y elif x < 0 or y < 0: return -multiply(abs(x), abs(y)) if x == 0 or y == 0: return 0 if x == 1 or y == 1: return x+y-1 bits = 0; tempx = x; tempy = y while tempx: tempx >>= 1; bits += 1 while tempy: tempy >>= 1; bits += 1 bits >>= 2 a = x >> bits; b = x & ((1 << bits) - 1) c = y >> bits; d = y & ((1 << bits) - 1) ac = multiply(a, c); bd = multiply(b, d) abcd = multiply(a+b, c+d) return (bd + ((abcd - bd - ac) << bits) + (ac << (bits + bits)))Admin
Got to add AutoIt:
Func _RussianMultiplication( $var1, $var2) Dim $iResult=0, $iLeft = $var1, $iRight = $var2 While Abs($iLeft) >= 1 If StringInStr("13579", StringRight($iLeft, 1)) > 0 Then $iResult+=$iRight $iLeft = Int($iLeft/2) $iRight *= 2 WEnd If $var1 < 0 Then $iResult *= -1 Return $iResult EndFuncAdmin
Short recursive C# technique:
int Russian(int left, int right, int progress){ if(x==0) return progress; return Russian(left/2, right*2, progress+((left%2==1)?right:0)); }Admin
This actually misses adding the first row if the initial lval is odd.
Admin
(sorry, I meant the first sample given)
Admin
Tail-recursive Mathematica implementation:
RussianPeasantTimes[x_Integer, y_Integer] := Sign[x] RussianPeasantTimesImpl[Abs[x], y, 0];
RussianPeasantTimesImpl[x, y, res] := RussianPeasantTimesImpl[Quotient[x, 2], 2 y, res + Mod[x, 2] y]; RussianPeasantTimesImpl[1, y, res_] := res + y; RussianPeasantTimesImpl[0, , res] := res;
Admin
Scheme:
(define peasant (lambda (x y) (letrec ((loop (lambda (ls1 ls2) (if (eq? (car ls1) 1) (apply + (select odd? ls1 ls2)) (loop (cons (quotient (car ls1) 2) ls1) (cons (* 2 (car ls2)) ls2)))))) (loop (list x) (list y)))))
Admin
I salute you sir!
Admin
I found a neat little trick to it. See if you can figure out what I did ;-) :
uint32_t multiply(uint32_t a, uint32_t b) { uint64_t ab = 0; uint32_t r = 9; while (--r) { ab <<= 4; ab |= ((0xf7b3d591e6a2c480ULL>>((a&0xF)<<2)) & 0xF); a >>= 4; } ab <<= 32; ab |= b; while (ab >> 32) { if (ab >> 63) r += ab; ab <<= 1; ab &= 0xFFFFFFFEFFFFFFFFULL; } return r; }I stress tested this (with 100 million random trials against the * operator) on an x86 and a PPC machine, so it works, trust me.
Admin
You spent more than 5 minutes on a 3 minute problem. Congratulations.
Admin
Here's a version in C that multiplies two 8-bit numbers and produces a 16-bit result. It requires a 64-bit unsigned type. I know it doesn't look much like the original algorithm but that's because it treats the 64-bit variables as an array of 8-bit values that can be operated on in parallel.
unsigned int mult(unsigned char a, unsigned char b) { uint64_t x, y; x = a; y = b; x |= x << 7; y |= y << 8; x |= x << 14; y |= y << 16; x |= x << 28; y |= y << 32; x &= 0x0101010101010101ULL; x = (0x8080808080808080ULL - x) ^ 0x8080808080808080ULL; x &= y; x = (x & 0x00FF00FF00FF00FFULL) + ((x & 0xFF00FF00FF00FF00ULL) >> 7); x = (x & 0x0000FFFF0000FFFFULL) + ((x & 0xFFFF0000FFFF0000ULL) >> 14); x = (x & 0x00000000FFFFFFFFULL) + ((x & 0xFFFFFFFF00000000ULL) >> 28); return (unsigned int)x; }Admin
C code. FACTOR can be changed to another integer > 1 without breaking the code.
#define FACTOR 2 unsigned int ruski_mul(unsigned int a, unsigned int b) { unsigned int result = 0; while (a >= 1) { result += (a % FACTOR) * b; a /= FACTOR; b *= FACTOR; } return result; }Admin
Here my implementation i JavaScript (yeah, I know, not a programming language :D )
Ok, the WTF is also that it doesn't work in IE, and looks funny in Opera. And that it's a bit long, not because of the calculation, but because of the whizbang :)
<script language="JavaScript"> function PeasantMultiply() { var one = Math.round(document.getElementById("first_value").value * 1); var two = Math.round(document.getElementById("second_value").value * 1); var mytable = document.getElementById("my_table"); var columns = 1; var rows = 1; var newRow = null; var newCell = null; var rowIndices = new Array(); var addValues = new Array(); if (one < 1 || two < 1) { alert ("Russian Peasants only knew how to multiply positive integer numbers!"); return false; } mytable.innerHTML = ""; newRow = document.createElement("tr"); newCell = document.createElement("td"); newCell.innerHTML = one + " * " + two; newRow.appendChild(newCell); mytable.appendChild(newRow); if (one % 2) { rowIndices.push(true); addValues.push(two); } else { rowIndices.push(false); addValues.push(0); } while (true) { one >>= 1; if (one <= 0) break; two *= 2; if (one % 2) { rowIndices.push(true); addValues.push(two); } else { rowIndices.push(false); addValues.push(0); } newCell = document.createElement("td"); newCell.innerHTML = one + "" + two + ""; newRow = document.createElement("tr"); for (r=null, i=0; i < mytable.getElementsByTagName("tr").length; i++) { r = mytable.getElementsByTagName("tr")[i]; //window.alert(r.innerHTML); r.appendChild(r.lastChild.cloneNode(true)); } for (var i=0; i < columns; i++) { newRow.appendChild(document.createElement("td")); } //window.alert("hello world 3"); newRow.appendChild(newCell); //window.alert("almost done!"); mytable.appendChild(newRow); columns++; rows++; } var first = true; for (r=null, i=0; i < mytable.getElementsByTagName("tr").length; i++) { r = mytable.getElementsByTagName("tr")[i]; newCell = r.lastChild.cloneNode(true); if (!(rowIndices[i])) newCell.innerHTML = "" + newCell.innerHTML + ""; r.appendChild(newCell); newCell = document.createElement("td"); if (rowIndices[i]) { newCell.innerHTML = addValues[i]; if (!first) newCell.innerHTML = "+ " + newCell.innerHTML; newCell.innerHTML = "" + newCell.innerHTML + ""; first = false; } else newCell.innerHTML = " "; r.appendChild(newCell); } newCell = document.createElement("td"); newCell.setAttribute( "rowspan", rows); newCell.setAttribute("style", "vertical-align:middle; padding-left:5px; padding-right: 5px;"); newCell.innerHTML = "="; mytable.firstChild.appendChild(newCell); newCell = document.createElement("td"); newCell.setAttribute( "rowspan", rows); newCell.setAttribute("style", "vertical-align:middle; padding-left:5px; padding-right: 5px;"); newCell.innerHTML = eval(addValues.join(" + ")); mytable.firstChild.appendChild(newCell); return false; } </script> <style type="text/css"> td { border: 1px solid black; padding: 2px; } </style> <form> Multiply: <input type="text" id="first_value" /> By: <input type="text" id="second_value" /> <input type="button" value="using russian peasant multiplication" onClick="javascript:PeasantMultiply(); return false;" /> </form>Admin
Bash: abusing the arithmetic evaluation to fit the bulk of the algorithm on one line. (Everything except the line starting with echo is to handle the first argument being negative.)
#! /bin/bash if [ $1 -lt 0 ]; then $0 $(( $1 * -1 )) $(( $2 * -1 )) else echo $(( $([ $(($1 & 1)) -eq 1 ] && echo $2 +) $(if [ $1 -gt 1 ]; then $0 $(($1 >> 1)) $(($2 << 1)); else echo 0; fi) )) fiRemove the outermost arithmetic brackets on the second last line to see the working.
(Note that this doesn't work unless it's in an actual script file and called as such)
Admin
Couldn't see if this had been done - but anyway how about some F#.
let rec multiply x y = match x with | 0 -> 0 | 1 -> y | -1 -> -y | x when x % 2 = 0 -> multiply (x / 2) (y * 2) | x when x > 0 -> y + multiply (x / 2) (y * 2) | x when x < 0 -> -y + multiply (x / 2) (y * 2);Admin
If you've got a copy of Excel you can always do it this way, and lets face if, if you've got Excel why wouldn't you?
Sub WhyOhWhy() Dim iRowNo As Integer Dim sValue As String
End Sub
Admin
In Newlisp. I came up with & on my own but after reading Tim's version, I used >> and <<. Mine's tested.
; odd? (= (& col1 1) 1) instead of (= (% col1 2) 0) ; half! (>> col1 1) instead of (/ col1 2) ; double! (<< col2 1) instead of (* col2 2) ; because %, / and * are expensive
(define (rus col1 col2) (let ((t 0)) (do-until (< col1 1) (if (= (& col1 1) 1) (setq t (+ col2 t))) (println col1 " x " col2) (set 'col1 (>> col1 1) 'col2 (<< col2 1))) (println t)))
Admin
;; Scheme using the design recipe and optimized for lowest number of iterations
(define (russian-multiply m n) (define (russian-multiply* x y p) (if (zero? x) p (russian-multiply* (quotient x 2) (+ y y) (if (odd? x) (+ p y) p)))) (if (< m n) (russian-multiply* m n 0) (russian-multiply* n m 0)))
Admin
these are all in python
the first is the most verbose:
The next one is less verbose, but still easy to follow:
Personally, I like this one for it's complete incomprehensibility (and that it says "lambda f,a,b:a", which makes me laugh):
agrif - 71aaeb8b415a620bf185b6093ebaf5c5
Admin
No branches in the innerloop. Should run pretty fast.
C-version:
int russianMul(int a, int b) { int s = 0; while(a > 1) { b <<= 1; a >>= 1; s += b & -(a & 1); } return s; }x86 Assembly version, as compiled by MSVC
Admin
Oops, I probably should have logged in. :)
Something to add - my version doesn't need the actual CPU's multiply or divide instructions, making it feasible to implement on some processor that doesn't have that. Also, in its current incarnation, it depends on 2's Complement numbers being used.
Admin
int mult(int a, int b) { return a*b; } /because that's how computers do it in hardware, anyway./
Admin
The question is, why would I want to?
Admin
Ok, so how do I run that? I tried the "Brainfuck Interpreter" (http://koti.mbnet.fi/villes/php/bf.php), but I couldn't get any meaningful result. How do I set the input?
Otherwise: Coolest solution so far -- imho.
Admin
Can we please end the off-topic rants about Russian peasant multiplication and get back to our juicy jewelry discussion?
Admin
Common Lisp:
This time it does the expected thing when the first number is negative instead of looping forever :)
(defun rpm4 (m n &optional (acc 0)) (do ((aux (abs m) (ash aux -1))) ((= aux 0) (if (< m 0) (- 0 acc) acc)) (incf acc (if (oddp aux) n 0)) (incf n n)))Admin
Common Lisp:
(defun rpm4 (m n) (do ((t1 (abs m) (ash t1 -1)) (t2 n (ash t2 1)) (acc 0 (+ acc (if (oddp t1) t2 0)))) ((= t1 0) (if (< m 0) (- 0 acc) acc))))Admin
This feels a little "me too" at this point but I've tried to follow all the "rules".
Here's PHP that accounts for negative numbers, doesn't use * or /, accounts for 0 in either position and generates nifty colored output.
<?php function Russian($a,$b) { echo "\n<tr bgcolor='".($a&1?"green":"red")."'>".$a."".$b.""; if(!$a || !$b) { return 0; } if($a < 0) { $a = ($a^-1)+1; $b = ($b^-1)+1; } return (($a <= 1)?($a?$b:0):((intval($a&1)?$b:0)+Russian(intval($a>>1),$b<<1))); } ?><html> <head><title>Russian Peasant</title></head> <body> <form method="get">Admin
Another using Oracle PL/SQL
Admin
#include <iostream>
template<int I> struct is_odd { enum { value = I % 2 }; };
template<int A, int B, int Odd> struct russian_impl;
template<int A, int B> struct russian_impl<A, B, 1> { enum { value = B + russian_impl<A/2, B*2, is_odd<A/2>::value>::value }; };
template<int A, int B> struct russian_impl<A, B, 0> { enum { value = russian_impl<A/2, B*2, is_odd<A/2>::value>::value }; };
template<int B> struct russian_impl<1, B, 1> { enum { value = B }; };
template<int A, int B> struct russian { enum { value = russian_impl<A, B, is_odd::value>::value }; };
int main(int argc, char* argv[]) { std::cout << russian<18, 23>::value << std::endl; return EXIT_SUCCESS; }
Admin
In VBA
Function RussianPeasantMultiplication() Dim a As Integer, b As Integer, c As Integer a = 18 b = 23 Debug.Print a & " x " & b Do Until a = 1 a = Int(a / 2) b = b * 2 If a / 2 <> Int(a / 2) Then c = c + b Debug.Print a & vbTab & b & vbTab & b Else Debug.Print a & vbTab & b End If Loop Debug.Print vbTab & vbTab & c End Function
Admin
CREATE FUNCTION Peasant_Mul (@A INT, @B INT) RETURNS INT AS BEGIN DECLARE @Result INT; WITH f AS ( SELECT @A A, @B B UNION ALL SELECT A / 2, B * 2 FROM f WHERE A > 1 ) SELECT @Result = SUM(B) FROM f WHERE A % 2 = 1;
RETURN @Result; END GO
Admin
Here is my solution in Java. It supports really big numbers and does pretty much what you do in Russian peasant multiplication.
Admin
In Perl:
print "Enter sum in form "a x b":\n";$=<>; s!(\n|^)(\d+) x (\d+)\n$!"$1$2 x $3\n".int(($2)/2)." x ".($3 * 2)."\n"!e while!/^1 x \d+$/m; s!(\n|^)(\d*[24680]) x (\d+)!$1-($2 x $3)-!g; $v+=$2 while/(\n|^)\d+ x (\d+)/g;$.="\nTotal: $v\n"; print "Paper working is:\n$_";
Admin
Repost now I've worked out how to create an account...
In Perl:
print "Enter sum in form "a x b":\n";$=<>; s!(\n|^)(\d+) x (\d+)\n$!"$1$2 x $3\n".int(($2)/2)." x ".($3 * 2)."\n"!e while!/^1 x \d+$/m; s!(\n|^)(\d*[24680]) x (\d+)!$1-($2 x $3)-!g; $v+=$2 while/(\n|^)\d+ x (\d+)/g;$.="\nTotal: $v\n"; print "Paper working is:\n$_";
Admin
private int RussianMultiply(int input1, int input2) { int retVal = 0; do { retVal += (input1 & 1) * input2;
Admin
10 PRINT "HELLO, WELCOME TO THE RUSSIAN (FORMERLY ROMAN) PEASANT MULTIPLICATION" 20 INPUT "PLEASE, ENTER THE TWO OPERANDS: "; A, B 30 SIGN = 1 40 PRINT "IS "; A; " NEGATIVE? (Y/N)" 50 INPUT ANSWER 60 IF ANSWER = "Y" THEN SIGN = -1 70 PRINT "IS "; B; " NEGATIVE? (Y/N)" 80 INPUT ANSWER 90 IF ANSWER = "Y" THEN SIGN = SIGN * -1 100 PRINT A; " EQUALS 0? (Y/N)" 110 INPUT ANSWER 120 IF ANSWER = "Y" THEN PRINT "THE PRODUCT IS 0": END 130 PRINT B; " EQUALS 0? (Y/N)" 140 INPUT ANSWER 150 IF ANSWER = "Y" THEN PRINT "THE PRODUCT IS 0": END 160 PRINT A; " EQUALS 1? (Y/N)" 170 INPUT ANSWER 180 IF ANSWER = "Y" THEN PRINT "THE PRODUCT IS "; B: END 190 PRINT B; " EQUALS 1? (Y/N)" 200 INPUT ANSWER 210 IF ANSWER = "Y" THEN PRINT "THE PRODUCT IS "; A: END 220 INDEX = 1 230 PRINT "IS "; A; " EVEN? (Y/N)" 240 INPUT ANSWER 240 IF ANSWER = "Y" THEN PRINT "USEFUL VALUE "; INDEX; " -> "; B: INDEX = INDEX+1 250 PRINT "PLEASE, DIVIDE "; A; " BY 2 (GIVE ME THE SMALLEST PART):" 260 INPUT A 270 PRINT "PLEASE, DOUBLE "; B 280 INPUT B 290 PRINT A; " EQUALS 1? (Y/N)" 300 INPUT ANSWER 310 IF ANSWER = "Y" THEN PRINT "USEFUL VALUE "; INDEX; " -> "; B: GOTO 330 320 GOTO 250 330 PRINT "PLEASE, GIVE ME THE USEFUL VALUE 1, FROM ABOVE:" 340 INPUT A 350 AINDEX = 1 360 FOR I=2 TO INDEX 370 PRINT "PARTIAL RESULT "; AINDEX; " -> "; A 380 PRINT "PLEASE, SUM USEFUL ANSWER "; I; " WITH PARTIAL RESULT ": AINDEX 390 INPUT A 400 AINDEX = AINDEX + 1 410 NEXT 420 PRINT "THE PRODUCT IS "; A 430 END
Admin
whoops...
420 PRINT "THE PRODUCT IS "; A * SIGN
There, fixed.
CYA
Admin
Oracle SQL version, showing the working out:
with my_data as (select :p1 col1, :p2 col2 from dual), list_gen as (select level -1 lvl from my_data connect by power(2,level-1) <= col1), results as (select lvl, floor(col1/power(2,lvl)) col3, col2*power(2, lvl) col4 from my_data, list_gen) select col3, col4, decode(floor(col3/2)*2, col3, null, sum(case when floor(col3/2)*2 != col3 then col4 end) over (order by lvl)) sum_col from results order by lvlAdmin
multiply: XOR EAX, EAX XOR EDX, EDX CMP ECX, EAX JNL .ps NEG ECX NEG EBX .ps: XOR EDI, EDI CMP EBX, EAX SBB EBP, EBP SHR ECX, 1 JZ .nd .lp: SBB ESI, ESI MOV EDI, ESI AND ESI, EBX AND EDI, EBP ADD EBX, EBX ADC EBP, EBP ADD EAX, ESI ADC EDX, EDI SHR ECX, 1 JNZ .lp .nd: SBB ESI, ESI MOV EDI, ESI AND ESI, EBX AND EDI, EBP ADD EAX, ESI ADC EDX, EDI ; done ; ... or just use IMUL
Admin
And of course in Haskell:
multiply n m = sum $ map snd $ filter (odd . fst) $ russian n m where russian 1 m = [(1,m)] russian n m = (n,m) : russian (n
div2) (m * 2)