Russian Peasant Multiplication

« Return to Article
  • Alex Papadimoulis 2009-07-22 02:27
    This is my quick hack using VBScript.

    I don't feel it fully implements the algorithm (no "maintaining two columns"), or is as efficient as it could be.... but, it's a start of what your code should NOT end up like...

    Function Mult( a, b )
    While a > 1
    a = a \ 2 ' Surprise: "\" is Int division!
    b = b * 2
    If a Mod 2 = 1 Then Mult = Mult + b
    Wend
    End Function
  • Tim 2009-07-22 08:20

    int Multiply(int a, int b)
    {
    int c = 0;
    do
    {
    if (a & 1)
    c += b;
    a >>= 1;
    b <<= 1;
    } while (a > 0);
    return c;
    }


    Untested, might not work for negative numbers.
  • Tim 2009-07-22 08:22
    Actually not sure why I did do..while instead of just while... Oh well.
  • Cookie 2009-07-22 08:22
    Cheeky Java solution..

    private int multiple(int a, int b) {

    int rtn = 0;
    while (a > 0) {

    if (a % 2 != 0) {
    rtn += b;
    }

    a = a / 2;
    b = b * 2;
    }

    return rtn;
    }

    :-)
    http://www.supercookie.co.uk
  • Jay 2009-07-22 08:23
    public static int multiply(int first, int second){
    if(first == 1){
    return second;
    }

    int result = 0;

    if(first%2 != 0){
    result += second;
    }
    result += multiply(first/2, second * 2);
    return result;
    }
  • The Wolf 2009-07-22 08:24
    And in PHP:

    <?php
    

    function russian($x, $y) {
    $left = array();
    $right = array();

    while ($x > 1) {
    $left[] = $x;
    $right[] = $y;

    $x = floor($x / 2);
    $y *= 2;
    }

    $left[] = $x;
    $right[] = $y;
    $result = 0;

    foreach ($left as $index => $x) if ($x % 2) {
    $result += $right[$index];
    }

    return $result;
    }

    echo russian(41238, 193625);

    ?>
  • The Dopefish 2009-07-22 08:25
    A recursive C# solution:

    static int Multiply(int a, int b)
    {
    if (a < 2)
    return (a == 1 ? b : 0);
    if (a % 2 == 1)
    return b + Multiply(a / 2, b * 2);
    return Multiply(a / 2, b * 2);
    }
  • ath 2009-07-22 08:26
    Same thing in python:

    def is_odd(n):
    return (n % 2) != 0

    def rmul(x, y):
    s = 0
    while(x != 1):
    if is_odd(x):
    s += y
    x /= 2
    y *= 2
    return y + s

  • snoofle 2009-07-22 08:26
    Waiting for a solution in brainfuck...
  • mat 2009-07-22 08:26
    This is my implementation of the algorithm using standard *nix bash script (with the addition of awk):

    #!/bin/bash

    X="$1"
    Y="$2"

    if [ $X -lt 0 ]
    then
    SIGN=-1
    X=$(( X * -1 ))
    else
    SIGN=1
    fi

    LEFT="$X"
    RIGHT="$Y"

    while [ "$X" -ne 1 ]
    do
    X=$(( X / 2 ))
    Y=$(( Y * 2 ))
    LEFT="$LEFT $X"
    RIGHT="$RIGHT $Y"
    done

    L=`echo $LEFT | wc -w`
    RESULT=0
    for I in `seq 1 $L`
    do
    X=`echo $LEFT | awk "{print $"$I"}"`
    Y=`echo $RIGHT | awk "{print $"$I"}"`
    if [ $(( X % 2 )) -ne 0 ]
    then
    RESULT=$(( RESULT + Y ))
    fi
    done

    RESULT=$(( RESULT * SIGN ))

    echo "$1 x $2 = $RESULT"
  • hydrus 2009-07-22 08:34
    Obligatory Clojure entry:


    (defn rmult
    ([x y] (rmult x y 0))
    ([x y p]
    (if (= x 1)
    (+ y p)
    (recur (quot x 2) (* y 2) (if (odd? x) (+ p y) p)))))
  • Dascandy 2009-07-22 08:37
    X86:

    ; assumption: eax contains arg1, ebx contains arg2
    mov edx, eax
    next:
    shr ebx, 1
    cmovc ecx, edx
    cmovnc ecx, 0
    jz end
    lea eax, [eax*2 + ecx]
    jmp next

    end:
    ret


    ARM:

    mov r2, r0
    next test r1, 1
    mov r1, #0, r1 shr 1
    addc r0, r0, r2
    movz pc, lr
    add r0, r0, r0
    b next



    Both approximated. Appreciate comments.
  • ParkinT 2009-07-22 08:39
    Wow!
    I had not time to submit a solution.
    Everyone was too busy Russian to provide an answer!
  • SQLDork 2009-07-22 08:39
    And a SQL implementation...

    create function wtf.RussianMultiply(@m1 bigint, @m2 bigint)
    returns bigint
    as
    begin
    declare @out bigint
    set @out =0
    while @m1 > 1
    select @m1 = @m1 / 2,
    @m2 = @m2 * 2,
    @out = @out + case when @m1 & 1 = 1 then @m2 else 0 end
    return(@out)
    end
    go
  • Z 2009-07-22 08:40
    function ruM (left, right) {
    var route = '', remainder = 0;
    while (left>1) {
    if (left % 2 != 0) {
    remainder += right;
    left -= 1;
    //route += 'remainder: ' + remainder + '\n';
    }
    left /= 2;
    right *= 2;
    //route += left + 'x' + right + '\n';
    }
    return right + remainder;
    }
  • Erin 2009-07-22 08:40
    A simpler PHP version:

    <?php

    function in_mother_russia($x, $y)
    {
    $z = 0;

    while ($x)
    {
    if ($x % 2) $z += $y;

    $x = floor($x / 2);
    $y *= 2;
    }

    return $z;
    }

    echo 'In mother Russia, 18 x 23 = '.in_mother_russia(18, 23);
  • Larry H. 2009-07-22 08:41

    unsigned russian(unsigned a, unsigned b)
    {
    return ((a & 1) ? b : 0) + ((a & ~1) ? russian(a>>1, b<<1) : 0);
    }


    Not tested.
  • The Wolf 2009-07-22 08:41
    Not sure why I used that array bullcrap, too used to string manipulation I guess. Here's a better version for PHP:

    <?php
    

    function russian($x, $y) {
    $result = 0;

    while ($x > 1) {
    if ($x % 2) $result += $y;

    $x = floor($x / 2);
    $y *= 2;
    }

    return $y + $result;
    }

    echo russian(41238, 193625);

    ?>
  • dv 2009-07-22 08:41
    using ABAP (only a bit esoteric:-))


    FORM multiply USING a TYPE I
    b TYPE I
    CHANGING c TYPE I.
    CLEAR c.
    WHILE a GT 0.
    IF ( a MOD 2 EQ 1 ).
    ADD b TO c.
    ENDIF.
    DIVIDE a BY 2.
    MULTIPLY b BY 2.
    ENDWHILE.
    ENDFORM.
  • Paula 2009-07-22 08:42
    public class Paula extends WTF {
    public static string Paulabean = "brillant!";
    }
  • Mat Rantell 2009-07-22 08:42
    A short recursive Java version:

    public static long multiply( long left, long right ) {
    return ( ( left % 2 ) == 0 ? 0 : right
    + ( left == 1 ? 0 : multiply( left / 2, right * 2 ) );
    }
  • Kees 2009-07-22 08:43
    Function Diederick ( Jan, Piet )
    While Jan > 1
    Jan = Jan \ 2
    Piet = Piet * 2
    If Jan Mod 2 = 1 Then Diederick = Diederick + Piet
    Wend
    End Function
  • Bosshog 2009-07-22 08:44

    ; 6502 Assembler (4-bit operands only)
    ; $0001 should contain operand 1 (not preserved)
    ; $0002 should contain operand 2 (not preserved)

    LDA #0
    LDX #0
    loop:
    CPX $02
    BEQ done
    CLC
    LSR $02
    BCC skip
    CLC
    ADC $01
    skip:
    ASL $01
    JMP loop

    done:
    STA $00
  • ath 2009-07-22 08:48
    Another Python version. This time it handles zero and negative numbers properly... Floats works as second arg but not as first. Seems like too much work to fix it though...


    def is_odd(n):
    return (n % 2) != 0

    def rmul(x, y):
    if(x < 0):
    sgn = -1
    x = -x
    else:
    sgn = 1

    s = 0
    while(x >= 1):
    if is_odd(x):
    s += y
    x /= 2
    y *= 2
    return sgn*s
  • Me 2009-07-22 08:49
    Bah to all your bloaty solutions. Perlmongers do it in one line :P

    sub m(){my($a,$b)=@_;my $t;while($a){$t+=$b if ($a&1);$a>>=1;$b<<=1;}return $t;}
  • Anonymous 2009-07-22 08:49
    Win!
  • Bombe 2009-07-22 08:51
    In Soviet Russia, peasants multiply you.
  • phihag 2009-07-22 08:53
    Various iterative solutions in python:


    # python3 only, one-liner!
    def mul3(a,b):
    return sum(b << i if (a>>i)&1 else 0 for i in range(a.bit_length()))

    def bits(value):
    while value > 0:
    yield value & 1
    value = value // 2

    def mul1(a,b):
    res = 0
    for a in bits(a):
    if a:
    res += b
    b *= 2

    return res

    def mul2(a,b):
    return sum(b << i if abit else 0 for i,abit in enumerate(bits(a)))

    try:
    mul = mul3
    except AttributeError:
    mul = mul2
  • Brettm 2009-07-22 08:54
    Ta for the teaser, well back to my reports :(


    static void Main(string[] args)
    {
    Console.WriteLine(RM(18, 23, 0));
    Console.ReadLine();
    }

    public static int RM(int val1, int val2, int rem)
    {
    int mod = val1 % 2;
    int _rem = (mod * val2) + rem;
    int _v1 = val1 / 2;
    int _v2 = val2 * 2;
    if (val1 != 1)
    {
    return RM(_v1, _v2, _rem);
    }
    return _v1 + _rem;
    }


    Addendum (2009-07-22 09:01):
    Condensed version:

    public static int RM(int val1, int val2, int rem)
    {
    if (val1 != 1)
    {
    return RM((val1 / 2), val2 * 2, ((val1 % 2) * val2) + rem);
    }
    return (val1 / 2) + ((val1 % 2) * val2) + rem;
    }
  • Stefan 2009-07-22 08:55
    simple c with a little optimization

    unsigned int mul(unsigned int x, unsigned int y)
    {
    unsigned int r = 0;
    unsigned int t;
    if (y > x)
    {
    t = y;
    y = x;
    x = t;
    }
    while(x)
    {
    if (x & 1)
    r += y;
    x >>= 1;
    y <<= 1;
    }
    return r;
    }
  • Takis 2009-07-22 08:55
    VB.Net


    Private Function Russiply(ByVal a As Long, ByVal b As Long) As Long

    Do
    If (a And 1) = 1 Then Russiply += b
    a = a >> 1
    b = b << 1
    Loop Until a <= 1

    If (a And 1) = 1 Then Russiply += b

    End Function
  • Zombywuf 2009-07-22 08:56

    template<int x, int y, int accum, int mutliple>
    struct multiply_ {
    static const int value = multiply_<x / 2, y * 2, accum, (x / 2) & 1>::value;
    };

    template<int x, int y, int accum>
    struct multiply_<x, y, accum, 1> {
    static const int value = multiply_<x / 2, y * 2, accum + y, (x / 2) & 1>::value;
    };

    template<int y, int accum>
    struct multiply_<0, y, accum, 0> {
    static const int value = accum;
    };

    template<int x, int y>
    struct multiply : multiply_<x, y, 0, x & 1> {};
  • KnowOracle 2009-07-22 08:57
    Oracle SQL version:


    14:55:42 SQL> set echo on
    SQL> @russian_mult 18 23
    SQL> select sum(b)
    2 from (select floor(a / power(2, rn)) as a,
    3 b * power(2, rn) as b
    4 from (select &1 as a,
    5 &2 as b,
    6 rownum as rn
    7 from dual
    8 connect by level < log(2, 18)))
    9 where mod(a, 2) <> 0
    10 /
    old 4: from (select &1 as a,
    new 4: from (select 18 as a,
    old 5: &2 as b,
    new 5: 23 as b,

    SUM(B)
    ----------
    414

    1 row selected.
  • Captain Obvious 2009-07-22 08:59
    I haven't done APL in a LONG time...

         Z <- A RUSSIAN B
    
    [1] Z <- 0
    [2] TOP:
    [3] Z <- Z + A * 0 = 2 | B
    [4] A <- |_ A (divide) 2
    [5] B <- B x 2
    [6] -> (A>0) / TOP
  • phihag 2009-07-22 08:59
    An addition to my solution (see above): The python3 version is not only one line, but only one statement! Is there any other language where you can implement it in one statement without recursion?
  • freakpants 2009-07-22 08:59
    seems like you killed esolangs :D
  • SR 2009-07-22 09:00
    Bah. Looks like we've bost the esolangs.org server.

    esolangs.org:
    Esolang has a problem

    Sorry! This site is experiencing technical difficulties.

    Try waiting a few minutes and reloading.

    (Can't contact the database server: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (61) (localhost))


    Anyone know if ColdFusion was on there? ;o)
  • KnowOracle 2009-07-22 09:00
    log(2, 18) should read log (1, &1)
  • Fenris 2009-07-22 09:01
    Handle Negs
    >>> def mult(a,b):
    ... neg = (a < 0)
    ... if neg:
    ... a *= -1
    ... res = 0
    ... while a >= 1:
    ... if a % 2 != 0:
    ... res += b
    ... a /= 2
    ... b *= 2
    ... if neg:
    ... return res * -1
    ... else:
    ... return res
    ...
  • KnowOracle 2009-07-22 09:01
    Correct Oracle SQL


    select sum(b)
    from (select floor(a / power(2, rn)) as a,
    b * power(2, rn) as b
    from (select &1 as a,
    &2 as b,
    rownum as rn
    from dual
    connect by level < log(2, &1)))
    where mod(a, 2) <> 0
    /
  • arnemart 2009-07-22 09:04
    Here's a recursive version in Ruby:

    class Integer
    
    def russianmultiply num
    return num if self == 1
    return num + (self/2).russianmultiply(num*2) if self%2 == 1
    (self/2).russianmultiply(num*2)
    end
    end

    puts 18.russianmultiply(23)
  • Herman 2009-07-22 09:05
    As this is the exact implementation of the multiply function on binary computing hardware, a simple

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

    should do for most platforms :)
  • Matthew Verleger 2009-07-22 09:05
    int RussianSum( int A, int B ){
    return A ? RussianSum(A>>2,B<<2) + (!!(A&1))*(B): 0;
    }
  • ruckc 2009-07-22 09:05
    Without reading the comments.


    public static int russianMultiplication(int left, int right) {
    int result = 0;

    while(left > 1) {
    result += left%2==1?right:0;

    left /= 2;
    right *= 2;
    }
    return result + right;
    }
  • Mike Dotterer 2009-07-22 09:05
    A ruby version:

    def russian_peasant_multiply(numerator, denomenator)
    table = [[numerator, denomenator]]
    while table.last[0] != 1
    (n, d) = table.last
    table << [n / 2, d * 2]
    end
    table.reject { |r| r[0] % 2 != 1 }.
    inject(0) { |sum, r| sum + r[1]}
    end
  • gosse 2009-07-22 09:06
    // todo: implement russian algorithm
    #define multiply(a, b) ((a)*(b))
  • Will 2009-07-22 09:06
    Java

    public int mult(int a, int b){
    return (b*(a%2)) + (a==1?0:mult(a/2,b*2));
    }
  • darkwraith 2009-07-22 09:07
    My solutions with unit testing goodness:

    #include <iostream>

    using namespace std;

    void assert_equals(unsigned long a, unsigned long b)
    {
    if (a != b)
    {
    cerr << a << " != " << b << endl;
    exit(1);
    }
    }

    unsigned long russianMult(unsigned a, unsigned b)
    {
    unsigned long ret = 0;
    while (a > 0)
    {
    if (a % 2)
    ret += b;
    a >>= 1;
    b <<= 1;
    }
    return ret;
    }

    int main()
    {
    assert_equals(414, russianMult(18, 23));
    assert_equals(0, russianMult(0, 2));
    assert_equals(0, russianMult(2, 0));

    return 0;
    }
  • mverleg1 2009-07-22 09:08
    Matthew Verleger:
    int RussianSum( int A, int B ){
    return A ? RussianSum(A>>2,B<<2) + (!!(A&1))*(B): 0;
    }


    Whoops... Shoulda logged in first. :)
  • Dan 2009-07-22 09:09
    Non-recursive C#:

    public int PeasantMul(int i, int j)
    {
    int accum = 0;

    while (i != 0)
    {
    accum += (i / Math.Abs(i)) * ((0 - (i & 1)) & j);
    i /= 2;
    j *= 2;
    }

    return accum;
    }
  • AdamK 2009-07-22 09:11
    Nice one for a golf challenge.
  • Chris Hunt 2009-07-22 09:11
    Recursive approach using ORACLE PL/SQL:


    CREATE OR REPLACE FUNCTION russian_mult (pleft IN NUMBER,
    pright IN NUMBER)
    RETURN NUMBER IS
    newleft NUMBER;
    BEGIN
    -- Sanity checking: pleft has to be an integer
    IF pleft != TRUNC(pleft) THEN
    RAISE VALUE_ERROR;
    END IF;

    newleft := TRUNC(pleft/2);

    -- tests for 0 and negative numbers added for completeness
    IF pleft < 0 THEN
    RETURN - russian_mult(-pleft,pright);
    ELSIF pleft = 0 THEN
    RETURN 0;
    -- the main bit starts here!
    ELSIF pleft = 1 THEN
    RETURN pright;
    ELSIF pleft/2 = newleft THEN -- even number
    RETURN russian_mult(newleft,pright*2);
    ELSE -- odd number
    RETURN russian_mult(newleft,pright*2) + pright;
    END IF;
    END;
    /
    SQL> SELECT russian_mult(18,23) FROM dual

    RUSSIAN_MULT(18,23)
    -------------------
    414
  • Azeroth 2009-07-22 09:11
    You and your prmature optimizations! I made my code follow the instructions (in Pascal implementation of SCAR)


    program PhilBewig;

    type
    TNumberLine = record
    LeftColumn: Integer;
    RightColumn: Integer;
    CrossedOut: Boolean;
    end;

    TNumberLineSheet = array of TNumberLine;

    function MultiplyNumbers(a, b: Integer): Integer;
    var
    Sheet: TNumberLineSheet;
    i: Integer;
    begin
    //They start by writing the two numbers to be multiplied at the head of two columns
    i:= 0;
    SetArrayLength(Sheet, i + 1);
    Sheet[i].CrossedOut:= False;
    Sheet[i].LeftColumn:= a;
    Sheet[i].RightColumn:= b;

    //Then they repeatedly .. until the number in the left column is one
    while(Sheet[i].LeftColumn > 1)do
    begin
    //writing the two new numbers immediately below their predecessors
    i:= i + 1;
    SetArrayLength(Sheet, i + 1);
    Sheet[i].CrossedOut:= False;
    //divide the number in the left column by two (dropping any remainder)
    Sheet[i].LeftColumn:= Sheet[i - 1].LeftColumn div 2;
    //double the number in the right column
    Sheet[i].RightColumn:= Sheet[i - 1].RightColumn * 2;
    end;

    //Then they cross out all rows where the number in the left column is even
    for i:= 0 to GetArrayLength(Sheet) - 1 do
    begin
    if(Sheet[i].LeftColumn mod 2 = 0)then
    Sheet[i].CrossedOut:= True;
    end;

    //and add the remaining numbers in the right column, which is the desired product
    Result:= 0;
    for i:= 0 to GetArrayLength(Sheet) - 1 do
    begin
    if(not Sheet[i].CrossedOut)then
    Result:= Result + Sheet[i].RightColumn;
    end;
    end;

    begin
    Writeln(IntToStr(MultiplyNumbers(18, 23)));
    end.
  • freako 2009-07-22 09:11
    What, no Haskell? Oh you sorry bunch of infidels...

    mlt :: Int -> Int -> Int
    mlt 1 y = y
    mlt x y = (if x `mod` 2 == 0 then 0 else y) + mlt (x `div` 2) (y * 2)
  • Dave Ingram 2009-07-22 09:13
    Haskell:

    peasant :: Int -> Int -> Int
    
    peasant x y = sum (map (\(_, z) -> z) (filter (\(x, _) -> mod x 2 == 1) (peasantnums x y)))
    where peasantnums 1 b = [ (1, b) ]
    peasantnums a b = (a, b) : peasantnums (div a 2) (b*2)
  • Bonce 2009-07-22 09:13
    A few people have missed a bug in their code when the first value equals 1.
  • Russian Peasant 2009-07-22 09:13
    Bah. Looks like me hearing of this method for the first time. In Soviet Russia we just multiply it by electronic calculators. Or by abacus. Or by slide rule. Whatever appropriate.
  • RayS 2009-07-22 09:13
    Quick and dirty (just how I like it!) and hopefully stays true to the manual working process, not being naughty and skipping a few steps. When run in a suitable VBA host (e.g. Excel) will even show the working table.

    Public Function RussianMultiply(x As Long, y As Long) As Long
    
    Dim vals() As Long
    ReDim vals(1 To Round(Sqr(x), 0) + 1, 1 To 2) As Long
    Dim i As Long, j As Long, c As Long, Msg As String
    i = 1
    Do Until x = 0
    vals(i, 1) = x
    vals(i, 2) = y
    i = i + 1
    x = x \ 2
    y = y * 2
    Loop
    For j = 1 To i - 1
    If vals(j, 1) / 2 = vals(j, 1) \ 2 Then
    Msg = " X"
    Else
    c = c + vals(j, 2)
    Msg = vals(j, 2)
    End If
    Debug.Print vals(j, 1) & vbTab & vals(j, 2) & vbTab & Msg
    Next
    Debug.Print vbCrLf & "=" & vbTab & c
    RussianMultiply = c
    End Function


    Sample output:
    >RussianMultiply 18,23
    
    18 23 X
    9 46 46
    4 92 X
    2 184 X
    1 368 368

    = 414


    Addendum (2009-07-22 09:26):
    Oops, posted the +ve numbers only version. Replace Sqr(x) with Sqr(Abs(x))), add a new long s, where s = Sgn(x) * Sgn(y), and amend the output as required
  • Damien 2009-07-22 09:15
    C# (I normally do VB, but wanted simple iterator support):

    static void Main(string[] args)
    {
    Int32 total = 0;
    foreach (NumPair p in GetColumns(Int32.Parse(args[0]), Int32.Parse(args[1])))
    {
    if (p.First % 2 == 1)
    {
    total = total + p.Second;
    }
    }
    Console.WriteLine(total);
    Console.ReadLine();
    }

    private struct NumPair
    {
    public Int32 First;
    public Int32 Second;
    }

    private static IEnumerable<NumPair> GetColumns(Int32 Num1, Int32 Num2)
    {
    NumPair current = new NumPair();
    current.First = Num1;
    current.Second = Num2;
    while (current.First > 0)
    {
    yield return current;
    current.Second = current.Second * 2;
    current.First = Convert.ToInt32(Math.Floor(current.First / 2.0));
    }
    yield break;
    }
  • Drew 2009-07-22 09:15
    Java. Untested and recursive.

    public void int multiply(int x, int y) {
    if(x == 1) {
    return y;
    } else if(x%2 == 1) {
    return y + multiply(x/2, y*2);
    } else {
    return multiply(x/2, y*2);
    }
    }
  • Me 2009-07-22 09:16
    I was concerned my entry was too long and too legible. So I've shaved 11 bytes off it :)

    sub m(){my($a,$b)=@_;my$t;while($a){$t+=$b if$a&1;$a>>=1;$b<<=1;}$t;}
  • Dave Ingram 2009-07-22 09:16
    You got there a couple of minutes before me... and more concisely. In my defence, it has been about 5 years since I last wrote any Haskell... but I share your sentiment ;)
  • Anon 2009-07-22 09:17
    TRWTF is the animated gif
  • lemon 2009-07-22 09:17
    int russianPeasantMultiply(int a, int b)
    {
    // Russian peasant just optimized his code
    return a * b;
    }
  • epv 2009-07-22 09:18
    Perl solution. Obeys strict pragma and has error checking.


    use strict;

    main:
    {
    my $arg1 = shift;
    my $arg2 = shift;

    my $russian = russianMultiply($arg1, $arg2);
    my $real = $arg1 * $arg2;

    print "Russian Method: $russian\nNormal Method: $real\n";
    $russian==$real?print "Success, same result\n":print "Failure, different results\n";
    }

    sub russianMultiply
    {
    use integer;

    my $leftArg;
    my $rightArg;
    my $product;

    ($leftArg, $rightArg) = @_;

    for(;
    $leftArg >= 1;
    $leftArg /= 2 and $rightArg *= 2)
    {
    if($leftArg%2)
    {
    $product += $rightArg;
    }
    }

    return $product;
    }
  • KimmoS 2009-07-22 09:20
    simple non-WTF C++ template version:
    -----

    template <typename T>
    T russian_multiply(T paula, T bean)
    {
    T brillant = 0;
    for(;;) {
    if( paula & 1 ) brillant += bean;
    paula /= 2;
    if( paula == 0 ) return brillant;
    bean *= 2;
    }
    }

    #include <iostream>

    int main()
    {
    long a, b;
    std::cin >> a >> b;
    std::cout << a << "*" << b << "=" << russian_multiply(a,b) << std::endl;
    }
  • KnoNoth 2009-07-22 09:20
    //Not really important part :)
    #define and ,int
    #define lets int
    #define be =
    #define is =
    #define jack_is_alive (jack>1){
    #define jack_is_not_even (jack%2)
    #define plus +
    #define divided /
    #define multiplied *
    #define begin_action {
    #define end_action }

    //The code itself
    lets multiple(lets jack and john)
    begin_action
    lets bill be 0;
    while jack_is_alive
    if jack_is_not_even
    bill is bill plus john;
    jack is jack divided 2;
    john is john multiplied 2;
    end_action
    return bill plus john;
    end_action

    //You can call function like that multiple(int num1, int num2). It's written in C of course
  • Jeff Kemp 2009-07-22 09:21
    I've just learned Python so I just had to contribute... this version doesn't actually use the * or / operators, which I think defeats the purpose somewhat. Works with all integers, positive or negative.

    def rusky_mult (left, right):
    
    """multiply
    In Russia, peasants multiply You!
    """
    if left < 0 and right < 0:
    left, right = -left, -right
    # left must be positive
    elif left < 0:
    left, right = right, left
    product = 0
    while left >= 1:
    if left & 1:
    product = product + right
    left = left >> 1
    right = right << 1
    return product
  • freako 2009-07-22 09:21
    Dave Ingram:
    You got there a couple of minutes before me... and more concisely. In my defence, it has been about 5 years since I last wrote any Haskell... but I share your sentiment ;)


    Ah, but yours is truer to the spirit of the algorithm provided. Mind, I'm a mere dabbler in the high mysteries of Haskell.
  • Stefan 2009-07-22 09:21
    Lua


    function russian(a, b)
    local s = 0;
    if a < 0 then s = s + 1; end
    if b < 0 then s = s + 1; end
    a, b = math.abs(a), math.abs(b);
    if b > a then a, b = b, a; end
    if s == 1 then b = -b; end
    local r = 0;
    while(a > 0) do
    if (a % 2) > 0 then r = r + b; end
    a, b = math.floor(a / 2), b * 2;
    end
    return r;
    end
  • arnemart 2009-07-22 09:22
    New and improved recursive ruby version:


    class Fixnum
    def * num
    self == 1 ? num : (self/2) * (num+num) + (self%2 == 1 ? num : 0)
    end
    end

    puts 7 * 7


    <3 operator overloading
  • Dan 2009-07-22 09:23
    C# again, but without that stinky Math.Abs():

    public int PeasantMul(int i, int j)
    {
    int accum = 0;

    while (i != 0)
    {
    accum += ((i >> 31) | 1) * ((0 - (i & 1)) & j);
    i /= 2;
    j *= 2;
    }

    return accum;
    }
  • db2 2009-07-22 09:24
    In UserRPL, as I've got my HP 48 handy, and I'm in the mood for the unconventional approach.

    << 0 3 ROLLD WHILE OVER 0 > REPEAT IF OVER 2 MOD THEN ROT OVER + 3 ROLLD END 2 * SWAP 2 / FLOOR SWAP END DROP2 >>
  • Clark S 2009-07-22 09:24
    The Wolf:
    And in PHP:
    <?php
    

    function russian($x, $y) {
    $left = array();
    $right = array();

    while ($x > 1) {
    $left[] = $x;
    $right[] = $y;

    $x = floor($x / 2);
    $y *= 2;
    }

    $left[] = $x;
    $right[] = $y;
    $result = 0;

    foreach ($left as $index => $x) if ($x % 2) {
    $result += $right[$index];
    }

    return $result;
    }

    echo russian(41238, 193625);

    ?>
    I'll see that and raise you:
    <?php
    
    function russkiply($a, $b) {
    $product = 0;
    while ($a >= 1) {
    if ($a % 2)
    $product += $b;
    $a = floor((float)$a /= 2);
    $b *= 2;
    }
    return $product;
    }
  • arnemart 2009-07-22 09:25
    KimmoS:
    simple non-WTF C++ template version


    Oxymoron!
  • malach 2009-07-22 09:27
    In Delphi:

    function RussianPeasantMultiply(a,b: Integer);
    begin
    result := 0;
    while a>0 do begin
    if (a AND 1) = 1 then
    result := result + b;
    a := a div 2;
    b := b * 2;
    end;
    end;
  • newlisp.org 2009-07-22 09:27
    in newLISP:


    (define (rmul x y , s)
    (until (= x 1)
    (unless (zero? (% x 2))
    (inc s y))
    (setq x (>> x) y (<< y)))
    (+ y s)
    )

  • Dave Ingram 2009-07-22 09:28
    Since I got beaten to the punch with the Haskell version, here's one for vimscript:

    :fun Peasant(n1, n2)
    
    : if a:n1 == 1
    : retu a:n2
    : elsei a:n1 % 2 == 1
    : retu a:n2 + Peasant(float2nr(a:n1/2), a:n2*2)
    : el
    : retu Peasant(float2nr(a:n1/2), a:n2*2)
    : en
    :endf


    To use: save to ~/peasant.vim, :source ~/peasant.vim, then
    i<C-R>=Peasant(42,71)<CR>
    will insert the result of 42 × 71. Maybe if I have some time later, I'll make it print out the workings too ;)
  • Ryan 2009-07-22 09:28
    Here's a PHP version that displays the process sequentially, like the example:
    <html>
    
    <body>
    <style type="text/css">
    .result {
    margin-right: 10px;
    float: left;
    }
    h3 {
    clear: both;
    }
    table {
    text-align: right;
    }
    .final .strike {
    text-decoration: line-through;
    }
    </style>
    <?php

    $left = $_GET['left'];
    $right = $_GET['right'];
    if ($left && $right && preg_match('/^[0-9]+$/', $left) && preg_match('/^[0-9]+$/', $right)) {

    function mult($lefts, $rights) {
    echo '<div class="result"><table>';
    if ($lefts[count($lefts) - 1] == 1) {
    echo '<tbody class="final">';
    } else {
    echo '<tbody>';
    }

    for ($i = 0; $i < count($lefts); $i++) {
    echo '<tr'.(!($lefts[$i] % 2) ? ' class="strike"' : '')."><td>$lefts[$i]</td><td>".(!$i ? 'x' : '')."</td><td>$rights[$i]</td></tr>";
    }
    echo '</tbody></table></div>';

    $i--;
    if ($lefts[$i] == 1) return array_combine($lefts, $rights);
    $lefts[] = floor($lefts[$i] / 2);
    $rights[] = $rights[$i] * 2;
    return mult($lefts, $rights);
    }

    $result = 0;
    $dispResult = '';
    foreach (mult(array($left), array($right)) as $l=>$r) {
    if ($l % 2) {
    $result += $r;
    $dispResult .= $r.' + ';
    }
    }

    echo '<h3>Result is: '.substr($dispResult, 0, strlen($dispResult) - 2).'= '.number_format($result).'</h3>';
    }

    ?>
    <form method="get" action="wtf.php">
    <div>Left Number: <input type="text" name="left" value="<?php echo $left; ?>"/></div>
    <div>Right Number: <input type="text" name="right" value="<?php echo $right; ?>"/></div>
    <input type="submit" value="Go!"/>
    </form>
    </body>
    </html>


    Working demo at http://sandbox.secularcoding.com/wtf.php?left=18&right=23
  • pjt33 2009-07-22 09:29
    Herman:
    As this is the exact implementation of the multiply function on binary computing hardware, a simple

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

    should do for most platforms :)

    That's what I was going to say, so since you beat me to it here's a more long-winded implementation in SML:

    fun mult_inner(x, y, accum) =
    if (x = 0) then accum
    else if (x mod 2 = 1) then mult_inner(x div 2, y * 2, accum + y)
    else mult_inner(x div 2, y * 2, accum);
    fun mult(x, y) = mult_inner(x, y, 0);

    I think this is the first recursive implementation in the comments to be truly tail-recursive (and hence use a fixed amount of memory with a non-braindead compiler).
  • Whatever 2009-07-22 09:30
    Java. Untested and recursive.


    Every good WTF starts with these words.
  • Bob 2009-07-22 09:31
    Someone straighten me out here but I think the peasant don't know math for crap.

    May be I'm doing it wrong but when I Multiply 45 x 76, I get 3420

    Peasants get:

    45 x 76
    22 152 0
    11 304 304
    5 608 608
    2 1216 0
    1 2432 2432
    ======================
    3344

    Flip the numbers and you get the right answer
    76 45
    38 90 0
    19 180 180
    9 360 360
    4 720 0
    2 1440 0
    1 2880 2880
    =====================
    3420

    Peasant math apparently only works if one of the number is even and in the first column.

    This must be why they remain peasants.
  • Felix Ungman 2009-07-22 09:31
    C#, with yield return, of course!


    static class Program
    {
    public static bool IsOdd(this int value) { return (value % 2) != 0; }

    public static IEnumerable<KeyValuePair<int, int>> RussianPeasantSequence(int a, int b)
    {
    while (a > 0)
    {
    yield return new KeyValuePair<int, int>(a, b);
    a /= 2;
    b *= 2;
    }
    }

    [STAThread]
    static void Main()
    {
    System.Diagnostics.Debug.WriteLine(
    RussianPeasantSequence(18, 23)
    .Where(x => x.Key.IsOdd())
    .Select(x => x.Value)
    .Sum());
    }
    }

  • baka0815 2009-07-22 09:31
    Well, here is a version in Pascal.

    function RussianMultiply(Left, Right: Integer): Integer;
    
    begin
    if (Left = 1) then
    begin
    Result := Right;
    Exit;
    end;

    Result := 0;
    while Left <> 1 do
    begin
    Left := Left div 2;
    Right := Right * 2;

    if ((Left mod 2) <> 0) then Inc(Result, Right);
    end;
    end;


    Anyone noticed this only works if the left number is even?!

    18*23 works fine (414), bit 23*18 would be 396.
  • phihag 2009-07-22 09:31
    code golf: Python 3, 1 statement, 1 line, 70 characters:

    m=lambda a,b:sum(b<<i if a&1<<i else 0 for i in range(a.bit_length()))
  • Sebastian Paaske Tørholm 2009-07-22 09:32
    Oh hey, I did this in my first algorithms class lecture a while back.

    Haskell:
    import Data.Bits (shiftL, shiftR)
    

    x :: Integer -> Integer -> Integer
    1 `x` b = b
    a `x` b | a > b = b `x` a
    | otherwise = (if a `mod` 2 == 0 then 0 else b) +
    ((a `shiftR` 1) `x` (b `shiftL` 1))
  • MP 2009-07-22 09:33
    LISP

    ((defun russianpeasant ("They start by writing the two numbers to be multiplied at the head of two columns.) (Then they repeatedly divide the number in the left column by (two
    ) (dropping any remainder) and ((double) the number in the right column), writing the (two new numbers) immediately below their predecessors, until the number in the left column is one.) ((Then they) (cross out all rows) where the number in the left column is even), and (((add the remaining numbers) in the right column), which is the desired product)). (For instance, the product eighteen times twenty-three is found like this.")))))
  • Clark S 2009-07-22 09:33
    Clark S:
    I'll see that and raise you:
    <?php
    
    function russkiply($a, $b) {
    $product = 0;
    while ($a >= 1) {
    if ($a % 2)
    $product += $b;
    $a = floor((float)$a /= 2);
    $b *= 2;
    }
    return $product;
    }
    Actually, I just realized that my function doesn't take into account negatives. In order to be functionally complete I must do this:
    <?php
    
    function russkiply($a, $b) {
    $product = 0;
    if ($a < 0) {
    $a = -$a;
    $b = -$b;
    }
    while ($a >= 1) {
    if ($a % 2)
    $product += $b;
    $a = floor((float)$a /= 2);
    $b *= 2;
    }
    return $product;
    }
    The new check at the beginning will reverse the signs if the first part is less than 0; That way, if just $a is negative, it switches $b to the negative, and if both are negative, they both switch to positive.

    CAPTCHA: appellatio -- sounds like a dirty fruit fetish
  • whileloopsareugly 2009-07-22 09:34
    int mul(unsigned a, unsigned b)
    {
    for (int s=0; a; a>>=1, b<<=1) s+=a&0x1?b:0;
    return s;
    }
  • Jeff Kemp 2009-07-22 09:34
    Bob:

    Peasants get:[code]
    45 x 76
    22 152 0
    11 304 304
    5 608 608
    2 1216 0
    1 2432 2432
    ======================
    3344


    You forgot to add the initial 76: 45 is odd.
  • Tempura 2009-07-22 09:35
    Simple and readable recursive python-function:

    In [23]: def russia_peasants(x, y):
    ....: x, y = float(x), float(y)
    ....: if x <= 1:
    ....: return 0
    ....: elif (x%2) == 1:
    ....: return (x*y) + russia_peasants(x/2, y*2)
    ....: else:
    ....: return russia_peasants(x/2, y*2)

    In [24]: russia_peasants(18, 23)
    Out[24]: 414.0
  • TerraNova 2009-07-22 09:36

    #define F(name, op)\
    int name(int num) {\
    int i, j = 0;\
    for (i = 0; i < 32; ++i) {\
    op;\
    }\
    return j;\
    }

    #define _BUFFER_SIZE 16
    long b[_BUFFER_SIZE]; // long to avoid integer overflow

    F(explode, j = 1; i[b] = num & j << i; i[b] >>= i)
    F(implode, i[b] *= num << i)
    F(deplode, j+= i[b])

    #include <stdio.h>

    void main(int argc, char *argv[]) {
    if (argc != 3) return 1; // TODO: Display help text

    int i;

    printf("%d\n", (explode(atoi(argv[1])), implode(atoi(argv[2])), deplode(0)));
    }


    "Features":

    * Uses the , operator
    * buffer overflow (which passes valgrind!)
    * The ever-popular TODO - commenting on the one piece of verification code
    * Macros
    * arrays-as-pointer - need i say more?
    * Does not implement the actual algorithm, just something deceptively similar to what the requirements talk about
    * Violates the language standard for no good reason
  • baka0815 2009-07-22 09:38
    Ok, screw that about the left number needing to be even. Just forgot to use that one, too.

    Well, guess it goes with my name. ;)

    function RussianMultiply(Left, Right: Integer): Integer;
    
    begin
    if (Left = 1) then
    begin
    Result := Right;
    Exit;
    end;

    Result := 0;

    // Check if the first one is odd and add it
    if ((Left mod 2) <> 0) then Inc(Result, Right);

    while Left <> 1 do
    begin

    Left := Left div 2;
    Right := Right * 2;
    if ((Left mod 2) <> 0) then Inc(Result, Right);
    end;
    end;
  • HypocriteWorld 2009-07-22 09:38
    Better Haskell version: (this one pretty much follows the algorithm given part by part).

    peasant :: Integer -> Integer -> Integer
    peasant = curry (sum . map snd . filter (odd . fst) . unfoldr gen)
    where gen (0, _) = Nothing
    gen (x, y) = ((x, y), (x `div` 2, y * 2))

    Sometimes the unfoldr function feels silly.

    And to satisfy your craze for testing:

    import Test.QuickCheck
    prop_peasant x y = (x > 0 && y > 0) ==> peasant x y == x * y
  • Arjan 2009-07-22 09:39
    Recursive Java version. Also works with negative and zero.


    public class Russian {
    public static long multiply(long a,long b){long r=multiply(a>0?a:-a,b>0?b:-b,0);return a<0^b<0?-r:r;}
    private static long multiply(long a,long b,long r){if(a%2==1)r+=b; return a<=1?r:multiply(a>>1,b<<1,r);}
    }
  • Stalin 2009-07-22 09:39
    def inSovietRussiaIntegerMultipliesYou(
    
    a: "foul capitalist pig",
    b: "patriotic worker comrade"
    ) -> "glorious empowerment of the proletariat for the motherland":
    assert isinstance(a, int) and a > -1 and\
    isinstance(b, int) and b > -1
    al = [a]
    bl = [b]
    while 1 not in al:
    al.append(al[-1]//2)
    bl.append(bl[-1]*2)
    return sum(b for a, b in zip(al, bl) if a%2)


    Only works under Python 3.x
  • leppie 2009-07-22 09:39
    #!r6rs ;Scheme (for Phil :)

    (define (russian* x y)
    (cond
    [(zero? x) 0]
    [else
    (let-values (((d m) (div-and-mod x 2)))
    (+ (if (zero? m) 0 y)
    (russian* d (bitwise-arithmetic-shift-left y 1))))]))
  • Zishan 2009-07-22 09:40

    function ruM (input) {
    var left=0,right=0,remainder=0,sum=0,num;
    input = input.replace(/\s+/g, '').replace(/x/g,'*');
    if (input.indexOf('*')) num = input.split('*');
    if (num) for (var i=1; i<num.length; i++) {
    left = (i==1 ? parseInt(num[i-1], 10) : sum);
    right = parseInt(num[i], 10);
    while (left>1) {
    if (left % 2 != 0) {
    remainder += right;
    left -= 1;
    }
    left /= 2;
    right *= 2;
    }
    sum = right + remainder;
    remainder = 0;
    }
    return sum;
    }

    String input:
    ruM("18 x 23 x 23 x 23");
  • douglas 2009-07-22 09:40
    Bob:
    Someone straighten me out here but I think the peasant don't know math for crap.

    May be I'm doing it wrong but when I Multiply 45 x 76, I get 3420

    Peasants get:

    45 x 76
    22 152 0
    11 304 304
    5 608 608
    2 1216 0
    1 2432 2432
    ======================
    3344


    You're doing it wrong. The correct peasant algorithm here is:

    45 x 76 76
    22 152 0
    11 304 304
    5 608 608
    2 1216 0
    1 2432 2432
    ======================
    3420


    Note the first line in particular.
  • Steven de B 2009-07-22 09:40
    Perl, with some nice recursion...
    Code:

    sub mul($$)
    {
    my($a,$b)=@_;
    return $a?(($a&1?$b:0)+mul(int($a/2),$b*2)):0;
    }

    Probably already mentioned before in some variations, but I just want to have such a cool WTF-sticker :-)
  • Romeo 2009-07-22 09:41
    You've just forget to sum the first line...

    Bob:
    Someone straighten me out here but I think the peasant don't know math for crap.

    May be I'm doing it wrong but when I Multiply 45 x 76, I get 3420

    Peasants get:

    45 x 76
    22 152 0
    11 304 304
    5 608 608
    2 1216 0
    1 2432 2432
    ======================
    3344

    Flip the numbers and you get the right answer
    76 45
    38 90 0
    19 180 180
    9 360 360
    4 720 0
    2 1440 0
    1 2880 2880
    =====================
    3420

    Peasant math apparently only works if one of the number is even and in the first column.

    This must be why they remain peasants.
  • Bob 2009-07-22 09:41
    Jeff Kemp:
    Bob:

    Peasants get:[code]
    45 x 76
    22 152 0
    11 304 304
    5 608 608
    2 1216 0
    1 2432 2432
    ======================
    3344


    You forgot to add the initial 76: 45 is odd.


    I will blame this on poor specifications.
  • djjeavons 2009-07-22 09:42

    Private Function Multiply(ByVal number As Integer, ByVal multiplyBy As Integer)

    Dim lastNumber As Integer = number
    Dim remainder As Integer = 0
    Dim additionNumbers As Integer = 0
    Dim lastMultiplyByValue As Integer = multiplyBy

    System.Math.DivRem(System.Math.DivRem(lastNumber, 2, remainder), 2, remainder)
    If remainder = 0 Then additionNumbers += lastMultiplyByValue

    Do Until lastNumber = 1

    lastMultiplyByValue *= 2
    System.Math.DivRem(System.Math.DivRem(lastNumber, 2, remainder), 2, remainder)
    lastNumber = System.Math.Floor(lastNumber / 2)

    If Not remainder = 0 Then
    additionNumbers += lastMultiplyByValue
    End If

    Loop

    Return additionNumbers

    End Function
  • csulli13 2009-07-22 09:43
    SQL function using columns

    CREATE FUNCTION RussianMultiply
    (@Num1 int, @Num2 int)
    RETURNS int
    AS
    BEGIN

    CREATE TABLE #Columns(C1 int, C2 int)

    WHILE @Num1 >= 1
    BEGIN

    INSERT INTO #Columns VALUES(@Num1, @Num2)

    SET @Num1 = @Num1/2
    SET @Num2 = @Num2 * 2

    END

    DELETE FROM #Columns WHERE C1 % 2 = 0

    RETURN SUM(C2) FROM #Columns

    END
  • Maxim 2009-07-22 09:43
    Haskell, point-free style:

    russian = curry $ sum . map snd . filter (odd.fst) . takeWhile ((>0).fst) . iterate ((`div`2) *** (*2))
  • darklajid 2009-07-22 09:43
    Nice idea. F# solution, without much thoughts put into it (in other words: Nicer solutions probably exist) and assuming #light:


    let russianMultiplication (x:int) (y:int) =
    let rec russianMultiplicationRec x y l =
    match x with
    | 0 -> [(1, 0)]
    | 1 -> ((1, y) :: l)
    | _ -> russianMultiplicationRec (x/2) (y*2) ((x, y) :: l)

    russianMultiplicationRec x y []
    |> List.fold (fun acc (x, y) ->
    if x % 2 = 1 then acc + y
    else acc
    ) 0
  • ruckc 2009-07-22 09:44
    I think we did one worse.


    Database error
    A database query syntax error has occurred. This may indicate a bug in the software. The last attempted database query was:

    (SQL query hidden)

    from within function "MediaWikiBagOStuff::_doquery". MySQL returned error "1194: Table 'mw_objectcache' is marked as crashed and should be repaired (localhost)".
  • Osno 2009-07-22 09:44
    All the people looping on 1 instead of 0 fail.
    All the people using multiplication and division instead of shifting (except in languages where there is no shifting) also fail.
  • SR 2009-07-22 09:45
    ColdFusion:

    &lt;cffunction name="multiply" returntype="numeric"&gt;
    &lt;cfargument name="x" required="Yes" type="numeric"&gt;
    &lt;cfargument name="y" required="Yes" type="numeric"&gt;
    &lt;cfargument name="total" required="no" type="numeric"&gt;

    &lt;cfif NOT IsDefined("arguments.total")&gt;
    &lt;cfif arguments.x MOD 2 NEQ 0&gt;
    &lt;cfset arguments.total = arguments.y&gt;
    &lt;cfelse&gt;
    &lt;cfset arguments.total = 0&gt;
    &lt;/cfif&gt;
    &lt;/cfif&gt;

    &lt;cfset newX = Int(arguments.x / 2)&gt;
    &lt;cfset newY = arguments.y * 2&gt;

    &lt;cfif newX MOD 2 NEQ 0&gt;
    &lt;cfset arguments.total = arguments.total + newY&gt;
    &lt;/cfif&gt;
    &lt;cfif arguments.x GT 1&gt;
    &lt;cfset arguments.total = multiply(newX, newY, arguments.total)&gt;
    &lt;/cfif&gt;
    &lt;cfreturn arguments.total&gt;
    &lt;/cffunction&gt;

    Glad I use Java these days.
  • GM 2009-07-22 09:45
    Another C# one:
    private int Multiply(int a, int b)
    {
    int result = 0, aBy2, bBy2;

    if (a == 1) return b;

    aBy2 = a ;
    bBy2 = b ;
    do
    {
    aBy2 = aBy2 / 2;
    bBy2 = bBy2 * 2;
    if (aBy2 % 2 == 1)
    {
    result += bBy2;
    }
    } while (aBy2 != 1);

    return result;
    }
  • Damien 2009-07-22 09:45
    For those "handling negatives and zero" - the correct behaviour for these, given the literal description of the algorithm, is to loop forever, because the left hand column will never equal 1. (Not that my previous solution gets this right either)
  • SR 2009-07-22 09:45
    2nd attempt:

    <cffunction name="multiply" returntype="numeric">
    <cfargument name="x" required="Yes" type="numeric">
    <cfargument name="y" required="Yes" type="numeric">
    <cfargument name="total" required="no" type="numeric">

    <cfif NOT IsDefined("arguments.total")>
    <cfif arguments.x MOD 2 NEQ 0>
    <cfset arguments.total = arguments.y>
    <cfelse>
    <cfset arguments.total = 0>
    </cfif>
    </cfif>

    <cfset newX = Int(arguments.x / 2)>
    <cfset newY = arguments.y * 2>

    <cfif newX MOD 2 NEQ 0>
    <cfset arguments.total = arguments.total + newY>
    </cfif>
    <cfif arguments.x GT 1>
    <cfset arguments.total = multiply(newX, newY, arguments.total)>
    </cfif>
    <cfreturn arguments.total>
    </cffunction>
  • Soops 2009-07-22 09:46
    Clue:

    3420 - 3344 = 76

  • Jason Knight 2009-07-22 09:47
    Javascript version:

    function calculate() {
    var num1 = 28;
    var num2 = 13;
    var tot = 0;
    if ((num1 % 2) != 0) { tot = num2 }
    while (num1 > 1) {
    num1 = Math.floor(num1 / 2);
    num2 *= 2;
    if ((num1 % 2) != 0) { tot += num2 }
    }
    alert(tot);
    }
  • cwink 2009-07-22 09:48
    public static int Multiply( int op1, int op2 )
    {
    return Mult( Math.Abs(op1), op2*op1/Math.Abs(op1) );
    }

    private static int Mult( int op1, int op2 )
    {
    if( op1 == 1 )
    return op2;
    else
    return (op1 & 1)*op2 + Mult( op1 >> 1, op2 << 1 );
    }
  • dee 2009-07-22 09:50
    Iterative Scheme:


    (define (peasant left right)
    (define (peasant-i left right sum)
    (if (= left 0)
    (apply + sum)
    (peasant-i (floor (/ left 2))
    (+ right right)
    (if (= (modulo left 2) 1)
    (append sum (list right))
    sum))))
    (if (< left 0)
    (peasant-i (- left) (- right) '())
    (peasant-i left right '())))


    Works with negative numbers and zeroes. I tried to follow the manual process as closely as possible :)
  • Jim 2009-07-22 09:51
    phihag:
    code golf: Python 3, 1 statement, 1 line, 70 characters:

    m=lambda a,b:sum(b<<i if a&1<<i else 0 for i in range(a.bit_length()))


    Python 3, 64 characters
    m=lambda a,b:sum(b<<i for i in range(a.bit_length()) if a&1<<i)
  • Bob 2009-07-22 09:51
    Bob:
    Jeff Kemp:
    Bob:

    Peasants get:[code]
    45 x 76
    22 152 0
    11 304 304
    5 608 608
    2 1216 0
    1 2432 2432
    ======================
    3344


    You forgot to add the initial 76: 45 is odd.


    I will blame this on poor specifications.


    I will add that many solutions here are making the same error.
  • Philipp 2009-07-22 09:52
    public class SmallTest {
    public static void main(String [] args) {
    try {
    int m1 = Math.abs(Integer.parseInt(args[0]));
    int m2 = Math.abs(Integer.parseInt(args[1]));
    if (m1 > m2) {int temp = m1; m1 = m2; m2 = temp;}
    int result = 0;
    while (m1 >= 1) {
    if ((m1 & 1) > 0) result += m2;
    m1 >>= 1; m2 <<= 1;
    }
    System.err.println(args[0] + " * " + args[1] + " == " + result);
    } catch (Exception e) {
    System.err.println("Whoops: " + e.getMessage());
    }
    }
    }

    There you go. Even works for negative numbers ;) -- and it heavily optimizes... :)
  • Daniel 2009-07-22 09:52
    Recursion is always the right answer!!

    function peasantMath($a,$b) {
    return (($a>>1)%2 == 0 ? 0 : $b<<1) + ($a>>1 == 1 ? 0 : peasantMath($a>>1, $b<<1));
    }

    Also, TRWTF is that the link to esoteric languages is throwing database errors.

  • cwink 2009-07-22 09:54
    public static int Multiply( int op1, int op2 )
    {
    if( op1 == 0 || op2 == 0 )
    return 0;
    else
    return Mult( Math.Abs(op1), op2*op1/Math.Abs(op1) );
    }

    private static int Mult( int op1, int op2 )
    {
    if( op1 == 1 )
    return op2;
    else
    return (op1 & 1)*op2 + Mult( op1 >> 1, op2 << 1 );
    }
  • Anonymous 2009-07-22 09:56
    Oh wow, this is unbelievable. No trolls, no grammar nazis, no flame-bait, no spammers - just everyone chipping in on an interesting coding challenge. I think this is probably the most civilised comments page I've ever seen on TDWTF. Well done everyone, you've all earnt a cookie.
  • Bob 2009-07-22 09:56

    (define (halve x) (quotient x 2))
    (define (double x) (+ x x))
    (define (mul x y)
    (let iter ((x (abs x))
    (y (if (negative? x)
    (- y)
    y))
    (acc 0))
    (cond
    ((zero? x) acc)
    ((even? x) (iter (halve x) (double y) acc))
    (else (iter (- x 1) y (+ acc y))))))

  • Jeff Kemp 2009-07-22 09:57
    Bob:
    Bob:
    Jeff Kemp:
    ...

    You forgot to add the initial 76: 45 is odd.


    I will blame this on poor specifications.


    I will add that many solutions here are making the same error.


    and only those who said their solution is "untested" have half an excuse... :)
  • Daniel 2009-07-22 09:58
    Adjusted to handle negatives, and to handle an initial odd left operand, as pointed out above. This is PHP by the way, though it's not doing anything special.


    function peasantMath($a,$b) {
    
    if ( $a < 0 ) {
    $a *= -1;
    $b *= -1;
    }
    return (($a)%2 == 0 ? 0 : $b) + ($a == 1 ? 0 : peasantMath($a>>1, $b<<1));
    }



    CAPTCHA: nulla. mmmm, nulla wafers.
  • Éibhear 2009-07-22 09:59
    Using emacs lisp (and the dreaded recursion):

    (defun russian-peasant-multiply (factor1 factor2)
    (cond ((eq factor1 1)
    factor2
    )
    ((eq (mod factor1 2) 0)
    (russian-peasant-multiply (/ factor1 2) (* factor2 2))
    )
    (t
    (+ factor2 (russian-peasant-multiply (/ factor1 2) (* factor2 2))))
    )
    )
  • Stalker 2009-07-22 09:59
    Another assembly version, this time x64 using nasm


    SECTION .text
    GLOBAL RussianMul
    RussianMul:

    [BITS 64]
    xor rax, rax
    .start:
    bt rcx, 0
    jnc .even
    add rax, rdx
    .even:
    shr rcx, 1
    shl rdx, 1
    test rcx, rcx
    jnz .start

    ret
  • YES WE CAN! 2009-07-22 10:00
    doesn't use any * or /, supports negative numbers:

    #define NEGATE(x) (~(x) + 1)

    int russian_multiplication(int a, int b) {
    short think_positive = 1;
    int result=0;

    if (a < 0) {
    a=NEGATE(a);
    think_positive=NEGATE(think_positive);
    }

    if (b < 0) {
    b=NEGATE(b);
    think_positive=NEGATE(think_positive);
    }

    // do it the russian way:
    while (a > 0) {
    if (a & 1) {
    result+=b;
    }
    a >>= 1;
    b <<= 1;
    }

    // think positive!
    if (think_positive == -1)
    result = NEGATE(result);
    return result;
    }
  • Stefan 2009-07-22 10:00
    Osno:
    All the people looping on 1 instead of 0 fail.
    All the people using multiplication and division instead of shifting (except in languages where there is no shifting) also fail.


    java.math.abs(int x)


    public static int abs(int a)

    Returns the absolute value of an int value. If the argument is not negative, the argument is returned. If the argument is negative, the negation of the argument is returned.

    Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.

    Parameters:
    a - the argument whose absolute value is to be determined
    Returns:
    the absolute value of the argument.
    See Also:
    Integer.MIN_VALUE


    if you use shifting operators, russion(Integer.MIN_VALUE, ...) will always end in an infinity loop if your loop condition depends on a value != 0
  • little3lue 2009-07-22 10:01
    Damn: someone beat me to a C++ metaprogramming solution. This is easier to read:


    template <long a, long b>
    struct RusMult
    {
    enum { value = ((a&1) ? b : 0 ) + RusMult<(a>>1),(b<<1)>::value };
    };

    template <long b>
    struct RusMult<0,b>
    {
    enum { value = 0 };
    };

    // Usage: result = RusMult< a, b >::value;

  • Eutactic 2009-07-22 10:02
    Python 3.x
    Why else would they support unicode?
    Translation is probably hilariously wrong.

    #Русский крестьянин умножения модуль

    def Умножение(X,Y):
    пар = []

    def Населять(X,Y):
    пар = []
    while X > 0:
    пар.append([X,Y])
    X = X//2
    Y = Y*2
    return Суммавсех(Ликвидировать(пар))

    def Ликвидировать(пар):
    пар = [Элемент for Элемент in пар if Элемент[0] %2 != 0]
    return пар

    def Суммавсех(пар):
    Сумма = 0
    for Элемент in пар:
    Сумма += Элемент[1]
    return Сумма

    пар = Населять(X, Y)
    return пар

    print(Умножение(18, 23))

    >>> 414
  • RECURSIVEMAN 2009-07-22 10:02
    RECURSIVE MAN SAYS:

    def _mult(a,b):
    if a == 1: return [(a,b)]
    return [(a,b)]+_mult(a/2,b*2)
    def mult(a,b):
    return sum(b for (a,b) in _mult(a,b) if a%2==1)

    I was trying to stick exactly to the algorithm. The intermediate list of numbers that you'd write down on paper is first produced by _mult. The list comprehension then crosses out which ones are unnecessary, and adds the rest.
  • rob tracey 2009-07-22 10:02
    python:

    def rus(a,b):
    c = 0
    while a > 0:
    a = a/2
    b = b*2
    if a % 2 != 0:
    c += b
    print 'total = ',c
  • krat 2009-07-22 10:03

    def russian_peasant(n1, n2):
    remainder = 0
    if n1 > n2: n1, n2 = n2, n1
    while n1 != 1:
    if n1 % 2:
    remainder += n2
    n1 >>= 1
    n2 <<= 1

    return n2 + remainder
  • Philipp 2009-07-22 10:03
    Small improvement; now it _really_ works with negative numbers...

    public class SmallTest {
    public static void main(String [] args) {
    try {
    boolean n = args[0].trim().startsWith("-") ^ args[1].trim().startsWith("-");
    int m1 = Math.abs(Integer.parseInt(args[0]));
    int m2 = Math.abs(Integer.parseInt(args[1]));
    if (m1 > m2) {int temp = m1; m1 = m2; m2 = temp;}
    int result = 0;
    while (m1 >= 1) {
    if ((m1 & 1) > 0) result += m2;
    m1 >>= 1; m2 <<= 1;
    }
    System.out.println(args[0] + " * " + args[1] + " == " + ((n && result != 0) ? "-" : "") + result);
    } catch (Exception e) {
    System.err.println("Whoops: " + e.getMessage());
    }
    }
    }
  • JaguarOne 2009-07-22 10:04
    Not very esoteric.... LOLCODE

    HAI
    CAN HAS STDIO?

    HOW DUZ I MULTIPLY_STALIN YR SOVIETA AN YR SOVIETB
    I HAS A PROFIT
    PROFIT R TROOF
    I HAS A THROWFUD
    THROWFUD R 0

    IM IN YR USSR_LOOP WILE PROFIT AN SOVIETA BIGGR 0
    IZ MOD OF SOVIETA AN 2 NOT 0?
    YARLY
    THROWFUD R SUM THROWFUD N SOVIETB

    KTHX

    SOVIETA R QUOSHUNT SOVIETA AN 2
    SOVIETB R PRODUKT SOCIETB AN 2
    IM OUTTA YR USSR_LOOP
    IF U SAY SO
    KTHXBYE

    (captcha vulputate? sounds nasty!)
  • Andrew Brehm 2009-07-22 10:04
    "It is said that Russian peasants multiply using a most curious method"

    Is that why there are so many of them?

  • Fabio Lima 2009-07-22 10:05
    Minimalist C#

    static int RussianMultiply(int a, int b) {
    int r=0;
    for (int i=a/2;i!=1;i--,a=a/2,b=b*2,r=r+(a%2)*b){}
    return r;
    }
  • povman 2009-07-22 10:06
    Here's my very realistic solution, in C:


    /* Oh god, who wrote this? - geoff */
    int RussianMultiply(int a, int b)
    {
    return a * b; /* TODO: Implement russian peasant multiplication */
    }
  • GWO 2009-07-22 10:07
    unsigned long long mult(unsigned long a, unsigned b)
    {
    unsigned long long acc = 0;
    while(a != 0) acc += (a%2)*b,a/=2,b*=2;
    return acc;
    }
  • drBeat 2009-07-22 10:08
    This never terminates if x == 0.

    My try:


    def russian_multiply(a, b):
    product = 0
    while a:
    if a & 1:
    product += b
    a >>= 1
    b <<= 1
    return product
  • exo 2009-07-22 10:10
    a very horribly ruby one-liner:

    def mul(a, b)
    (t=[[a, b]]).inject(0){|acc,(a, b)|a<=0?acc:acc+(t<<[a>>1,b<<1])[-2][1]*(a%2==1?1:0)}
    end
  • method1 2009-07-22 10:13
    Paula:
    public class Paula extends WTF {
    public static string Paulabean = "brillant!";
    }


    Best solution by far
  • Benjamin Bridges 2009-07-22 10:13
    Don't see anyone doing this for the adding portion:
    sum += b * (a & 1);

    Save an if statement.
  • avl 2009-07-22 10:19
    uint32 rpMultiply(uint32 a, uint32 b)
    {
    uint32 res = 0;

    if (b < a)
    {
    // change for shorten time
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    }

    do
    {
    if (a & 1)
    {
    res += b;
    a >>= 1;
    b <<= 1;
    } while (a);
    }
    return res;
    }
  • kastein 2009-07-22 10:20
    Dascandy:
    X86:

    ; assumption: eax contains arg1, ebx contains arg2
    mov edx, eax
    next:
    shr ebx, 1
    cmovc ecx, edx
    cmovnc ecx, 0
    jz end
    lea eax, [eax*2 + ecx]
    jmp next

    end:
    ret


    ARM:

    mov r2, r0
    next test r1, 1
    mov r1, #0, r1 shr 1
    addc r0, r0, r2
    movz pc, lr
    add r0, r0, r0
    b next



    Both approximated. Appreciate comments.

    awesome! more assembly required...

    In IA64 assembly:


    .text
    .align 32
    .global russian_multiply
    .proc russian_multiply
    russian_multiply::
    alloc r14=ar.pfs,2,0,0,0
    mov r2=pr
    movl r8=0;;
    startloop:
    tbit.nz p6=r32,1
    cmp.e p7=1,r32;;
    (p6) add r8=r8,r33;;
    (p7) br.cond endloop;;
    shr r32=r32, 1
    shl r33=r33, 1;;
    br.cond startloop;;
    endloop:
    mov pr=r2
    mov ar.pfs=r14;;
    br.ret.sptk b0;;
    .endp russian_multiply


    Usable in C as:
    int russian_multiply(int num1, int num2);


    Addendum (2009-07-22 10:26):
    cmp.eq not cmp.e. brainfart...
  • ross 2009-07-22 10:20
    Python. Recursive, works with positive integers.

    def mul(a,b):
    if a != 1:
    if a % 2 == 1:
    return b + mul(a >> 1, b << 1)
    else:
    return mul(a >> 1, b << 1)
    else:
    return b
  • FatherStorm 2009-07-22 10:21

    <?php
    $x=rand(1,65535);
    $y=rand(1,65535);
    $ans=$x*$y;
    while($x>=1){
    if($x % 2==1 ){
    $z+=$y;
    }
    $x=intval($x/2);
    $y=$y*2;
    }
    echo"$ans == $z";;
    ?>
  • Phil 2009-07-22 10:21
    Bob:
    Someone straighten me out here but I think the peasant don't know math for crap.

    May be I'm doing it wrong but when I Multiply 45 x 76, I get 3420

    Peasants get:

    45 x 76
    22 152 0
    11 304 304
    5 608 608
    2 1216 0
    1 2432 2432
    ======================
    3344

    Flip the numbers and you get the right answer
    76 45
    38 90 0
    19 180 180
    9 360 360
    4 720 0
    2 1440 0
    1 2880 2880
    =====================
    3420

    Peasant math apparently only works if one of the number is even and in the first column.

    This must be why they remain peasants.


    You're doing it wrong. In the first example you forgot to add the 76 on the first row.
  • threecheese 2009-07-22 10:22
    Me:
    I was concerned my entry was too long and too legible. So I've shaved 11 bytes off it :)

    sub m(){my($a,$b)=@_;my$t;while($a){$t+=$b if$a&1;$a>>=1;$b<<=1;}$t;}

    if you wanted illegible, you should assume no strict (drop the 'my $t') and use indexes of @_ instead of assigning $a and $b to it...
  • halber_mensch 2009-07-22 10:23
    A recursive python solution

    def умножить(a,b):
    if (a==1): return b
    _b = b
    while(1):
    a=a>>1
    b=b<<1
    if(a%2): break
    return _b+умножить(a,b)
  • Alex Ciarlillo 2009-07-22 10:24
    recursive scala soln.


    def do_mult(left : Int, right : Int) : Int = {
    if (left == 1) right
    else if (left%2 == 0) do_mult(left/2, right*2)
    else do_mult(left/2, right*2) + right
    }
  • Anonymous Coward 2009-07-22 10:25
    Prolog:

    rusmul(0,_,0).
    rusmul(A,B,X) :- C is A//2, D is B*2, rusmul(C,D,E), X is E+(A mod 2)*B.
  • SR 2009-07-22 10:25
    Anonymous:
    Oh wow, this is unbelievable. No trolls, no grammar nazis, no flame-bait, no spammers - just everyone chipping in on an interesting coding challenge. I think this is probably the most civilised comments page I've ever seen on TDWTF. Well done everyone, you've all earnt a cookie.


    If you fancy a return to normal we could have a slanging match about earnt/earned ;o)
  • Jeff Kemp 2009-07-22 10:26
    IMHO any multiplication and division operators (and related ones like the "-" unary operator) should be disallowed. Only bitwise ops!

    New & improved Python implementation, borrowed "YES WE CAN!"'s trick for negating using ~; handles all combinations of positive/negative/zero integers, and only uses the ~, >> and << operators (apart from comparison ops):

    def rusky_mult(l,r):
    
    if l<0 and r<0:
    l,r=~l+1, ~r+1
    elif l<0:
    l,r=r,l
    p=0
    while l>=1:
    if l&1: p+=r
    l>>=1
    r<<=1
    return p
  • darklajid 2009-07-22 10:26
    Another F# take. This time without recursion. I love "infinite" sequences..


    let russianMultiplication x y =
    Seq.initInfinite (fun i -> (x >>> i, y <<< i))
    |> Seq.takeWhile (fun t -> fst t > 0)
    |> Seq.filter (fun f -> fst f % 2 = 1)
    |> Seq.sumBy (fun z -> snd z)
  • Will 2009-07-22 10:27
    Not tested and not guaranteed correct (It's been years since I've used this stuff), but here's my attempt at a MUSH code solution.

    @create peasant
    &cmd_russianMult peasant = $russianMult *: @emit v(russianMult, %0, %1)
    &russianMult peasant = add(mult(mod(%0,2),%1), switch(%0,1,0,v(russianMult, div(%0,2), mult(%1,2))))
  • halber_mensch 2009-07-22 10:27
    No, this fails if a is even. damn
  • WarheadsSE 2009-07-22 10:27
    Perl >> 1 line >> 55 chars ... beat that python :)
    sub r{($_[0]?r($_[0]>>1,$_[1]<<1):0)+($_[0]&1)*$_[1];}
  • SR 2009-07-22 10:28
    function russianMultiplication(a, b) {
    if (frist) {
    alert('FRIST');
    } else {
    // do nothing
    }
    }
  • WarheadsSE 2009-07-22 10:28
    love that russian translation function name!
  • Romeo 2009-07-22 10:30
    This way, you won't make much money on those "pay-per-line" jobs...

    Jim:
    phihag:
    code golf: Python 3, 1 statement, 1 line, 70 characters:

    m=lambda a,b:sum(b<<i if a&1<<i else 0 for i in range(a.bit_length()))


    Python 3, 64 characters
    m=lambda a,b:sum(b<<i for i in range(a.bit_length()) if a&1<<i)
  • Matt 2009-07-22 10:32
    Didn't see Groovy listed, so:

    import static Math.floor

    def multiply(ln, rn){
    def results = [[left: ln, right: rn]]
    def product = 0
    while ( results[-1]["left"] > 1){
    results << [left: floor(results[-1]["left"]/2) as int, right: results[-1]["right"]*2]
    }
    results.findAll{it["left"] % 2 != 0}.each{product += it["right"]}
    product
    }
  • Archimidas 2009-07-22 10:33
    Where's the Shakespeare version?
  • Nick Pope 2009-07-22 10:34
    WarheadsSE:
    Perl >> 1 line >> 55 chars ... beat that python :)
    sub r{($_[0]?r($_[0]>>1,$_[1]<<1):0)+($_[0]&1)*$_[1];}


    Easy... I beat that with bc :) New target is sub 50 characters!

    Code:
    a=read();b=read();while(a){c+=b*(a%2);a/=2;b*=2};c
  • ponky 2009-07-22 10:34

    #define HALF(X,Y) y*(1&Y)+a

    int multiply(int x, int y)
    {
    int a = 0;
    while (a=HALF(x,x),y<<=1,x>>=1);
    return HALF(a,x);
    }


    maybe trying too hard :/
  • WarheadsSE 2009-07-22 10:34
    Romeo:
    This way, you won't make much money on those "pay-per-line" jobs...

    Jim:
    phihag:
    code golf: Python 3, 1 statement, 1 line, 70 characters:

    m=lambda a,b:sum(b<<i if a&1<<i else 0 for i in range(a.bit_length()))


    Python 3, 64 characters
    m=lambda a,b:sum(b<<i for i in range(a.bit_length()) if a&1<<i)


    And they still have 9 characters to go to catch up with perl.
  • halber_mensch 2009-07-22 10:35
    Better recursive python solution:

    def умножить(a,b):
    if (a==1): return b
    return b*(a%2)+умножить(a>>1,b<<1)
  • kastein 2009-07-22 10:36
    Also, I'm disappointed... no MUMPS? no MS-DOS batch?
  • Fabio Lima 2009-07-22 10:36
    I stand corrected. Was missing the case where the first parameter was odd.

    static int RussianMultiply(int a, int b) {
    int rest=0;
    for (int i=a/2,r=(a%2)*b;i!=0;i--,a=a/2,b=b*2,r=r+(a%2)*b)
    {if (a == 1) { return r ; }}
    return 0;
    }
  • Nicholas Laux 2009-07-22 10:36
    Ruby non-recursive:

    print "First number: "
    q = gets.chomp.to_i
    print "Second number: "
    t = gets.chomp.to_i

    def ahh_motherland!(a, z)
    p = (a > 0) == (z > 0)
    a, z = (a > 0 ? a : -a), (z > 0 ? z : -z)
    s = 0
    while a > 0 do
    s += a % 2 == 0 ? z : 0
    a /= 2
    z *= 2
    end
    return p ? s : -s
    end

    puts "#{q} * #{t} = #{ahh_motherland!(q, t)}"
  • MeesterTurner 2009-07-22 10:36
    Some lunchtime T-SQL:
    DECLARE @N1 int
    DECLARE @N2 int
    DECLARE @tblMult TABLE(N1 int, N2 int)

    SELECT @N1 = 18, @N2 = 23 -- The two numbers to multiply peasantly

    WHILE @N1 >= 1
    BEGIN
    INSERT INTO @tblMult VALUES (@N1, @N2)
    SELECT @N1 = @N1 * 0.5, @N2 = @N2 * 2

    END


    DELETE FROM @tblMult WHERE (N1 * 0.5) - (CAST((N1 / 2) AS INT)) = 0

    SELECT SUM(N2) FROM @tblMult -- The Answer!
  • WarheadsSE 2009-07-22 10:36
    Nick Pope:
    WarheadsSE:
    Perl >> 1 line >> 55 chars ... beat that python :)
    sub r{($_[0]?r($_[0]>>1,$_[1]<<1):0)+($_[0]&1)*$_[1];}


    Easy... I beat that with bc :) New target is sub 50 characters!

    Code:
    a=read();b=read();while(a){c+=b*(a%2);a/=2;b*=2};c


    Did you check the output? ;)
  • Osno 2009-07-22 10:36
    @Stefan Agreed, but I don't think a russian counting peasants is counting negative peasants.
  • GWO 2009-07-22 10:36
    K&R C:
    int m(a,b){c=0;while(a!=0)c+=a%2*b,a/=2,b*=2;return c}

    54 characters - 59 if you include "K&R C"
  • Kook 2009-07-22 10:37
    Takes care of zeroes and negatives --

    public static int compute(int left, int right) {
    int result = 0;
    int multiplier = 1;

    if (left < 0) {
    multiplier = -1;
    left *= -1;
    }

    if (right < 0) {
    multiplier *= -1;
    right *= -1;
    }

    while (left > 0) {
    if (left % 2 == 1) {
    result += right;
    }

    left /= 2;
    right *= 2;
    }

    return result * multiplier;
    }
  • GWO 2009-07-22 10:38
    GWO:
    K&R C:
    int m(a,b){c=0;while(a!=0)c+=a%2*b,a/=2,b*=2;return c}

    54 characters - 59 if you include "K&R C"

    Oops : I meant

    m(a,b){int c=0;while(a!=0)c+=a%2,a/=2,b*=2;return c;}

  • GWO 2009-07-22 10:39
    GWO:
    GWO:
    K&R C:
    int m(a,b){c=0;while(a!=0)c+=a%2*b,a/=2,b*=2;return c}

    54 characters - 59 if you include "K&R C"

    Oops : I meant

    m(a,b){int c=0;while(a!=0)c+=a%2,a/=2,b*=2;return c;}


    m(a,b){int c=0;while(a)c+=a%2*b,a/=2,b*=2;return c;}

    Stupid stale clipboard
  • Matt 2009-07-22 10:40
    int russianPeasantMultiplication(double a, double b) {
    cout << "You";
    return 0;
    }

    // In Soviet Russia, functions write You
  • Jonathan 2009-07-22 10:41
    Recursive version that handles negatives:


    public int PeasantMultiply(int n1, int n2)
    {
    bool negate = false;
    if (n1 < 0){
    negate = true;
    n1 = -n1;
    }
    int tot = n1 > 1 ? tot += PeasantMultiply(n1 / 2, n2 * 2) : 0;

    if (n1 % 2 == 1) tot += n2;
    if (negate) tot = -tot;

    return tot;
    }
  • Jeff Kemp 2009-07-22 10:43
    Kook:
    ...
    if (right < 0) {
    multiplier *= -1;
    right *= -1;
    }
    ...
    [/code]


    You can remove this bit and it'll still work.
  • hh10k 2009-07-22 10:43
    Here's my specially optimised version, for all you C++ lovers:

    unsigned do_it_like_a_russian(unsigned a, unsigned b)
    
    {
    // Make rows
    std::stringstream rows;
    rows << a << " x " << b << "\n";
    while (a > 0)
    {
    rows << (a>>=1) << " " << (b<<=1) << "\n";
    }

    // Cross out even rows
    std::string line;
    std::stringstream crossed;
    crossed.fill('-');
    while (std::getline(rows, line))
    {
    std::stringstream(line) >> a;
    crossed.width(line.size());
    crossed << ((a & 1) ? line : "") << "\n";
    }

    // Total remaining rows
    unsigned total = 0;
    while (std::getline(crossed, line))
    {
    std::string::size_type p = line.find_last_of(' ');
    if (p != std::string::npos)
    {
    std::stringstream(line.substr(p)) >> b;
    total += b;
    }
    }
    return total;
    }
  • Frits 2009-07-22 10:43
    Bob:
    Someone straighten me out here but I think the peasant don't know math for crap.

    May be I'm doing it wrong but when I Multiply 45 x 76, I get 3420

    Peasants get:

    45 x 76
    22 152 0
    11 304 304
    5 608 608
    2 1216 0
    1 2432 2432
    ======================
    3344

    Flip the numbers and you get the right answer
    76 45
    38 90 0
    19 180 180
    9 360 360
    4 720 0
    2 1440 0
    1 2880 2880
    =====================
    3420

    Peasant math apparently only works if one of the number is even and in the first column.

    This must be why they remain peasants.


    you forgot the first line contains an odd number, wich adds up to the total, there's your missing 76
  • Nicholas Laux 2009-07-22 10:44
    Ruby: 49 characters, counting spaces.

    def a(b,c) return b==1?c:c*(b%2)+a(b>>1,c<<1) end

    Ball's in your court.
  • Osno 2009-07-22 10:44
    Btw, it's not in the spirit of the thread to criticize without chipping in. C#. Doesn't handle negative numbers, as per my previous logic:

    private static long Multiply(long firstNum, long secondNum)
    {
    long acum = 0;
    while (firstNum > 0)
    {
    if ((firstNum & 1) == 1)
    acum += secondNum;
    firstNum = firstNum >> 1;
    secondNum = secondNum << 1;
    }
    return acum;
    }

    captcha: ludus (programming is always a game)
  • Nick Pope 2009-07-22 10:45
    WarheadsSE:
    Did you check the output? ;)


    Aye, I did. And still seems to work fine... Are you having a problem with it?
  • Real russian peasant :) 2009-07-22 10:46


    >Python 3.x
    >Why else would they support unicode?
    >Translation is probably hilariously wrong.

    I corrected yor translation a bit :)

    # Модуль умножения, используемый русскими крестьянами

    def Перемножить(X,Y):
    пары = []

    def СоздатьПары(X,Y):
    пары = []
    while X > 0:
    пары.append([X,Y])
    X = X//2
    Y = Y*2
    return СуммаВсех(Ликвидировать(пары))

    def Ликвидировать(пары):
    пары = [Элемент for Элемент in пары if Элемент[0] %2 != 0]
    return пары

    def СуммаВсех(пары):
    Сумма = 0
    for Элемент in пары:
    Сумма += Элемент[1]
    return Сумма

    пары = СоздатьПары(X, Y)
    return пары

    print(Перемножить(18, 23))

    >>> 414
  • jcs 2009-07-22 10:47
    You do know about this, don't you?
  • Samuel A. Falvo II 2009-07-22 10:47
    I didn't see a Forth version yet. Maybe I scanned too quickly.

    : russian* ( n1 n2 -- n3 )
    0 -rot begin dup while
    dup 1 and if -rot over + swap rot then 2/ swap 2* swap
    repeat drop nip ;
  • Anonymous 2009-07-22 10:48
    Me:
    Bah to all your bloaty solutions. Perlmongers do it in one line :P

    sub m(){my($a,$b)=@_;my $t;while($a){$t+=$b if ($a&1);$a>>=1;$b<<=1;}return $t;}


    But surely that's just..

    sub m()
    {
    my($a,$b)=@_;
    my $t;
    while($a)
    {
    $t+=$b if ($a&1);
    $a>>=1;
    $b<<=1;
    }
    return $t;
    }

    ..with the returns stripped out..
  • rst 2009-07-22 10:48
    4 pages and no FORTRAN?

    integer function mult (a, b)
    integer a, b
    logical neg
    mult = 0
    neg = (a .lt. 0)
    if (neg) a = (-1) * a
    do while (a .gt. 0)
    if (mod(a, 2) .eq. 1) then
    mult = mult + b
    endif
    a = a / 2
    b = b * 2
    enddo
    if (neg) mult = (-1) * mult
    return
    end
  • halber_mensch 2009-07-22 10:49
    halber_mensch:
    Better recursive python solution:

    def умножить(a,b):
    if (a==1): return b
    return b*(a%2)+умножить(a>>1,b<<1)


    And one that handles all integers, not just natural numbers:

    def умножить(a,b):
    if (-1<=a<=1): return a*b
    return b*(a%2)+умножить(a>>1,b<<1)
  • groknroll 2009-07-22 10:49
    Recursive C# solution.

    private int PeasantMultiply( int n1, int n2) {
    if ( n1 == 1 )
    return n2;

    return ( n1 % 2 == 0 ? 0 : n2 ) + (n1 == 0 ? 0 : PeasantMultiply( n1 >> 1, n2 << 1 ));
    }
  • Samuel A. Falvo II 2009-07-22 10:51
    Bugger! There's a bug in the code I posted, and I don't have time to fix it right now. :( At any rate, the Russian algorithm is what Chuck Moore used to implement his "*+" operator in his MISC processors.
  • Xthlc 2009-07-22 10:52
    Here's a slightly shorter and bitshiftier recursive ruby version, although I like that you modified the integer class. How very Ruby. :D

    def russian(a, b)
    return 0 if a == 0
    (a & 0x1) * b + russian(a>>1, b*2)
    end
  • buzkie 2009-07-22 10:53
    static int russianmult(int a,int b){
    int total = 0;
    while (a >= 1){
    if (a% 2 != 0){total += b;}
    a = a /2; b = b *2;
    }
    return total;
    }

    Any suggestions welcomed
  • shub 2009-07-22 10:54

    #include <stdio.h>

    int peasant_multiply(int x, int y)
    {
    int result;
    for(result = 0; x != 0 && y != 0; x /= 2, y *= 2)
    {
    result += (x % 2) * y;
    }
    return result;
    }


    Addendum (2009-07-22 11:03):
    Depending on compiler behavior you could move
    result += (x % 2) * y
    into the update step and save a few lines, but that would be evil and wrong. :)
  • Stephen 2009-07-22 10:58
    This is similar to how I multiply numbers in my head, except that I will divide by any factor, and when I run into too large of a prime, I either change to estimating or play the "multiply by 7 means multiply by 8 and subtract by one" game. I don't recall where I learned to do that...
  • Xthlc 2009-07-22 11:00
    Curses! More-or-less beaten by this solution. For some reason I didn't think to shift b.
  • Rootbeer 2009-07-22 11:00
    Herman:
    this is the exact implementation of the multiply function on binary computing hardware


    Is this so? I had assumed that most CPUs with MULtiply opcodes used hardware lookup tables, in order to achieve a fast and constant O(1) execution time, but perhaps I am mistaken. It's certainly a less sensible approach with 32- or 64-bit operands than it would have been with 8- or 16-bit operands.

  • campkev 2009-07-22 11:01
    in C#
    public int RussianMultiply(int operand1, int operand2)
    {
    int res = 0;
    while (operand1 > 0)
    {
    if (operand1 % 2 == 1) res += operand2;
    operand1 /= 2;
    operand2 *= 2;
    }
    return res;
    }
  • Dmitri Savichev 2009-07-22 11:01
    Yet another Scheme solution

    ;;proper R5RS
    (define (rusmult a b)
    (cond ;;special cases
    ((= a 0) 0);; okay, it's dirty, but i'm way to lasy
    ((= b 0) 0);; to try to come up with something better
    ((negative? a) (* -1 (rusmult (* -1 a) b)))
    (else (if (= a 1) ;; real computation
    (+ (if (odd? a) b 0))
    (+ (if (odd? a) b 0)
    (rusmult (if (even? a) (/ a 2) (/ (- a 1) 2)) (* b 2)))))))
  • campkev 2009-07-22 11:02
    Recursive in C#
    public int RecursiveRussianMultiply(int operand1, int operand2)
    {
    return operand1 == 0 ? 0 : RecursiveRussianMultiply(operand1 / 2, operand2 * 2) + (operand1 % 2 == 1 ? operand2 : 0);
    }
  • Sean Handley 2009-07-22 11:03
    C# solution (boilerplate not included)


    private static List<Pair> _pairs = new List<Pair>();

    private static void RussianPeasant(int a, int b)
    {
    _pairs.Add(new Pair(a, b));
    if (a == 1)
    {
    int result = 0;
    foreach (Pair pair in _pairs)
    {
    if (pair.FirstNum % 2 != 0)
    result += pair.SecondNum; //accumulate all second nums, if first num in pair is an odd number
    }
    DisplayMessage("Result: " + result.ToString());
    }
    else
    {
    //tail recursive call
    RussianPeasant(a / 2, b * 2); //half first number (ignoring remainder), double second number
    }
    }
  • lyml 2009-07-22 11:03
    Scheme

    (define (mult a b)
    (cond ((= b 1) a)
    ((= (remainder b 2) 1) (+ b (mult (* 2 a) (quotient b 2))))
    (else (mult (* 2 a) (/ b 2)))))

    not tested
    CAPTHA: vereor
  • Osno 2009-07-22 11:03
    Recursive C# in one line :)

    private static long m(long f, long s) { return ((f&1)==1?s:0)+(f>0?m(f>>1,s<<1):0); }

    Ok, it's just like the perl sample. Here, how it should be read:

    private static long m(long f, long s)
    {
    return ((f&1)==1?s:0)+(f>0?m(f>>1,s<<1):0);
    }

    And for the whole "I can do it in a few chars" thing, from the return to the colon it's only 43 characters.
  • Someone 2009-07-22 11:04
    An ABAP solution that compiles:

    REPORT MULTIP.

    DATA: product TYPE i,
    left_num TYPE f VALUE 18,
    right_num TYPE f VALUE 23,
    half_left TYPE f,
    half_left_floor TYPE f.

    WHILE left_num > 0.
    "check for even number and add to product (there must be a better way...)
    half_left = left_num / 2.
    half_left_floor = FLOOR( left_num / 2 ).
    IF half_left <> half_left_floor.
    product = product + right_num.
    ENDIF.

    "move to next set
    left_num = FLOOR( left_num / 2 ).
    right_num = right_num * 2.
    ENDWHILE.

    WRITE product.
  • Dmitri Savichev 2009-07-22 11:04
    ugh, i meant it that way

    ;;proper R5RS
    (define (rusmult a b)
    (cond ;;special cases
    ((= a 0) 0);; okay, it's dirty, but i'm way to lasy
    ((= b 0) 0);; to try to come up with something better
    ((negative? a) (* -1 (rusmult (* -1 a) b)))
    (else (if (= a 1) ;; real computation
    (+ (if (odd? a) b 0))
    (+ (if (odd? a) b 0)
    (rusmult (if (even? a) (/ a 2) (/ (- a 1) 2)) (* b 2)))))))
  • Oliver Klozoff 2009-07-22 11:04
    This is going to get lost in the mix, but here's my take.

    Note: I'm betting that most of the naive implementations people have done don't function correctly when multiplying negative numbers. This one does.


    using System;
    using System.Data;
    using System.Diagnostics;

    using o = System.Console;

    // to compile on any modern Windows machine:
    //
    // PATH=%PATH%;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
    // csc rusmult.cs

    class X {

    public static void Main(string[] args) {
    try {
    if (args.Length != 2) {
    o.WriteLine("Usage: {0} n1 n2", Environment.GetCommandLineArgs()[0]);
    return;
    }

    // doing this makes negative numbers work
    uint n1 = (uint)Convert.ToInt32(args[0]);
    uint n2 = (uint)Convert.ToInt32(args[1]);

    // ensure n1 < n2 to minimize steps
    if (n1 > n2) { n1 ^= n2; n2 ^= n1; n1 ^= n2; }

    int dig1 = (n1==0) ? 1 : (int) Math.Ceiling(Math.Log10(n1));
    int dig2 = (n2==0) ? 1 : (int) Math.Ceiling(Math.Log10(n2));
    int dig3 = dig1 + dig2;

    string fmt1 = string.Format("{{0,{0}}} x {{1,{1}}} ", dig1, dig3);
    string fmt2 = string.Format(" | + {{0,{0}}}", dig3);
    string fmt3 = string.Format("{{0,{0}}} x {{1,{1}}} = {{2}}", dig1, dig3);

    uint accum = 0;
    while (n1 > 0) {
    o.Write(fmt1, n1, n2);
    if ( (n1 & 1) != 0) {
    o.Write(fmt2, n2);
    accum += n2;
    } else {
    o.Write(" | strike");
    }
    o.WriteLine();
    n1 >>= 1;
    n2 <<= 1;
    }
    o.WriteLine(new string('-', dig1 + 3 + dig3 + 5 + dig3));
    o.WriteLine(fmt3, args[0], args[1], (int)accum);

    } catch (Exception ex) {
    o.WriteLine("Error: {0}", ex);
    }
    }
    }



  • Slinky 2009-07-22 11:05
    Function PeasantMultiply(x As Integer, y As Integer) As Integer
    
    Dim product As Integer = 0

    While x >= 1
    If x Mod 2 == 1 Then
    product += y;
    End If

    x /= 2
    y *= 2
    End If

    Return product
    End Function
  • _flt 2009-07-22 11:07
    Some considerations for speed optimisation:
    - Division, multiplication and modulo are quite complex and will take longer than standard bit operations on most CPUs.
    - Have the smaller value be decremented will save cycles

    unsigned int rmul( unsigned int a, unsigned int b )
    {
    if ( a > b ) rmul( b, a );

    unsigned int acc = (a & 1) ? b : 0;

    for ( ; a >>= 1 ; b <<= 1 ) {
    if ( a & 1 ) acc += b;
    }
    return acc;
    }
  • Remy 2009-07-22 11:07
    Here's mine, in Python. It works for all integers.

    def russian(a, b):
    
    if a < 0:
    a, b = -a, -b
    c = 0
    while 1:
    if a & 1:
    c += b
    a >>= 1
    b <<= 1
    if a <= 0:
    break
    return c
  • Mestafais 2009-07-22 11:08
    Mine on javascript
    function peasentDevide(a, b){r=0;while(a!=0){if (a%2==1)r+=b;a=Math.floor(a/2);b=b*2;}return r;}
  • Rief 2009-07-22 11:08
    Wrote in D language :P but the mult function should work also in C++, I think...well, with unsigned int instead of uint :P:

    import std.stdio;
    import std.string;

    int mult(uint fst, uint snd)
    {
    uint result;

    for(uint i=0; fst >= 1; fst/=2, snd*=2, i+=1)
    if(fst % 2)
    {
    result += snd;
    fst -= 1;
    }

    return result;
    }

    void main(string[] args)
    {
    if(args.length != 3)
    {
    writefln("Usage: %s <num> <num>", args[0]);
    return 0;
    }
    if(!args[1].isNumeric())
    {
    writefln("First argument isn't a number");
    return 0;
    }
    if(!args[2].isNumeric())
    {
    writefln("Second argument isn't a number");
    return 0;
    }

    writefln(mult(atoi(args[1]),atoi(args[2])));

    return 0;
    }

    To run put it in a file and use the gdc compiler....
  • Billy 2009-07-22 11:09
    In Python (Works with 0 and negative numbers!)

    def p_mult(num1, num2) :
    if num1 == 0 or num2 == 0 : return 0
    sign = bool(num1 < 0) ^ bool(num2 < 0)
    num1 = abs(num1)
    num2 = abs(num2)
    dat = [[num1, num2]]
    while num1 != 1 :
    num1 /= 2
    num2 *= 2
    dat.append([num1, num2])
    total = 0
    for n in dat :
    if n[0] % 2 == 1 : total += n[1]
    if sign : return total * -1
    else : return total

    http://www.codeskilled.com
  • Harleqin 2009-07-22 11:09
    Common Lisp:

    (defun russkiply (a b &optional (sum 0))
    "returns the product of a and b,
    achieved by peasant multiplication."
    (cond ((or (zerop a) (zerop b)) 0)
    ((minusp a) (- (russkiply (- a) b)))
    ((minusp b) (- (russkiply a (- b))))
    ((= a 1) (+ b sum))
    (t (russkiply (floor (/ a 2))
    (* b 2)
    (+ sum (* b (logand a 1)))))))

    C:

    int russkiply (int a, int b)
    { if (a == 0 || b == 0) { return 0; };
    if (a < 0) { return - russkiply (- a, b); };
    if (b < 0) { return - russkiply (a, - b); };
    int p = 0;
    for (;
    p += (a & 1) * b, a != 1;
    a /= 2, b *= 2) {};
    return p; };

  • Will 2009-07-22 11:09
    My solution in LUA:
    function f(x, y)
    
    return (x % 2 == 1 and y or 0) + (x > 0 and f(math.floor(x / 2), y * 2) or 0)
    end
  • Anonymous 2009-07-22 11:10
    SR:
    Anonymous:
    Oh wow, this is unbelievable. No trolls, no grammar nazis, no flame-bait, no spammers - just everyone chipping in on an interesting coding challenge. I think this is probably the most civilised comments page I've ever seen on TDWTF. Well done everyone, you've all earnt a cookie.

    If you fancy a return to normal we could have a slanging match about earnt/earned ;o)
    I dropped that in there to test the waters (FYI it is proper English) but amazingly enough, nobody took the bait. Everyone's just happy to work on the coding problem. I'm aghast at just how civil developers can be when they've got something to develop!
  • bluebearr 2009-07-22 11:10
    Windows XP batch file:
    @echo off
    
    set _a=18
    set _b=23
    call :mult %_a% %_b% _result
    echo %_a% x %_b% = %_result%
    goto :EOF


    :mult
    :: Multiply two numbers
    :: Parameters:
    :: %1 - first number
    :: %2 - second number
    :: %3 - variable to return result in
    setlocal
    set _a=%1
    set _b=%2
    set _res=0
    :calc
    set _eventest=0
    for /L %%i in (0,2,8) do if %_a:~-1%==%%i set _eventest=1
    if %_eventest%==0 set /a _res+=_b
    if %_a% LEQ 1 goto endcalc
    set /a _a/=2
    set /a _b*=2
    goto calc
    :endcalc
    endlocal & set %3=%_res%
    goto :EOF
  • WarheadsSE 2009-07-22 11:10
    Nick Pope:
    WarheadsSE:
    Did you check the output? ;)


    Aye, I did. And still seems to work fine... Are you having a problem with it?


    Forgive, i missed the automagic vivification of c to existance and 0
  • Josh Bohde 2009-07-22 11:11
    Python 2.6

    m=lambda a,b:sum(a<<n for n in range(b) if b>>n&1)


    51 characters
  • baka0815 2009-07-22 11:12
    Since everyone is bragging about shifting instead of multiply/divide, here is a Pascal version with shifting:

    function RussianMultiply(Left, Right: Integer): Integer;
    
    begin
    if (Left = 1) then
    begin
    Result := Right;
    Exit;
    end;

    Result := 0;

    if ((Left mod 2) <> 0) then Inc(Result, Right);
    while Left <> 1 do
    begin

    Left := Left shr 1;
    Right := Right shl 1;
    if ((Left mod 2) <> 0) then Inc(Result, Right);
    end;
    end;


    You could strip the
      if (Left = 1) then
    
    begin
    Result := Right;
    Exit;
    end;

    part, but it would be slower I guess.
  • Osno 2009-07-22 11:12
    Shorter:
    return f>0?m(f>>1,s<<1)+(f&1)*s:0;

    Just realized that ( (a&1) == 1? s : 0 ) === ( (a&1)*s )

    34 chars without the function header.
  • Ian McLaird 2009-07-22 11:13
    Alex Ciarlillo:
    recursive scala soln.


    def do_mult(left : Int, right : Int) : Int = {
    if (left == 1) right
    else if (left%2 == 0) do_mult(left/2, right*2)
    else do_mult(left/2, right*2) + right
    }


    And, for even more fun, with a custom operator


    object praxis2 {
    implicit def RussianIntInt(i: Int):RussianInt = new RussianInt(i)
    implicit def IntRussianInt(i: RussianInt):Int = i.a

    class RussianInt(val a: Int) {
    def ***(b: RussianInt): RussianInt = {
    if (a < 2) if (a == 1) b else 0
    else if (a % 2 == 1) b + ((a / 2) *** (b * 2))
    else ((a / 2) *** (b * 2))
    }
    }

    def main(args: Array[String]) {
    val a = args(0).toInt
    val b = args(1).toInt
    val res: Int = a *** b
    println(res)
    }
    }
  • Wulf0r 2009-07-22 11:14
    Python:

    def russianMultiply(lst):
    """ param is a list with one entry of tupel containing the ints to multiply """
    # take head of list
    arg = lst[-1]
    # check if recursion is complete
    if arg[0] == 1:
    # pythons X-trem X-pressivnes -> filter all unevens and add them
    return reduce( lambda x,y: x+y, [x[1] for x in lst if x[0] % 2 != 0])

    lst.append( (arg[0] / 2, arg[1] * 2) )
    return russianMultiply( lst)


    print russianMultiply( list([(18,23)]))
  • Xthlc 2009-07-22 11:15
    Final version of my ruby function, slightly altered with some cribbage from halber_mensch to handle all integers.

    def russian(a, b)
    
    return a*b if (-1..1).include? a
    (a & 0x1) * b + russian(a>>1, b<<1)
    end
  • baka0815 2009-07-22 11:16
    Last one I submit, I promise! :)

    - shifting instead of multiply/divide
    - bit-and instead of modulo

    function RussianMultiply(Left, Right: Integer): Integer;
    
    begin
    Result := 0;

    if ((Left and 1) = 1) then Inc(Result, Right);
    while Left <> 1 do
    begin
    Left := Left shr 1;
    Right := Right shl 1;
    if ((Left and 1) = 1) then Inc(Result, Right);
    end;
    end;
  • Steve the Cynic 2009-07-22 11:17
    Captain Obvious:
    I haven't done APL in a LONG time...

         Z <- A RUSSIAN B
    
    [1] Z <- 0
    [2] TOP:
    [3] Z <- Z + A * 0 = 2 | B
    [4] A <- |_ A (divide) 2
    [5] B <- B x 2
    [6] -> (A>0) / TOP


    Or

         RET <- A RUSSIAN B
    
    [1] X <- 2 * (highminus)1 + (iota) (upside down L) 2 (star-in-circle) A + 1
    [2] Y <- X x B
    [3] Z <- 2 | |_ A / X
    [4] RET <- +/ Y x Z


    X gets a list of powers of two starting with 1

    Y gets a list of B times powers of two

    Z gets a list of (A/power of two) mod 2 (0 or 1)

    RET gets the sum of the list of Y and Z elements multiplied together.

    4 lines, no loops, no recursion, and only one Greek letter!

    NOT TESTED. Written using a memory of APL not exercised in 25 years.
  • - 2009-07-22 11:18
    Herman:
    As this is the exact implementation of the multiply function on binary computing hardware, a simple

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

    should do for most platforms :)


    Well that one wins Best Abuse Of The Rules.:) I've only seen one C preprocessor nasty so far.... any more takers?
  • Ken B 2009-07-22 11:19
    kastein:
    Also, I'm disappointed... no MUMPS? no MS-DOS batch?
    You just didn't wait long enough. :-)

    Here is my MS-Windows Batch file:

    @echo off
    
    rem Multiply.bat
    rem Multiplication the "Russian Peasant" way.
    rem To be called with two parameters -- the numbers to multiply.
    rem For example: multiply 18 23
    rem
    rem Note: No sanity check is provided to verify two numbers are passed.

    set /a Multiplier=%1
    set /a Multiplicand=%2
    set /a Product=0

    :loop

    set /a OddOrEven=%Multiplicand% / 2
    set /a OddOrEven=%OddOrEven% * 2
    if not %OddOrEven%==%Multiplicand% set /a Product=%Product% + %Multiplier%

    set /a Multiplicand=%Multiplicand% / 2
    set /a Multiplier=%Multiplier% * 2

    if not %Multiplicand%==0 goto loop

    echo %1 times %2 equals %Product%
    Now, how does one get code to single-space?
  • Lupe 2009-07-22 11:20
    A database query syntax error has occurred. This may indicate a bug in the software. The last attempted database query was:

    (SQL query hidden)

    from within function "MediaWikiBagOStuff::_doquery". MySQL returned error "1194: Table 'mw_objectcache' is marked as crashed and should be repaired (localhost)".
  • aBase 2009-07-22 11:20
    The problem says two numbers, not two integers, so here's the first draft of a PHP solution that will handle decimal fractions (and also negative numbers):
    function potemkin_multiply($two_numbers)
    
    {
    $frac_len = array(0, 0);
    foreach ($two_numbers as $num) {
    if ($num == 0) {
    return 0;
    }
    $num = rtrim($num, '.');
    if ($len = strrchr($num, '.')) {
    $frac_len[] = strlen(strrchr($num, '.')) - 1;
    }
    }
    $power = max($frac_len);
    $neg = false;
    foreach ($two_numbers as & $num) {
    if ($num < 0) {
    $neg = !$neg;
    }
    $num = abs($num * pow(10, $power));
    }
    $total = 0;
    while ($two_numbers[0] > 1) {
    if ($two_numbers[0] % 2) {
    $total += $two_numbers[1];
    }
    $two_numbers[0] = floor($two_numbers[0] / 2);
    $two_numbers[1] *= 2;
    }
    $total = ($total + $two_numbers[1]) / pow(10, $power * 2);
    if ($neg) {
    $total *= -1;
    }
    return $total;
    }
    Test code:
    $nums = array(0, -1, 1, 18, -23, 154., -229.5, 49.0, 389.99, 
    
    67.99999, -592.8729, .678, 0.00678);
    for ($i = 0; $i < 50; $i++) {
    $pair = array($nums[array_rand($nums)], $nums[array_rand($nums)]);
    $russian = potemkin_multiply($pair);
    $orthodox = $pair[0] * $pair[1];
    echo $pair[0] . ' * ' . $pair[1] . ' = <b>' . $russian . '</b>';
    if ((string) $russian != (string) $orthodox) {
    echo ' <span style="color:red">(' . $orthodox . ')</span>';
    }
    echo '<br />';
    }
  • Qwertyuiopas 2009-07-22 11:21
    I know everybody wants it :)

    Hopefully none of it was removed.

    Also, everything after the first . is disabled debugging code. Remove the [-] to see what is left of the memory.

    >>>>>,>>,[->+>+<<]<<[[-[>+<-]>[>+>>>+<<<<-[[<+>-]>[-]<]]<]>>[>>[-]<<[-]]+>[->>>>>++>++<<<<<<]>>]>>>>[-]<<<<<<<[<<<<<]>>>>>[>>[->>>>>+<<<<<]>>>]>>.[-][<<<<<<<[<<<<<]>>>.>.>[.>.>.>.>.>].>.>.]
  • Markus Persson 2009-07-22 11:21
    48 characters in javascript:

    function m(a,b){return a>1?a%2*b+m(a>>1,b*2):b;}
  • campkev 2009-07-22 11:23
    Jay:

    public static int multiply(int first, int second){
    if(first == 1){
    return second;
    }

    int result = 0;

    if(first%2 != 0){
    result += second;
    }
    result += multiply(first/2, second * 2);
    return result;
    }


    Didn't test it, but I think this will infinite loop if the first number is 0;
  • Ken B 2009-07-22 11:23
    Steve the Cynic:
    Captain Obvious:
    I haven't done APL in a LONG time...

    ...snip...
    


    Or

    ...snip...
    


    ...snip...

    NOT TESTED. Written using a memory of APL not exercised in 25 years.
    Noted. (Also, I am not familiar with using standard ASCII characters for APL, as I had a "real" APL character set to work with.) However, where's your single-line solution, as any "good" APL programmer knows is the target.
  • christopher.n 2009-07-22 11:23
    Efficient C solution:

    int russianMult( int a, int b ){

    return a*b;
    }
  • Zor 2009-07-22 11:24
    All of these solutions are soooooo slooooooooow. Try this one out. Just call the function you need! Ex: for 5 x 18, call "F5x18();". Note: Doesn't yet work for all values, but I'm working on it.

    static int F10x1() { return F5x2(); }
    static int F10x10() { return F5x20(); }
    static int F10x2() { return F5x4(); }
    static int F10x3() { return F5x6(); }
    static int F10x4() { return F5x8(); }
    static int F10x5() { return F5x10(); }
    static int F10x6() { return F5x12(); }
    static int F10x7() { return F5x14(); }
    static int F10x8() { return F5x16(); }
    static int F10x9() { return F5x18(); }
    static int F11x150() { return F5x300() + 150; }
    static int F1x1() { return 1; }
    static int F1x10() { return 10; }
    static int F1x12() { return 12; }
    static int F1x1200() { return 1200; }
    static int F1x14() { return 14; }
    static int F1x16() { return 16; }
    static int F1x18() { return 18; }
    static int F1x2() { return 2; }
    static int F1x20() { return 20; }
    static int F1x24() { return 24; }
    static int F1x28() { return 28; }
    static int F1x3() { return 3; }
    static int F1x32() { return 32; }
    static int F1x36() { return 36; }
    static int F1x4() { return 4; }
    static int F1x40() { return 40; }
    static int F1x48() { return 48; }
    static int F1x5() { return 5; }
    static int F1x56() { return 56; }
    static int F1x6() { return 6; }
    static int F1x64() { return 64; }
    static int F1x7() { return 7; }
    static int F1x72() { return 72; }
    static int F1x8() { return 8; }
    static int F1x80() { return 80; }
    static int F1x9() { return 9; }
    static int F23x75() { return F11x150() + 75; }
    static int F2x1() { return F1x2(); }
    static int F2x10() { return F1x20(); }
    static int F2x12() { return F1x24(); }
    static int F2x14() { return F1x28(); }
    static int F2x16() { return F1x32(); }
    static int F2x18() { return F1x36(); }
    static int F2x2() { return F1x4(); }
    static int F2x20() { return F1x40(); }
    static int F2x24() { return F1x48(); }
    static int F2x28() { return F1x56(); }
    static int F2x3() { return F1x6(); }
    static int F2x32() { return F1x64(); }
    static int F2x36() { return F1x72(); }
    static int F2x4() { return F1x8(); }
    static int F2x40() { return F1x80(); }
    static int F2x5() { return F1x10(); }
    static int F2x6() { return F1x12(); }
    static int F2x600() { return F1x1200(); }
    static int F2x7() { return F1x14(); }
    static int F2x8() { return F1x16(); }
    static int F2x9() { return F1x18(); }
    static int F3x1() { return F1x2() + 1; }
    static int F3x10() { return F1x20() + 10; }
    static int F3x12() { return F1x24() + 12; }
    static int F3x14() { return F1x28() + 14; }
    static int F3x16() { return F1x32() + 16; }
    static int F3x18() { return F1x36() + 18; }
    static int F3x2() { return F1x4() + 2; }
    static int F3x20() { return F1x40() + 20; }
    static int F3x3() { return F1x6() + 3; }
    static int F3x4() { return F1x8() + 4; }
    static int F3x5() { return F1x10() + 5; }
    static int F3x6() { return F1x12() + 6; }
    static int F3x7() { return F1x14() + 7; }
    static int F3x8() { return F1x16() + 8; }
    static int F3x9() { return F1x18() + 9; }
    static int F4x1() { return F2x2(); }
    static int F4x10() { return F2x20(); }
    static int F4x12() { return F2x24(); }
    static int F4x14() { return F2x28(); }
    static int F4x16() { return F2x32(); }
    static int F4x18() { return F2x36(); }
    static int F4x2() { return F2x4(); }
    static int F4x20() { return F2x40(); }
    static int F4x3() { return F2x6(); }
    static int F4x4() { return F2x8(); }
    static int F4x5() { return F2x10(); }
    static int F4x6() { return F2x12(); }
    static int F4x7() { return F2x14(); }
    static int F4x8() { return F2x16(); }
    static int F4x9() { return F2x18(); }
    static int F5x1() { return F2x2() + 1; }
    static int F5x10() { return F2x20() + 10; }
    static int F5x12() { return F2x24() + 12; }
    static int F5x14() { return F2x28() + 14; }
    static int F5x16() { return F2x32() + 16; }
    static int F5x18() { return F2x36() + 18; }
    static int F5x2() { return F2x4() + 2; }
    static int F5x20() { return F2x40() + 20; }
    static int F5x3() { return F2x6() + 3; }
    static int F5x300() { return F2x600() + 300; }
    static int F5x4() { return F2x8() + 4; }
    static int F5x5() { return F2x10() + 5; }
    static int F5x6() { return F2x12() + 6; }
    static int F5x7() { return F2x14() + 7; }
    static int F5x8() { return F2x16() + 8; }
    static int F5x9() { return F2x18() + 9; }
    static int F6x1() { return F3x2(); }
    static int F6x10() { return F3x20(); }
    static int F6x2() { return F3x4(); }
    static int F6x3() { return F3x6(); }
    static int F6x4() { return F3x8(); }
    static int F6x5() { return F3x10(); }
    static int F6x6() { return F3x12(); }
    static int F6x7() { return F3x14(); }
    static int F6x8() { return F3x16(); }
    static int F6x9() { return F3x18(); }
    static int F7x1() { return F3x2() + 1; }
    static int F7x10() { return F3x20() + 10; }
    static int F7x2() { return F3x4() + 2; }
    static int F7x3() { return F3x6() + 3; }
    static int F7x4() { return F3x8() + 4; }
    static int F7x5() { return F3x10() + 5; }
    static int F7x6() { return F3x12() + 6; }
    static int F7x7() { return F3x14() + 7; }
    static int F7x8() { return F3x16() + 8; }
    static int F7x9() { return F3x18() + 9; }
    static int F8x1() { return F4x2(); }
    static int F8x10() { return F4x20(); }
    static int F8x2() { return F4x4(); }
    static int F8x3() { return F4x6(); }
    static int F8x4() { return F4x8(); }
    static int F8x5() { return F4x10(); }
    static int F8x6() { return F4x12(); }
    static int F8x7() { return F4x14(); }
    static int F8x8() { return F4x16(); }
    static int F8x9() { return F4x18(); }
    static int F9x1() { return F4x2() + 1; }
    static int F9x10() { return F4x20() + 10; }
    static int F9x2() { return F4x4() + 2; }
    static int F9x3() { return F4x6() + 3; }
    static int F9x4() { return F4x8() + 4; }
    static int F9x5() { return F4x10() + 5; }
    static int F9x6() { return F4x12() + 6; }
    static int F9x7() { return F4x14() + 7; }
    static int F9x8() { return F4x16() + 8; }
    static int F9x9() { return F4x18() + 9; }
  • derula 2009-07-22 11:26
    While I haven't checked if it already exists, here a non-recursive Ruby solution overwriting the default operator.

    I couldn't test it, so it'll probably not work.

    But it has comments, works with negative numbers, and doesn't interfere with non-integral multiplication.

    class Bignum
    
    # Save the old multiplication
    alias old_mult *
    end

    class Fixnum
    # Save the old multiplication
    alias old_mult *
    end

    class Integer
    def *(b)
    # Only perform RPM on two integers
    if b.is_a? Integer
    # Copy first operand so that it can be modified in place *
    a = self
    # If any of the two is 0, result is 0
    return 0 if a == 0 or b == 0
    # Get the sign of the result **
    sgn = ((a <=> 0) + (b <=> 0)).abs - 1
    # Get the absolute values
    a, b = a.abs, b.abs
    # Initialize the result
    result = 0
    # > 0 because we want to do a last addition when a is 1
    while a > 0
    # Add b to result if a is odd
    result += b if a % 2 == 1
    a << -1 # Right shift a by one
    b << 1 # Left shift b by one
    end
    # Return the result (also: get the sign right)
    sgn * result
    else
    # Use old multiplication if no Integer supplied
    old_mult(b)
    end
    end
    end

    =begin
    * Not sure if this is neccessary, but as I said, I wasn't able to test it.
    ** You got it? No? Okay, explanation:
    a<0^b>0 => (a<=>0)=-1^(b<=>0)=1 => sgn=(-1+1).abs-1=-1
    a<0^b<0 => (a<=>0)=-1^(b<=>0)=-1 => sgn(-1-1).abs-1=1
    a>0^b>0 => (a<=>0)=1^(b<=>0)=1 => sgn=(1+1).abs-1=1
    a>0^b<0 => (a<=>0)=1^(b<=>0)=-1 => sgn(1-1).abs-1=-1
    (a<=>0)=0 or (b<=>0)=0 cannot occur, because of the line above that.
    =end


    Addendum (2009-07-22 11:36):
    Okay, so this is one of the least clever solutions... but it is commented like no other. Does this get me a sticker?

    Addendum (2009-07-22 13:32):
    Damn! I'm stupid. Of course, sgn*result is incorrect. Take this instead:
          (sgn == -1) ? 0 - result : result

    Addendum (2009-07-22 13:34):
    (gotta close those tags.)
  • Ken B 2009-07-22 11:28
    Zor:
    All of these solutions are soooooo slooooooooow. Try this one out. Just call the function you need! Ex: for 5 x 18, call "F5x18();". Note: Doesn't yet work for all values, but I'm working on it.

    static int F10x1() { return F5x2(); }
    static int F10x10() { return F5x20(); }
    ...snip...
    static int F9x8() { return F4x16() + 8; }
    static int F9x9() { return F4x18() + 9; }
    The problem is when you don't know the two parameters until runtime. In that case, you'll need something like this:

    switch( x*y )
    {
    case 1: return F1x1();
    case 2: return F1x2();
    case 3: return F1x3();
    case 4: return F2x2();
    }
    As in your code, it won't handle all cases, but you can finish this "enhancement" as you finish your original code.
  • Steve the Cynic 2009-07-22 11:28
    Ken B:
    Noted. (Also, I am not familiar with using standard ASCII characters for APL, as I had a "real" APL character set to work with.) However, where's your single-line solution, as any "good" APL programmer knows is the target.


    Exercise for the reader, as always.

    Or if you insist:

         RET <- A RUSSIAN B
    
    [1] RET <- +/ X x B x 2 | |_ X <- 2 * (highminus)1 + (iota) (upside down L) 2 (star-in-circle) A + 1
  • shub 2009-07-22 11:29
    Osno:
    All the people looping on 1 instead of 0 fail.
    All the people using multiplication and division instead of shifting (except in languages where there is no shifting) also fail.
    Except that C doesn't define bit shift on negative integers. How do you like this signature:
    int peasant_multiply(int x, int y, int *result);
    Maybe we could set errno, in the grand tradition of sqrt().

    Or how about this:
    unsigned int peasant_multiply(unsigned int x, unsigned int y);
    Using multiply and divide expands our domain from N × N to Z × Z. If that's not worth the minor performance penalty, you're doing much more interesting work than I am.
  • WraithShade 2009-07-22 11:30
    Since I read this as "Multiply exactly like russian peasants would" then I did it the old-fashioned C# way.

    public static int RussianPeasantMultiplication(int CurrentLeftValue, int CurrentRightValue)
    
    {
    List<int> LeftColumn = new List<int>();
    List<int> RightColumn = new List<int>();
    int FinalValue = 0;

    LeftColumn.Add(CurrentLeftValue);
    RightColumn.Add(CurrentRightValue);

    while (true)
    {
    CurrentLeftValue = LeftColumn[LeftColumn.Count - 1];
    CurrentRightValue = RightColumn[RightColumn.Count - 1];

    CurrentLeftValue /= 2;
    CurrentRightValue *= 2;

    LeftColumn.Add(CurrentLeftValue);
    RightColumn.Add(CurrentRightValue);

    if (CurrentLeftValue <= 1) break;
    }

    for (int i = 0; i < LeftColumn.Count; i++)
    {
    if (LeftColumn[i] % 2 != 0)
    FinalValue += RightColumn[i];
    }

    return FinalValue;
    }
  • CF Guru 2009-07-22 11:30
    Dammit...Someone beat me the the CF solution...

    Where are the COBOL developers? Don't make me bust out my college COBOL!!!
  • porty 2009-07-22 11:30
    Zor, this is very useful.
    Perhaps something like this would make it easier for the user?

    #define multiply(X, Y) F##X##x##Y ()
  • WarheadsSE 2009-07-22 11:31
    Did that already...

    But...

    sub t{$_[0]?t($_[0]>>1,$_[1]<<1)+($_[0]&1)*$_[1]:0}

    52 char is about as far down as I can get it, and does not handle (-) due to Perl using C shifts, which dont operate properly on (-)..
  • Kman 2009-07-22 11:31
    inline bool shift(unsigned int& result, unsigned int a, unsigned int b)
    {
    return result += a & 1 ? b : 0;
    }

    unsigned int RM(unsigned int a, unsigned int b)
    {
    unsigned int result = 0;
    while (a != 1 && shift(result, a>>=1, b<<=1)) {
    }
    return result;
    }
  • HonestJoe 2009-07-22 11:32
    public class NotCheating {

    public static int multiply(int i, int j) {
    // using russian multiplication
    return multiplyRussian(i, j);
    }

    private static int multiplyRussian(int i, int j) {

    /*
    * This method is so secret, you should not even know
    * it is here!
    * Please stop reading immediately!
    * No kidding!
    * Stop now, before it is to late!
    * Trust me, this is a really neat implementation of the
    * russian peasants algorithm, but for your own sake,
    * STOP NOW!
    */


    return i*j;

    }

    }
  • baka0815 2009-07-22 11:32
    Well, what's a promis if you don't break it? :)

    - using bit shifting
    - using and instead of mod
    - working with zeros
    - not working with negatives - but why should a peasant multiply negative values?

    function RussianMultiply(Left, Right: Integer): Integer;
    
    begin
    Result := 0;

    Inc(Result, Right * (Left and 1));
    while Left > 1 do
    begin
    Left := Left shr 1;
    Right := Right shl 1;
    Inc(Result, Right * (Left and 1));
    end;
    end;
  • ponky 2009-07-22 11:32
    C++ version


    void russian(int x, int y)
    {
    if (x == 0) throw 0;
    try { russian(x>>1, y<<1); }
    catch (int a) { throw a + y * (x & 1); }
    }

    int multiply(int x, int y)
    {
    try { russian(x, y); }
    catch (int a) { return a; }
    }
  • antelopelovefan 2009-07-22 11:34
    Here's another VBScript version meant to run as an Excel macro.

    It assumes the values to be multipled are in cells A2 and B2 of the first Worksheet and it stores all of the intermediate numbers in the cells below as it calculates.

    The final output is put in cell C2


    Public Sub CalculateRussianPeasant()
    Dim curSheet As Worksheet
    Dim curRow: curRow = 2
    Dim bDone
    Dim i As Integer
    Dim total

    Set curSheet = Worksheets(1)

    Rows("3:65536").Select
    Selection.Delete Shift:=xlUp

    While Not bDone
    curSheet.Cells((curRow + 1), 1).Value = CInt(curSheet.Cells(curRow, 1).Value / 2)
    curSheet.Cells((curRow + 1), 2).Value = CInt(curSheet.Cells(curRow, 2).Value * 2)

    curRow = curRow + 1

    If curSheet.Cells(curRow, 1).Value = 1 Then
    bDone = True
    End If
    Wend

    curSheet.Cells(2, 3).Value = 0
    For i = 2 To curRow
    If curSheet.Cells(i, 1).Value Mod 2 <> 0 Then
    curSheet.Cells(2, 3).Value = curSheet.Cells(2, 3).Value + curSheet.Cells(i, 2).Value
    ElseIf i > 2 Then
    Range("A" & i & ":B" & i).Select
    With Selection.Font
    .Strikethrough = True
    .ColorIndex = 3
    End With
    End If
    Next

    Range("C2").Select
    End Sub
  • Quxxy 2009-07-22 11:35
    A version for the D programming language; both as an interative function and a template:

    // Regular version.  Can also be used in compile-time code.
    
    long multiply(long a, long b)
    {
    if( a == 0 || b == 0 ) return 0;
    if( a < 0 ) return -multiply(-a, b);
    if( b < 0 ) return -multiply(a, -b);

    long acc = 0;
    do
    {
    if( a % 2 == 1 )
    acc += b;
    a /= 2;
    b *= 2;
    }
    while( a >= 1 );
    return acc;
    }

    // Template version
    template Multiply(long a, long b)
    {
    static if( a == 0 || b == 0 )
    const Multiply = 0L;

    else static if( a < 0 )
    const Multiply = Multiply!(-a, b);

    else static if( b < 0 )
    const Multiply = Multiply!(a, -b);

    else static if( a == 1 )
    const Multiply = b;

    else static if( a % 2 == 1 )
    const Multiply = b + Multiply!(a/2, b*2);

    else
    const Multiply = Multiply!(a/2, b*2);
    }
  • f3nd3r 2009-07-22 11:35
    Wow, you make PHP look good, that is pretty impressive.
  • Amadan 2009-07-22 11:37
    In Ruby,

    class Fixnum
    def *(b)
    a, k = self, 0
    a, b = -a, -b if a < 0
    while a != 0
    k += b if a & 1 == 1
    a >>= 1
    b <<= 1
    end
    k
    end
    end
  • Northpole 2009-07-22 11:37
    Ruby, one line, non-recursive:
    a,b,res=a/2,b*2,(res||0)+(a&1)*b while a>0
  • campkev 2009-07-22 11:42
    Second attempt at C#, this works with negative numbers:
    public int RussianMultiply(int operand1, int operand2)
    {
    int res = 0;
    while (operand1 != 0)
    {
    if (operand1 % 2 == 1) res += operand2;
    else if (operand1 % 2 == -1) res -= operand2;
    operand1 /= 2;
    operand2 *= 2;
    }
    return res;
    }
  • jweir77 2009-07-22 11:42
    Different twist on a Ruby solution:


    class Fixnum
    def rum n
    product = 0
    self.to_s(2).reverse.split(//).each_with_index do |bit, pos|
    product += ( n << pos ) if bit.to_i == 1
    end
    product
    end
    end

    p 3.rum(2)
    p 2.rum(3)
    p 18.rum(23)
    p 23.rum(18)
    p 76.rum(45)
    p 45.rum(76)

  • halber_mensch 2009-07-22 11:43
    Josh Bohde:
    Python 2.6

    m=lambda a,b:sum(a<<n for n in range(b) if b>>n&1)


    51 characters


    I'd argue it's not quite the russian algorithm though, since you've both reversed the operands and you are evaluating a-log2(a) more iterations than would be done in the real algorithm. For example, if I were to feed 5,4 into the russian algorithm, it would make 3 iterations (the left column being 5,2,1). Taking into account that you've swapped the parameters, your algorithm would evaluate 5 iterations (the left column being 5,2,1,0,0), or two more (5 - log2(5)) iterations than you should if you were adhering to the real algorithm, which stops evaluating when reaching 1 in the left column. Your solution also fails for negative values of a.
  • campkev 2009-07-22 11:43
    second attempt at C# recurisive, this works with negative numbers:
    public int RecursiveRussianMultiply(int operand1, int operand2)
    {
    return operand1 == 0 ? 0 : RecursiveRussianMultiply(operand1 / 2, operand2 * 2) + (operand1 % 2 == 1 ? operand2 : 0) + (operand1 % 2 == -1 ? -operand2 : 0);
    }
  • Floyd 2009-07-22 11:45

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Linq;

    namespace RussianPeasant
    {
    class RussianPeasant
    {
    static void Main(string[] args)
    {
    if (args.Length != 2)
    {
    Console.Error.WriteLine("Peasants can't multiply " + args.Length + " operands!");
    return;
    }

    int left = 0;
    int right = 0;

    if ((!int.TryParse(args[0], out left)) || (!int.TryParse(args[1], out right)))
    {
    Console.Error.WriteLine("Peasants can't multiply non-numeric operands!");
    }


    int solution = (from pair in GetColumns(left, right)
    where pair.First() % 2 != 0
    select pair).Sum(p => p.ElementAt(1));

    Console.WriteLine(solution);
    Console.Read();
    }

    public static IEnumerable<IEnumerable<int>> GetColumns(int left, int right)
    {
    yield return new int[] { left, right };

    while (left > 0)
    {
    left = left >> 1;
    right = right * 2;

    yield return new int[] { left, right };
    }
    }
    }
    }
  • Alex Guzman 2009-07-22 11:46
    int first = 18;
    int second = 23;

    int result = 0;

    while ((first = first / 2) >= 1)
    {
    second = second * 2;

    if (first % 2 != 0)
    result += second;
    }

  • kastein 2009-07-22 11:47
    Rootbeer:
    Herman:
    this is the exact implementation of the multiply function on binary computing hardware


    Is this so? I had assumed that most CPUs with MULtiply opcodes used hardware lookup tables, in order to achieve a fast and constant O(1) execution time, but perhaps I am mistaken. It's certainly a less sensible approach with 32- or 64-bit operands than it would have been with 8- or 16-bit operands.

    Yeah... it isn't really a good idea. I thought it was more sane until I considered the results...
    for 8 bit multiplication we have two 8 bit inputs and a 16 bit output, so the table is 2^16 bits long with 16 bit entries... that's 1M transistors without the decoders/addressing logic. The average 8 bit CPU has a few thousand to a few tens of thousands of transistors. It just gets worse from there - multiplying two 16 bit numbers requires 4G 32-bit entries (128G transistors!) and multiplying two 32 bit numbers requires 1024E transistors... multiplying 64 bit numbers using a lookup table would require more transistors than there are on the planet (by at least a factor of 1 pentillion based on my napkin calculations...)

    If you want to know how processors multiply, several methods are listed here: wikibooks: multiply
    Booth's Algorithm
    some more are listed here, not all easily applicable to microprocessor design: multiplication algorithms

    More (basically the peasant's method in hardware!) binary multiplier
  • Jürgen 2009-07-22 11:48
    Python:


    def rpmul(a, b):
    return ((a == 1) and b or (a % 2) * b + rpmul(a/2, 2*b))


    Ruby:


    def rpmul a, b
    (a == 1) ? b : (a % 2) * b + rpmul(a/2, 2*b)
    end


  • Bryan 2009-07-22 11:53
    All we need is a SAS submission and this thread will be complete.
  • Alex Muscar 2009-07-22 11:53
    Common Lisp

    Imperative/iterative and functional solutions. Ain't it nice that Lisp's so versatile? :P

    (defun rpm (m n)
    (do ((t1 m (ash t1 -1))
    (t2 n (ash t2 1))
    (r 0 (+ r (* (mod t1 2) t2))))
    ((= t1 0) r)))


    (defun rpm-r (m n)
    (labels ((rec (acc m n)
    (if (= m 0)
    acc
    (rec (+ acc (* (mod m 2) n)) (ash m -1) (ash n 1)))))
    (rec 0 m n)))
  • Josh Bohde 2009-07-22 11:55
    halber_mensch:
    Josh Bohde:
    Python 2.6

    m=lambda a,b:sum(a<<n for n in range(b) if b>>n&1)


    51 characters


    I'd argue it's not quite the russian algorithm though, since you've both reversed the operands and you are evaluating a-log2(a) more iterations than would be done in the real algorithm. For example, if I were to feed 5,4 into the russian algorithm, it would make 3 iterations (the left column being 5,2,1). Taking into account that you've swapped the parameters, your algorithm would evaluate 5 iterations (the left column being 5,2,1,0,0), or two more (5 - log2(5)) iterations than you should if you were adhering to the real algorithm, which stops evaluating when reaching 1 in the left column. Your solution also fails for negative values of a.


    Yeah, I was saving some characters (at the cost of a lot of memory).

    Here's a recursive version that is 48 characters

    m=lambda a,b:[0,b][a&1]+m(a>>1,b<<1)if a else 0
  • Sal 2009-07-22 11:56
    Postscript:
    /rmul{0{2 index 0 eq{exit}if exch dup 1 bitshift 4 1 roll 3 -1 roll dup -1 bitshift 5 1 roll 1 and 1 eq {add}{pop}ifelse}loop exch pop exch pop}def
  • AdT 2009-07-22 11:58
    Osno:
    All the people using multiplication and division instead of shifting (except in languages where there is no shifting) also fail.


    All the people who don't know what an optimizing compiler is also fail.
  • Alex Muscar 2009-07-22 11:59
    Common Lisp:

    Shorter version of the recursive implementation:


    (defun rpm-r1 (m n &optional (acc 0))
    (if (= m 0)
    acc
    (rpm-r1 (ash m -1) (ash n 1) (+ acc (* (mod m 2) n)))))
  • Murray 2009-07-22 11:59
    public String multiply(int a, int b){
    return "Murray is awesome";
    }
  • PopeHappyCat 2009-07-22 12:03
    Damn, you beat me too it. But here you can has lolcode spec 1.2

    (Untested)


    HAI 1.2
    CAN HAS STDIO?

    I HAS A X
    I HAS A Y
    I HAS A MULTIPL
    X R NUMBR
    Y R NUMBR

    VISIBLE "CAN HAS X?:)"
    GIMMEH X
    VISIBLE "CAN HAS Y?:)"
    GIMMEH Y

    HOW DUZ I RPM YR X AN YR Y
    I HAS A MUTLIPL ITZ 0
    I HAS A MODD
    I HAS A LOLCAT ITZ MAEK WIN A NUMBR BTW IS DUMMY VARIABLE FOR L00P
    IM IN YR RPMLOOP UPPIN YR LOLCAT WILE DIFFRINT X AN 1
    X R MAEK QUOSHUNT OF X AN 2 A NUMBR
    Y R PRODUKT OF Y AN 2
    MODD R MOD X AN 2
    BOTH SAEM MODD AN 1, O RLY?
    YA RLY, MULTIPL R SUM OF MULTIPL AN Y
    NO WAI, BTW NOTHING HAPPENS
    OIC
    IM OUTTA YR RPMLOOP
    FOUND YR MULTIPL
    IF U SAY SO

    MULTIPL R RPM X Y

    VISIBLE "PRODUKT OF " N X N " N " N Y N " IZ " N MULTIPL N ":)"

    KTHXBYE
  • Fooba 2009-07-22 12:03
    C implementation:

    int russian(int a, int b) {int c=0,d=a^b;a*=(a<0)?-1:1;for(a<<=1;(a>>=1)!=0;b<<=1)c+=a&0x1?b:0;return((c^d)<0?-c:c);}

  • koblas 2009-07-22 12:03
    Another python version


    def mult(a, b) :
    v = []
    while a != 0 :
    v.append((a % 2 != 0, b))
    print a%2, a, b
    a >>= 1
    b <<= 1
    print reduce(lambda x, y: x+y, [p[1] for p in v if p[0]])

  • Bosshog 2009-07-22 12:06


    ; 6502 Assembler
    ; Runs on NES, BBC, C64, Atari 2600 and Apple II :)
    ; This is the 16-bit version to handle the example 18x23!

    ; $0002 contains unsigned 8-bit operand 1 (not preserved)
    ; $0004 contains unsigned 8-bit operand 2 (not preserved)
    ; $0001:0000 will contain HI:LO bytes of 16-bit answer

    LDA #0
    STA $00
    STA $01
    STA $03
    LDX #0
    loop:
    CPX $04
    BEQ done
    CLC
    LSR $04
    BCC skip

    CLC
    LDA $00
    ADC $02
    STA $00
    LDA $01
    ADC $03
    STA $01
    skip:
    CLC
    ASL $02
    ROL $03
    JMP loop
    done:
  • halber_mensch 2009-07-22 12:07
    Josh Bohde:
    halber_mensch:
    Josh Bohde:
    Python 2.6

    m=lambda a,b:sum(a<<n for n in range(b) if b>>n&1)


    51 characters


    I'd argue it's not quite the russian algorithm though, since you've both reversed the operands and you are evaluating a-log2(a) more iterations than would be done in the real algorithm. For example, if I were to feed 5,4 into the russian algorithm, it would make 3 iterations (the left column being 5,2,1). Taking into account that you've swapped the parameters, your algorithm would evaluate 5 iterations (the left column being 5,2,1,0,0), or two more (5 - log2(5)) iterations than you should if you were adhering to the real algorithm, which stops evaluating when reaching 1 in the left column. Your solution also fails for negative values of a.


    Yeah, I was saving some characters (at the cost of a lot of memory).

    Here's a recursive version that is 48 characters

    m=lambda a,b:[0,b][a&1]+m(a>>1,b<<1)if a else 0

    m(-1,2)
    ....
    File "<stdin>", line 1, in <lambda>
    File "<stdin>", line 1, in <lambda>
    RuntimeError: maximum recursion depth exceeded

    =(

  • Timepass 2009-07-22 12:08

    package com.timepass;

    public class RussianMultiply {

    private int mulTotal = 0;
    RussianMultiply(){
    super();
    }
    private void multiply(int first,int second, boolean isFirstTime){
    if(first == 0 || second ==0){
    return;
    }
    if(isFirstTime && first%2!=0){
    mulTotal = mulTotal + second;
    }
    int tempFirst = first/2;
    int tempSecond = second*2;
    if(tempFirst%2!=0){
    mulTotal = mulTotal + tempSecond;
    }
    if(tempFirst != 1){
    multiply(tempFirst,tempSecond,false);
    }
    }
    public void multiply(int first,int second){
    multiply(first,second,true);
    }

    public void clearMulTotal(){
    setMulTotal(0);
    }

    public int getMulTotal() {
    return mulTotal;
    }
    public void setMulTotal(int mulTotal) {
    this.mulTotal = mulTotal;
    }


    /**
    * @param args
    */
    public static void main(String[] args) {
    RussianMultiply rm = new RussianMultiply();

    rm.clearMulTotal();
    rm.multiply(18, 23);
    System.out.println("Multiplication of 18 and 23:" + rm.getMulTotal());

    rm.clearMulTotal();
    rm.multiply(13, 13);
    System.out.println("Multiplication of 13 and 13:" + rm.getMulTotal());



    }


    }


    result:
    Multiplication of 18 and 23:414
    Multiplication of 13 and 13:169
  • chriswatson 2009-07-22 12:08
    C# using the delightful LINQ to objects


    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace RussianPeasantMultiplication
    {
    class Program
    {
    static void Main(string[] args)
    {
    Console.WriteLine("Russian Peasant Multiplication");

    Console.Write("Number 1: ");
    int number1 = Convert.ToInt32(Console.ReadLine());
    Console.Write("Number 2: ");
    int number2 = Convert.ToInt32(Console.ReadLine());

    List<Gimley> steps = new List<Gimley>();
    steps.Add(new Gimley(number1, number2));

    Console.WriteLine("Mutiply {0} by {1}", number1, number2);

    while (steps.Last().Left != 1)
    {
    Gimley lastStep = steps.Last();

    int newLeft = lastStep.Left / 2;
    int newRight = lastStep.Right * 2;

    steps.Add(new Gimley(newLeft, newRight));

    Console.WriteLine("Interim step: {0}, {1}", newLeft, newRight);
    }

    // discard even lefts and sum remaining rights
    decimal answer = (from g in steps
    where g.Left % 2 != 0
    select g.Right).Sum();

    Console.WriteLine("Answer is: {0}", answer);

    Console.ReadLine();
    }

    class Gimley
    {
    public int Left { get; set; }
    public int Right { get; set; }

    public Gimley(int left, int right)
    {
    Left = left;
    Right = right;
    }
    }
    }
    }
  • Jürgen 2009-07-22 12:11
    Alex thats nice, and very similiar to my ruby/python versions, except where summarization occurs.

    I didn't bother with the 3rd acc parameter because
    ruby/python don't do tail-end optimization on recursive calls any way.

    That's probably why many diss recursive solutions,
    but my profiler tells me theres little difference especially if you compare to solutions using python list comprehensions or ruby's .each iteration.


  • Anonymous 2009-07-22 12:11
    NO U!
  • Rob W. 2009-07-22 12:12
    #!/usr/bin/env python
    import sys

    try:
    sys.argv[1]
    sys.argv[2]
    except IndexError:
    numbers = raw_input("Please enter the two integers you wish to multiply separated by a space: ").split(' ')
    else:
    numbers = sys.argv[1:3]

    left = int(numbers[0].strip())
    right = int(numbers[1].strip())
    product = 0


    while left != 0:
    if left % 2 != 0:
    product += right
    left /= 2
    right*= 2

    print "The product of " + numbers[0].strip() + " x " + numbers[1].strip() + " is " + str(product)
  • serg 2009-07-22 12:13
    Some thoughts...

    ------------8<-------------------
    int mult(int a, int b) {
    int result = 0;

    while(a) {
    if(a & 0x01) {
    result += b;
    }

    a >>= 1;
    b <<= 1;
    }

    return result;
    }
    ------------8<-------------------
    int mult2(int a, int b) {
    int result = 0;

    if(a != 0) {
    result = mult2(a >> 1, b << 1);

    if(a & 0x01) {
    result += b;
    }
    }

    return result;
    }

  • Jannik Jochem 2009-07-22 12:13
    My functional-style java version...


    public static int multiply(int a, int b) {
    if (a == 0 || b == 0)
    return 0;
    else if (a == 1)
    return b;
    else
    return multiply(a/2, b*2) + ((a % 2 == 1) ? b : 0);
    }
  • Osno 2009-07-22 12:14
    All the people who don't know what an optimizing compiler is also fail.


    So you're basically agreeing with the " a * b " solution? Because defining multiplication by using multiplication is kind of weird (ok, I agree is in the spec, but anyway).

    And no, when you're using rounding in vb.net (or the "\" operator) I can assure you that doesn't get optimized. And C# doesn't get optimized, at least not in IL (but maybe at the JIT level).
  • wolf550e 2009-07-22 12:14
    http://www.phy6.org/outreach/edu/roman.htm

    This is not a Russian method but an ancient Roman one.
  • tirerim 2009-07-22 12:17
    #!/usr/bin/perl
    
    use integer;($a,$b)=@ARGV;while($a){$a%2and$r+=$b;$a/=2;$b*=2;}print $r;


    I admit that this takes a bit of a shortcut: it checks each pair of numbers as it comes up, and adds the second to the result if necessary at that time, rather than saving them all and waiting for the end.

    For anyone who really likes whitespace:

    #!/usr/bin/perl
    use integer;
    ($a, $b) = @ARGV;
    while ($a) {
    $a % 2 and $r += $b;
    $a /= 2;
    $b *= 2;
    }
    print $r;

  • SimonY 2009-07-22 12:17
    let peasant a b =
    let rec peasant a b acc =
    if a = 1 then b + acc else
    match a%2 with
    | 0 -> peasant a/2 b*2 acc
    | 1 -> peasant a/2 b*2 acc+b
    in peasant a b 0
  • Dave Havlicek 2009-07-22 12:18
    ruby:

    class Fixnum
    

    def *(num)
    cols = Array.new
    cols.push([self, num])
    while cols.last[0] != 1 do
    cols.push([cols.last[0] / 2, cols.last[1] + cols.last[1]])
    end
    cols.inject(0) { |sum, n| (n[0] % 2 == 1) ? sum + n[1] : sum }
    end
    end
  • Thuktun 2009-07-22 12:19
    Well, that's freakishly easy.

    public class RussianPeasantMultiplication {
    
    public static int multiply(int left, int right) {
    int sum = 0;
    while (left > 0) {
    System.out.println("left=" + left + " right=" + right);
    if ((left & 1) == 1) { // if odd
    sum += right; // collect this row
    }
    left >>= 1; // divide by two
    right <<= 1; // multiply by two
    }
    return sum;
    }

    public static void main(String[] args) {
    int left = Integer.parseInt(args[0]);
    int right = Integer.parseInt(args[1]);
    int result = multiply(left, right);
    System.out.println("result=" + result);
    }
    }

    left=18 right=23
    left=9 right=46
    left=4 right=92
    left=2 right=184
    left=1 right=368
    result=414
  • JoLoCo 2009-07-22 12:23
    Here, for the sake of it, is a Sinclair BASIC version.


    10 LET a=18: LET b=23
    20 LET tot=0
    30 IF a<0 THEN LET a=0-a: LET b=0-b
    40 IF (a/2) <> INT (a/2) AND a>0 THEN LET tot=tot+b
    50 LET a= INT (a/2)
    60 LET b=b*2
    70 IF a>0 THEN GO TO 40
    80 PRINT tot


    Is this the first entry to feature line numbers?
  • Patrick Simpson 2009-07-22 12:23
    An F# quicky:

    let rec RussianPeasantMultiplication a b = 
    
    if a < 0 then -(RussianPeasantMultiplication (-a) b)
    else (if a % 2 = 1 then b else 0) + (if a > 1 then RussianPeasantMultiplication (a / 2) (b * 2) else 0)
  • idle 2009-07-22 12:24
    untested Java, quick and dirty...

    public static int mult(int x, int y){

    Integer x1 = new Integer(x);
    int result = 0;

    for(int i = 0; i < Integer.toBinaryString(x1).length(); i++){
    if(Integer.toBinaryString(x1).endsWith("1"))
    result += y * (int)Math.pow(2, i);
    x1 = Integer.rotateRight(x1, 1);
    }
    return result;
    }
  • halber_mensch 2009-07-22 12:25
    Extrapolated from discussion with Josh Bohde:

    m=lambda a,b:b*(a&1)+m(a>>1,b<<1) if abs(a)>1 else a*b

    55 chars... not as short but handles all integers.
  • Noah Easterly 2009-07-22 12:25
    Haskell:


    let peasantMultiply a b = f a b 0
    where f a b s | a < 0 = f (negate a) (negate b) s
    | a == 0 = s
    | otherwise =
    let (a',r) = a `divMod` 2 in
    f a' (2*b) (if r == 1 then s + b else s)
  • klagdon 2009-07-22 12:26
    Accounts for either argument being zero, also throws an exception if trying to multiply a negative number. Tested with given main() method

    public static long multiply(long first, long second) {
    if(first < 0 || second < 0) {
    throw new IllegalArgumentException("May only multiply positive numbers");
    } else if(first == 0 || second == 0) {
    return 0;
    } else if(first == 1) {
    return second;
    } else if(first % 2 == 1) {
    return second + multiply(first / 2, second * 2);
    } else {
    return multiply(first / 2, second * 2);
    }
    }

    public static void main(String[] args) {
    Random r = new Random();
    for(int i = 0 ; i < 1000000 ; i++) {
    long first = (long)Math.abs(r.nextInt());
    long second = (long)Math.abs(r.nextInt());
    if((first * second) != multiply(first,second)) {
    System.out.println("Failed for " + first + " * " + second + "\t" + (first * second) + "\t" + multiply(first,second));
    }
    }
    }
  • Chad M 2009-07-22 12:26

    def russian_mult(l, r):
    """Use Russian-peasant multiplication method. They don't understand zero
    or negative numbers very well, according to the description. We fix that
    with simple rules. If left side has negative sign, change sign of result. tdwtf at chad org
    """

    rows = list()
    rows.append((l, r))
    while abs(l) > 1:
    l = l // 2
    r = r * 2
    rows.append((l, r))

    if l < 0:
    return 0 - sum(r for l, r in rows if l%2==1)
    else:
    return sum(r for l, r in rows if l%2==1)

  • Dave van der Brugge 2009-07-22 12:26
    So many nice solutions, yet nobody has offered a solution using XSLT yet.

    So here is mine. The xsl and xml code can be seen here:
    http://damastabrain.mine.nu/RPA/highlight.php
    For a better highlight function (at least Firefox), view the xsl itself:
    http://damastabrain.mine.nu/RPA/russianPeasantAlgorithm.xsl
    And ofcourse to show the outcome:
    http://damastabrain.mine.nu/RPA/russianPeasantAlgorithm.xml

    Note: it Does work with negative numbers, on either one of the two or both sides. (Integer only)
  • jjs105 2009-07-22 12:28

    function russian_multiply_true_lookup (left, right) {

    if (left == 0) return 0;
    if (left == 1) return right;

    var lookup = [{left: left, right: right}];

    while (left > 1) {
    left = Math.floor(left / 2);
    right = right * 2;
    lookup.push({left: left, right: right});
    }

    var result = 0;

    for (var index = 0; index < lookup.length; index++)
    if (lookup[index].left % 2 == 1)
    result += lookup[index].right;

    return result;
    }

  • darklajid 2009-07-22 12:29
    Forget about the sticker, I played a lot with F# today. Thanks for the motivation.


    let russianMultiplication x y =
    let rec l a b = seq { yield (a, b); yield! l (a>>>1) (b<<<1) }
    l x y |> Seq.takeWhile (fun c -> fst c > 0) |> Seq.fold (fun acc (x,y) ->
    if x % 2 = 1 then acc + y else acc
    ) 0
  • imhe 2009-07-22 12:31
    Accounts for 0 and negative numbers, tested with main
    //Earlier posted as guest, now posting as member}

    package com.timepass;

    public class RussianMultiply {

    private int mulTotal = 0;
    private boolean isMulTotalNegative = false;
    RussianMultiply(){
    super();
    }
    private void multiply(int first,int second, boolean isFirstTime){
    // if any number 0 return
    if(first == 0 || second ==0){
    return;
    }
    //check for negative numbers
    if(isFirstTime){

    if(first < 0 && second < 0) {
    isMulTotalNegative = false;
    first = first*-1;
    second = second * -1;
    }
    if(first < 0){
    isMulTotalNegative = true; first = first*-1;
    }
    if(second < 0){
    isMulTotalNegative = true;second = second * -1;
    }
    }
    // first time and odd number add to total
    if(isFirstTime && first%2!=0){
    mulTotal = mulTotal + second;
    }

    // 1st column not even , add to total
    int tempFirst = first/2;
    int tempSecond = second*2;
    if(tempFirst%2!=0){
    mulTotal = mulTotal + tempSecond;
    }
    // first colum not 1, do it again
    if(tempFirst != 1){
    multiply(tempFirst,tempSecond,false);
    }
    }
    public void multiply(int first,int second){
    multiply(first,second,true);
    }

    public void clearMulTotal(){
    setMulTotal(0);
    }

    public int getMulTotal() {
    if(isMulTotalNegative()){
    return -1*this.mulTotal;
    }
    return this.mulTotal;
    }
    public void setMulTotal(int mulTotal) {
    this.mulTotal = mulTotal;
    }


    /**
    * @param args
    */
    public static void main(String[] args) {
    RussianMultiply rm = new RussianMultiply();

    rm.clearMulTotal();
    rm.multiply(18, 23);
    System.out.println("Multiplication of 18 and 23:" + rm.getMulTotal());

    rm.clearMulTotal();
    rm.multiply(13, 12);
    System.out.println("Multiplication of 13 and 12:" + rm.getMulTotal());

    rm.clearMulTotal();
    rm.multiply(12, 12);
    System.out.println("Multiplication of 12 and 12:" + rm.getMulTotal());

    rm.clearMulTotal();
    rm.multiply(-12, -12);
    System.out.println("Multiplication of -12 and -12:" + rm.getMulTotal());

    rm.clearMulTotal();
    rm.multiply(-12, 12);
    System.out.println("Multiplication of -12 and 12:" + rm.getMulTotal());

    }
    public boolean isMulTotalNegative() {
    return isMulTotalNegative;
    }
    // public void setMulTotalNegative(boolean isMulTotalNegative) {
    // this.isMulTotalNegative = isMulTotalNegative;
    // }


    }



    Multiplication of 18 and 23:414
    Multiplication of 13 and 12:156
    Multiplication of 12 and 12:144
    Multiplication of -12 and -12:144
    Multiplication of -12 and 12:-144
  • Codism 2009-07-22 12:32
    Yet another Linq solution:
    public static int rpm(int a, int b)
    {
    return Enumerable.
    Range(0, a < 2 ? 1 : (int)Math.Ceiling(Math.Log(a % 2 == 0 ? a + 1 : a, 2)))
    .Select(i => new { L = a / (1 << i), R = b * (1 << i) })
    .Where(x => x.L % 2 != 0).Sum(x => x.R);
    }
  • Anonymous 2009-07-22 12:32
    I've never seen a comments page fill up so quickly (at least, not with legitimate and well thought out comments). This has been a rousing success!
  • John Evans, btradish@earthlink.net 2009-07-22 12:33
    This is PHP, although it probably works as Perl too.


    $a = 18;
    $b = 23;

    for ($t = 0; $a > 0; $a >>= 1, $b <<= 1)
    $t += (($a % 2) * $b);

    echo "total: $t\n";
  • Albrecht from Germany 2009-07-22 12:36
    # This one ist Tcl/Tk http://www.tcl.tk
    proc russ {a b} {
    set erg 0
    if {$a < 0} {
    set a [expr {-1 * $a}]
    set b [expr {-1 * $b}]
    }
    for {} {$a} {} {
    if {$a&1} {
    incr erg $b
    puts [format %5d%5d%5d $a $b $erg]
    } else {
    puts [format %5d%5d $a $b ]
    }
    set a [expr {$a >> 1}]
    set b [expr {$b << 1}]
    }
    puts "==========[format %5d $erg] ======="
    return $erg
    }
    russ 18 23
  • Jim Halfpenny 2009-07-22 12:37
    Here's the 'schoolbook' perl version to demonstrate recusive fuctions. No fancy operators, indentation where appropriate and variable names which provide no description of that they do. And of course no comments.

    It's kind of beautiful.

    print axb($ARGV[0],$ARGV[1]) . "\n";
    sub axb {
    my $a = shift;
    my $b = shift;
    my $total = 0;
    if ($a == 1) {
    return $b;
    } else {
    if ($a % 2) {
    $total += $b;
    }
    $ah = int($a / 2);
    $bh = $b * 2;
    return $total + axb($ah,$bh);
    }
    }
  • leppie 2009-07-22 12:38
    People still using * directly.

    That's cheating yourself!

    Try harder!
  • Albrecht from Germany 2009-07-22 12:40
    # This one ist Tcl/Tk http://www.tcl.tk
    
    # now with indentation
    proc russ {a b} {
    set erg 0
    if {$a < 0} {
    set a [expr {-1 * $a}]
    set b [expr {-1 * $b}]
    }
    for {} {$a} {} {
    if {$a&1} {
    incr erg $b
    puts [format %5d%5d%5d $a $b $erg]
    } else {
    puts [format %5d%5d $a $b ]
    }
    set a [expr {$a >> 1}]
    set b [expr {$b << 1}]
    }
    puts "==========[format %5d $erg] ======="
    return $erg
    }
    russ 18 23
  • Bob Montgomery 2009-07-22 12:40
    Bosshog:

    ; 6502 Assembler (4-bit operands only)
    ; $0001 should contain operand 1 (not preserved)
    ; $0002 should contain operand 2 (not preserved)

    LDA #0
    LDX #0
    loop:
    CPX $02
    BEQ done
    CLC
    LSR $02
    BCC skip
    CLC
    ADC $01
    skip:
    ASL $01
    JMP loop

    done:
    STA $00

    You beat me to the punch, but there is some unnecessary code in there (you don't need to clear the carry before a LSR). And trashing X is unnecessary since you can test for zero just as fast with LDA $02. Or with some crazy jujitsu to save a byte...
    Here's my version, handles 8-bit operands:
    ;--$00 holds operand 1
    
    ;--$01 (low byte) and $02 (high byte) hold operand 2
    ;--$03 (low byte) and $04 (high byte) hold product
    cld
    Loop
    lsr $00
    bcc NoAdd
    clc
    lda $03
    adc $01
    sta $03
    lda $04
    adc $02
    sta $04
    .byte $2C
    NoAdd
    beq Done
    asl $01
    rol $02
    bcc Loop ;this assumes that operand 2 is 8-bit
    Done
  • Jared Youtsey 2009-07-22 12:41
    public static double Multiply(long left, long right)
    {
    AddRecord(left, right);
    Recurse(left, right);
    var result = 0D;
    foreach (var row in table)
    {
    result += row.Value;
    }

    return result;
    }

    public static void Recurse(long left, long right)
    {
    var newLeft = (long)(left / 2);
    var newRight = right * 2;
    AddRecord(newLeft, newRight);
    if (newLeft != 1)
    {
    Recurse(newLeft, newRight);
    }
    }

    private static void AddRecord(long newLeft, long newRight)
    {
    long remainder;
    var ignored = Math.DivRem(newLeft, 2L, out remainder);
    if (remainder != 0)
    {
    table.Add(newLeft, newRight);
    Console.WriteLine("left = " + newLeft + "\tright = " + newRight);
    }
    }
  • acsi 2009-07-22 12:42
    Spreadsheet...

    First number goes in A2
    A3 through A41 have "=TRUNC(A2/2)", "=TRUNC(A3/2)", etc (enter in A3, drag lower-right corner to expand to full range, in Excel at least the formulas in the additional cells will be adjusted to keep the relative positions of the referenced cells the same).

    Second number goes in B2
    B3 through B41 have "B2*2", "B3*2", etc.

    C2 through C41 have "=IF(MOD(A2, 2) = 1, B2, 0)", "=IF(MOD(A3, 2) = 1, B3, 0)", etc.

    D2 has "=SUM(C2:C41)", and is the result.

    A1 through D1 have headers "First Number", "Second Number", "Cross out where A is even", and "Result".


    This function can be called by using the MSOffice interop libraries to open the spreadsheet, populate A2 and B2, and read D2 (there might be another step in between to tell it to run the actual calculation, I forget).
  • amischiefr 2009-07-22 12:43
    Just my own little recursive Java solution:

    private int multiply(int n, int m, int val) {
    if(n <= 1)
    return val;
    return multiply(n/2,m*2,((n/2)%2!=0 ? val+=m*2 : val) );
    }

    And of course, the ternary one liner:

    private int multiplyOneLiner(int n, int m, int val) {
    return (n <= 1 ? val : multiply(n/2,m*2,((n/2)%2!=0 ? val+=m*2 : val) ));
    }
  • Osno 2009-07-22 12:43
    MSIL:

    .method private hidebysig static int64 Multiply(int64 f, int64 s) cil managed
    {
    .maxstack 3
    start:
    ldarg.0
    dup
    ldc.i4.0
    beq.s done
    ldc.i4.1
    and
    ldarg.1
    mul
    next:
    ldarg.0
    ldc.i4.1
    shr
    ldarg.1
    ldc.i4.1
    shl
    call int64 RussianMult.Program::Multiply(int64, int64)
    add
    done:
    ret
    }
  • Lunkwill 2009-07-22 12:44
    As we haven't had any m68k yet:

    ; op1: d0
    
    ; op2: d1
    ; out: d0
    ; scratch: d2
    peasantmult:
    clr.l d2
    .loop: tst.l d0
    beq.s .exit
    lsr.l d0
    bcc.s l
    add.l d1,d2
    asl.l d1
    bra.s .loop
    .exit: move.l d2,d0
    rts


    20 bytes in binary :)
  • Jared Youtsey 2009-07-22 12:45
    After looking at some of the other solutions I realize that I don't do this kind of programming and why. This kind of boolific bitshifty goodness is brain melting. But it was fun. But boy am I shamed by the cleverness of many of the other solutions.
  • HonoredMule 2009-07-22 12:46
    This revision of The Wolf's PHP solution handles negative numbers and displays the columns in a table with unused rows crossed out.


    <?php

    function visual_russian($x, $y) {
    $left = array();
    $right = array();
    $str = "<table><th><tr><td><em>Operand:<br />$x</em></td><td><em>Operator:<br />$y</em></td></tr></th><tbody>";

    $sign = 1;
    if($x < 0) {
    $sign *= -1;
    $x = abs($x);
    }
    if($y < 0) {
    $sign *= -1;
    $y = abs($y);
    }

    while ($x >= 1) {
    $left[] = $x;
    $right[] = $y;
    if($x % 2)
    $str .= "<tr><td><s>$x</s></td><td><s>$y</s></td></tr>";
    else
    $str .= "<tr><td>$x</td><td>$y</td></tr>";
    $x = floor($x / 2);
    $y *= 2;
    }

    $result = 0;
    foreach ($left as $index => $x) if ($x % 2)
    $result += $right[$index];
    $result = $sign * $result;
    $str .= "<tr><td>Answer:</td><td>$result</td></tr></tbody></table>";
    return $str;
    }

    echo visual_russian(156657, -159643248);

    ?>
  • Alex Muscar 2009-07-22 12:47
    Common Lisp:

    No multiplication.

    (defun rpm (m n)
    (do ((t1 m (ash t1 -1))
    (t2 n (ash t2 1))
    (r 0))
    ((= t1 0) r)
    (when (= (logand t1 1) 1)
    (incf r t2))))

    The parens might be unbalanced since I'm writing this from my phone.
  • David C. 2009-07-22 12:47
    33 characters in C#:

    (a,b)=>a==1?b:m(a/2,b*2)+b*(a&1);

    Implementing this lambda expression in code is left as an exercise for the reader (hint: assign it to a delegate named 'm')
  • HonoredMule 2009-07-22 12:50
    Reading many of these ingenious, esoteric, or even simple and straight-forward implementations in various languages makes me very happy that I don't often have to use languages other than PHP.
  • Jörg 2009-07-22 12:50
    A slightly more sophisticated python version:
    def peasant_mul(a,b):
    
    def numbers(a=a, b=b):
    if a < 0:
    a, b = -a, -b
    while a:
    if a & 1:
    yield b
    a >>= 1
    b <<= 1
    return sum(numbers())


    why is code double-spaced or is that my firefox?
  • Josh Bohde 2009-07-22 12:51
    halber_mensch:
    Extrapolated from discussion with Josh Bohde:

    m=lambda a,b:b*(a&1)+m(a>>1,b<<1) if abs(a)>1 else a*b

    55 chars... not as short but handles all integers.


    Just because I think using * isn't in the spirit of this.


    m=lambda a,b:[0,b][a&1]+m(a>>1,b<<1)if a else 0
    n=lambda a,b:(lambda n,t:[n,~n+1][t])((m(abs(a),abs(b))),(a<0)^(b<0))


    n will handle negatives.
    118 characters, including newline.
  • HonoredMule 2009-07-22 12:52
    One last tweak: forgot to switch the floor($x / 2) for a bit shift.


    <?php

    function visual_russian($x, $y) {
    $left = array();
    $right = array();
    $str = "<table><th><tr><td><em>Operand:<br />$x</em></td><td><em>Operator:<br />$y</em></td></tr></th><tbody>";

    $sign = 1;
    if($x < 0) {
    $sign *= -1;
    $x = abs($x);
    }
    if($y < 0) {
    $sign *= -1;
    $y = abs($y);
    }

    while ($x >= 1) {
    $left[] = $x;
    $right[] = $y;
    if($x % 2)
    $str .= "<tr><td><s>$x</s></td><td><s>$y</s></td></tr>";
    else
    $str .= "<tr><td>$x</td><td>$y</td></tr>";
    $x = $x >> 1; //floor($x / 2);
    $y *= 2;
    }

    $result = 0;
    foreach ($left as $index => $x) if ($x % 2)
    $result += $right[$index];
    $result = $sign * $result;
    $str .= "<tr><td>Answer:</td><td>$result</td></tr></tbody></table>";
    return $str;
    }

    echo visual_russian(156657, -159643248);

    ?>
  • DaMastaBrain 2009-07-22 12:53
    Dave van der Brugge:
    So many nice solutions, yet nobody has offered a solution using XSLT yet.

    So here is mine. The xsl and xml code can be seen here:
    http://damastabrain.mine.nu/RPA/highlight.php
    For a better highlight function (at least Firefox), view the xsl itself:
    http://damastabrain.mine.nu/RPA/russianPeasantAlgorithm.xsl
    And ofcourse to show the outcome:
    http://damastabrain.mine.nu/RPA/russianPeasantAlgorithm.xml

    Note: it Does work with negative numbers, on either one of the two or both sides. (Integer only)

    Hadnt registered yet...
    Also it now works with 0 on any side.
  • semanticprecision 2009-07-22 12:54
    Obligatory solution from a Haskell neophyte:


    rpMultiply a b =
    ( sum . map snd . filter ( odd . fst ) ) ( zip ( takeWhile ( >= 1 ) a' ) b' )
    where
    a' = a : ( map ( `div` 2 ) a' )
    b' = b : ( map ( (*) 2 ) b' )
  • martinp 2009-07-22 12:55
    Did this in Python, and it made me remember why I like it so much.

    def rp_multiply(m, n):
    
    sum = 0
    while m >= 1:
    if m % 2 != 0:
    sum += n
    n *= 2
    m /= 2;
    return sum


  • hornet 2009-07-22 12:59
    long rmultiply(long a, long b)
    {
    return (a==1)?b:((a&1)?b:0)+rmultiply(a>>1,b<<1);
    }
  • Cindi Knox 2009-07-22 12:59
    mIRC

    alias productRussianPeasant {
    ;multiplies two integers using Russian Peasant method
    ;parms: multiplier, multiplicand
    ;returns: product
    var %lMultiplier
    var %lMultiplicand
    var %lProduct

    ;use minimum iterations - smaller parm goes in multiplier:
    if ($1 < $2) {
    %lMultiplier = $1
    %lMultiplicand = $2
    }

    else {
    %lMultiplier = $2
    %lMultiplicand = $1
    }

    ;clear product accumulator:
    %lProduct = 0


    while (%lMultiplier > 0) {
    if ($calc(%lMultiplier % 2) > 0) {
    ;multiplicans counts toward product if multiplier is odd:
    %lProduct = $calc(%lProduct + %lMultiplicand)
    }
    %lMultiplier = $int($calc(%lMultiplier / 2))
    %lMultiplicand = %lMultiplicand * 2
    }

    return %lProduct
    }

  • Bored 2009-07-22 12:59

    int rmul(auto a, auto b) {
    auto sum=0,target=a*b;
    while(sum!=target) {
    sum += a&1?b:0, a>>=1, b<<=1;
    }
    return sum;
    }


    I like it since it does the builtin multiply anyway, and then the calculation. NB: infinite loops may happen with -ve numbers.
  • xtremezone 2009-07-22 13:00
    My implementation is in C (or C++).
    typedef unsigned long ulong;
    
    ulong russian_peasant_mult(ulong x, ulong y)
    {
    ulong result = 0;
    if(x == 0 || y == 0)
    return 0;
    if(x % 2 != 0)
    result += y;
    while(x != 1)
    {
    y *= 2;
    if((x /= 2) % 2 != 0)
    result += y;
    }
    return result;
    }

    If you accuse me of initially using std::list and std::pair I'll deny it! Deny!
  • Tim Pierce 2009-07-22 13:01
    There is no language restriction, though anything on the esoteric language list will probably be ignored.


    Including Perl? :-)
  • DougB 2009-07-22 13:02
    Quick Solution in Delphi. Accompanying form has a StdCtrls Memo to display columns named Memo1. Two edit boxes allow input of multiplicands (edit1 := Leftside, edit2 := Rightside). ClearValues simply clears the edit boxes and resets all totals. lblResult is a label displaying the result. This routine will not handle negative numbers.

    procedure TForm1.ComputeRpProduct;
    var
    vTotal : Integer;

    {SUB}
    procedure AddLineToMemo;
    begin
    if (Leftside mod 2) <> 0 then
    begin
    Memo1.Lines.Add(inttostr(Leftside) + ' ' + inttostr(RightSide));
    vTotal := vTotal + Rightside;
    end
    else
    begin
    Memo1.Lines.Add(inttostr(Leftside) + ' ' + inttostr(RightSide) + ' ---');
    end;
    end;
    {/SUB}

    begin
    if (Leftside <> 0) and (Rightside <> 0) then
    begin

    vTotal := 0;

    AddLineToMemo;

    while Leftside <> 1 do
    begin

    Leftside := Leftside div 2;
    Rightside := Rightside * 2;

    AddLineToMemo;

    end;

    lblResult.Caption := IntToStr(vTotal);

    end
    else
    begin
    ShowMessage('Please enter numeric nonzero values to compute.');
    ClearValues;
    Edit1.setfocus;
    end;


    end;
  • mucki.at 2009-07-22 13:06
    I didn't read all the comments but this is also called "Shift and Add" in information processing, and this is typically how computers actually implement multiply. Thus, I propose this "hardware accelerated" version of the algorithm:

    return a*b;

    (see http://en.wikipedia.org/wiki/Multiplication_algorithm#shift_and_add for more info)
  • HonoredMule 2009-07-22 13:07
    I missed a lot previously...enough to make me register so I can erase evidence of future blunders. This PHP handles negative numbers, outputs an HTML table with the unused rows crossed out, and is derived from the code posted by The Wolf on page one of the comments:


    <?php

    function visual_russian($x, $y) {
    $str = "<table><th><tr><td><em>Operand:<br />$x</em></td><td><em>Operator:<br />$y</em></td></tr></th><tbody>";
    $result = 0;

    $sign = 1;
    if($x < 0) {
    $sign *= -1;
    $x = abs($x);
    }
    if($y < 0) {
    $sign *= -1;
    $y = abs($y);
    }

    while ($x > 1) {
    $x = $x >> 1;
    $y *= 2; // Bit-shifting $y causes overflow, but multiplication does not.
    if($x % 2) {
    $str .= "<tr><td><s>$x</s></td><td><s>$y</s></td></tr>";
    } else {
    $str .= "<tr><td>$x</td><td>$y</td></tr>";
    $result += $y;
    }
    }
    $str .= "<tr><td>Answer:</td><td>$result</td></tr></tbody></table>";
    return $str;
    }

    echo visual_russian(156657, -159643248);

    ?>
  • David Young 2009-07-22 13:07
    int russian_peasant(int n1, int n2) {
    int product = 0, sign = 1;

    if(n1 < 0) {
    sign = -1;
    }

    for(; n1 != 0; n1 /= 2, n2 *= 2) {
    if(n1 & 1) {
    product += n2;
    }
    }

    return product * sign;
    }
  • wombat 2009-07-22 13:08
    Recursive Common Table Expression in MS SQL Server:

    WITH russian
    AS (
    SELECT 45 a, 76 b
    UNION ALL
    SELECT a / 2, b + b
    FROM russian
    WHERE a > 1)
    SELECT ISNULL(SUM(b), 0) AS product
    FROM russian
    WHERE a & 1 = 1
  • Haggis 2009-07-22 13:10
    C++ using for loop

    for(int a=3,b=5,c=0;a>0;c+=(a&1?b:0),a>>=1,b<<=1,std::cout<<c<<std::endl);
  • xtremezone 2009-07-22 13:10
    xtremezone:
    My implementation is in C (or C++).
    typedef unsigned long ulong;
    
    ulong russian_peasant_mult(ulong x, ulong y)
    {
    ulong result = 0;
    if(x == 0 || y == 0)
    return 0;
    if(x % 2 != 0)
    result += y;
    while(x != 1)
    {
    y *= 2;
    if((x /= 2) % 2 != 0)
    result += y;
    }
    return result;
    }

    If you accuse me of initially using std::list and std::pair I'll deny it! Deny!
    I wrongly assumed it only worked for positive integers so I used unsigned types. :-[ Here's a quick fix.
    long russian_peasant_mult(long x, long y)
    
    {
    int negative = 0;
    long result = 0;
    if(x == 0 || y == 0)
    return 0;
    if(x < 0 && y > 0)
    {
    x *= -1;
    negative = 1;
    }
    else if(x > 0 && y < 0)
    {
    y *= -1;
    negative = 1;
    }
    if(x % 2 != 0)
    result += y;
    while(x != 1)
    {
    y *= 2;
    if((x /= 2) % 2 != 0)
    result += y;
    }
    if(negative)
    result *= -1;
    return result;
    }
  • hornet 2009-07-22 13:12
    Supporting negative numbers:
    long multiply(long a, long b)
    {
    return (a<0)?-multiply(-a,b):(a==1)?b:((a&1)?b:0)+multiply(a>>1,b<<1);
    }
  • anonymous 2009-07-22 13:12
    In JavaScript
    var s = 7 * 38;

    The binary approach is taken behind the scenes.
  • JJM 2009-07-22 13:13

    def multiply(a,b):
    c=0
    while a>1:
    a >>= 1
    b <<= 1
    c += b*(a&1)
    return c
  • Trey Jackson 2009-07-22 13:14
    common lisp from Emacs:

    (defun mymult (nn mm)
    (loop for n = nn then (/ n 2)
    for m = mm then (* m 2)
    until (< n 1)
    sum (if (oddp n) m 0)))
  • IcePanther 2009-07-22 13:14
    Solution in PHP :

    function peasant($a,$b)
    {
    $s = 0;
    while($a > 1)
    {
    $b *= 2;
    $a = floor($a/2);
    if(($a % 2) != 0) { $s += $b; }
    }

    return $s;
    }

    Could probably be made more efficient by using bitwise operations instead of base mathematical operators. Well, would obviously be more efficient NOT being written in PHP, too.
  • Tim 2009-07-22 13:15
    My recursive PHP CLI version. (Inputs must be >0)
    The output will create the table as shown in the instructions and even cross out the even rows.


    <?php


    function multiply($x, $y, $padX, $padY)
    {
    $even = ($x % 2 == 0);

    if ($even) {
    $pad = '-';
    } else {
    $pad = ' ';
    }

    echo $pad . $pad
    . str_pad($x, $padX, $pad, STR_PAD_LEFT)
    . $pad . 'x' . $pad
    . str_pad($y, $padX + $padY, $pad, STR_PAD_LEFT)
    . $pad . $pad . "\n";

    if (abs($x) == 1) {
    return $y;
    }

    $add = multiply((int) ($x/2), $y * 2, $padX, $padY);

    if (!$even) {
    return $y + $add;
    } else {
    return $add;
    }

    }

    $x = $argv[1];
    $y = $argv[2];
    $padX = strlen($x);
    $padY = strlen($y);

    if ($x <= 0 || $y <= 0) {
    echo 'Usage: ' . $argv[0] . ' x y' . "\n"
    . 'Both x and y must be greater than 0' . "\n";
    exit;
    }

    $product = multiply ($x, $y, $padX, $padY);

    echo str_pad('', $padX + $padX + $padY + 7, '_') . "\n"
    . str_pad($product, $padX + $padX + $padY + 5, ' ', STR_PAD_LEFT) . "\n";

  • Osno 2009-07-22 13:16
    Non-recursive MSIL, more stack-based:


    .method private hidebysig static int64 m(int64 f, int64 s) cil managed
    {
    .maxstack 4
    ldc.i4.0
    conv.i8
    start:
    ldarg.0
    ldc.i4.0
    beq.s done
    ldarg.0
    ldc.i4.1
    and
    ldarg.1
    mul
    add
    ldarg.0
    ldc.i4.1
    shr
    starg.s 0
    ldarg.1
    ldc.i4.1
    shl
    starg.s 1
    br.s start
    done:
    ret
    }
  • Andrew Nurse 2009-07-22 13:16
    This was perfectly timed, since I'm learning Haskell. It gave me the perfect opportunity to try out what I've learned so far :). So to add to the already numerous Haskell solutions, here's mine (I noticed it looked similar to others, so I guess I'm getting the hang of this functional programming thing :D):


    russianMult :: (Integral a) => a -> a -> a
    russianMult 1 y = y
    russianMult x y = if x `mod` 2 == 0 then
    multStep
    else
    multStep + y
    where multStep = russianMult (x `div` 2) (y * 2)


    I'm sure there's more concise ways to do this, but this works :).
  • Igor V. 2009-07-22 13:17
    Unobfuscated Perl:
    sub russian_peasant_multiply {
    
    my ($one, $two) = @_;
    my $rus = 0;
    do {
    $rus += $two if ($one & 1);
    } while ($one >>= 1 and $two <<= 1);
    return $rus;
    }
  • jeff.woodhull 2009-07-22 13:22
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace ConsoleApplication1
    {
    class Program
    {
    static void Main(string[] args)
    {
    var leftNum = 0;
    var rightNum = 0;

    if (args.Length != 2 || (!Int32.TryParse(args[0], out leftNum) || ! Int32.TryParse(args[1], out rightNum)))
    {
    Console.WriteLine("Please enter numbers like ConsoleApplication1.exe 5 10");
    return;
    }

    var answer = (from p in RussianPairs(leftNum, rightNum)
    where p.Left % 2 != 0
    select p.Right).Sum();

    Console.WriteLine("The answer to {0} * {1} is {2}", leftNum, rightNum, answer);
    Console.WriteLine("Press <enter> to exit");
    Console.ReadLine();
    }


    static IEnumerable<Pair> RussianPairs(int leftNumber, int rightNumber)
    {
    while (leftNumber >= 1)
    {
    yield return new Pair(leftNumber, rightNumber);
    leftNumber /= 2;
    rightNumber *= 2;
    }
    }

    internal class Pair
    {
    internal Pair(int left, int right)
    {
    Left = left;
    Right = right;
    }

    internal int Left { get; private set; }
    internal int Right { get; private set; }
    }
    }
    }
  • Tyler 2009-07-22 13:23
    You didn't add the first row in your first example.
  • It'sMe (It_sMe@jabber.org) 2009-07-22 13:24
    non recusive version in c# with 64bit in because russians love big numbers right?


    private static Int64 RussianPeasantMultiplication(Int64 first, Int64 second)
    {
    Int64 rvalue = 0;

    while(first > 0)
    {
    if(first % 2 != 0)
    {
    rvalue += second;
    }
    first /= 2;
    second *= 2;
    }

    return rvalue;
    }
  • Mike5 2009-07-22 13:27
    Anonymous Coward:
    Prolog:

    rusmul(0,_,0).
    rusmul(A,B,X) :- C is A//2, D is B*2, rusmul(C,D,E), X is E+(A mod 2)*B.

    "optimized" with bit-shifting


    russian( 0, _, 0 ).

    russian( A, B, C ) :-
    A /\ 1 =:= 1,
    B1 is B << 1,
    A1 is A >> 1,
    russian( A1, B1, C1 ),
    C is C1 + B.

    russian( A, B, C ) :-
    B1 is B << 1,
    A1 is A >> 1,
    russian( A1, B1, C ).
  • xtremezone 2009-07-22 13:28
    xtremezone:
    I wrongly assumed it only worked for positive integers so I used unsigned types. :-[ Here's a quick fix.
    long russian_peasant_mult(long x, long y)
    
    {
    int negative = 0;
    long result = 0;
    if(x == 0 || y == 0)
    return 0;
    if(x < 0 && y > 0)
    {
    x *= -1;
    negative = 1;
    }
    else if(x > 0 && y < 0)
    {
    y *= -1;
    negative = 1;
    }
    if(x % 2 != 0)
    result += y;
    while(x != 1)
    {
    y *= 2;
    if((x /= 2) % 2 != 0)
    result += y;
    }
    if(negative)
    result *= -1;
    return result;
    }
    <sigh/> Accounted for one negative number, but not two... Fixed. :P Maybe.
    long russian_peasant_mult(long x, long y)
    
    {
    int negative = x < 0 && y > 0 || x > 0 && y < 0;
    long result = 0;
    if(x == 0 || y == 0)
    return 0;
    if(x < 0)
    x *= -1;
    if(y < 0)
    y *= -1;
    if(x % 2 != 0)
    result += y;
    while(x != 1)
    {
    y *= 2;
    if((x /= 2) % 2 != 0)
    result += y;
    }
    if(negative)
    result *= -1;
    return result;
    }

    Though the negative workarounds do use multiplication which may be a paradox of sorts... >_<

    Addendum (2009-07-22 13:34):
    I suppose you could replace...
    x *= -1;

    ...with...
    x -= russian_peasant_mult(x, 2);

    :P

    Addendum (2009-07-22 13:36):
    No, no, wait, no you couldn't... Infinite recursion...
  • Bob 2009-07-22 13:28
    Scheme:

    (define (peasant* a b)
    
    (do ([acc '() (if (odd? a)
    (cons b acc)
    acc)]
    [a a (quotient a 2)]
    [b b (+ b b)])
    [(= a 1)
    (fold + b acc)]))


    Assumes fold:

    (define (fold p x l)
    
    (if (null? l)
    x
    (fold p
    (p (car l) x)
    (cdr l))))


    Easily done without the list, I thought it was more in keeping, though.
  • Nick Pope 2009-07-22 13:29
    After my earlier attempt with bc, I decided to try something more difficult: dc. Seems to work with negative numbers nicely too.

    Using dc (GNU bc 1.06.95) 1.3.95:

    Code (peasant.dc):

    sbsa0[la2~rsalbd2*sb*+0la!=r]dsrxp



    Examples:

    $ dc -e 39 -e 83 peasant.dc
    3237
    $ dc -e _45 -e 76 peasant.dc
    -3420
  • jonnyq 2009-07-22 13:32
    Ok here's mine... in javascript, which has its limits
    function multiply(x,y) {
    
    var z = 0;
    if(x < 0) y = 0-y;
    do {
    if(x&1 != 0) z += y; // add to z if x is odd
    x = (x>0?Math.floor:Math.ceil)(x/2); // halve x, drop remainder
    y += y; // double y
    } while(x != 0);
    return z;
    }


    Works for signed integers.

    Haven't read the comments, so someone may have already done the same thing.
  • Ronuk Raval 2009-07-22 13:32
    Don't know if this has been done yet (probably has).

    Naive recursive Python implementation:

    def mult(n1, n2):
    if n1 == 1:
    return n2
    if n1 % 2 == 1:
    return n2 + mult(n1 // 2, 2 * n2)
    else:
    return mult(n1 // 2, 2 * n2)


    Faster, bit-oriented C89 version (handles negatives):

    long mult(int n1, int n2)
    {
    int sign = 1, place = 1;
    long result = 0;

    if(n1 < 0) {
    sign *= -1;
    n1 = -n1;
    }
    if(n2 < 0) {
    sign *= -1;
    n2 = -n2;
    }

    while(n1 > 0) {
    if(n1 & 1) {
    result += place * n2;
    }
    n1 >>= 1;
    place <<= 1;
    }

    return sign * result;
    }
  • shane blake 2009-07-22 13:32
    wombat:
    Recursive Common Table Expression in MS SQL Server:


    ya beat me to it, but here's my similar effort anyway :

    ;with russia(x, y) as
    (
    select 18, 23
    union all
    select x / 2, y * 2 from russia where x > 1
    )
    select sum(y)
    from russia
    where x % 2 <> 0
  • MUMPS 2009-07-22 13:33
    MUMPS:
    P(I,S)
    
    S Q=I I I I S#2 S Q=0
    Q Q+P(I\2,S*2)

    Features:
    Shortened keywords!
    Keywords reused for variable names!
    Recursion!
    Untested!
  • Greg R 2009-07-22 13:35
    Recursive Java, taking advantage of its Unicode support.


    public static int умножить(int Значение1, int Значение2) {
    if(Значение1 == 1)
    return Значение2;

    int крестьянин = умножить(Значение1 / 2, Значение2 * 2);
    if(Значение1 % 2 == 1)
    крестьянин += Значение2;

    return крестьянин;
    }
  • aBase 2009-07-22 13:36
    I cleaned-up the PHP function I posted earler. As before, it
    - handles non-integers,
    - handles negative numbers,
    - doesn't choke on zero.
    function potemkin_multiply($two_numbers)
    
    {
    $power = 0;
    $sign = 1;
    foreach ($two_numbers as $num) {
    if ($num == 0) {
    return 0;
    } elseif ($num < 0) {
    $sign *= -1;
    }
    if (($len = strlen(strrchr($num, '.'))) > $power) {
    $power = $len - 1;
    }
    }
    foreach ($two_numbers as & $num) {
    $num = abs($num * pow(10, $power));
    }
    $total = 0;
    while ($two_numbers[0] > 1) {
    if ($two_numbers[0] % 2) {
    $total += $two_numbers[1];
    }
    $two_numbers[0] = floor($two_numbers[0] / 2);
    $two_numbers[1] *= 2;
    }
    return (($total + $two_numbers[1]) / pow(10, $power * 2)) * $sign;
    }
    Test code:
    $nums = array(0, -1, 1, 18, -23, 154., -229.5, 49.0, 389.99, 
    
    67.99999, -592.8729, .678, 0.00678);
    for ($i = 0; $i < 50; $i++) {
    $pair = array($nums[array_rand($nums)], $nums[array_rand($nums)]);
    $russian = potemkin_multiply($pair);
    $orthodox = $pair[0] * $pair[1];
    echo $pair[0] . ' * ' . $pair[1] . ' = <b>' . $russian . '</b>';
    if ((string) $russian != (string) $orthodox) {
    echo ' <span style="color:red">(' . $orthodox . ')</span>';
    }
    echo '<br />';
    }
  • Jeremy Weathers 2009-07-22 13:37
    Ruby solution:

    def rpm (first, second) # russian peasant multiplication
    
    total = 0
    while first > 0
    total += second if 0 != first % 2
    first = first / 2
    second = second * 2
    end
    total
    end
  • xtremezone 2009-07-22 13:39
    jonnyq:
    y = 0-y;
    There's the solution I was looking for. :P
  • Jonas Kramer 2009-07-22 13:46
    Haskell:


    multiply = ((sum . map snd . filter (odd . fst)) .) . tuples
    where
    tuples 1 y = [(1, y)]
    tuples x y = (x, y) : tuples (x `div` 2) (y * 2)
  • Phroggy 2009-07-22 13:46
    Here's mine, in HTML5, JavaScript and CSS!
  • lostlogic 2009-07-22 13:49
    Pythonic solution:

    def mult(a,b):
    def g(a,b):
    while a > 0:
    yield a,b
    a /= 2
    b *= 2
    return reduce(lambda x,y: x+y, [b for a,b in g(a,b) if a % 2 == 1])


    Addendum (2009-07-22 14:02):
    Fixed for negatives and zeros.

    def mult(a,b):
    a,b = (-a,-b) if a < 0 else (a,b)
    def g(a,b):
    while a > 0:
    yield a,b
    a /= 2
    b *= 2
    return sum([b for a,b in g(a,b) if a % 2 == 1])


    Addendum (2009-07-22 14:10):
    Reduce memory usage at the cost of one line:

    def mult(a,b):
    a,b = (-a,-b) if a < 0 else (a,b)
    def g(a,b):
    while a > 0:
    if a % 2 == 1:
    yield b
    a /= 2
    b *= 2
    return sum(g(a,b))
  • Darren 2009-07-22 13:51

    #!/usr/bin/perl
    package russianPeasantMultiplier;
    use strict; use warnings;

    if (@ARGV < 2) { die "I take a list of numbers to multiply together - I need at least 2" }

    my $register = shift @ARGV;
    while (@ARGV) {
    $register = multiply( $register, shift @ARGV );
    printf "Result: %6d\n", $register;
    }

    sub multiply {
    die "multiply() takes two integers" unless (
    @_ == 2
    && $_[0] == int($_[0])
    && $_[1] == int($_[1])
    );

    my ($left, $right) = @_;
    my %set;

    my $expected_result = $left * $right;

    do {
    $set{$left} = $right;
    $left = int( $left / 2 ); #deliberately throw away remainder
    $right = $right * 2;
    } until $left == 1;
    $set{$left} = $right; # make sure the 1=>x pair is recorded

    my $result = 0;
    foreach (keys %set) {
    next if $_ % 2 == 0; # skip any set with an even number on the "left"
    $result += $set{$_};
    }

    warn "Result mismatch: expected $expected_result, got $result.\n" unless $result == $expected_result;
    return $result;
    }
  • Chewbie 2009-07-22 13:51
    In ruby :

    def russian_peasant(x, y)
    return y if x/2 == 0
    (x % 2 == 0) ? russian_peasant(x/2, y*2) : y + russian_peasant(x/2, y*2)
    end

    Not properly tested, but I think it should work.
  • Qwertyuiopas 2009-07-22 13:53
    Any time you use n = n * 2 or n *=2, n += n would work.
    Any time you use n = n * -1 or n *= -1, n = -n would work.

    Anyone using * for 2 or -1 has NO EXCUSE.
  • David C. 2009-07-22 13:57
    Rather than settle with one 33-character entry, I decided to add a more robust solution. This does 2 things my previous solution doesn't: it handles negatives. And it doesn't use b*2 for doubling. Or a/2 for halving. I figured, since I'm writing a multiplication function anyway, why not use that instead?

    static int RecursiveMultiply(int a, int b)
    {
    if (a == 0 || b == 0)
    return 0;

    if (a == 1)
    return b;

    if (b == 1)
    return a;

    if (a == -1)
    return -b;

    if (b == -1)
    return -a;

    if (a == 2)
    return b + b;

    if (b == 2)
    return a + a;

    bool negA = a < 0;
    bool negB = b < 0;

    a = Math.Abs(a);
    b = Math.Abs(b);

    int halfA = 0;

    for (int x = 0; x < a; x++)
    if (RecursiveMultiply(x, 2) == a || RecursiveMultiply(x, 2) + 1 == a)
    {
    halfA = x;
    break;
    }

    int retVal = RecursiveMultiply(halfA, RecursiveMultiply(b, 2)) + RecursiveMultiply(a & 1, b);

    if (negA ^ negB)
    return RecursiveMultiply(retVal, -1);

    return retVal;
    }
  • Davi Cavalcanti 2009-07-22 13:57
    public static int multiplicate(int num1, int num2) {
    System.out.print("call: " + num1 + " * " + num2);
    int result = num2;
    int oddLineValuesSum = 0;
    while (num1 > 1) {
    if (num1%2 == 1) {
    oddLineValuesSum += result;
    }
    num1 /= 2;
    result *= 2;
    }
    result += oddLineValuesSum;

    // In case the left number was negative
    if (num1 == -1) {
    result = -result;
    }

    System.out.println(" = " + result);
    return result;
    }
  • Trevor Dubinsky 2009-07-22 13:59
    Pascal, though specifically written in Delphi 7

    Function rpm (num1, num2 : integer; var accumulator : integer) :integer;
    { Russion Peasant Multiplication implementation}
    begin
    // If the first number is not even add the second number
    // to the total
    if (num1 mod 2 <> 0) then
    accumulator := accumulator + num2;

    // If the first number is not 1 recursively call self
    if num1 > 1 then
    rpm (num1 div 2, num2 * 2, accumulator);

    //return result
    result := accumulator;
    end;
  • DeepThought 2009-07-22 14:01
    Here is my submission. I've not looked at any of the other comments yet, so I apologize if this is similar to any earlier posts.

    The realize that submitting an entire class is probably overkill, but I thought it would be helpful to see the recursive method (_multiply(int,int,int)) in context.


    /**
    * Simple utility class containing the static
    * {@link #multiply(int,int) multiply} method used to determine the product
    * of the two integer operands, but it does this by using the
    * <a href="http://thedailywtf.com/Articles/Programming-Praxis-Russian-Peasant-Multiplication.aspx">
    * Russian Peasant algorithm</a>. <br/>
    * This code is a response to a &quot;Programming Praxis&quot; challenge put
    * forth by the <a href="http://thedailywtf.com">thedailywtf.com</a> website.
    * <br/>While not a specific requirement of the challenge, this class was
    * specifically coded to avoid directly making use of the language's
    * multiplication (*) or division (/) operators.
    * @author DeepThought (2009-07-22)
    */
    public class RussianPeasantMultiply2
    {
    /**
    * Recursive method used to determine which of the second operands is to
    * be summed into the final result. It returns the results of that
    * summation when the first operand has been reduced to 1. <br/>
    * Each successive call to this method will result in the first operator
    * being reduced by half while the second operator is doubled.
    * The value of second operator will be added to the final results
    * whenever the first operator is found to be an odd number.
    * @param operand1 int - first operand
    * @param operand2 int - second operand
    * @param intermediateSum int - current result of summing up the second
    * operators when the first operator is odd
    */
    protected static int _multiply(int operand1, int operand2, int intermediateSum)
    {
    int results = 0;
    if ((operand1 & 1) == 1)
    {
    intermediateSum += operand2;
    }
    results = (operand1 == 1) ?
    intermediateSum :
    _multiply(operand1 >> 1, operand2 + operand2, intermediateSum);
    return(results);
    }
    /**
    * This method is what is to be called to evaluate the product of the two operands.
    * It will short-circuit the logic when either operand is 0 or 1 and will also negate
    * the results of the recursive
    * {@link #_multiply(int,int,int) _multiply(int,int,int)} method when the first
    * operator is a negative number.
    */
    public static int multiply(int operand1, int operand2)
    {
    int results;
    int absOp1 = Math.abs(operand1);
    int absOp2 = Math.abs(operand2);
    if (absOp1 == 0 || absOp2 == 0)
    {
    results = 0;
    }
    else if (absOp1 == 1)
    {
    results = absOp2;
    }
    else if (absOp2 == 1)
    {
    results = absOp1;
    }
    else
    {
    results = _multiply(absOp1, operand2, 0);
    if (operand1 < 0) results = (results ^ -1) + 1;
    }
    return(results);
    }
    /**
    * Parsed a string argument supplied by the command-line and returns
    * the integer equivalent.<br/>It will display an error message and
    * exit processing if a <code>java.lang.NumberFormatException</code>
    * is thrown.
    */
    public static int parseIntArguement(String strValue)
    {
    int intValue = 0;
    try
    {
    intValue = Integer.parseInt(strValue);
    }
    catch (NumberFormatException nfe)
    {
    System.err.println("Invalid number for operand \"" + strValue + "\"!");
    System.exit(1);
    }
    return(intValue);
    }
    /**
    * Main application entry point
    */
    public static void main(String args[])
    {
    try
    {
    if (args.length < 2)
    {
    System.err.println("Please supply two operands!");
    System.exit(1);
    }
    int operand1 = parseIntArguement(args[0]);
    int operand2 = parseIntArguement(args[1]);
    System.out.println("results = " + multiply(operand1,operand2));
    }
    catch (Exception e)
    {
    e.printStackTrace();
    }
    }
    }


    P.S. While previewing the comment I can see that the site appears to be inserting <br/> tags and the beginning of each line of my code block even though it is embedding the code within a <pre> tag. If that is also the case for the final post then not a result of me intentionally adding extra carriage returns or line-feeds in the original source. Sorry, but there doesn't appear to be anything I can do about it.
  • Greg R 2009-07-22 14:02
    Fine, I've rewritten mine to handle negative numbers (even if they are restricted to the party elite who will simply subtract the peasants from the population until they have the proper answer) and to avoid explicitly using multiplication anywhere.


    public static int умножить(int Значение1, int Значение2) {
    if(Значение1 == 1)
    return Значение2;

    if (Значение1 < 0) {
    Значение2 = 0 - Значение2;
    Значение1 = 0 - Значение1;
    }

    int крестьянин = умножить(Значение1 / 2, Значение2 + Значение2);
    if(Значение1 % 2 == 1)
    крестьянин += Значение2;

    return крестьянин;
    }
  • Tyches 2009-07-22 14:04
    I think I've implemented a quantum physics one, but can't tell unless I open the box, and then it might kill the cat. Damn Schrödinger.
  • bb 2009-07-22 14:05
    Here is the wtf of java program you would likely find when looking at others code :

    int multiply(int a, int b){
    int stuff = 0, z = -1;
    while ( a >> ++z > 0)
    stuff += (((a >> z) & 0x1) == 1 ? b * Math.pow(2, z) : 0 );

    return stuff;
    }
  • Shiftyness 2009-07-22 14:08
    C#
    int RussianMult(int a, int b)
    {
    int c = 0;
    if (a == 0 || b == 0) return c;
    else
    {
    int d = 0;
    while (a != 0)
    {
    if ((a % 2) != 0) d += (b * 2);
    a = a / 2;
    b = b * 2;
    }
    c = d/2;
    return c;
    }

    }
  • cincinnatvs 2009-07-22 14:08
    public int multiply (int operand1, int operand2) throws Exception {
    int product = 0;

    // While the first operand is still at least one, continue to execute the loop...
    while (operand1 >= 1) {
    // Show the current values...
    System.out.println ("" + operand1 + "\t" + operand2);

    // If the first operand is odd, add the value of the second operand to the total (our product).
    if (operand1 % 2 > 0) product += operand2;

    // In accordance with the "Russian Peasant Multiplication" method, divide the first operand by 2
    // and multiply the second operand by two.
    operand1 /= 2;
    operand2 *= 2;
    }

    // Return the product of this process.
    return product;
    }
  • Humanoid Life-form 2009-07-22 14:08
    int russianMultiply(int a, int b) {
    
    // Create vars
    int left=a;
    int right=b;
    int rightSum=0;
    int errorOffset=0;

    if(left % 2 != 0 && right % 2 == 0) { // Prevent incorrect results
    int t = left;
    left = right;
    right = t;
    } else if(left % 2 != 0 && right % 2 != 0) {
    errorOffset = right;
    left++;
    }

    // Multiply
    for(;left > 1;) {
    left /= 2;
    right *= 2;
    if((left % 2) != 0) rightSum += right;
    }

    return rightSum - errorOffset;
    }


    I had to compensate for the algorithm's failure when a is odd.
  • Alan Woodland 2009-07-22 14:09
    My attempt at a compile time C++ version - outputs the answer in the form of an error message. Actually builds the whole table like the pen and paper working in the example animation too.


    template <int N, int M, typename NEXT=void>
    struct mult_list {
    enum {n=N};
    enum {m=M};
    typedef NEXT tail;
    };

    template <int N, int M>
    struct mult_list<N,M,void> {
    enum {n=N};
    enum {m=M};
    typedef void tail;
    };

    template <int N, int M>
    struct russian {
    typedef mult_list<N,M, typename russian<N/2,M*2>::result> result;
    };

    template <int M>
    struct russian<1,M> {
    typedef mult_list<1,M> result;
    };

    template <typename LIST>
    struct add_odd {
    enum {total=add_odd<typename LIST::tail>::total + (LIST::n % 2 ? LIST::m : 0) };
    };

    template <>
    struct add_odd<void> {
    enum {total=0};
    };

    template <int N>
    struct output;

    namespace {
    output<add_odd<russian<18,23>::result>::total> result;
    }
  • Eyrieowl 2009-07-22 14:09
    brainfuck...not sure if this is going to show up properly with all the angle braces, but let's give it a try....

    >+<+[>[>[-]+<-]>[<+>>>>>>>>>>>>>>[-]<<<<<<<<<<<<+[->,.----------[<+>>++++++[<------>-]>>>>>>>>>>[<<<<<<<<<<+>>>>>>>>>>-]<<<<<<<<<<[>>>>
    
    >>>>>>++++++++++<<<<<<<<<<-]<[>>>>>>>>>>>+<<<<<<<<<<<-]]<]>>>>>>>>>>>>>[-]<<<<<<<<<<<<<+[->,.----------[<+>>++++++[<------>-]>>>>>>>>>>
    >[<<<<<<<<<<<+>>>>>>>>>>>-]<<<<<<<<<<<[>>>>>>>>>>>++++++++++<<<<<<<<<<<-]<[>>>>>>>>>>>>+<<<<<<<<<<<<-]]<]>>>>>>>>[-]>>[-]<<[>>+<<-][-]>
    >>>>[<<<<<+<<<<<<<<+>>>>>>>>>>>>>-]<<<<<<<<<<<<<[>>>>>>>>>>>>>+<<<<<<<<<<<<<-]>>>>>>>>>>>[-]<<<[>>>+<<<-][-]>>>>[<<<<+<<<<<<<<+>>>>>>>>
    >>>>-]<<<<<<<<<<<<[>>>>>>>>>>>>+<<<<<<<<<<<<-]>>>>>>>>>[-]<[>+<-]<<<<<<<<<-]>>>>>>>>>>>>>>>>>[<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>-]<<
    <<<<<<<<<<<<<<<<[>[-]+<-]>[<+>>>>>>>>>>[-]>[<+<<<<<<<<+>>>>>>>>>-]<<<<<<<<<[>>>>>>>>>+<<<<<<<<<-]>>>>>>>[-]>>>>>>>>>>[<<<<<<<<<<+<<<<<<
    <+>>>>>>>>>>>>>>>>>-]<<<<<<<<<<<<<<<<<[>>>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<<<-]>>>>>>>>>>>>>>[-]++>[-]+<[<<<<<<<<<<<<<+>>>>>>>>>>>>>-]->[<
    <<<<<<<<<<<<<-<+>>>>>>>>>>>>>>>-]<<<<<<<<<<<<<<<[>>>>>>>>>>>>>>>+<<<<<<<<<<<<<<<-]>[>>>>>>>>>>>>>+<<<<<<<<<<<<<[-]]<->>>>>>>>>>>>>>[<<<
    <<<<<<<<<<<->>>>>>>>>>>>>>-]<<<<<<<<<<<<<<[>>>>>>>>>>>>>>+<<<<<<<<<<<<<<-]>>>>>>>>[>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>[-]]<<<<<<
    <<<-]<[>[-]+<-]>[<+>>>>>>>>>>[-]>>[<<+<<<<<<<<+>>>>>>>>>>-]<<<<<<<<<<[>>>>>>>>>>+<<<<<<<<<<-]>>>>>>>[-]>>>>[<<<<+<<<<<<<+>>>>>>>>>>>-]<
    <<<<<<<<<<[>>>>>>>>>>>+<<<<<<<<<<<-]>>>>>>>[>+<<<<<<<<+>>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>>>>>>>>>>[-]<<[>>+<<-][-]>[<+<<<<<<<<+>>>>>>>
    >>-]<<<<<<<<<[>>>>>>>>>+<<<<<<<<<-]>>>>>>>[-]+>[<<<<<<<+>>>>>>>-]-<[<<<<<<-<+>>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>[>>>>>>>+<<<<<<<[-]]>>>
    >>>>[>>>>>>>>>>>+<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>[-]]<<<<<<<<<-]<[>[-]+<-]>[<+>>>>>>>>>>[-]>[<+<<<<<<<<+>>>>>>>>>-]<<<<<<<<<[>>>>>>>>>+
    <<<<<<<<<-]>>>>>>>[-]++>[<<<<<+>>>>>-]<<<<<[>>>>[<<<<<+<<+>>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>>[>-[<<+<+>>>-]<<<[>>>+<<<-]+>[<->[-]]<[>>
    -[>>>>>>-<<<<<<[-]]+<<[-]]>>-]>>>>>>+<<<<<]>>>>>>[-]<[>+<-][-]>>>[<<<+<<<<<<<<+>>>>>>>>>>>-]<<<<<<<<<<<[>>>>>>>>>>>+<<<<<<<<<<<-]>>>>>>
    >[-]++>[<<<<<<<+>>>>>>>-]<<<<<<<[>>>>>>[>+<<<<<<<<+>>>>>>>-]<<<<<<<[>>>>>>>+<<<<<<<-]>-]>>>>>>>>>>[-]<<<[>>>+<<<-]>>>>>>>>+<<<<<<<<<<<<
    <<<<<<->-]>>>>>>>>>>>>>>>>>>>>[<<<<<<<<<<<<<<<<<<<<<+>>>>>>>>>>>>>>>>>>>>>-]<<<<<<<<<<<<<<<<<<<<<[>[-]+<-]>[<+>>++++++++++++++[>++++++>
    +++++++>++++++++>++++>++<<<<<-]>--.>+++.>+++.++.<+++++++.>-.>++.>++++.[-]<[-]<[-]<[-]<[-]<>>>>>>>>[-]>>[<<+<<<<<<<<+>>>>>>>>>>-]<<<<<<<
    <<<[>>>>>>>>>>+<<<<<<<<<<-]>[-]>[-]>[-]>[-]>>>>[<<<<<+[>+<<<<+>>>-]<<<[>>>+<<<-]+>>>>----------[<<<<->>>>[-]]<<<<[>>+>[-]<<<-]>>[>>+<<<
    <+>>-]<<[>>+<<-]+>>>>----------[<<<<->>>>[-]]<<<<[>+>[-]<<-]>>>>>>>>-]<<<<<<<[<++++++++[>++++++>++++++<<-]>.>.[-]<[-]]>[<<++++++++[>>++
    ++++<<-]>>.[-]]<<++++++++[>>>++++++<<<-]>>>.[-]<<<++++++++++.[-]<<<->>-]<<]@
  • klagdon 2009-07-22 14:11
    Ok, once more with bit shifting and accounting for negative numbers.

    public static long multiply(long first, long second) {
    if(first < 0 && second < 0) {
    return multiply(Math.abs(first), Math.abs(second));
    } else if(first < 0 || second < 0) {
    return -multiply(Math.abs(first), Math.abs(second));
    } else if(first == 0 || second == 0) {
    return 0;
    } else if(first == 1) {
    return second;
    } else if(first % 2 == 1) {
    return second + multiply(first >> 1, second << 1);
    } else {
    return multiply(first >> 1, second << 1);
    }
    }

    public static void main(String[] args) {
    Random r = new Random();
    for(int i = 0 ; i < 1000000 ; i++) {
    long first = (long)r.nextInt();
    long second = (long)r.nextInt();
    long result = multiply(first,second);
    if((first * second) != result) {
    System.out.println("Failed for " + first + " * " + second + " = " + (first * second) + "\t" + result);
    }
    }
    }
  • bluebearr 2009-07-22 14:11
    Fine, since everyone seems soooo concerned that peasants be able to properly multiply negative numbers, I revised my Windows XP batch file answer. I also removed the multiplication assignment step, since I guess it is cheating.

    Check out the _sign variable! Don't you wish your language could do that sort of nonsense?
    @echo off
    
    set _a=18
    set _b=23
    call :mult %_a% %_b% _result
    echo %_a% x %_b% = %_result%
    goto :EOF


    :mult
    :: Multiply two numbers
    :: Parameters:
    :: %1 - first number
    :: %2 - second number
    :: %3 - variable to return result in
    setlocal
    set _a=%1
    set _b=%2
    set _res=0
    set _sign=LEQ 1
    if "%_a:~0,1%"=="-" set _sign=GEQ -1
    :calc
    set _eventest=0
    for /L %%i in (0,2,8) do if %_a:~-1%==%%i set _eventest=1
    if %_eventest%==0 set /a _res+=_b
    if %_a% %_sign% goto endcalc
    set /a _a/=2
    set /a _b=_b+_b
    goto calc
    :endcalc
    if "%_a:~0,1%"=="-" (
    if "%_res:~0,1%"=="-" set _res=%_res:~1%
    if Not "%_res:~0,1%"=="-" set _res=-%_res%
    )
    endlocal & set %3=%_res%
    goto :EOF
  • EngleBart 2009-07-22 14:12
    ath:
    Same thing in python:

    def is_odd(n):
    return (n % 2) != 0

    def rmul(x, y):
    s = 0
    while(x != 1):
    if is_odd(x):
    s += y
    x /= 2
    y *= 2
    return y + s


    
    

    Any of these solutions checking for != 1 need to double check when the argument is 0.

    This (and floating point numbers) are why it is always safer to use > or >= versus trying to "hit" an exact match.

    As far as I can tell rmul(0,y) == infinite loop.
  • aef123 2009-07-22 14:14
    public static long PeasantMult(long operand1, long operand2)
    {
    long product = 0;
    while (operand1 != 1)
    {
    if (operand1 % 2 != 0) { product += operand2; }
    operand1 /= 2;
    operand2 *= 2;
    }
    return (product + operand2);
    }
  • Trurl 2009-07-22 14:17

    MUMPS:

    P(I,S)

    S Q=I I I I S#2 S Q=0

    Q Q+P(I\2,S*2)

    Features:
    Shortened keywords!
    Keywords reused for variable names!
    Recursion!
    Untested!


    That doesn't work:

    $ZE:<UNDEFINED>P+2^cTRAL1



    This is tested and i added some extra MUMPS-flavour:


    M(S,Q) N N,FN,F Q:$G(S)=""!($G(Q)="") "0" ; wtf?!
    S N=$S('(+S<0=(+Q<0)):"-",1:""),S=$FN(+S,"-",0),Q=$FN(+Q,"-",0)
    S F=$S(S#2:Q,1:"") Q:S=0!(Q=0) "0"
    S FN="" F S S=S\2,Q=Q*2 S:S#2 FN=FN+Q Q:S=1
    Q N_(FN+F)


    ->


    :W $$M^cTRAL1(18,23)
    414
    :W $$M^cTRAL1(19,23)
    437
    :W $$M^cTRAL1(-23,42)
    -966
    :W $$M^cTRAL1(-23,-12.5)
    299

    :
  • aef123 2009-07-22 14:18
    public static long PeasantMult(long operand1, long operand2)
    {
    long product = 0;
    while (operand1 > 1)
    {
    if (operand1 % 2 != 0) { product += operand2; }
    operand1 /= 2;
    operand2 *= 2;
    }
    return operand1 * (product + operand2);
    }
  • astonerbum 2009-07-22 14:18
    JavaScript. No Bitwise operations, but no use of multiplication either... Thats v2 :) Though still uses division so its still a problem, bitwise operations eliminate the need.

    Handles positive and negative numbers.


    function rpmult(x, y){
    var flip = false;
    if ( x === 0 || y === 0 ) {
    return 0;
    }
    if ( x === 1 ) {
    return y;
    }
    if ( x < 0 ) {
    x = -x;
    flip = true;
    }
    if ( x % 2 === 0) {
    added = 0;
    }
    var added = ( x % 2 === 0 ? 0 : y );
    var recurse = rpmult(Math.floor(x / 2), y + y);
    return flip ? - (added + recurse) : added + recurse;
    }
  • Matt 2009-07-22 14:20
    Here's another scala solution. It's not as neat as the recursive solution but it's based on lists, so more like the pen-and-paper version.

    def mult(a: Int, b: Int) = {
    def m(a: Int, b: Int): List[(Int,Int)] =
    if (a==1) List((a,b)) else (a,b) :: m(a/2,b*2)
    m(a,b).filter(_._1%2 == 1).foldLeft(0)(_ + _._2)
    }
  • blueberry 2009-07-22 14:23
    Osno:
    All the people using multiplication and division instead of shifting (except in languages where there is no shifting) also fail.


    Granted, the goal was to define the multiply operator so it shouldn't be in the code.

    HOWEVER, it is almost always a really bad idea to bitshift instead of using multiply/divide:

    - << may lead to silent overflows instead of throwing an exception.

    int z1 = int.MaxValue * 2; // Compile-time exception
    int z2 = int.MaxValue << 1; // Silent overflow, return -2


    - For negative values, >> and / are NOT equivalent ((-1 >> 1) != (-1 / 2)).

    int y1 = -1 >> 1; // -1
    int y2 = -1 / 2; // 0


    Numerical multiply/divide are hardly the bottleneck of any modern application. Let's keep the bitshift operators for what it was intended: shift bits. It was probably a smart optimization 30 years ago, but in 2009 it is a bad and pointless practice.

  • Maks Verver 2009-07-22 14:27
    Eyrieowl:
    brainfuck...

    Nice, but two questions:
    - How am I supposed to format the input? I wasn't able to get anything sensible out of it.
    - Was this hand-written? (I always think generated Brainfuck code is lame.)
  • Trurl 2009-07-22 14:29
    Granted, the goal was to define the multiply operator so it shouldn't be in the code.

    I see...

    Here's my altered submission:

    MUMPS:

    ;-
    M(S,Q) N N,FN,F Q:$G(S)=""!($G(Q)="") "0" ; wtf?!
    S N=$S('(+S<0=(+Q<0)):"-",1:""),S=$FN(+S,"-",0),Q=$FN(+Q,"-",0)
    S F=$S(S#2:Q,1:"") Q:S=0!(Q=0) "0"
    S FN="" F S S=S\2,Q=Q+Q S:S#2 FN=FN+Q Q:S=1
    Q N_(FN+F)
    ;-



    Trurl
  • CMIT 2009-07-22 14:30
    method1:
    Paula:
    public class Paula extends WTF {
    public static string Paulabean = "brillant!";
    }


    Best solution by far


    especially since she misspelled 'brilliant' ;)
  • tirerim 2009-07-22 14:31
    Qwertyuiopas:
    Any time you use n = n * 2 or n *=2, n += n would work.
    Any time you use n = n * -1 or n *= -1, n = -n would work.

    Anyone using * for 2 or -1 has NO EXCUSE.


    Nonsense. In Perl, $n*=2 has fewer characters than $n+=$n. :-P
  • Warr 2009-07-22 14:32
    I figured that, to keep things interesting, I'd try to implement this using only regular expressions, instead of any real "math." I didn't quite accomplish it, since writing regular expressions to perform addition seemed too tedious, so I threw in a lookup table to assist with the additon step (only accounting for 2 addition operators in code, and a fixed 200 of them at run-time).

    Interestingly enough, the thing actually works pretty well, has no theoretical limits on integer size, and never has to do decimal/binary translation at any point (though, technically, operations are carried out internally in a sort of base-30 system). Works with positive and negative integers of arbitrary size. Faster run-time if the smaller operand is on the left. :-)



    #!/usr/bin/perl -w
    $_ = join(' ', @ARGV);
    m#^\s*-?\d+\s*x\s*-?\d+\s*# or die('Input should be in "#### x ####" format.');
    $sign = '+'; while(s#-##) { $sign =~ tr#+-#-+#; }
    s#\s##g;
    s#$#=0\n#;
    %sums = ();
    %out = ();
    %carry = ();
    for($a = 0; $a < 10; $a++)
    {
    $i = $a; $i =~ tr#0-9#a-j#;
    $k = $a; $k =~ tr#0-9#A-J#;
    for($b = 0; $b < 10; $b++)
    {
    $c = $a + $b; # FIXME: Math on processor!
    $d = $c + 1; # FIXME: Math on processor!
    $j = $b; $j =~ tr#0-9#a-j#;
    length($c) > 1 and
    $c =~ tr#0-9#A-J# or
    $c =~ tr#0-9#a-j#;
    $c =~ s#.*(?=.)##;
    length($d) > 1 and
    $d =~ tr#0-9#A-J# or
    $d =~ tr#0-9#a-j#;
    $d =~ s#.*(?=.)##;
    for($e = 0; $e < 10; $e++)
    {
    $f = $e; $f =~ tr#0-9#a-j#;
    $g = $e; $g =~ tr#0-9#A-J#;
    $sums{$a . $b . $e} = $c;
    $sums{$i . $b . $e} = $c;
    $sums{$a . $j . $e} = $c;
    $sums{$i . $j . $e} = $c;
    $sums{$a . $b . $f} = $c;
    $sums{$i . $b . $f} = $c;
    $sums{$a . $j . $f} = $c;
    $sums{$i . $j . $f} = $c;
    $sums{$a . $b . $g} = $d;
    $sums{$i . $b . $g} = $d;
    $sums{$a . $j . $g} = $d;
    $sums{$i . $j . $g} = $d;
    }
    }
    $out{$a} = $i;
    $carry{$a} = $k;
    }
    while(!m#^0+x#)
    {
    s#(?<!\d)(\d)#0$1#g;
    if(m#\d+[13579]x#)
    {
    s#(\d)(=\d*)(\d)#$out{$1}$2$sums{$1.$3.0}#;
    while(m#\d[a-j]*=#)
    {
    s#=([^0])#=0$1#;
    s#(\d)([a-j]*=\d*)(\d)(.)#$out{$1}$2$sums{$1.$3.$4}$4#;
    }
    while(m#=0*[0-9A-J]#)
    {
    s#=([A-J])#=0$1#;
    s#0(?=[a-j]*$)#a#;
    s#1(?=[a-j]*$)#b#;
    s#2(?=[a-j]*$)#c#;
    s#3(?=[a-j]*$)#d#;
    s#4(?=[a-j]*$)#e#;
    s#5(?=[a-j]*$)#f#;
    s#6(?=[a-j]*$)#g#;
    s#7(?=[a-j]*$)#h#;
    s#8(?=[a-j]*$)#i#;
    s#9(?=[a-j]*$)#j#;
    s#0(?=[A-J]*$)#b#;
    s#1(?=[A-J]*$)#c#;
    s#2(?=[A-J]*$)#d#;
    s#3(?=[A-J]*$)#e#;
    s#4(?=[A-J]*$)#f#;
    s#5(?=[A-J]*$)#g#;
    s#6(?=[A-J]*$)#h#;
    s#7(?=[A-J]*$)#i#;
    s#8(?=[A-J]*$)#j#;
    s#9(?=[A-J]*$)#A#;
    }
    tr#A-Ja-j#0-90-9#;
    }
    s#^0#a#;
    s#^1#A#;
    s#^2#b#;
    s#^3#B#;
    s#^4#c#;
    s#^5#C#;
    s#^6#d#;
    s#^7#h#;
    s#^8#i#;
    s#^9#j#;
    while(m#^[A-Ja-j]*\d#)
    {
    s#(?<=[a-j])0#a#;
    s#(?<=[a-j])1#A#;
    s#(?<=[a-j])2#b#;
    s#(?<=[a-j])3#B#;
    s#(?<=[a-j])4#c#;
    s#(?<=[a-j])5#C#;
    s#(?<=[a-j])6#d#;
    s#(?<=[a-j])7#D#;
    s#(?<=[a-j])8#e#;
    s#(?<=[a-j])9#E#;
    s#(?<=[A-J])0#f#;
    s#(?<=[A-J])1#F#;
    s#(?<=[A-J])2#g#;
    s#(?<=[A-J])3#G#;
    s#(?<=[A-J])4#h#;
    s#(?<=[A-J])5#H#;
    s#(?<=[A-J])6#i#;
    s#(?<=[A-J])7#I#;
    s#(?<=[A-J])8#j#;
    s#(?<=[A-J])9#J#;
    }
    tr#A-Ja-j#0-90-9#;
    s#0=#a=#;
    s#1=#c=#;
    s#2=#e=#;
    s#3=#g=#;
    s#4=#i=#;
    s#5=#A=#;
    s#6=#C=#;
    s#7=#E=#;
    s#8=#G=#;
    s#9=#I=#;
    while(m#\d[A-Ja-j]*=#)
    {
    s#0(?=[a-j])#a#;
    s#1(?=[a-j])#c#;
    s#2(?=[a-j])#e#;
    s#3(?=[a-j])#g#;
    s#4(?=[a-j])#i#;
    s#5(?=[a-j])#A#;
    s#6(?=[a-j])#C#;
    s#7(?=[a-j])#E#;
    s#8(?=[a-j])#G#;
    s#9(?=[a-j])#I#;
    s#0(?=[A-J])#b#;
    s#1(?=[A-J])#d#;
    s#2(?=[A-J])#f#;
    s#3(?=[A-J])#h#;
    s#4(?=[A-J])#j#;
    s#5(?=[A-J])#B#;
    s#6(?=[A-J])#D#;
    s#7(?=[A-J])#F#;
    s#8(?=[A-J])#H#;
    s#9(?=[A-J])#J#;
    }
    tr#A-Ja-j#0-90-9#;
    s#(?<!\d)0+(?=\d|0(?!\d))##g;
    }
    s#.*=##;
    s#^#$sign#;
    s#^\+##;
    print;
  • stannius 2009-07-22 14:32
    Mine is similar. Too bad we were prevented from making one-liners by "The yield statement cannot be used inside an anonymous method or lambda expression!"


    private int PeasantMultiply(int first, int second)
    {
    return GetColumns(first, second).Where(foo => foo.First % 2 == 1).Sum(bar => bar.Second);
    }

    private IEnumerable<Pair<int>> GetColumns(int a, int b)
    {
    while (a >= 1)
    {
    yield return new Pair<int>(a, b);
    a = a / 2;
    b = b * 2;
    }
    }
  • moltonel 2009-07-22 14:35
    #!/bin/sh

    grep -q '^1\*' <<< $1 && echo $(( $1 )) || $0 "$(( $(sed 's/\*.*//' <<< $1)/2 ))*$(( $(sed 's/.*\*//;s/+.*//' <<< $1)*2 ))$(grep -oE '[13579]\*[0-9]+' <<< $1| sed 's/.*\*/+/')$(grep -o '\+.*' <<< $1)"


    # only one line and no modification of a variable :p

    Addendum (2009-07-22 14:42):
    That's bash of course, not sh.
  • flax 2009-07-22 14:35
    Nobody has submitted ARM code yet that I have seen. Does this win for smallest number of instructions?

    ; multiplicands in r0 and r1

    mov r2,#0
    loop
    movs r0,r0,lsr #1
    addcs r2,r1
    mov r1,r1,asl #1
    bne loop
  • astonerbum 2009-07-22 14:37
    finally its time i learned how to do bitwise operations in javascript :P

    This time there is absolutely no division or multiplication used in the algorithm, or Math.floor :P


    function rpmult(x, y){
    var flip = false;
    if (x === 0 || y === 0) {
    return 0;
    }
    if (x === 1) {
    return y;
    }
    if (x < 0) {
    x = -x;
    flip = true;
    }
    var added = (((x & 0x1) === 0x1) ? 0 : y);
    var recurse = rpmult(x >>> 1, y + y);
    return flip ? - added + recurse : added + recurse;
    }
  • Paul 2009-07-22 14:37
    Sorry, in advance.

    interface IMultiplierStrategy {
    public function mul( $a, $b );
    }
    abstract class Arithmetic {
    protected
    $a, $b;
    public function __construct( $a, $b ) {
    $this->a = $a;
    $this->b = $b;
    }
    }
    class Multiply extends Arithmetic {
    public function mul( IMultiplierStrategy $strategy ) {
    return $strategy->mul( $this->a, $this->b );
    }
    }
    class RussianMultiplierStrategy implements IMultiplierStrategy {
    protected
    $tally = 0;
    public function mul( $a, $b ) {
    if( $a > 1 && $a %2 != 0 ) {
    $this->tally += $b;
    }
    if( $a == 1 ) {
    return $this->tally + $b;
    }
    return $this->mul( intval( $a /2 ), $b *2 );
    }
    }
    $mul = new Multiply( 18, 23 );
    echo $mul->mul( new RussianMultiplierStrategy );

    To the PHB: it's extensible multiplication architecture.
  • java.lang.Chris; 2009-07-22 14:38
    FORTRAN 77


    PROGRAM RUSSIAN_MULTIPLY
    IMPLICIT NONE

    INTEGER RM
    INTEGER N

    N = RM(34, 4)

    PRINT *, '34 * 4 = ', N

    STOP
    END

    INTEGER FUNCTION RM(X, Y)
    INTEGER X
    INTEGER Y

    INTEGER Z

    Z = 0

    DO WHILE (X .GT. 0)
    Z = Z + MOD(X, 2) * Y
    X = X / 2
    Y = Y * 2
    ENDDO

    RM = Z

    RETURN
    END
  • Михаил 2009-07-22 14:38
    #define int инт
    #define return разврат
    #define if еслибы
    #define while покашто
    #define else иначе
    #define printf напечатать
    //к черту всех floats
    инт множение(инт пиво,инт квас)
    {
    инт чердылка=0;
    еслибы(пиво > квас ) //чтобы быстрее работала, пацаны
    {чердылка=квас;квас=пиво;пиво=чердылка;чердылка=0;}


    покашто(пиво!=1)
    {
    еслибы((пиво & 0x1)==1) //ne делитса на два
    чердылка+= квас;
    пиво>>=1;
    еслибы(квас < 0)
    напечатать("Ну твою мать!");
    }

    разврат чердылка;
    }

    инт негативноеMноение(инт пиво,инт квас)
    {разврат -1*множение(инт пиво,инт квас);}
  • Qwertyuiopas 2009-07-22 14:41
  • OmnipotentEntity 2009-07-22 14:43
    My solution.

    #include <stdio.h>
    

    int main (int argc, char* argv[]) {
    if (argc == 3) {
    long a = atoi(argv[1]);
    long b = atoi(argv[2]);
    long sum = 0;
    if (b&1) {
    sum += a;
    }
    while (b > 1) {
    b = b >> 1;
    a = a << 1;
    if (b&1) {
    sum += a;
    }
    }
    printf("%ld\n", sum);
    return 0;
    } else {
    return 1;
    }
    }

  • samanddeanus 2009-07-22 14:43
    Scheme with fold and unfold:

    (define (mul a b)
    (fold +
    0
    (unfold (lambda (x)
    (zero? (car x)))
    (lambda (x)
    (if (odd? (car x))
    (cdr x)
    0))
    (lambda (x)
    (cons (quotient (car x) 2)
    (+ (cdr x) (cdr x))))
    (cons (abs a)
    (if (negative? a)
    (- b)
    b)))))
  • Maks Verver 2009-07-22 14:43
    moltonel:
    #!/bin/sh
    grep -q '^1\*' <<< $1 && echo $(( $1 )) || $0 "$(( $(sed 's/\*.*//' <<< $1)/2 ))*$(( $(sed 's/.*\*//;s/+.*//' <<< $1)*2 ))$(grep -oE '[13579]\*[0-9]+' <<< $1| sed 's/.*\*/+/')$(grep -o '\+.*' <<< $1)"

    I can't get this to work properly. With BSD sh it doesn't parse, with Bash it runs, but produces incorrect answers for the simplest arguments (and when the first argument is 1, it doesn't produce a result at all).

    Any explanation? Maybe some of the code got mangled while posting, or you're using yet a different shell?
  • Ingo 2009-07-22 14:45
    I can beat that...

    int RussianPeasantMultiplyFor18And23( )
    {
    return 414;
    }

    OMG.. my code is fastest?
  • moltonel 2009-07-22 14:51
    Maks Verver:
    moltonel:
    #!/bin/sh
    grep -q '^1\*' <<< $1 && echo $(( $1 )) || $0 "$(( $(sed 's/\*.*//' <<< $1)/2 ))*$(( $(sed 's/.*\*//;s/+.*//' <<< $1)*2 ))$(grep -oE '[13579]\*[0-9]+' <<< $1| sed 's/.*\*/+/')$(grep -o '\+.*' <<< $1)"

    I can't get this to work properly. With BSD sh it doesn't parse, with Bash it runs, but produces incorrect answers for the simplest arguments (and when the first argument is 1, it doesn't produce a result at all).

    Any explanation? Maybe some of the code got mangled while posting, or you're using yet a different shell?


    Yes, bash, sorry.
    You'll have to give it two numbers, without space, and the multiplication sign must be an actual '*'.

    eg:
    $ ./russian.sh 19*29
    551
    $ ./russian.sh 18*23
    414
  • newlisp.org 2009-07-22 14:51
    improvement for some problems starting with even number:


    (define (rmul x y , (s 0))
    (until (= x 1)
    (unless (zero? (% x 2))
    (inc s y))
    (setq x (>> x) y (<< y)))
    (+ y s)
    )
  • MG 2009-07-22 14:52
    Why recurse when you can use a linked list?


    #include <stdio.h>
    #include <stdlib.h>

    struct rus_row {
    long left;
    long right;
    struct rus_row *next;
    };
    int main(int, char **);
    long rus_multiply(long, long, int);
    struct rus_row *make_row(long, long, struct rus_row *);
    void rus_freemem(struct rus_row *);

    int main(int argc, char *argv[]) {
    if (argc != 3) {
    printf("Usage: %s <num> <num>\n", argv[0]);
    exit(1);
    }
    long a = atol(argv[1]);
    long b = atol(argv[2]);
    long result = rus_multiply(a, b, 1);
    return 0;
    }

    long rus_multiply(long a, long b, int print) {
    long total = 0;

    struct rus_row *head = make_row(a, b, NULL);
    struct rus_row *tail = head;
    while(tail->left > 1) {
    struct rus_row *new_row = make_row(tail->left / 2, tail->right * 2, NULL);
    tail->next = new_row;
    tail = tail->next;
    }
    struct rus_row *curr = head;
    while (curr) {
    if (curr->left & 1) {
    // odd
    if (print) {
    printf ("%ld\t%ld\t+ %ld\n", curr->left, curr->right, curr->right);
    }
    total = total + curr->right;

    } else {
    // even
    if (print) {
    printf ("%ld\t%ld\n", curr->left, curr->right);
    }
    }
    curr = curr->next;
    }
    if (print) {
    printf ("\t\t-----\n\t\t= %ld\n", total);
    }
    rus_freemem(head);
    return total;
    }

    struct rus_row *make_row(long left, long right, struct rus_row *next) {
    struct rus_row *row = (struct rus_row *) malloc(sizeof(struct rus_row)); //todo: check for malloc failure
    row->left = left;
    row->right = right;
    row->next = next;
    return row;
    }

    void rus_freemem(struct rus_row *head) {
    struct rus_row *next = head;
    while (next) {
    struct rus_row *curr = next;
    next = curr->next;
    free(curr);
    }
    }
  • Will 2009-07-22 14:56
    Nice callback to the futility closet article from last week. It is interesting to see how many different languages / methods people found for executing this procedure.
  • blueberry 2009-07-22 14:59
    Here is my solution in C#:


    static int PeasantMult(int x, int y)
    {
    switch (x)
    {
    case -1: return -y;
    case 0: return 0;
    case 1: return y;
    default: return PeasantMult(x % 2, y) + PeasantMult(x / 2, y + y);
    }
    }


    -Works with negative values on any or both operands
    -No multiplication
  • Alan Woodland 2009-07-22 15:00
    MG:
    Why recurse when you can use a linked list?


    You could always recurse over linked lists and get the best of both worlds :P
  • Osno 2009-07-22 15:03
    I think everybody misrepresented my comment on using multiplication/division instead of bitshifting being fail as a performance comment. What I was aiming at is that if you're defining multiplication, multiplying is kind of lame. Then, I changed my mind and started using ( left & 1 ) * right, but that was just a shortcut :). Also, bitshifting was closer to the original demonstration in the "spec".

    I agree with all that multiplying here is safer and probably close in performance. I doubt most of the compilers present (python, java, c#, vb.net, javascript, etc) will optimize it to the same thing, but who cares? (btw, I do think C, C++, Delphi, Scheme, Haskell and a few others may optimize).
  • Osno 2009-07-22 15:05
    Google Search (by far the most commonly used programming language):

    http://lmgtfy.com/?q=russian+peasant+multiplication
  • VirtualBlackFox 2009-07-22 15:07
    C#, just for fun :

    namespace Test
    
    {
    using System;
    using System.Collections.Generic;
    using System.Linq;

    class Program
    {
    class Elem
    {
    public int Left { get; set; }
    public int Right { get; set; }
    }

    static IEnumerable<Elem> DivideUntilOneOnLeft(Elem e)
    {
    while (e.Left != 1)
    {
    e = new Elem() { Left = e.Left / 2, Right = e.Right * 2 };
    yield return e;
    }
    }

    static int Mutiply(int left, int right)
    {
    return DivideUntilOneOnLeft(new Elem() { Left = left, Right = right })
    .Where(e => e.Left % 2 != 0)
    .Aggregate(0, (accum, e) => accum + e.Right);
    }

    static void Main(string[] args)
    {
    Console.WriteLine(Mutiply(18, 23));
    Console.ReadLine();
    }
    }
    }
  • nine 2009-07-22 15:08
    C# Recursive solution. Handles edge cases (negative integers, 0). Focus is on readability/clarity and not performance:

    public static int RussianMultiply(int x, int y)
    {
    if (x < 0) return RussianMultiply(-x, -y);
    else if (x == 0) return 0;
    else if (x == 1) return y;
    else if (x % 2 == 1) return y + RussianMultiply(x/2, y*2);
    else return RussianMultiply(x/2, y*2);
    }
  • Scott 2009-07-22 15:09
    Here is an interesting javascript version

    function russia(a,b){ return new (function(){
    while(a&1?((this.c?this.c+=b:this.c=b),a=a>>1,b=b<<1,(a==0?false:true)):(a=a>>1,b=b<<1,true)){};
    })().c;}


    The reason for the anonymous function is because of a variable scope issue that occurs when the function is called multiple times.
  • darkscout 2009-07-22 15:18
    function [c] = rpm(a,b)
    
    while (a(end)~=1)
    a(end+1)=floor(a(end)/2);
    b(end+1)=b(end)*2;
    end
    c=sum(b(logical(mod(a,2))));
  • ikorb 2009-07-22 15:19
    Yet another Haskell version. Distinguishing features: No indented lines, overly verbose

    peasant_step :: (Int, Int) -> (Int, Int)
    peasant_step (x,y) = (div x 2, y + y)

    first_is_positive :: (Int, Int) -> Bool
    first_is_positive (x,y) = x > 0

    peasant_list :: (Int, Int) -> [(Int, Int)]
    peasant_list args = takeWhile first_is_positive $ iterate peasant_step args

    first_is_odd :: (Int, Int) -> Bool
    first_is_odd (x,y) = (mod x 2) == 1

    peasant_filter :: [(Int, Int)] -> [(Int, Int)]
    peasant_filter = filter first_is_odd

    accumulate_second :: (Int, Int) -> Int -> Int
    accumulate_second (x,y) a = y + a

    peasant_sum :: [(Int, Int)] -> Int
    peasant_sum = foldr accumulate_second 0

    peasant_multiply :: Int -> Int -> Int
    peasant_multiply x y = peasant_sum $ peasant_filter $ peasant_list (x,y)
  • treyb 2009-07-22 15:23
    In excel:

    Column A:
    A1: number_1
    A2: =rounddown(A1/2,0)
    A3: =rounddown(A2/2,0)
    A4: and so on

    Column B:
    B1: number_2
    B2: =if(A2,B1*2,0)
    B3: =if(A3,B2*2,0)
    B4: and so on

    Column C:
    C1: =if(mod(A1,2)=0,0,1)
    C2: =if(mod(A2,2)=0,0,1)
    C3: and so on

    Column D:
    D1: =sumproduct(B:B,C:C)
  • iMalc 2009-07-22 15:26
    Anyone done is using a .BAT script yet?
  • TNProgrammer 2009-07-22 15:27
    //C#
    public static void Go()
    {
    Console.WriteLine(PraxisMultiply(18, 23).ToString());
    }

    public static int PraxisMultiply(int number1, int number2)
    {
    List<PraxisPair> pairs = new List<PraxisPair>();
    pairs.Add(new PraxisPair(number1, number2));
    while(number1 > 1)
    {
    number1 = number1 / 2;
    number2 = number2 * 2;
    pairs.Add(new PraxisPair(number1, number2));
    }
    int result = 0;
    foreach(PraxisPair p in pairs)
    {
    if(p.Left % 2 == 0)
    {
    p.Right = 0;
    }
    result += p.Right;
    }
    return result;
    }

    public class PraxisPair
    {

    public PraxisPair(int left, int right)
    {
    Left = left;
    Right = right;
    }


    public int Left{ get; set; }
    public int Right{ get; set; }
    }
  • Josue Chi 2009-07-22 15:28
    Short as can be

    public static int russian(int multiplier1, int multiplier2) {
    int result = 0;
    while (multiplier1 >= 1) {
    result += (multiplier1 % 2 == 1)? multiplier2: 0;
    multiplier2 *= 2;
    multiplier1 /= 2;
    }
    return result;
    }
  • SoaperGEM 2009-07-22 15:32
    I'm not going to read through all the 400+ comments to see if this exact version's been done yet, but here's an implementation in Python:

    def multtwo(one, two):
    
    result = 0
    while (one >= 1):
    if (one & 1):
    result += two
    one >>= 1
    two <<= 1
    return result


    I did scan through the code a little bit though, and seeing so many people using division and modulo operators made me sad. Don't they teach kids anything about bitwise operators anymore?
  • blueberry 2009-07-22 15:35
    SoaperGEM:

    I did scan through the code a little bit though, and seeing so many people using division and modulo operators made me sad. Don't they teach kids anything about bitwise operators anymore?


    See post #278250
    Maybe it's time to go back to school :P
  • asdfghj 2009-07-22 15:51
    recursive scheme solution:

    (define (russian_m a b) (if (= b 1)
    a
    (russian a b)
    )
    )

    (define (russian a b)
    (if (= a 1)
    b
    (+
    (if (= (remainder a 2) 0) 0 b)
    (russian (/ a 2) (* b 2))
    )
    )
    )

    not tested
  • Josue Chi 2009-07-22 15:52
    blueberry:
    SoaperGEM:

    I did scan through the code a little bit though, and seeing so many people using division and modulo operators made me sad. Don't they teach kids anything about bitwise operators anymore?


    See post #278250
    Maybe it's time to go back to school :P


    As long as we don't multiply directly A * B, we are not violating any of the "original requirements". Of course using bit shifting can give you points, if we were at school (and may give you points here too :), but if it is not part of the requirements, I don't think we should feel forced to use it.

    Cheers and good luck (I want my Sticker!)
  • Alvie 2009-07-22 15:54
    You win so far :) As long as that works, obviously.
  • guille_ 2009-07-22 15:57

    (defun rmul (x y)
    (let ((l (truncate x 2))
    (r (* y 2)))
    (reduce '+ (do ((sums '())
    (l l (truncate l 2))
    (r r (* r 2)))
    ((< l 1) sums)
    (when (oddp l)
    (push r sums))))))
  • ZzzZZZz 2009-07-22 15:57
    Recursive Python. Pretty disappointed with my work after seeing some of the others!

    def peasant(x, y): 
    
    n = 1
    m = n
    while (n < y):
    m = n
    n = n * 2
    out = m * x
    d = y - m
    if (d == 0):
    return out
    else:
    return peasant(x, d) + out
  • Beat by the system 2009-07-22 15:58
    anyone done this in javascript?
    function multiply (x, y, total)
    {
    (x == 0) ? alert(total) : multiply (Math.floor(x/2),Math.floor(y*2),(x % 2 == 0) ? total : total+y);
    }
  • Resistance 2009-07-22 16:00
    In spite of being epic late, here's mine:

    #include <stdio.h>

    int main() {
    int a;
    int b;
    int c;

    printf("A = ");
    scanf("%d", &a);
    printf("B = ");
    scanf("%d", &b);

    asm(
    "movl $0, %%ecx\n\t"
    "loop:\n\t"
    "shrl $1, %%eax\n\t" // divide left side by 2
    "jnc skip_add\n\t" // carry is set if eax was odd
    "addl %%ebx, %%ecx\n\t" // accumulate right side
    "skip_add:\n\t"
    "shll $1, %%ebx\n\t" // multiply right side by 2
    "cmpl $0, %%eax\n\t"
    "jne loop" // equal if left side was 1
    : "=c" (c) // out: ecx - result
    : "a" (a), "b" (b) // in: eax - left side, ebx - right side
    );

    printf("A * B = %d\n", c);

    return 0;
    }
  • Dave Havlicek 2009-07-22 16:01
    how about PL/pgSQL?

    DECLARE
    
    tmp1 INTEGER;
    tmp2 INTEGER;
    BEGIN
    CREATE TEMPORARY TABLE tmp_columns ( "left_col" INTEGER NOT NULL, "right_col" INTEGER NOT NULL );
    tmp1 := $1;
    tmp2 := $2;
    INSERT INTO tmp_columns (left_col, right_col) VALUES (tmp1, tmp2);
    WHILE tmp1 != 1 LOOP
    tmp1 := tmp1 / 2;
    tmp2 := tmp2 + tmp2;
    INSERT INTO tmp_columns (left_col, right_col) VALUES (tmp1, tmp2);
    END LOOP;
    return ( SELECT SUM(right_col) FROM tmp_columns WHERE (left_col % 2) = 1 );
    END
  • dontera 2009-07-22 16:02

    private static int CalculateLikeRussianPeasant(int a, int b, List<int[]> lines)
    {
    if (lines == null)
    {
    lines = new List<int[]>();
    int[] lr = new int[2];
    lr[0] = a;
    lr[1] = b;
    lines.Add(lr);
    CalculateLikeRussianPeasant(-1, -1, lines);
    }

    int[] lastLr = lines[lines.Count - 1];
    if (lastLr[0] != 1)
    {
    int[] lr = new int[2];
    lr[0] = lastLr[0] / 2;
    lr[1] = lastLr[1] * 2;
    lines.Add(lr);
    if (lr[0] != 1)
    CalculateLikeRussianPeasant(-1, -1, lines);
    }

    int result = 0;
    lines.ForEach(delegate(int[] lr)
    {
    if (lr[0] % 2 != 0)
    result += lr[1];
    });

    return result;
    }


    call into it with CalculateLikeRussianPeasant(101, 202, null);
  • AshG 2009-07-22 16:05
    I'm at the end of the third page of comments and have yet to see an Objective C solution.

    What, no Apple/iPhone developers here? WTF?
  • The Answer + 2 2009-07-22 16:11
    C# (assumes a,b,c are defined and assigned elsewhere)

    for(c=(a&1)*b;(a>1);c+=((a>>=1)&1)*(b<<=1));

    44 characters
  • Rob Hulswit 2009-07-22 16:15
    Arrgh, some challenges are just too challenging...
    35 characters, freestanding, no need to declare and assign delegates ;-)

    C++, supports negative (at least the C++ dialect of Borland C++ Builder 5, the sign of (negative number % another number) is implementation defined in C++... sigh).
    int r=0;for(;b;r+=b%2*c;b/=2;c*=2;}

    Or a recursive version in 42 characters:
    int a(b,c){return b?a(b/2,c*2)+(b%2)*c:0;}

    C++ template meta programming:
    template <int b, int c>
    struct r
    {
    static const int s = b?r<b/2,c*2>::s+b%2*c:0;
    };

    Javascript 35 characters (works in firefox 3.0.11 and IE6). Damn, difficult to do integer division by 2 that also works good for negative numbers.
    for(r=0;b/=2;b-=d=b%1,r+=d*(c*=2));
  • Rob Hulswit 2009-07-22 16:21
    Oops, copy-paste for the fail.

    Real C++ version:
    int r=0;for(;b;r+=b%2*c,b/=2,c*=2);
  • Unlabeled Meat 2009-07-22 16:25
    Shifty recursive Scala


    def rusMult(x: Int, y: Int): Int =
    rusMult(x, y, 0)

    def rusMult(x: Int, y: Int, sum: Int): Int =
    if ((x == 0) || (y == 0)) 0
    else
    x match {
    case 1 =>
    sum + y
    case _ =>
    rusMult(x >> 1, y << 1, (if (x % 2 == 0) sum else sum + y))
    }

  • Talks Funny 2009-07-22 16:28
    newlisp.org:
    improvement for some problems starting with even number:


    (define (rmul x y , (s 0))
    (until (= x 1)
    (unless (zero? (% x 2))
    (inc s y))
    (setq x (>> x) y (<< y)))
    (+ y s)
    )


    If you're gonna do it in good LISP, don't use setq so much.
  • Anti-Ruski 2009-07-22 16:30
    Hell with them, just do:

    Function mult (a,b)
    mult = a*b
    end


    Screw the Russians
  • Roger 2009-07-22 16:38
    Free format RPGLE

    SOURCE FILE . . . . . . . QRPGLESRC
    MEMBER . . . . . . . . . RUSPEASANT
    SEQNBR*...+... 1 ...+... 2 ...+... 3 ...+... 4 ...+... 5 ...+... 6 ...+... 7 ...+... 8
    100 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    200 H DEBUG OPTION(*SRCSTMT:*NODEBUGIO) DFTACTGRP(*NO)
    300 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    400 Fqsysprt O F 85 printer OFLIND(*INOF)
    500 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    600 D A S 10I 0
    700 D B S 10I 0
    800 D DIV S 10I 0
    900 D REM S 10I 0
    1000 D RESULT S 10I 0
    1100 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    1200 D RUSPEASANT PR
    1300 D IN_A 15P 5
    1400 D IN_B 15P 5
    1500 D RUSPEASANT PI
    1600 D IN_A 15P 5
    1700 D IN_B 15P 5
    1800 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    1900 /FREE
    2000 A = IN_A ;
    2100 B = IN_B ;
    2200 RESULT = A * B ;
    2300 except head ;
    2400 except detail1 ;
    2500 dow A > 1 ;
    2600 A = %div(A:2) ;
    2700 REM = %REM(A:2) ;
    2800 B = B * 2 ;
    2900 if rem > 0 ;
    3000 RESULT += B ;
    3100 endif ;
    3200 except detail2 ;
    3300 if *INOF ;
    3400 except head ;
    3500 endif ;
    3600 enddo ;
    3700 except total ;
    3800 *INLR = *on ;
    3900 return ;
    4000 /END-FREE
    4100 Oqsysprt E head 1 1
    4200 O 20 'Russian Peasant '
    4300 O 34 'Multiplication'
    4400 O E detail1 1
    4500 O A Z 15
    4600 O 20 '*'
    4700 O B Z 35
    4800 O 40 '='
    4900 O RESULT ZB 55
    5000 O E detail2 1
    5100 O A Z 15
    5200 O B Z 35
    5300 O E total 1
    5400 O RESULT Z 55
    * * * * E N D O F S O U R C E * * * *
  • bluebearr 2009-07-22 16:41
    SoaperGEM:
    I did scan through the code a little bit though, and seeing so many people using division and modulo operators made me sad.

    Alex Papadimoulis:
    Your challenge: write a function that multiplies two numbers using the Russian peasant algorithm.


    I didn't see anything in the original article about the peasants using bit shifting. I did see information about the peasants multiplying by two, and dividing by two and dropping the remainder.

    But hey, maybe I missed something.
  • hornet 2009-07-22 16:44
    Threaded solution for maximum performance on a multicore system - not yet capable of negative or zero first multiplicand:


    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ComponentModel;
    using System.Threading;

    namespace RussianMultiply
    {
    struct Multiplicands
    {
    public ManualResetEvent waitHandle;
    public int a;
    public int b;
    }

    class RussianMultiplyData
    {
    public volatile int result;
    public RussianMultiplyData()
    {
    result = 0;
    }
    public void PartialCalculateMultiplication(object o, DoWorkEventArgs dwea)
    {
    Multiplicands mp = (Multiplicands)dwea.Argument;
    if ((mp.a % 2) == 1) result += mp.b;
    mp.waitHandle.Set();
    }
    };

    class Program
    {
    static int MultiplyMultiCore(int a, int b)
    {
    List<BackgroundWorker> multiplicationWorkers = new List<BackgroundWorker>();
    List<ManualResetEvent> threadCompletedEvents = new List<ManualResetEvent>();
    RussianMultiplyData rmd = new RussianMultiplyData();
    while (a > 0)
    {
    BackgroundWorker bw = new BackgroundWorker();
    Multiplicands mps;
    mps.waitHandle = new ManualResetEvent(false);
    mps.a = a;
    mps.b = b;
    threadCompletedEvents.Add(mps.waitHandle);
    bw.DoWork += rmd.PartialCalculateMultiplication;
    bw.RunWorkerAsync(mps);
    multiplicationWorkers.Add(bw);

    a >>= 1;
    b <<= 1;
    }

    WaitHandle.WaitAll(threadCompletedEvents.ToArray());
    return rmd.result;
    }

    static void Main(string[] args)
    {
    Console.WriteLine(MultiplyMultiCore(18, 23));
    }
    }
    }
  • Bodestone 2009-07-22 16:44
    I happened to be in SQL server at the the time so...


    DECLARE @factor1 INT, @factor2 INT SET @factor1 =18 SET @factor2 = 23

    SELECT SUM(rightCol)
    FROM (SELECT @factor1/POWER(2,N) AS leftCol, @factor2*POWER(2,N) AS rightCol
    FROM Tally
    WHERE N < cast(log10(@factor1)/log10(2) as int) +1) таблица
    WHERE leftCol%2=1


    This does require that you have a Tally table with the integers 0 to x where x is big enough to do any calculation that won't overflow.
  • mxsscott 2009-07-22 16:45
    A solution in C that must be given the input as English transliterations of Russian numbers, in case voice input is used [a must for all future programs]. e.g. 18x23 is
    ./russianmultiply AdeenDva TriVosyem

    It outputs in a similar form, as well as digits.


    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>

    /* Must be 1+7 (not 8 or 7+1) */
    #define MAGIC_LEN 1+7
    const char* numerals[] =
    {
    "Nol","Adeen","Dva","Tri","Chetyre","Pyat’","Shest","Syem","Vosyem","Dyeviat"
    };

    char* intToRussian(unsigned int num)
    {
    char b[11];
    sprintf(b,"%lu",num);
    /* Allocate enough for longest string int and one terminating character */
    char* russian = calloc(MAGIC_LEN * 10, sizeof(char));
    for (int i = 0; i < 10 && b[i]; ++i)
    {
    strcat(russian, numerals[b[i] - '0']);
    }
    return russian;
    }

    unsigned int russianToInt(const char *russian)
    {
    int i,j,num;
    num = j - j;
    for (i = num ; i < strlen(russian); ++i)
    {
    for (j = i - i; j < 0x0A; ++j)
    {
    if ((j - j) == strncmp(russian + i, numerals[j], strlen(numerals[j])))
    {
    num *= 10;
    num += j;
    }
    }
    }
    return num;
    }

    char *multiply(const char* a, const char* b)
    {
    unsigned int a1 = russianToInt(a);
    unsigned int b1 = russianToInt(b);

    unsigned int answer = 0;
    while (a1 > 0)
    {
    a1 = a1 >> 1;
    b1 = b1 << 1;
    if (a1 & 0x01)
    answer += b1;
    }
    return intToRussian(answer);
    }

    int main (int argc, const char * argv[]) {
    char *answer = multiply(argv[1], argv[2]);
    printf("%s\n", answer);
    printf("%lu\n", russianToInt(answer));
    return 0;
    }
  • astonerbum 2009-07-22 16:45
    Beat by the system:
    anyone done this in javascript?
    function multiply (x, y, total)
    {
    (x == 0) ? alert(total) : multiply (Math.floor(x/2),Math.floor(y*2),(x % 2 == 0) ? total : total+y);
    }


    http://thedailywtf.com/Comments/Programming-Praxis-Russian-Peasant-Multiplication.aspx?pg=8#278264

    Also an inefficiency I had was not using shift for multiply by two. I added the y to itself. Also I coulda removed one comparison. Hey we want ultimate efficiency.

    I still wonder if this algorithm is what is used for doing multiplication internally in the processor. Seems a WHOLE lot more efficient than doing addition a whole lota times, or even doing times tables or whatever... Those brilliant russian peasents :)


    function rpmult(x, y){
    if (x === 0) {
    return 0;
    }
    if (x === 1) {
    return y;
    }

    var flip = false;
    if (x < 0) {
    x = -x;
    flip = true;
    }
    var added = (((0x1 & num) === 0x1) ? 0 : y);
    var recurse = rpmult(x >> 1, y << 1);
    return flip ? - (added + recurse) : added + recurse;
    }
  • Ted Walther, newLISP fan 2009-07-22 16:46
    Unlike the perl one-liner, this newlisp one-liner is actually readable!

    (define (rmul x y) (if (= x 1) y (+ (if (zero? (% x 2)) 0 y) (rmul (>> x) (<< y)))))
  • Jeb Walter Strate 2009-07-22 16:46
    My javascript version uses no multiplication, division, nor bit-shifting. Handles decimals, but negatives are left as an exercise for the reader.
    <html><head><title>Multiply WFT</title><script>
    
    double={0:0,1:2,2:4,3:6,4:8,'.':'.'};
    doubleNeedsCarry={5:0,6:2,7:4,8:6,9:8};
    carriedDouble={0:1,1:3,2:5,3:7,4:9};
    carriedDoubleNeedsCarry={5:1,6:3,7:5,8:7,9:9,'.':'.'};
    halve={0:0,2:1,4:2,6:3,8:4,'.':'.'}
    halveHasRemainder={1:0,3:1,5:2,7:3,9:4};
    RemainderedHalve={0:5,2:6,4:7,6:8,8:9};
    RemainderedHalveHasRemainder={1:5,3:6,5:7,7:8,9:9,'.':'.'};
    function halveRow(row){
    var cells=row.cells;
    var out=document.createElement('tr');
    var remaindered=false;
    var leading=true;
    var visible='hidden';
    for(var cellIndex=0;cellIndex<cells.length;cellIndex++){
    var cell=cells[cellIndex];
    var cellValue=cell.innerHTML;
    var newCell=document.createElement('td');
    if(remaindered==false){
    if(cellValue in halve){
    newCell.innerHTML=halve[cellValue];}
    if(cellValue in halveHasRemainder){
    newCell.innerHTML=halveHasRemainder[cellValue];}}
    else if(remaindered=true){
    if(cellValue in RemainderedHalve){
    newCell.innerHTML=RemainderedHalve[cellValue];}
    if(cellValue in RemainderedHalveHasRemainder){
    newCell.innerHTML=RemainderedHalveHasRemainder[cellValue];}}
    if(!remaindered && cellValue in halve || remaindered && !(cellValue in RemainderedHalveHasRemainder)){
    remaindered=false;}
    else{
    remaindered=true;}
    if(leading==true){
    if(newCell.innerHTML=='0'){
    newCell.style.visibility=visible;}
    else if(newCell.innerHTML=='.'){
    visible='';}
    else
    leading=false;}
    out.appendChild(newCell);}
    if(newCell.innerHTML in halve){
    out.style.textDecoration='line-through';}
    row.parentNode.appendChild(out);
    if(leading==true){
    out.style.visibility='hidden';
    return false;}
    else{
    return !leading;}}
    function doubleRow(row){
    var cells=row.cells;
    var cellIndex=cells.length;
    var out=document.createElement('tr');
    var carried=false;
    while(cellIndex--){
    var cell=cells[cellIndex];
    var cellValue=cell.innerHTML;
    var newCell=document.createElement('td');
    if(carried==false){
    if(cellValue in double){
    newCell.innerHTML=double[cellValue];}
    if(cellValue in doubleNeedsCarry){
    newCell.innerHTML=doubleNeedsCarry[cellValue];}}
    else if(carried=true){
    if(cellValue in carriedDouble){
    newCell.innerHTML=carriedDouble[cellValue];}
    if(cellValue in carriedDoubleNeedsCarry){
    newCell.innerHTML=carriedDoubleNeedsCarry[cellValue];}}
    if(!carried && cellValue in double || carried && !(cellValue in carriedDoubleNeedsCarry)){
    carried=false;}
    else{
    carried=true;}
    out.insertBefore(newCell,out.firstChild);}
    if(carried!=false){
    var newCell=document.createElement('td');
    newCell.innerHTML=carriedDouble['0'];
    out.insertBefore(newCell,out.firstChild);}
    var tb=row.parentNode;
    tb.appendChild(out);
    if(row.cells.length==out.cells.length){}
    else{
    for(var i=0;i<tb.rows.length;i++){
    while(tb.rows[i].cells.length<out.cells.length){
    var blank=document.createElement('td');
    blank.innerHTML='0';
    blank.style.visibility='hidden';
    tb.rows[i].insertBefore(blank,tb.rows[i].firstChild);}}}}
    function multiply(form){
    var a=form.inta.value;
    var b=form.intb.value;
    if(a.charAt(a.length-1)=='.'){a+='0'}
    if(b.charAt(b.length-1)=='.'){b+='0'}
    var row=document.getElementsByTagName('tr')[0];
    var t=document.createElement('table');
    t.cellSpacing=0;
    var tb=document.createElement('tbody');
    var tr=document.createElement('tr');
    t.appendChild(tb).appendChild(tr);
    var digits=a.split('');
    for(var i=0;i<digits.length;i++){
    var td=document.createElement('td');
    td.innerHTML=digits[i];
    tr.appendChild(td);}
    if(digits[digits.length-1] in halve){
    tr.style.textDecoration='line-through';}
    row.cells[0].innerHTML='';
    row.cells[0].appendChild(t);
    row.cells[1].innerHTML='<table cellSpacing=0><tbody><tr><td>&nbsp;X</td></tr></tbody></table>';
    t=document.createElement('table');
    t.cellSpacing=0;
    tb=document.createElement('tbody');
    tr=document.createElement('tr');
    t.appendChild(tb).appendChild(tr);
    if(digits.pop() in halve){
    tr.style.textDecoration='line-through';}
    digits=b.split('');
    for(var i=0;i<digits.length;i++){
    var td=document.createElement('td');
    td.innerHTML=digits[i];
    tr.appendChild(td);}
    row.cells[2].innerHTML='';
    row.cells[2].appendChild(t);
    while(halveRow(row.cells[0].firstChild.firstChild.lastChild) ){
    doubleRow(row.cells[2].firstChild.firstChild.lastChild);
    row.cells[2].firstChild.firstChild.lastChild.style.textDecoration=row.cells[0].firstChild.firstChild.lastChild.style.textDecoration
    row.cells[1].firstChild.firstChild.insertRow(-1).insertCell(0).innerHTML='&nbsp;';}
    row.cells[1].firstChild.firstChild.insertRow(-1).insertCell(0).innerHTML='&nbsp;';
    row.cells[2].firstChild.firstChild.insertRow(-1).insertCell(0).innerHTML='&nbsp;';
    row.cells[1].firstChild.cellSpacing=0;
    t=document.createElement('table');
    t.cellSpacing=0;
    tb=document.createElement('tbody');
    tr=document.createElement('tr');
    t.appendChild(tb).appendChild(tr);
    row.cells[3].innerHTML='';
    row.cells[3].appendChild(t);
    var decimala=0;
    for(var i=0;i<row.cells[0].firstChild.firstChild.firstChild.cells.length;i++){
    if(row.cells[0].firstChild.firstChild.firstChild.cells[i].innerHTML=='.'){
    decimala=row.cells[0].firstChild.firstChild.firstChild.cells.length-i;
    break}}
    var decimalb=0;
    for(var i=0;i<row.cells[2].firstChild.firstChild.firstChild.cells.length;i++){
    if(row.cells[2].firstChild.firstChild.firstChild.cells[i].innerHTML=='.'){
    decimalb=row.cells[2].firstChild.firstChild.firstChild.cells.length-i;
    break}}
    var r=row.cells[2].firstChild.firstChild.lastChild;
    while(r=r.previousSibling){
    var newRow=tb.insertBefore(r.cloneNode(true),tb.firstChild);
    if(tb.firstChild.style.textDecoration){
    tb.firstChild.style.visibility='hidden';}
    if(decimala && decimalb){
    var dec=newRow.removeChild(newRow.cells[newRow.cells.length-decimalb]);
    newRow.insertBefore(dec, newRow.cells[newRow.cells.length-decimalb-decimala+2]);}
    if(decimala && !decimalb){
    var dec=document.createElement('td');
    dec.innerHTML='.';
    newRow.insertBefore(dec, newRow.cells[newRow.cells.length-decimala+1]);}}
    var carry=0;
    for(var i=tb.rows[0].cells.length;i;){
    --i;
    var t=carry*1;
    carry=0;
    for(var j=0;j<tb.rows.length-1;j++){
    if(tb.rows[j].style.visibility=='hidden') continue;
    if(tb.rows[j].cells[i].innerHTML=='.'){
    carry=t;
    t='.';
    break;}
    t+=parseInt(tb.rows[j].cells[i].innerHTML);}
    if(t>9){
    var s=t.toString().split('');
    t=s.pop();
    carry=s.join('');}
    tb.lastChild.insertCell(0).innerHTML=t;}
    if(carry!='0'){
    for(j=0;j<tb.rows.length;j++){
    var blank=document.createElement('td');
    blank.innerHTML='0';
    blank.style.visibility='hidden';
    tb.rows[j].insertBefore(blank,tb.rows[j].firstChild);}
    blank.innerHTML=carry;
    blank.style.visibility='visible';}
    row.cells[3].getElementsByTagName('tr')[row.cells[3].getElementsByTagName('tr').length-1].style.textDecoration='overline';}
    </script>
    </head><body><form action="javascript:multiply(document.forms[0])"><br>
    <input name=inta><br>
    <input name=intb><br>
    <input type=submit value=multiply><br>
    <table cellspacing=5><tbody><tr><td></td><td></td><td></td><td></td></tr></tbody></table>
    </body></html>
  • Roger 2009-07-22 16:46
    The program listed above produces this output

    Russian Peasant Multiplication
    18 * 23 = 414
    9 46
    4 92
    2 184
    1 368
    414
  • WTF! 2009-07-22 16:51
    My WTF is that I'd just create a huge times-table in MS Access and use DAO calls to read it back.
  • Tom Medley - www.tommedley.com 2009-07-22 16:54
    This problem is trivial in ML (4 lines):

    fun peasant (1,r,q) = sum(r::q)
    | peasant (l,r,q) = if(l mod 2 = 1)
    then peasant((l div 2),(r*2),(r::q))
    else peasant((l div 2),(r*2),q);

    ...a wrapper function to make it nice:

    fun russian(x,y) = peasant(x,y,[]);

    ...and in case you need a sum function (most ml versions come with standard functions such as sum):

    fun sum [] = 0
    | sum (x::xs) = x + sum(xs);
  • Rob H 2009-07-22 16:55
    In C, C++, C#, taking zeros and negative numbers into account:

    Recursive (not tested):
    INT Multiply(INT a, INT B)
    
    {
    INT c, PosNeg = 1;

    // first, deal with zeros
    if ((a == 0) || (b == 0))
    return 0;

    // now, deal with negative numbers
    if (a < 0)
    {
    a = -a;
    PosNeg = -PosNeg;
    }
    if (b < 0)
    {
    b = -b;
    PosNeg = -PosNeg;
    }

    // now, the meat of the problem
    if (a == 1)
    return b;
    else
    return (b * (a & 1) + Multiply(a / 2, b * 2)) * PosNeg;
    }
    Alternatively, if you use the following as the last line, you accomplish this using only one multiplication (the one dealing with +/-) and one division per step:
        return ((a & 1) ? b : 0) + Multiply(a / 2, b + b)) *
    
    PosNeg;

    Non-recursive (also not tested):
    INT Multiply(INT a, INT B)
    
    {
    INT c = 0, PosNeg = 1;

    // first, deal with zeros
    if ((a == 0) || (b == 0))
    return 0;

    // now, deal with negative numbers
    if (a < 0)
    {
    a = -a;
    PosNeg = -PosNeg;
    }
    if (b < 0)
    {
    b = -b;
    PosNeg = -PosNeg;
    }

    // now, the meat of the problem
    while (a > 0)
    {
    if (a & 1)
    c += b;
    a /= 2;
    b *= 2; // or b += b; if you want to get rid of a multiplication
    }
    return c * PosNeg;
    }

    (Of course, in C++ and C#, you would probably move the declarations for c and PosNeg down closer to where they're actually used.)
  • qoo3h 2009-07-22 16:59
    Is anyone reading this far?

    In Perl, implementing the algorithm as described, showing working:

    #!/usr/bin/perl -w

    use strict;

    my $a = shift or die( "need arg 1" );
    my $b = shift or die( "need arg 2" );
    my $neg = ($a < 0 xor $b < 0) ? -1 : 1;
    my @nums;
    for ($a = abs $a, $b = abs $b; $a > 0; push(@nums,{'a'=>$a, 'b'=>$b}), $a >>= 1, $b <<= 1) {}
    map {print "$_->{'a'} + $_->{'b'}\n" } @nums;
    print( "###\n" );
    @nums = grep {$_->{'a'} % 2} @nums;
    map {print "$_->{'a'} + $_->{'b'}\n" ;$a += $_->{'b'} } @nums;
    print( 'sum: ', $a * $neg, "\n" );
  • Lee Crabtree 2009-07-22 17:03
    A Python solution. It could definitely be done in less code, but I'd rather be able to understand it.

    import math

    def russian_multiply(x, y):
    cols = [(x, y)]

    while True:
    x = int(math.floor(x / 2))
    y = int(math.floor(y * 2))

    cols.append((x, y))

    if x <= 1:
    break

    col_sum = sum([c[1] for c in cols if c[0] % 2 != 0])

    return col_sum

    print russian_multiply(18, 23)
  • J.I. 2009-07-22 17:04
    Pretty similar in C;

    int l(int l1, int ll) { return l1&-2?l1%2*ll+l(l1/2,ll*2):ll; }

    Looks kind of like a traffic accident, doesn't it?
  • ajp 2009-07-22 17:09
    I didn't check to see if there was an F# one done yet or not. But here is my attempt.

    F# Version 1.9.6.16, compiling for .NET Framework Version v4.0.20506
    
    #light
    let isOdd x =
    (x%2) = 1

    let rec mult x y =
    match x with
    | 1 -> y
    | _ when isOdd x -> y + mult (x/2) (y*2)
    | _ -> mult (x/2) (y*2)

  • Andrew Rodland 2009-07-22 17:10
    I was disturbed by the fact that the Perl uses the multiplication operator when it doesn't need to, so I offer:

    sub rp_mult {
    my ($i, $j) = @_;
    my $r = 0;
    do {
    $r += ($j & 1) && $i;
    $i <<= 1;
    $j >>= 1;
    } while ($i);
    $r;
    }

    Or, moderately golfed:
    sub rpmul{($r,$i,$j)=(0,@_);$r+=$j&1&&$i,$i<<=1,$j>>=1while$i;$r;}

    Or, from a slightly different angle:

    use List::Util 'sum';
    sub rp_mult {
    my ($i, $j) = @_;
    sum map $j >> $_ & 1 && $i << $_,
    0 .. log $j / log 2;
    }
  • sdeek 2009-07-22 17:11
    python. Gratuitous use of list comprehensions and generators.
    Doesn't work for negative numbers. Patches welcome ;-)


    a=22
    b=66
    import math
    def half():
    aa=a
    while aa >=1:
    yield aa
    aa= aa/2
    print sum([y for (x,y) in zip([x for x in half()],[b*(2**(x)) for x in range(0,len([x for x in half()])+1)]) if x%2==1])
  • Michael Clark (mjac.co.uk) 2009-07-22 17:13
    fun pmulti 1 r t = t + r
    | pmulti l r t = pmulti (l div 2) (r * 2) (t + r * (l mod 2))

    pmulti 3 4 0 will give you 3 * 4, t is just an accumulator
  • opussf 2009-07-22 17:15
    In Python:

    a,b = 190, 232
    if a<0: a=-a; b=-b
    print sum([b<<s for s in xrange(0,int(math.log(a,2)+1)) if ((a>>s>0) and ((a>>s)%2)) ])

  • KukkerMan 2009-07-22 17:25

    def rpmult(a, b):
    rows = []
    while a > 1:
    rows.append( (a, b) )
    a, b = a >> 1, b << 1
    rows.append( (a, b) )
    return reduce(lambda (_, b1), (__, b2): b1 + b2, filter(lambda (a, _): a & 1, rows))

  • Jimmy Selgen 2009-07-22 17:26
    (Readable) Ruby version
    Handles negative numbers (and unlike some of the examples i read, returns correct signs)

    class Rpm
    
    def self.multiply(x1,x2)
    ret = 0
    is_neg = false

    if x1 < 0
    is_neg = true
    x1 = -x1
    end

    if x2 < 0
    is_neg = !is_neg
    x2 = -x2
    end

    return 0 if x1 == 0

    begin
    ret += x2 if x1 % 2 != 0
    x1 = (x1 / 2).floor
    x2 = x2 * 2
    end while( x1 >= 1)

    ret = -ret if is_neg
    return(ret)
    end
    end
  • Tiogshi 2009-07-22 17:29
    For maximum speed, I pre-allocate the tables I use for storage, and avoid all floating-point multiplies and divides. A complete executable program in Lua; run with an argument (any argument) for the peasant-product, without to use the baseline-for-testing "Gold" function.

    function Gold(a, b)
    
    return a * b
    end

    function DivideByTwo(n)
    local m = n
    while m + m > n do
    m = m - 1
    end
    return m
    end

    function AllocateTable(a)
    local t = {}
    while a >= 1 do
    a = DivideByTwo(a)
    t[#t + 1] = {}
    end
    return t
    end

    function AllocateColumnTable(t)
    for i = 1, #t do
    t[i].aColumn = 0
    t[i].bColumn = 0
    end
    end

    function AllocateValidTable(t)
    for i = 1, #t do
    t[i].truth = false
    end
    end

    function TestIsOdd(n)
    n = math.abs(n)

    while n > 1 do
    n = n - 2
    end

    if n == 0 then
    return false
    elseif n == 1 then
    return true
    else
    print("unknown failure")
    os.exit(-1)
    end
    end

    function PopulateTable(t, a, b)
    for i = 1, #t do
    local j = i - 1
    local aC, bC = a, b
    while j > 0 do
    if TestIsOdd(aC) then
    aC = DivideByTwo(aC - 1)
    else
    aC = DivideByTwo(aC)
    end

    bC = bC + bC

    j = math.floor(j - 1)
    end

    t[i].aColumn = aC
    t[i].bColumn = bC
    end
    end

    function CollectValidRows(t, v)
    local n = math.min(#t, #v)
    for i = 1, n do
    if TestIsOdd(t[i].aColumn) then
    v[i].truth = true
    end
    end
    end

    function SumValidRows(t, v)
    local n = math.min(#t, #v)
    local sum = 0
    for i = 1, n do
    if v[i].truth == true then
    sum = sum + t[i].bColumn
    end
    end
    return sum
    end

    function PeasantProduct(a, b)
    local columTable = AllocateTable(a)
    local validTable = AllocateTable(a)

    AllocateColumnTable(columTable)
    AllocateValidTable(validTable)

    PopulateTable(columTable, a, b)
    CollectValidRows(columTable, validTable)

    return SumValidRows(columTable, validTable)
    end

    function DoTest(f)
    -- Generated by fair dice roll. Guaranteed to be random.
    math.randomseed(4)

    for n = 1, 1000 do
    local a = math.random(1, 200)
    local b = math.random(1, 200)
    print( string.format("%d * %d = %d", a, b, f(a,b)))
    end
    end

    local args = {...}

    if args[1] then
    print("Peasant")
    DoTest(PeasantProduct)
    else
    print("Baseline")
    DoTest(Gold)
    end
  • ikegami 2009-07-22 17:31
    As a circuit diagram



    (Handles 4-bit unsigned integers)

    The selection of input wires for AND gates perform the right shifts.
    The AND gates perform the oddness test.
    The selection of input wires for the adders perform the left shifts.


    Addendum (2009-07-22 23:27):
    I forgot to mention this was done in MS Paint
  • Eric 2009-07-22 17:31
    Take your pick:

    (defun multiply (x y)
    
    (loop
    with result = 0
    for first = x then (floor first 2)
    for second = y then (* second 2)
    if (oddp first)
    do (incf result second)
    if (= first 1)
    do (return result)))

    (defun trmultiply (x y)
    (labels
    ((inner
    (x y acc)
    (if (> x 0)
    (inner (floor x 2)
    (* y 2)
    (if (oddp x) (+ y acc) acc))
    acc)))
    (inner x y 0)))
  • Yorick 2009-07-22 17:31
    Speccy basic, recursive:

    10 DEF FN m(a,b)=VAL ((("FN m(
    "+STR$ a+"*2,INT ("+STR$ b+"/2))
    +("+STR$ b+"-2*INT ("+STR$ b+"/2
    ))*"+STR$ a) AND b<>1)+(STR$ a A
    ND b=1))

  • mol1111 2009-07-22 17:35
    Originally I thought about sending 1235th boring C# version or 436th Python version but then I realized that there is no GUI version (except for few PHP or JS versions with HTML WUI [Web User Interface :-) ]). So I created one using my all-time favourite library: Turbo Vision (so it's really TUI and not GUI). Tested with BP7 and recent FreePascal.

    program RussianMultiplicationTV;

    uses App, Dialogs, Drivers, Menus, MsgBox, Objects, Validate, Views;

    const
    cmCalculate = 1001;

    type
    TRussMultApp = object(TApplication)
    procedure InitMenuBar; virtual;
    procedure HandleEvent(var Event: TEvent); virtual;
    procedure ExecuteMainDlg;
    end;

    PMainDlg = ^TMainDlg;
    TMainDlg = object(TDialog)
    ResultListBox: PListBox;
    FirstInputLine: PInputLine;
    SecondInputLine: PInputLine;
    constructor Init;
    procedure HandleEvent(var Event: TEvent); virtual;
    end;

    function Calculate(x, y: longint): PCollection;
    type
    TFormatRec = record
    Line, X, Y, Extra: longint;
    end;
    var
    List: PStringCollection;
    TempStr: String;
    FormatRec: TFormatRec;
    begin
    New(List, Init(10, 10));
    List^.Insert(NewStr(#0 + 'Step First Second Extra'));
    FormatRec.Line := 1;
    FormatRec.Extra := 0;
    while (x > 0) do begin
    FormatRec.X := x;
    FormatRec.Y := y;
    Inc(FormatRec.Extra, (x mod 2) * y);
    FormatStr(TempStr, '%5d %8d %8d %8d', FormatRec);
    List^.Insert(NewStr(TempStr));
    x := x shr 1;
    y := y shl 1;
    Inc(FormatRec.Line);
    end;
    List^.Insert(NewStr(' ------'));
    Str(FormatRec.Extra, TempStr);
    List^.Insert(NewStr(' Result = ' + TempStr));
    Calculate := List;
    end;

    procedure TRussMultApp.ExecuteMainDlg;
    var
    Dlg: PMainDlg;
    begin
    New(Dlg, Init);
    ExecuteDialog(Dlg, nil);
    end;

    procedure TMainDlg.HandleEvent(var Event: TEvent);
    var
    x, y: longint;
    code: integer;
    begin
    inherited HandleEvent(Event);
    if (Event.What = evCommand) and (Event.Command = cmCalculate) then begin
    Val(FirstInputLine^.Data^, x, code);
    if code <> 0 then begin
    MessageBox('Please put valid number into the first input field.', nil,
    mfError or mfOKButton);
    exit;
    end;
    Val(SecondInputLine^.Data^, y, code);
    if code <> 0 then begin
    MessageBox('Please put valid number into the second input field.', nil,
    mfError or mfOKButton);
    exit;
    end;
    ResultListBox^.NewList(Calculate(x, y));
    ClearEvent(Event);
    end;
    end;

    procedure TRussMultApp.HandleEvent(var Event: TEvent);
    begin
    inherited HandleEvent(Event);
    if ((Event.What = evCommand) and (Event.Command = cmNew)) then begin
    ExecuteMainDlg;
    ClearEvent(Event);
    end;
    end;

    procedure TRussMultApp.InitMenuBar;
    var
    R: TRect;
    begin
    GetExtent(R);
    R.B.Y := R.A.Y + 1;
    MenuBar := New(PMenuBar, Init(R, NewMenu(
    NewItem('~C~alculator', '', kbNoKey, cmNew, 0,
    NewItem('E~x~it', 'Alt+X', kbAltX, cmQuit, hcExit,
    nil)))));
    end;

    constructor TMainDlg.Init;
    var
    R: TRect;
    ScrollBar: PScrollBar;
    S: String[8];
    begin
    R.Assign(0, 0, 60, 20);
    inherited Init(R, 'Russian Multiplication');
    Options := Options or ofCentered;

    R.Assign(2, 2, 12, 3);
    New(FirstInputLine, Init(R, 8));
    FirstInputLine^.SetValidator(New(PRangeValidator, Init(1, 1000)));
    Str(Random(9999) + 1, S);
    FirstInputLine^.SetData(S);
    Insert(FirstInputLine);
    R.Assign(14, 2, 26, 3);
    New(SecondInputLine, Init(R, 8));
    SecondInputLine^.SetValidator(New(PRangeValidator, Init(1, 1000)));
    Str(Random(999) + 1, S);
    SecondInputLine^.SetData(S);
    Insert(SecondInputLine);
    R.Assign(27, 2, 45, 4);
    Insert(New(PButton, Init(R, 'Calculate!', cmCalculate, bfDefault)));
    R.Assign(57, 4, 58, 19);
    New(ScrollBar, Init(R));
    Insert(ScrollBar);
    R.Assign(2, 4, 57, 19);
    New(ResultListBox, Init(R, 1, ScrollBar));
    Insert(ResultListBox);

    { Selects first input box }
    SelectNext(False);
    end;

    var
    RussMultApp: TRussMultApp;

    begin
    Randomize;
    RussMultApp.Init;
    RussMultApp.Run;
    RussMultApp.Done;
    end.


    Addendum (2009-07-22 21:05):
    Download (Source+binaries for DOS and Windows)
  • Edinburgh Mike 2009-07-22 17:36
    #!/usr/bin/env python

    def rus_mult(A, B):
    if A == 1:
    return B
    else:
    return rus_mult(A / 2, B * 2) + (A % 2) * B

    def run_tests():
    tests = [(18, 23), (12, 3), (1, 1), (15, 2), (8, 22), (7, 13), (9, 20)]

    for (A, B) in tests:
    print "Test", A, "*", B, "Result:", rus_mult(A, B) == A * B

    if __name__ == "__main__":
    run_tests()
  • Lernin ur codez 2009-07-22 17:42
    C#, handles negative numbers 0, 1.

    And, as usual, the most elegant solution is the recursive one.


    private int RussianPeasant(int a, int b)
    {
    int c;
    if (a < 0)
    {
    a = -a;
    b = -b;
    }
    for (c = (a & 1) * b; (a > 1); c += ((a >>= 1) & 1) * (b <<= 1)) ;
    return c;
    }

    private int RecursiveRussianPeasant(int a, int b)
    {
    if (a < 0)
    return RecursiveRussianPeasant(-a, -b);
    return (a == 0) ? 0 : ((a & 1) * b) + RecursiveRussianPeasant(a >> 1, b << 1);
    }

  • Redredredredredred 2009-07-22 17:47
    theres some ruby code for you

    def rmul(a,b)
    
    ret = 0
    begin
    ret = (a<0) ? ret-b : ret+b if a%2==1 or a%2==-1
    a = (a<0) ? a/2 + a%2 : a/2
    b = b*2
    end while a != 1 and a != -1 and a != 0
    ret = (a<0) ? ret-b : ret+b if a%2==1 or a%2==-1
    ret
    end

    puts rmul(-10,20)
    puts rmul(10,20)
    puts rmul(-3,500)
    puts rmul(1002,343)
  • Kevin Kofler 2009-07-22 17:48
    Here's one in Motorola 68000 assembly:
    .xdef __mulsi3
    
    __mulsi3:
    move.l 4(%a7),%d1
    move.l 8(%a7),%d2
    moveq.l #0,%d0
    0:
    lsr.l #1,%d1
    bcc.s 1f
    add.l %d2,%d0
    1:
    add.l %d2,%d2
    tst.l %d1
    bne.s 0b
    rts

    Note that this one is actually useful, it can be used if you don't have a working libgcc for your target. :-) Though that one is faster. ;-)

    That said, on CPUs like the Z80 which don't have a native multiplication instruction, Russian Peasant is actually extremely useful.
  • Rasmus 2009-07-22 17:52
    def Mul(a,b):
    return DirectionsFromLeaders( "mul", a, b )


    example:

    > Mul(3,56)
    : Illegal Question, Caller terminated
  • H2 2009-07-22 17:58
    My Perl-solution with optimization, a bit of math and several tests. It also handles negative numbers.


    #/usr/bin/perl
    use strict;
    use warnings;

    if ((@ARGV != 2) || ($ARGV[0]!~m/\d/) || ($ARGV[1]!~m/\d/)) {
    print "Missing or wrong arguments! Need two integers\n";
    exit(0);
    }

    my ($left,$right)=@ARGV;

    if ($right lt $left) {
    my $temp=$right;
    $right=$left;
    $left=$temp;
    }

    my $negative=1;

    if ($left==1) {
    print $right."\n";
    exit(0);
    }
    elsif ($left==0) {
    print "0\n";
    exit(0);
    }
    elsif (($left lt 0) && ($right lt 0)) {
    $left*=-1;
    $right*=-1;
    }
    elsif (($left lt 0) || ($right lt 0)) {
    $left=abs($left);
    $right=abs($right);
    $negative=-1;
    }

    my $result=0;
    for (my $iteration=int(log($left)/log(2));$iteration>=0;$iteration--) {
    if ($left%2!=0) {
    $result+=$right;
    }
    $left=int($left/2);
    $right*=2;
    }
    print $negative*$result."\n";
  • Ben 2009-07-22 17:59
    ath:
    Same thing in python:

    def is_odd(n):
    return (n % 2) != 0

    def rmul(x, y):
    s = 0
    while(x != 1):
    if is_odd(x):
    s += y
    x /= 2
    y *= 2
    return y + s


    Funnily enough, I did the same thing... then realized that is_odd() can be superseded by the simple statement "if (num%2)".
    Mine prints output, but it's basically the same. I wasn't aware that Python supported +=, though.
  • Sam 2009-07-22 18:07

    #include <libgen.h>
    #include <stdio.h>
    #include <stdlib.h>

    int main(int argc, char **argv)
    {
    int lhs, rhs;
    int res;

    if (argc != 3) {
    printf("usage: %s <lhs> <rhs>\n", basename(argv[0]));
    return (1);
    }

    lhs = atoi(argv[1]);
    rhs = atoi(argv[2]);

    res = 0;
    while (lhs > 1) {
    if (lhs % 2 == 1) {
    res += rhs;
    }
    lhs /= 2;
    rhs *= 2;
    }

    res += rhs;

    printf("result: %d\n", res);

    return (0);
    }
  • PatrickBeebe 2009-07-22 18:08
    In c#

    public static int RussianMultiplication(int x, int y)
    {
    if ((y >> 31 | 1) * y < (x >> 31 | 1) * x)
    y = (x + y) - (x = y);

    int result = 0;
    for (result = 0; x != 0; x /= 2, y >>= 1)
    result += ((x >> 31) | 1) * ((0 - (x & 1)) & y);

    return result;
    }

    Handles 0, negatives, and optimizes which digits to place in which column.

    And. Fast.


    Addendum (2009-07-23 13:39):
    Whoops, that should have been:

    public static int RussianMultiplication(int x, int y)
    {
    if ((y >> 31 | 1) * y < (x >> 31 | 1) * x)
    y = (x + y) - (x = y);

    int result = 0;
    for (result = 0; x != 0; x /= 2, y += y)
    result += ((x >> 31) | 1) * ((0 - (x & 1)) & y);

    return result;
    }
  • mwchase 2009-07-22 18:11
    Bah, one-liners. I figured I'd write my code in true WTF style.

    #!/usr/bin/env python
    

    def mult(a, b):
    d = {a: b}
    if d.keys() == [0] or d.values() == [0]:
    return 0
    if d.keys() < [0]:
    return mult(*(increment(~d.keys()[0]), increment(~d.values()[0])))
    extend(d)
    [d.__delitem__(k) for k in d.keys() if not k&1]
    return sum(d.values())

    def extend(d):
    d[min(d.keys())>>1] = (d[min(d.keys())])<<1
    if min(d.keys()) != 1 and min(d.keys()) != 0:
    extend(d)
    return

    def increment(x, p=0):
    if x & (1<<p):
    return increment(x^(1<<p), increment(p))
    return x | (1<<p)


    Note that I only used arithmetic-related stuff on the lists. Everything else is done bit-wise. See if you can spot the weird abuses and seemingly-random edge cases! (Hint: if there's code that doesn't seem to serve much of a purpose, especially in an if-statement, it's probably deflecting execution around an infinite loop. Either that or I thought it would be funny.)

    Addendum (2011-01-30 17:48):
    Looking back on this, it turns out I could have made parts of it even worse. The if-statement in extend, for example, could use instead "min(d.keys())&-2" (or ~1, if you like. The values are equivalent)

    I think the lesson to take away from this is, if any potential employers decided to see if Google knew about my python experience, this is all a joke.
  • LeCoyote 2009-07-22 18:11
    Two PHP functions in there: the first one does the maths, the second one displays a (very) barren page detailing the steps.
    <?php
    
    function motherland($a,$b)
    {
    $r=0 ;
    while($a)
    {
    ($a%2) && $r+=$b ;
    $a>>=1 ;
    $b<<=1 ;
    }
    return $r ;
    }

    function motherland2($a,$b)
    {
    $r = 0 ;
    $o = "<table>";
    while($a)
    {
    $t = " text-decoration: line-through" ;
    $o .= "<tr style='text-align: right;";
    ($a % 2) && list($r,$t) = array($r+$b,"") ;
    $o .= "$t'><td>$a</td><td>x</td><td>$b</td></tr>";
    $a >>= 1 ;
    $b <<= 1 ;
    }
    $o .= "<tr><td></td><td></td><td>$r</td></table>";
    return $o ;
    }
    echo motherland2(167, 24);
    echo motherland(167, 24);
    ?>

    Fun :-)
    Syntax highlighting was just ... too much free time ;)
  • AshG 2009-07-22 18:17
    ikegami:
    As a circuit diagram



    (Handles 4-bit unsigned integers)

    The selection of input wires for AND gates perform the right shifts.
    The AND gates perform the oddness test.
    The selection of input wires for the adders perform the left shifts.
    This one rocks! But you need to expand adders as well, either on a separate sheet or the same one. Also show the transistor logic for each AND gate and adders.
  • Florent 2009-07-22 18:24
    $ perl -E'($i,$j)=@ARGV;while($i){($i!=int($i/2)*2||!int($i/2))&&($k+=$j);$j*=2;$i=int($i/2)}say$k' 18 23
    414
    $
  • Adrian 2009-07-22 18:29
    Here's my code in python:

    def mul(a,b):
    m=[(a,b)]
    while(m[-1][0]<>1):
    m.append((m[-1][0]/2, m[-1][1]*2))
    return sum([x[1] for x in m if x[0]%2==1])
  • dee 2009-07-22 18:34
    I'm a little disappointed that I haven't seen any submissions in the language actually used to perform Important tasks involving numbers: COBOL.


    IDENTIFICATION DIVISION.
    PROGRAM-ID. RussianPeasantMultiplication.

    DATA DIVISION.
    WORKING-STORAGE SECTION.
    01 FirstNumber PIC S9(18).
    01 SecondNumber PIC S9(18).
    01 Result PIC S9(18) VALUE 0.
    01 ResultFormat PIC ------------------9.

    PROCEDURE DIVISION.
    MAIN.
    PERFORM DATA-ACQUISITION.
    PERFORM PEASANT-MULTIPLICATION-PROCEDURE.
    STOP RUN.

    DATA-ACQUISITION.
    DISPLAY "First number: " WITH NO ADVANCING.
    ACCEPT FirstNumber.
    DISPLAY "Second number: " WITH NO ADVANCING.
    ACCEPT SecondNumber.

    PEASANT-MULTIPLICATION-PROCEDURE.
    IF FirstNumber IS NEGATIVE THEN
    COMPUTE FirstNumber = - FirstNumber
    COMPUTE SecondNumber = - SecondNumber
    END-IF.

    PERFORM UNTIL FirstNumber IS ZERO
    IF FUNCTION MOD(FirstNumber 2) = 1 THEN
    ADD SecondNumber TO Result
    END-IF
    DIVIDE FirstNumber BY 2 GIVING FirstNumber
    ADD SecondNumber TO SecondNumber GIVING SecondNumber
    END-PERFORM.

    MOVE Result TO ResultFormat.
    DISPLAY 'Result: ' ResultFormat.


    Tested with OpenCobol 1.0.
  • Florent 2009-07-22 18:35
    Or shorter :
    $ perl -E'($i,$j)=@ARGV;while($i){($i%2||!$i/2)&&($k+=$j);$j*=2;$i=int($i/2)}say$k' 18 23
    414
    $
  • valderman 2009-07-22 18:37
    IMO, the peasants aren't actually multiplying and dividing by two, rather, they're doubling and halving numbers, a less generic but far simpler operation, that's why using * and / is cheating.

    Anyway, some more Haskell. This one handles negative numbers (don't think any Haskell entry so far does that,) is tail recursive AND uses type classes!

    import Data.Bits (shiftL, shiftR, Bits)
    

    rmult :: (Integral a, Bits a) => a -> a -> a
    rmult a b | a < 0 = - (rmult (-a) b)
    | a < 0 = - (rmult a (-b))
    | otherwise = go 0 a b where
    go acc 0 b = acc
    go acc a b = go (acc + if odd a then b else 0)
    (a `shiftR` 1)
    (b `shiftL` 1)
  • valderman 2009-07-22 18:38
    Oops, that second | a < 0 ... should be | b < 0 ...!
  • RayS 2009-07-22 18:47
    Updated from earlier post that I never bothered to updeate correctly.

    done in wonderful VBA, and just like in the article, shows full manual working out table in the debug window. Works with negatives, zeros, hopefully everything really. I stuck to the principle and process of the manual process instead of taking shortcuts.

    Public Function RussianMultiply(x As Long, y As Long) As Long
    
    Dim vals() As Long
    ReDim vals(1 To Round(Sqr(Abs(x)), 0) + 1, 1 To 2) As Long
    Dim i As Long, j As Long, c As Long, Msg As String, s As Long
    s = Sgn(x) * Sgn(y)
    i = 1
    Do Until x = 0
    vals(i, 1) = x
    vals(i, 2) = y
    i = i + 1
    x = x \ 2
    y = y * 2
    Loop
    For j = 1 To i - 1
    If vals(j, 1) / 2 = vals(j, 1) \ 2 Then
    Msg = " X"
    Else
    c = c + (s * Abs(vals(j, 2)))
    Msg = s * Abs(vals(j, 2))
    End If
    Debug.Print vals(j, 1) & vbTab & vals(j, 2) & vbTab & Msg
    Next
    Debug.Print vbCrLf & "=" & vbTab & c
    RussianMultiply = c
    End Function


    Sample output
    >RussianMultiply 18,23
    

    18 23 X
    9 46 46
    4 92 X
    2 184 X
    1 368 368

    = 414
  • Fred Dagg 2009-07-22 18:55
    package test;

    import java.util.ArrayList;
    import java.util.List;

    public class RussianMultiplication {

    public RussianMultiplication() {}

    public long multiply(long parameter1, long parameter2) {
    if (parameter2 < parameter1) {
    return handleMultiplication(parameter2, parameter1);
    } else {
    return handleMultiplication(parameter1, parameter2);
    }
    }

    private long handleMultiplication(long lhs, long rhs) {
    List<RussianNumber> numberList = new ArrayList<RussianNumber>();
    numberList.add(new RussianNumber(lhs, rhs));
    while (lhs > 1) {
    lhs = lhs / 2;
    rhs = rhs * 2;
    numberList.add(new RussianNumber(lhs, rhs));
    }
    long result = 0;
    for (RussianNumber number : numberList) {
    if (number.getLhs() % 2 != 0) {
    result = result + number.getRhs();
    }
    }
    return result;
    }

    public static void main(String[] args) {
    RussianMultiplication rm = new RussianMultiplication();
    long result = rm.multiply(23, 18);
    System.out.println("Result: " + result);
    }

    private class RussianNumber {
    private long lhs;
    private long rhs;

    public RussianNumber(long lhs, long rhs) {
    this.lhs = lhs;
    this.rhs = rhs;
    }

    public long getLhs() {
    return lhs;
    }

    public void setLhs(long lhs) {
    this.lhs = lhs;
    }

    public long getRhs() {
    return rhs;
    }

    public void setRhs(long rhs) {
    this.rhs = rhs;
    }

    public String toString() {
    return lhs + "::" + rhs;
    }
    }

    }
  • DFHawthorne 2009-07-22 18:55
    Another Oracle SQL Example:


    SQL> VARIABLE left_num NUMBER
    SQL> VARIABLE right_num NUMBER
    SQL> BEGIN
    :left_num := 18;
    :right_num := 23;
    END;
    PL/SQL procedure successfully completed.
    Elapsed: 00:00:00.06
    SQL> SELECT SUM (DECODE (MOD (TRUNC (:left_num / POWER (2, ROWNUM - 1), 0), 2),
    1, :right_num * POWER (2, ROWNUM - 1)
    )
    ) AS RESULT
    FROM DUAL
    CONNECT BY TRUNC (:left_num / POWER (2, ROWNUM - 1), 0) > 0

    RESULT
    ----------
    414


    1 row selected.
    Elapsed: 00:00:00.06
  • Jukka 2009-07-22 19:00
    In Python, aiming for readability.

    def russian_peasant(x,y):
    steps=[(x,y)]
    while x>1 or x<-1:
    x/=2
    y*=2
    steps.append((x,y))
    return sum([y for x,y in steps if x % 2 == 1]) * x # * x is there to give the correct sign for the result

    # Test it
    print russian_peasant(18,23), 18*23
    print russian_peasant(18,0), 18*0
    print russian_peasant(-2,400), -2*400
    print russian_peasant(40,-30), 40*-30
    print russian_peasant(40,30), 40*30
  • mjomble 2009-07-22 19:04
    How about a good dose of OOM?

    The code's too long to post here, but beyond this link you can enjoy it in fully highlighted PHP syntax: http://justas.ggcmedia.com/MultiplicationFramework.html (usage example at the end of the file)

    Sample output:
    Multiplying 18 by 23 Russian peasant style:
    

    Numeric result: 414

    Full result:
    18 x 23 | 0 +
    9 x 46 | 46 +
    4 x 92 | 0 +
    2 x 184 | 0 +
    1 x 368 | 368 =
    ----------------
    Total: 414

    ...hmm, I need to go clean my hands now.
  • spiderlama 2009-07-22 19:14
    int mul_rus(int a, int b)
    {
    int c = 0;

    while (a != 1)
    {
    if (a & 1)
    c += b;

    a >>= 1;
    b <<= 1;
    }

    return b + c;
    }
  • unit3 2009-07-22 19:23
    Here's a fairly straightforward implementation in common lisp:

    (defun mult (x y)
    (if (= x 1)
    y
    (+ (if (= (rem x 2) 0) 0 y) (mult (floor (/ x 2)) (* y 2)) )
    )
    )

    It could be all on one line, but that'd be harder to read. If someone has suggestions on how to simplify it, that'd be great. :)
  • Gumpy Guss 2009-07-22 19:24
    In PDP-8 assembly language. Untested



    X, 0
    Y, 0
    Z, 0

    RUSMUL, 0 // entry point
    CLA
    DCA Z / clear total

    LP, TAD X
    SNA
    JMP DONE

    ROR
    DCA X
    SZL CLA
    TAD Y
    TAD Z
    DCA Z
    TAD Y
    ROL
    DCA Y
    JMP LP

    DONE, TAD Y
    TAD Z
    JMP I RUSMUL

  • Crindigo 2009-07-22 19:29
    Sloppy JS version with animated step-by-step output: http://crindigo.com/stuff/praxis.html
  • Warr 2009-07-22 19:30
    Uses NO math operations, only regex and string operations. Almost all major work is kept in the global $_ variable. Numbers are represented internally using a base-30-like system, then converted directly back to decimal at the end of each operation. Some assumptions about collating sequence were made (e.g. \d == [0-9]).

    #!/usr/bin/perl
    
    $_ = join(' ', @ARGV);
    m#^\s*-?\d+\s*x\s*-?\d+\s*# or die('Input should be in "#### x ####" format.');
    $sign = '+'; while(s#-##) { $sign =~ tr#+-#-+#; }
    s#\s##g;
    s#$#=0#;
    while(!m#^0*x#)
    {
    s#(?<!\d)(\d)#0$1#g;
    if(m#\d+[13579]x#)
    {
    s#(.*x)(.*)(=.*)#$1$2$3+$2#;
    while(m#(.*)(\d)([a-jA-J]?)([a-jA-J]*\+\d*)(\d)(.*)#)
    {
    my($a, $b, $c, $d, $e, $f);
    $a = $1; $b = $2; $c = $3; $d = $4; $e = $5; $f = $6;
    while($e =~ m#[^a0]#)
    {
    $e =~ tr#1-9#a1-8#;
    $b =~ tr#0-9a-jA-I#b-jAb-jA-J#;
    }
    $e =~ tr#0#a#; $b =~ tr#0-9#a-j#;
    $c =~ m#[A-J]# and $b =~ tr#0-9a-jA-J#b-jAb-jA-J#;
    $_ = $a . $b . $c . $d . $e . $f;
    s#=(?!0)#=0#;
    }
    while(m#(.*)(\d)([A-J].*\+)#)
    {
    $x = $2;
    $x =~ tr#0-9#b-jA#;
    $_ = $1 . 0 . $x . $3;
    }
    tr#a-jA-J#0-90-9#;
    s#\+.*##;
    }
    if(m#^(\d)(.*)#)
    {
    $x = $1;
    $x =~ tr#0-9#aAbBcCdDeE#;
    $_ = $x . $2;
    }
    while(m#^([A-Ja-j]*?)([A-Ja-j]?)(\d)(.*)#)
    {
    my($a, $b, $c, $d);
    $a = $1; $b = $2; $c = $3; $d = $4;
    $b =~ m#[a-j]# and $c =~ tr#0-9#aAbBcCdDeE#
    or $c =~ tr#0-9#fFgGhHiIjJ#;
    $_ = $a . $b . $c . $d;
    }
    tr#A-Ja-j#0-90-9#;
    if(m#^(.*)(\d)(=.*)#)
    {
    $x = $2;
    $x =~ tr#0-9#acegiACEGI#;
    $_ = $1 . $x . $3;
    }
    while(m#(.*?)(\d)([A-Ja-j]?)([A-Ja-j]*=.*)#)
    {
    my($a, $b, $c, $d);
    $a = $1; $b = $2; $c = $3; $d = $4;
    $c =~ m#[a-j]# and $b =~ tr#0-9#acegiACEGI#
    or $b =~ tr#0-9#bdfhjBDFHJ#;
    $_ = $a . $b . $c . $d;
    }
    tr#A-Ja-j#0-90-9#;
    s#(?<!\d)0+(?=\d|0(?!\d))##g;
    }
    s#.*=##;
    s#^#$sign#;
    s#^\+##;
    s#$#\n#;
    print;
  • Paul N 2009-07-22 19:48
    --SQL Server using Common Table Expression

    DECLARE @number1 int;
    DECLARE @number2 int;

    SET @number1 = 18;
    SET @number2 = 23;

    WITH Multiplication (Row, Factor1, Factor2) AS
    (
    SELECT 1, @number1, @number2
    UNION ALL
    SELECT Row + 1, Factor1 / 2, Factor2 * 2
    FROM Multiplication
    WHERE Factor1 > 1
    )
    SELECT SUM(Factor2) FROM Multiplication
    WHERE Factor1 % 2 = 1;
  • Wheaties 2009-07-22 19:53
    func(a, b):
    if(a == 1)
    return b
    if(a%2 == 1)
    return b*2 + func(a/2, b*2)
    else
    return func(a/2, b*2)

    Had to do it with recursion. I can't think of a reason why not to do it that way. I also haven't looked at the comments. Someone probably came up with this solution or it has already been shown to be wrong. I could also shrink it to be a single line but then it wouldn't be nearly as readable.
  • Paul N 2009-07-22 19:56
    --It works better as a stored procedure

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    -- =============================================
    -- Author: Paul N
    -- Create date: 7/22/2009
    -- Description: multiplies two numbers using
    -- Russian Peasant Multiplication
    -- =============================================
    CREATE PROCEDURE dbo.[Russian Peasant Multiplication]
    -- Add the parameters for the stored procedure here
    @number1 int,
    @number2 int
    AS
    BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    WITH Multiplication (Row, Factor1, Factor2) AS
    (
    SELECT 1, @number1, @number2
    UNION ALL
    SELECT Row + 1, Factor1 / 2, Factor2 * 2
    FROM Multiplication
    WHERE Factor1 > 1
    )
    SELECT SUM(Factor2) FROM Multiplication
    WHERE Factor1 % 2 = 1;
    END
    GO
  • yowzer 2009-07-22 19:59
    open List

    let oddcar (n, _) = (n land 1) = 1
    let sum = fold_left (+) 0

    let rec do_mul = function
    | (x,_) :: _ as lst when x == 1 ->
    sum (map snd (filter oddcar lst))
    | (x,y) :: _ as lst ->
    do_mul ((x / 2, y * 2) :: lst)

    let mul x y =
    do_mul [x,y]

  • Veryth 2009-07-22 20:12
    C# + LINQ

    int Multiply(int x, int y)
    {
    return Enumerable.Range(0, (int)(1.0 + Math.Log(x)/Math.Log(2)))
    .Select(i => new {x = x >> i, y = y << i})
    .Where(p => p.x > 0 && p.x % 2 == 1)
    .Sum(p => p.y);
    }


    Addendum (2009-07-23 01:23):
    More LINQ-ish:

    int Multiply(int x, int y)
    {
    return (
    from i in Enumerable.Range(0, (int)(1.0 + Math.Log(x)/Math.Log(2)))
    where (x >> i) % 2 == 1
    select y << i
    ).Sum();
    }
  • Mike McNally 2009-07-22 20:12
    simple erlang:

    -module(rmult).
    -export([rmult/2]).

    rmult(M1, M2) -> rmult(M1, M2, [{M1, M2}]).

    rmult(1, _, P) -> rsum(P, 0);
    rmult(M1, M2, P) ->
    M1n = M1 div 2, M2n = M2 * 2,
    rmult(M1n, M2n, [{M1n, M2n} | P]).

    rsum([], S) -> S;
    rsum([{M, _} | P], S) ->
    rsum(P, S + case M rem 2 of 0 -> 0; 1 -> M end).
  • bd_ 2009-07-22 20:19
    ; Rabbit 2000 assembler
    
    ; Inputs in A, B
    ; Result in HL

    ld d, 0
    ld e, b ;; DE = second operand
    ld hl, 0 ;; accum = 0
    or a
    ;; For the first iteration, we need to just test whether the second
    ;; operand is even, rather than using a side effect of the rotate
    bit 0, a
    ..mul_loop:
    jr nc, ..odd
    add hl, de
    ..odd:
    or a ;; CF = 0
    jr z, ..done ;; A = 0?
    rl de ;; DE *= 2
    rr a ;; A /= 2. CF can't be nonzero as that would imply overflow
    jr ..mul_loop ;; CF from A is used on next iteration
    ..done:
    ;; result in HL
  • Twey 2009-07-22 20:19
    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)
  • Mike McNally 2009-07-22 20:22
    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).
  • tdh 2009-07-22 20:34
    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)
  • brian 2009-07-22 21:19
    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.
  • 0ffh 2009-07-22 21:25
    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;
    }
  • 0ffh 2009-07-22 21:27
    the wtf is of course that my spaces got eaten... =)
  • Bob 2009-07-22 21:35
    echo "In soviet russia, multiplication does YOU!"
  • 0ffh 2009-07-22 21:48
    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!
  • Thomas Eyde 2009-07-22 21:50

    using Microsoft.VisualStudio.TestTools.UnitTesting;

    namespace RussianPeasantMultiplication
    {
    /// <summary>
    /// The biggest WTF, of course, is there are tests!
    /// </summary>
    [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));
    }
    }

    /// <summary>
    /// What kind of entry would it be, if the expected code quality wasn't posted?
    /// </summary>
    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);
    }
    }

    /// <summary>
    /// Another WTF is to actually try to write readable, understandable code.
    /// </summary>
    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);
    }
    }
    }
  • Mr.'; Drop Database -- 2009-07-22 22:00
    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)))
  • bluebearr 2009-07-22 22:18
    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
    EndFunc
  • Joel 2009-07-22 22:22
    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));
    }
  • Bruce 2009-07-22 22:44
    This actually misses adding the first row if the initial lval is odd.
  • Bruce 2009-07-22 22:46
    (sorry, I meant the first sample given)
  • J 2009-07-22 22:51
    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;
  • noSignal 2009-07-22 23:14
    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)))))
  • noSignal 2009-07-22 23:17
    I salute you sir!
  • joeyadams 2009-07-22 23:17
    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.
  • noSignal 2009-07-22 23:20
    You spent more than 5 minutes on a 3 minute problem. Congratulations.
  • jnz 2009-07-22 23:25
    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;
    }

  • JXO 2009-07-22 23:28
    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;
    }
  • zcl 2009-07-22 23:45

    Yes ,your article is very good, we have the same belief with you,so let me introduce the area to you.Now Juicy Jewelry become more adn more popular within all kind of people. Juicy couture is a kind of juicy series . It won a good reputation. Juicy sale often held its regular discount juicy activities,such as juicy charms,cheap juicy and so on.In these activities juicy couture sale got great success. juicy couture consists of two main aspects, juicy couture jewelry and juicy couture accessories
    Juicy couture series are worthwhile than other juicy on sales. They have a lot of discounted jewelry,for example discount Juicy Couture necklaces, juicy earrings , juicy bracelets and rings on sale. Benefit from the discount,you can get juicy jewelry save up to 30%, We assure you of our best services at all times.
  • Chris 2009-07-23 00:14
    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 + "&nbsp;*&nbsp;" + 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 + "<span style='float:right'>" + two + "</span>";
    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 = "<strike>" + newCell.innerHTML + "</strike>";
    r.appendChild(newCell);
    newCell = document.createElement("td");
    if (rowIndices[i])
    {
    newCell.innerHTML = addValues[i];
    if (!first) newCell.innerHTML = "+ " + newCell.innerHTML;
    newCell.innerHTML = "<span style='float:right'>" + newCell.innerHTML + "</span>";
    first = false;
    }
    else
    newCell.innerHTML = "&nbsp;";
    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>

    <table id="my_table" style="border: 1px solid black; border-collapse: collapse; font-family: Arial,Helvetica;">
    <tr id="row_0">
    <td id="cell_0_0">
    Russian Peasant Multiplication
    </td>
    </tr>
    </table>
  • Julian Calaby 2009-07-23 00:33
    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) ))
    fi


    Remove 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)
  • cmugford 2009-07-23 00:37
    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);
  • James 2009-07-23 00:50

    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

    iRowNo = 2

    sValue = InputBox("Enter first value to mulitply", "Peasant Multiply")
    If sValue = "" Then
    MsgBox "You're not playing the game..."
    Do Until sValue <> ""
    sValue = InputBox("Enter first value to mulitply", "Peasant Multiply")
    If Not IsNumeric(sValue) Then
    MsgBox "You're not playing the game..."
    sValue = ""
    Else
    If CLng(sValue) > 33554431 Then
    MsgBox "Upper limit on first number is 33,554,431"
    sValue = ""
    End If
    End If

    Loop
    End If
    Cells(iRowNo, 3).Value = CLng(sValue)

    sValue = InputBox("Enter second value to mulitply", "Peasant Multiply")
    If sValue = "" Then
    MsgBox "You're not playing the game..."
    Do Until sValue <> ""
    sValue = InputBox("Enter second value to mulitply", "Peasant Multiply")
    If Not IsNumeric(sValue) Then
    MsgBox "You're not playing the game..."
    sValue = ""
    End If
    Loop
    End If
    Cells(iRowNo, 4).Value = CLng(sValue)

    Cells(iRowNo, 3).Interior.ColorIndex = 36
    Cells(iRowNo, 4).Interior.ColorIndex = 36
    Cells(iRowNo, 5).Interior.ColorIndex = 45
    Cells(iRowNo, 5).FormulaR1C1 = "=SUM(R[1]C:R[24]C)"

    iRowNo = iRowNo + 1
    Cells(iRowNo, 3).Value = Cells(iRowNo, 3).Value
    Cells(iRowNo, 4).Value = Cells(iRowNo, 4).Value
    Cells(iRowNo, 5).FormulaR1C1 = "=IF(RC[-2]<>"""",IF(MOD(RC[-2],2)<>0,RC[-1],0),"""")"

    For iRowNo = 3 To 26
    Cells(iRowNo, 3).FormulaR1C1 = "=IF(OR(R[-1]C=1,R[-1]C=""""),"""",INT(R[-1]C/2))"
    Cells(iRowNo, 4).FormulaR1C1 = "=IF(RC[-1]<>"""",R[-1]C*2,"""")"
    Cells(iRowNo, 5).FormulaR1C1 = "=IF(RC[-2]<>"""",IF(MOD(RC[-2],2)<>0,RC[-1],0),"""")"
    Next iRowNo
    MsgBox "There you go, the answer is " & Format(Cells(2, 5).Value, "#,##0")
    End Sub

  • iamtim2 2009-07-23 00:56
    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)))
  • jvmbsd7 2009-07-23 00:59
    ;; 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)))
  • agrif 2009-07-23 01:29
    these are all in python

    the first is the most verbose:

    def russian(x, y):
    def generate_list(x, y):
    while x != 0:
    yield x, y
    x /= 2
    y *= 2

    def filter_even(i):
    if i[0] % 2 == 0:
    return False
    return True

    def drop_first_column(i):
    return i[1]

    l = generate_list(x, y)
    l = filter(filter_even, l)
    l = map(drop_first_column, l)
    return sum(l)

    The next one is less verbose, but still easy to follow:

    def russian(x, y):
    l = []
    while x != 0:
    if x % 2:
    l.append(y)
    x /= 2
    y *= 2
    return sum(l)

    Personally, I like this one for it's complete incomprehensibility (and that it says "lambda f,a,b:a", which makes me laugh):

    russian = lambda x,y:(lambda f:f(f,x,y))(lambda f,a,b:a and f(f,a/2,b*2)+a%2*b)

    agrif - 71aaeb8b415a620bf185b6093ebaf5c5
  • Chris Walton 2009-07-23 01:35
    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

    00401000 xor eax,eax
    00401002 cmp ecx,1
    00401005 jle russianMul+1Dh (40101Dh)
    00401007 push esi
    00401008 sar ecx,1
    0040100A mov esi,ecx
    0040100C and esi,1
    0040100F add edx,edx
    00401011 neg esi
    00401013 and esi,edx
    00401015 add eax,esi
    00401017 cmp ecx,1
    0040101A jg russianMul+8 (401008h)
    0040101C pop esi
  • arke 2009-07-23 01:38
    Chris Walton:
    ...


    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.
  • sxeraverx 2009-07-23 02:11
    int mult(int a, int b) { return a*b; }
    /*because that's how computers do it in hardware, anyway.*/
  • Mr M 2009-07-23 02:14
    The question is, why would I want to?
  • Philipp 2009-07-23 02:23
    Qwertyuiopas:
    I know everybody wants it :)

    Hopefully none of it was removed.

    Also, everything after the first . is disabled debugging code. Remove the [-] to see what is left of the memory.

    >>>>>,>>,[->+>+<<]<<[[-[>+<-]>[>+>>>+<<<<-[[<+>-]>[-]<]]<]>>[>>[-]<<[-]]+>[->>>>>++>++<<<<<<]>>]>>>>[-]<<<<<<<[<<<<<]>>>>>[>>[->>>>>+<<<<<]>>>]>>.[-][<<<<<<<[<<<<<]>>>.>.>[.>.>.>.>.>].>.>.]


    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.
  • joeyadams 2009-07-23 02:28
    zcl:

    Yes ,your article is very good, we have the same belief with you,so let me introduce the area to you.Now Juicy Jewelry become more adn more popular within all kind of people. Juicy couture is a kind of juicy series . It won a good reputation. Juicy sale often held its regular discount juicy activities,such as juicy charms,cheap juicy and so on.In these activities juicy couture sale got great success. juicy couture consists of two main aspects, juicy couture jewelry and juicy couture accessories
    Juicy couture series are worthwhile than other juicy on sales. They have a lot of discounted jewelry,for example discount Juicy Couture necklaces, juicy earrings , juicy bracelets and rings on sale. Benefit from the discount,you can get juicy jewelry save up to 30%, We assure you of our best services at all times.


    Can we please end the off-topic rants about Russian peasant multiplication and get back to our juicy jewelry discussion?
  • Alex Muscar 2009-07-23 02:32
    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)))
  • Alex Muscar 2009-07-23 02:45
    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))))
  • mneimeyer 2009-07-23 03:08
    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")."'><td>".$a."</td><td>".$b."</td></tr>";
    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">
    <table border="0" align="center" cellspacing="0" cellpadding="5">
    <tr>
    <td><input type="text" size="4" name="a" value="<?= $_GET['a'] ?>"></td>
    <td>&nbsp;x&nbsp;</td>
    <td><input type="text" size="4" name="b" value="<?= $_GET['b'] ?>"></td>
    <td><input type="submit" value="Multiply"></td>
    </tr>
    </table>
    </form>

    <?php

    if(isset($_GET['a']) && isset($_GET['b']))
    {
    echo "\n<p align='center'>Quick: ".($_GET['a']*$_GET['b'])."</p>\n";

    echo "<table border='0' align='center'>\n";
    $c = Russian($_GET['a'],$_GET['b']);
    echo "\n<tr><td>Sum:</td><td>".$c."</td></tr>";
    echo "</table>\n";
    }

    ?>

    </body>
    </html>
  • Hidayat 2009-07-23 03:14
    Another using Oracle PL/SQL

    create or replace
    
    function russian(p in number, q in number) return number is
    res number;
    begin
    select sum( decode(mod(floor(p/power(2,level-1)),2),0,0,1) * q * power(2,level-1) ) into res
    from dual where floor(p/power(2,level-1))>0 connect by level<q;
    return res;
    end;

    select russian(18,23) from dual
  • demo 2009-07-23 03:15
    #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<A>::value>::value };
    };

    int main(int argc, char* argv[])
    {
    std::cout << russian<18, 23>::value << std::endl;
    return EXIT_SUCCESS;
    }

  • Don Knisley 2009-07-23 03:56
    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
  • SlyEcho 2009-07-23 03:59
    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
  • subanark 2009-07-23 04:04
    Here is my solution in Java. It supports really big numbers and does pretty much what you do in Russian peasant multiplication.

    public static BigInteger multiply(BigInteger a, BigInteger b)
    {
    BigInteger two = BigInteger.valueOf(2);
    ArrayList<BigInteger> numsToAdd = new ArrayList<BigInteger>();
    while(!a.equals(BigInteger.ONE))
    {
    if(a.mod(two).equals(BigInteger.ONE))
    numsToAdd.add(b);
    a = a.divide(two);
    b = b.multiply(two);
    }
    //trick: b already holds the last line
    for(BigInteger n : numsToAdd)
    b = b.add(n);
    return b;
    }
  • Toby Gray 2009-07-23 04:07
    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$_";
  • freewildebeest 2009-07-23 04:10
    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$_";
  • astander 2009-07-23 04:15
    private int RussianMultiply(int input1, int input2)
    {
    int retVal = 0;
    do
    {
    retVal += (input1 & 1) * input2;

    input1 = input1 >> 1;
    input2 = input2 << 1;

    } while (input1 > 0);
    return retVal;
    }
  • k1 2009-07-23 04:45
    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
  • k1 2009-07-23 04:58
    whoops...
    k1:

    <snip>
    420 PRINT "THE PRODUCT IS "; A
    430 END


    420 PRINT "THE PRODUCT IS "; A * SIGN

    There, fixed.

    CYA
  • Boneist 2009-07-23 05:29
    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 lvl
  • C 2009-07-23 05:49
    ; EDX:EAX <- ECX * EBX (untested)
    ; (all other gp registers trashed)
    MOV ECX, multiplicand
    MOV EBX, multiplier
    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
  • Joost 2009-07-23 05:54
    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 `div` 2) (m * 2)
  • StarLite 2009-07-23 06:10
    My take using Progress V9 (will probably work in most older versions as well)
    Code:

    function multiply returns integer (input ip_int1 as integer, input ip_int2 as integer):
    define variable v_result as integer no-undo.

    if ip_int1 = 1 then
    return ip_int2.

    if ip_int1 mod 2 <> 0 then
    v_result = v_result + ip_int2.

    v_result = v_result + multiply(integer(truncate(ip_int1 / 2, 0)), (ip_int2 * 2)).
    return v_result.
    end.

    message "Russian Peasant Notation: " multiply(18, 23) view-as alert-box info buttons ok.
  • col obvious 2009-07-23 06:15
    static int m(int x,int y){return x==1?y:x%2==0?m(x/=2,y*=2):y+m(x/=2,y*=2);}
  • LatecomerX 2009-07-23 06:28
    I've been a TDWTF reader for the past few months, and I'm dedicating my first comment to this interesting question here:

    In PHP:

    <?

    function multiply($x, $y, $o = 0) {
    return $x > 1 ?
    multiply(floor($x / 2), $y * 2, $o + $x % 2 * $y) :
    $o + $y;
    }

    echo multiply(18, 23);

    ?>

    Also available at:
    http://phpieceofcake.com/?83344437
  • Alex 2009-07-23 06:40
    Not sure if anyone posted this solution yet. Here's mine:

    private int Multiply(int x, int y)
    {
    return x == 1 ? y : Multiply(x / 2, y * 2) + x % 2 * y;
    }
  • A.T. 2009-07-23 06:45
    Mike5:

    Anonymous Coward:
    Prolog...

    "optimized" with bit-shifting ...


    To get the real prolog feeling:


    %% russian(?A,?B,?P).
    %% multiplies A and B the russian way,
    %% all parameters are optional
    russian(A,B,P) :- nonvar(A), var(B), !, russian(B,A,P).
    russian(A,B,P) :- var(A), (nonvar(B),!;length(_,P),between(0,P,B)),
    row(A,B,P,0,P).
    russian(A,B,P) :- nonvar(A), row(A,B,P,0,P), !.

    row(_,_,P,F,_) :- nonvar(P), P < 1<<(F-1), !, fail.
    row(0,_,_,_,0).
    row(A,B,P,F,R) :-
    row(Ax,B<<1,P,F+1,Rx),
    double(Ax,A,Odd),
    R is Rx+B*Odd.

    double(0,1,1) :- !.
    double(X,X2,Odd) :- (Odd=0;Odd=1), X2 is X*2+Odd.

    may need some optimization though...
  • A.T. 2009-07-23 06:51
    Mike5:

    Anonymous Coward:
    Prolog...

    "optimized" with bit-shifting ...


    To get the real prolog feeling:


    %% russian(?A,?B,?P).
    %% multiplies A and B the russian way,
    %% all parameters are optional
    russian(A,B,P) :- nonvar(A), var(B), !, russian(B,A,P).
    russian(A,B,P) :- var(A), (nonvar(B),!;length(_,P),between(0,P,B)),
    row(A,B,P,0,P).
    russian(A,B,P) :- nonvar(A), row(A,B,P,0,P), !.

    row(_,_,P,F,_) :- nonvar(P), P < 1<<(F-1), !, fail.
    row(0,_,_,_,0).
    row(A,B,P,F,R) :-
    row(Ax,B<<1,P,F+1,Rx),
    double(Ax,A,Odd),
    R is Rx+B*Odd.

    double(0,1,1) :- !.
    double(X,X2,Odd) :- (Odd=0;Odd=1), X2 is X*2+Odd.

    may need some optimization though...
  • bugmonkey 2009-07-23 06:54
    PHP and Perl, and gives the same output for both:
    #
    
    #<?php echo "\x8";ob_start();
    $rm='return int($a/2)==1?$b*2:(int($a/2)%2==1?$b*2+rm(int($a/2),$b*2):rm(int($a/2),$b*2));';
    #?><?php function int($a){return floor($a);}$a=$argv[1];$b=$argv[2];eval('function rm($a, $b){'.$rm.'}');?>
    $a=$ARGV[0];$b=$ARGV[1];eval("sub rm{\$a=shift;\$b=shift;$rm}");#<?php ob_end_clean();
    print rm($a,$b);
  • LatecomerX 2009-07-23 07:08
    Came up with a more condensed PHP function after another 45 minutes or so:

    function multiply($x, $y) {
    return $x % 2 * $y + ($x > 1 ? multiply(floor($x / 2), $y * 2) : 0);
    }

    LatecomerX:
    I've been a TDWTF reader for the past few months, and I'm dedicating my first comment to this interesting question here:

    In PHP:

    <?

    function multiply($x, $y, $o = 0) {
    return $x > 1 ?
    multiply(floor($x / 2), $y * 2, $o + $x % 2 * $y) :
    $o + $y;
    }

    echo multiply(18, 23);

    ?>

    Also available at:
    http://phpieceofcake.com/?83344437
  • Methuselah 2009-07-23 07:14
    Here's some Lua code:
    function russian(a, b)
    
    if a==1 then
    return b
    else
    if a%2==1 then
    return b+russian(math.floor(a/2), b*2)
    else
    return russian(math.floor(a/2), b*2)
    end
    end
    end

    Code only: 189 bytes
    Code with BBCode coloring: 1190 bytes
  • dv 2009-07-23 07:23
    Someone:
    An ABAP solution that compiles:

    REPORT MULTIP.

    DATA: product TYPE i,
    left_num TYPE f VALUE 18,
    right_num TYPE f VALUE 23,
    half_left TYPE f,
    half_left_floor TYPE f.

    WHILE left_num > 0.
    "check for even number and add to product (there must be a better way...)
    half_left = left_num / 2.
    half_left_floor = FLOOR( left_num / 2 ).
    IF half_left <> half_left_floor.
    product = product + right_num.
    ENDIF.

    "move to next set
    left_num = FLOOR( left_num / 2 ).
    right_num = right_num * 2.
    ENDWHILE.

    WRITE product.


    Yes there is a better way, the MOD operator. Also, when creating a whole report for it, why not include a nice, verbose, selection screen?


    SELECTION-SCREEN BEGIN OF BLOCK 1 WITH FRAME TITLE 'Input'.
    PARAMETER p_num1 TYPE I DEFAULT 18 OBLIGATORY.
    PARAMETER p_num2 TYPE I DEFAULT 23 OBLIGATORY.
    SELECTION-SCREEN END OF BLOCK 1.

  • Python 2009-07-23 07:26
    #! -*- Encoding: Latin-1 -*-

    import threading
    import Queue

    # classic spaghetti code
    def rupmul1(a,aa):
    aaa = lambda:(a % 2) and aa
    aaaa = aaa()
    while a > 1:
    a, aa = a/2, aa*2
    aaaa += aaa()
    return aaaa

    # functional programming
    rupmul2 = lambda a,b: sum(map(
    lambda b:a&b[0] and b[1],zip(map(
    lambda a:pow(2,a),range(31)),map(
    lambda a:b*pow(2,a),range(31)))))

    # multicore power using threads + functional programming = TOTAL WIN!
    def rupmul3(a,b,__=Queue.Queue()):
    return sum(map(lambda _:__.get(),map(lambda _:[threading.Thread(target=lambda _:
    __.put((a&1<<_) and b<<_),args=(_,)).start(),_][-1],range(32))))

    def selftest():
    import random

    for k in range(60):
    a = random.randrange(1,10000)
    b = random.randrange(1,10000)

    n = a*b
    assert rupmul1(a,b) == rupmul2(a,b) == rupmul3(a,b) == a*b

    if __name__ == "__main__":
    selftest()
  • London Developer 2009-07-23 07:32
    ParkinT:
    Wow!
    I had not time to submit a solution.
    Everyone was too busy Russian to provide an answer!


    OH DEAR!!! LOL!
  • Anonymous 2009-07-23 07:40
    That ARM code is both wrong and far too long. This is perhaps slightly less wrong:

        mov    r2,#0
    
    loop:
    movs r1,r1,lsr #1
    addcs r2,r2,r0
    mov r0,r0,lsl #1
    bne loop


  • rjp 2009-07-23 07:41
    Me:
    Bah to all your bloaty solutions. Perlmongers do it in one line :P

    sub m(){my($a,$b)=@_;my $t;while($a){$t+=$b if ($a&1);$a>>=1;$b<<=1;}return $t;}


    Apologies if this has been pointed out already but you can shorten that slightly.

    sub m{my($a,$b)=@_;my $t;while($a){$t+=$b*($a&1);$a>>=1;$b*=2}$t}
  • Osno 2009-07-23 08:00
    Tail recursive in IL (based on 278641, not sure if C# can compile a tail recursivity, I'll have to check later). The first param is the acumulator and should be initialized to 0 (or wrapped in another method):

    .method private hidebysig static int64 Russian(int64 a, int64 f, int64 s) cil managed
    {
    .maxstack 4
    ldarg.0
    dup
    ldarg.1
    brfalse.s done
    ldarg.1
    ldc.i4.1
    and
    ldarg.2
    mul
    add
    ldarg.1
    ldc.i4.1
    shr
    ldarg.2
    ldc.i4.1
    shl
    tail.
    call int64 RussianMult.Program::Russian(int64, int64, int64)
    done:
    ret
    }
  • Osno 2009-07-23 08:01
    BTW, I think I've never seen a post in this site with 12 pages of comments.
  • khahem 2009-07-23 08:01
    C++ with a 'simple' iterator.

    #include <numeric>
    struct gen {
    int a, b;
    gen(int a=0, int b=0) : a(a), b(b) { }
    gen operator*() { return *this; }
    void operator++() { a /= 2; b *= 2; }
    bool operator!=(gen b) { return a != b.a; }
    gen operator+(gen r) {
    if (r.a % 2)
    return gen(0, b + r.b);
    return gen(0, b);
    }
    };

    int mul(int a, int b) {
    return std::accumulate(gen(a, b), gen(), gen()).b;
    }
  • Lom 2009-07-23 08:02
    Python, nominate for shortest one :)
    49 characters.
    And, with python, numbers multiply peasants.

    m=lambda a,b:sum(b<<i for i in range(a)if a&1<<i)
  • Rorick 2009-07-23 08:13
    Java:

    public static long multiply(int a, int b) {
    if (a < 0) {
    a = -a;
    b = -b;
    }
    int result = 0;
    while (a > 0) {
    int tz = Integer.numberOfTrailingZeros(a);
    result += b << tz;
    a = a >> ++tz << tz;
    }
    return result;
    }
  • Queex 2009-07-23 08:16
    This nearly works; I'll leave the rest to the in-house coders.

        public static int multiply(int x, int y) {
    
    StringBuffer sb = new StringBuffer();
    sb.append("" + x);
    sb.append(" x "); // prettify output
    sb.append(y + "");

    while (doIt(sb));

    System.err.println(sb.toString());

    String str = sb.toString();
    StringTokenizer st = new StringTokenizer(sb.toString(), "\n ");
    int o = 0;
    while (st.hasMoreTokens()) {
    if (Integer.parseInt(st.nextToken()) % 2 == 0) {
    //do nothing
    } else {
    o += Integer.parseInt(st.nextToken());
    }
    }

    return o;
    }

    public static boolean doIt(StringBuffer sb) {
    int line = sb.lastIndexOf("\n");
    line++; //need this for some reason!!!!!1!

    //if(line<0){
    // line++;
    //}

    int split = sb.indexOf(" ", line);
    String x = sb.substring(line, split);
    String y = sb.substring(split);

    sb.append("\n");
    sb.append(Integer.parseInt(x) / 2);
    sb.append(" ");
    sb.append(Integer.parseInt(y.trim()) * 2);

    if (x.equalsIgnoreCase("1")) {
    return false;
    }

    return true;
    }

    // public static int multiply(int x, int y) {
    // int out = 0;
    // while (x != 1) {
    // if (x % 2 != 0) {
    // out += y;
    // }
    // x = x >> 1;
    // y = y << 1;
    // }
    // return out + y;
    // }
  • ath 2009-07-23 08:17
    Wow, the number of unreadable and unmaintainable examples outweight the readable and maintainable ones by about 50:1!
    That's the real WTF...
  • Mr. Black 2009-07-23 08:18
    my crappy C version that doesn't work for negative numbers ;)
    ----------------------- <snip> --------------------------

    #include <stdio.h>

    main( argc, argv)
    int argc;
    char *argv[3];
    {
    int n1 = 0;
    int n2 = 0;
    int n3 = 0;

    n1 = atoi(argv[1]);
    n2 = atoi(argv[2]);
    /* Implement Russian Peasant Multiplication algorithm */
    if ( argc != 3 )
    {
    printf("USAGE: rpm n n\nrpm multiplies two numbers via the Russian peasant method\n");
    return(1);
    }

    /* if either parameter is zero, the answer is zero */
    if ( n1 == 0 || n2 == 0 )
    {
    printf("Result of %d * %d via Russian peasant method is: 0.\n", n1, n2);
    return(0);
    }

    if ( n1 == 1 || n2 == 1 )
    {
    printf("Result of %d * %d via Russian peasant method is: %d.\n", n1, n2, n1*n2);
    return(0);
    }

    if ( (n1 % 2) != 0 )
    {
    n3 = n2;
    }

    while ( n1 >= 1 )
    {
    n1 = n1 / 2;
    n2 = n2 * 2;
    if ( (n1 % 2) != 0 )
    {
    n3 = n3 + n2;
    }
    }

    printf("Result of %d * %d via Russian peasant method is: %d.\n", atoi(argv[1]), atoi(argv[2]), n3);

    return(0);
    }

    ----------------------- <snip> ---------------------
  • Alex Muscar 2009-07-23 08:29
    The C# compiler does tail call optimisation only on x64 afaik.
  • Ralf 2009-07-23 09:08
    Smalltalk

    Note that this overwrites the System's definition of *
    and everything still works.

    * aNumber

    self isZero ifTrue: [^0].
    self < 0
    ifTrue: [^(self negated * aNumber) negated]
    ifFalse: [^ ((self bitShift: -1) * (aNumber + aNumber)) + ((self bitAnd: 1) = 1 ifTrue: [aNumber] ifFalse: [0])]


  • EJCorcoran 2009-07-23 09:13
    Another SQL (T-SQL) Answer:
    DECLARE @X INT, @Y INT, @Z INT
    SELECT @X=18,@Y=23,@Z=0
    WHILE @X!=1
    BEGIN
    IF (@X%2)!=0
    SET @Z=@Z+@Y
    SET @X=@X/2
    SET @Y=@Y*2
    END
    SET @Z=@Z+@Y
    SELECT @Z

  • Takis 2009-07-23 09:17
    577 comments later and still no recursive VB.Net solution, so here's my second try; it handles negatives as well and doesn't use multiplication:


    Function Russiply2(ByVal a As Long, ByVal b As Long) As Long

    Return If(a < 0, Russiply2(-a, -b), If(a > 1, If((a And 1) = 1, b, 0) + Russiply2(a >> 1, b << 1), If(a = 1, b, 0)))

    End Function

  • Osno 2009-07-23 09:18
    Just checked on an x64. At least by default, it doesn't do tail recursion. Also, when compiled in Release the output is really really close to my solution. The only real difference is that it branches on non-equal instead of false.
  • WarheadsSE 2009-07-23 09:21
    joeyadams:
    zcl:

    Yes ,your article is very good, we have the same belief with you,so let me introduce the area to you.Now Juicy Jewelry become more adn more popular within all kind of people. Juicy couture is a kind of juicy series . It won a good reputation. Juicy sale often held its regular discount juicy activities,such as juicy charms,cheap juicy and so on.In these activities juicy couture sale got great success. juicy couture consists of two main aspects, juicy couture jewelry and juicy couture accessories
    Juicy couture series are worthwhile than other juicy on sales. They have a lot of discounted jewelry,for example discount Juicy Couture necklaces, juicy earrings , juicy bracelets and rings on sale. Benefit from the discount,you can get juicy jewelry save up to 30%, We assure you of our best services at all times.


    Can we please end the off-topic rants about Russian peasant multiplication and get back to our juicy jewelry discussion?


    I believe the problem is that we've made this poor russian peasant thirsty, after warping his brain with such compressed algorithms in as many languages we could come up with. PDP-8, nice touch, but its still ASM! CP/M shell anyone???
  • WarheadsSE 2009-07-23 09:23
    Lom:
    Python, nominate for shortest one :)
    49 characters.
    And, with python, numbers multiply peasants.

    m=lambda a,b:sum(b<<i for i in range(a)if a&1<<i)


    There is a 44 character python, and a 40 characther bc, although you still have several characters to go to catch perl :)
  • WarheadsSE 2009-07-23 09:24
    rjp:
    Me:
    Bah to all your bloaty solutions. Perlmongers do it in one line :P

    sub m(){my($a,$b)=@_;my $t;while($a){$t+=$b if ($a&1);$a>>=1;$b<<=1;}return $t;}


    Apologies if this has been pointed out already but you can shorten that slightly.

    sub m{my($a,$b)=@_;my $t;while($a){$t+=$b*($a&1);$a>>=1;$b*=2}$t}

    It has, but then its perl.. TIMTOW! stub..! oww.
  • wombat 2009-07-23 09:25
    Only works with positive integers.


    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <!-- get initial values out of xml -->
    <xsl:template match="/">
    <xsl:variable name="number1">
    <xsl:value-of select="*/number[1]"/>
    </xsl:variable>

    <xsl:variable name="number2">
    <xsl:value-of select="*/number[2]"/>
    </xsl:variable>

    <!--call the loop for the first time-->
    <xsl:call-template name="loop">
    <xsl:with-param name="a" select="$number1"/>
    <xsl:with-param name="b" select="$number2"/>
    <xsl:with-param name="r" select="0"/>
    </xsl:call-template>
    </xsl:template>

    <!-- the loop to recurse over-->
    <xsl:template name="loop">
    <xsl:param name="a"/>
    <xsl:param name="b"/>
    <xsl:param name="r"/>
    <xsl:choose>
    <xsl:when test="$a = 1">
    <!-- we have finished print the result -->
    <xsl:value-of select="$b + $r"/>
    </xsl:when>
    <xsl:otherwise>
    <!--call the template again. each time divide "a" by 2 multiple "b" by 2, and sum "b" to the remainder if "a" is odd -->
    <xsl:call-template name="loop">
    <xsl:with-param name="a" select="round(($a div 2) - 0.5)"/>
    <xsl:with-param name="b" select="$b * 2"/>
    <xsl:with-param name="r" select="($a mod 2) * $b + $r"/>
    </xsl:call-template>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:template>

    </xsl:stylesheet>
  • Rorick 2009-07-23 09:27
    Another version, now in Rebol.

    multru: func [a b /local res] [
    res: copy []
    append res [res: 0]
    append res compose [(either a < 0 [[-res]] [[res]])]
    res: back tail res
    until [
    insert res compose/deep [either odd? (a) [add res (b)] [res]]
    insert res to-set-word 'res
    set [a b] compose [(round/down divide a 2) (multiply b 2)]
    zero? a
    ]
    do head res
    ]


    It generates rebol code composed from additions and checks for oddity and then executes it. For 23 and 18 generated code looks like:

    [res: 0 res: either odd? 1 [add res 288] [res] res: either odd? 2 [add res 144] [res] res: either odd? 5 [add res 72] [
    res] res: either odd? 11 [add res 36] [res] res: either odd? 23 [add res 18] [res] res]
  • Philipp 2009-07-23 10:12
    Ok, I couldn't resist. Here's an (amended!) brainfuck interpreter in Java, running the brainfuck code from Qwertyuiopas:


    public class BrainfuckJavaRussianMultiplication {
    private static final String input =
    ">>>>>,>>,[->+>+<<]<<[[-[>+<-]>[>+>>>+<<<<-[[<+>-]>[-]<]]<]>>[>>[-]" +
    "<<[-]]+>[->>>>>++>++<<<<<<]>>]>>>>[-]<<<<<<<[<<<<<]>>>>>[>>[->>>>>" +
    "+<<<<<]>>>]>>%";

    BrainfuckJavaRussionMultiplication(String code) {
    int ptr = 0;
    int [] cell = new int[10000];

    for (int i = 0; i < 10000; i++) {
    cell[i] = 0;
    }

    char [] chars = code.toCharArray();
    for (int i = 0, n = chars.length; i < n; i++) {
    char c = chars[i];
    if (c == '>') {
    ptr++;
    } else if (c == '<') {
    ptr--;
    } else if (c == '+') {
    cell[ptr]++;
    } else if (c == '-') {
    cell[ptr]--;
    } else if (c == '.') {
    System.out.print((char) cell[ptr]);
    } else if (c == '%') {
    System.out.print((int) cell[ptr]);
    } else if (c == ',') {
    Scanner in = new Scanner(System.in);
    try {
    cell[ptr] = Integer.parseInt(in.nextLine());
    } catch (Exception e) {
    cell[ptr] = 0;
    }
    } else if (c == '[') {
    if (cell[ptr] == 0) {
    int counter = 0;
    int position = i + 1;
    while (chars[position] != ']' || counter != 0) {
    if (chars[position] == '[') {
    counter++;
    }
    if (chars[position] == ']') {
    counter--;
    }
    position++;
    }
    i = position;
    }
    } else if (c == ']') {
    int counter = 0;
    int position = i - 1;
    while (chars[position] != '[' || counter != 0) {
    if (chars[position] == ']') {
    counter++;
    }
    if (chars[position] == '[') {
    counter--;
    }
    position--;
    }
    i = position - 1;
    }
    }
    }

    public static void main(String [] args) {
    new BrainfuckJavaRussianMultiplication(input);
    }
    }


    As you can see, you may enter integers (instead of characters whose ASCII code is interpreted), also we are dealing with Brainfuck++ here, since it has the % command ;)
  • jefu 2009-07-23 10:15
    Haskell (with quickCheck to test it) :

    import Test.QuickCheck

    pm 0 y = 0
    pm 1 y = y
    pm x y
    | x < 0 = - pm (-x) y
    | even x = next
    | otherwise = y + next
    where next = pm (x `div` 2) (y*2)

    prop_PMOK x y = pm x y == x*y
    where types = (x::Int,y::Int)

    quickCheck prop_PMOK
  • the real wtf fool 2009-07-23 10:20

    #!/usr/bin/python

    from sys import argv

    if len(argv) < 3:
    print "input values missing"
    print "usage: "
    print argv[0] + " value1 value2"
    exit()

    a = int(argv[1])
    b = int(argv[2])
    acc = 0
    sep = " x "

    justWidth = 5

    while (a > 0):
    if a & 0x1:
    acc = acc + b
    print " ",
    else:
    print "--",

    print str(a).rjust(justWidth) + sep + str(b).rjust(justWidth)
    sep = " "

    a = a >> 1
    b = b << 1

    print " " + "-" * ((justWidth*2)+len(sep))
    print " =" + str(acc).rjust((justWidth*2)+len(sep))


    The output:

    >pmath.py 18 23
    -- 18 x 23
    9 46
    -- 4 92
    -- 2 184
    1 368
    -------------
    = 414


    The lines starting with -- should be considered crossed out
  • n1L 2009-07-23 10:24
    soulution as c++ template:
    //////////////////////////////
    
    template <int I, int J>
    struct Pmul
    {
    operator int()
    {
    return (I%2)?J+Pmul<I/2,J*2>():Pmul<I/2,J*2>();
    }
    };
    //////////////////////////////
    template <int J>
    struct Pmul<1, J>
    {
    operator int()
    {
    return J;
    }
    };
    //////////////////////////////
    i.e.:
    int res = Pmul<2311, 1234>();
  • czetts 2009-07-23 10:27
    Well, I wanted to go back and make this more "clever", but this works just fine (C#):

    public static int MultiplyLikeARussianPeasant(int x, int y)
    
    {
    int sum = 0;
    do
    {
    sum += (x%2 == 1) ? y : 0;
    x /= 2;
    y *= 2;
    } while (x >= 1);
    return sum;
    }


    (I haven't checked the comments for this solution, that would have been cheating!)
  • Josh Bohde 2009-07-23 10:43
    WarheadsSE:
    Lom:
    Python, nominate for shortest one :)
    49 characters.
    And, with python, numbers multiply peasants.

    m=lambda a,b:sum(b<<i for i in range(a)if a&1<<i)


    There is a 44 character python, and a 40 characther bc, although you still have several characters to go to catch perl :)


    37 using * and /

    m=lambda a,b:a and(a&1)*b+m(a/2,b+b)


    41 without

    m=lambda a,b:a and[0,b][a&1]+m(a>>1,b+b)



  • some VBA coder 2009-07-23 10:50
    Function peasant(factor1, factor2)
    peasant = 0
    If factor1 < 0 Then factor2 = -factor2
    While factor1 <> 0
    If (factor1 / 2) <> Round(factor1 / 2, 0) Then peasant = peasant + factor2
    factor1 = factor1 / 2 - (factor1 Mod 2) / 2
    factor2 = 2 * factor2
    Wend
    End Function
  • Chris Judge 2009-07-23 10:55
    Bob:
    Someone straighten me out here but I think the peasant don't know math for crap.

    May be I'm doing it wrong but when I Multiply 45 x 76, I get 3420

    Peasants get:

    45 x 76
    22 152 0
    11 304 304
    5 608 608
    2 1216 0
    1 2432 2432
    ======================
    3344

    Flip the numbers and you get the right answer
    76 45
    38 90 0
    19 180 180
    9 360 360
    4 720 0
    2 1440 0
    1 2880 2880
    =====================
    3420

    Peasant math apparently only works if one of the number is even and in the first column.

    This must be why they remain peasants.


    When you start with the 45 in the left column, you forgot to include the 76 in your sum.

    Oh, and by the way:


    (define (pm x y)
    (define (pm2 acc x y)
    (cond
    [(= x 0) acc]
    [(= (remainder x 2) 0) (pm2 acc (floor (/ x 2)) (+ y y))]
    [else (pm2 (+ acc y) (floor (/ x 2)) (+ y y))]
    )
    )

    (pm2 0 x y)
    )
  • Rorick 2009-07-23 11:01
    In rebol with caching of generated code stuff.

    multru: func [a b /local res cached] [
    if not value? 'cache [
    set/any in system/words 'cache []
    ]
    select-cache: func [a b /local cached] [select/only cache compose [(a) (b)]]
    case [
    found? cached: any [select-cache a b select-cache b a] [return do cached]
    true [
    append/only cache compose [(a) (b)]
    res: copy []
    append res [res: 0]
    append res compose [(either a < 0 [[-res]] [[res]])]
    res: back tail res
    until [
    insert res compose/deep [either odd? (a) [add res (b)] [res]]
    insert res to-set-word 'res
    set [a b] compose [(round/down divide a 2) (multiply b 2)]
    zero? a
    ]
    append/only cache head res
    ]
    ]
    do last cache
    ]
  • dub 2009-07-23 11:01
    I'm in the process of learning Haskell so here's my haskell solution. Feel free to give feedback so I can improve.

    rus 0 _ = 0
    rus a b
    | a < 0 = (-1) * (rus (abs a) b)
    | b < 0 = (-1) * (rus a (abs b))
    | odd a = b + (rus (div a 2) (b*2) )
    | otherwise = (rus (div a 2) (b*2) )
  • MichaelWH 2009-07-23 11:06
    Erlang, as a module.
    -module(peasant).
    
    -export([peasant/2]).

    peasant (1,Y) -> Y;
    peasant (X,Y) when (X rem 2 == 1) ->
    Y + peasant ((X bsr 1),(Y bsl 1));
    peasant (X,Y) ->
    peasant ((X bsr 1),(Y bsl 1)).
  • Kman 2009-07-23 11:09
    c++ templates


    template <unsigned int a, unsigned int b> struct RM_ {
    static const unsigned int result = a & 0x1 ? b + RM_<a / 2, b * 2>::result : RM_<a / 2, b * 2>::result;
    };
    template <unsigned int b> struct RM_<1, b> {
    static const unsigned int result = b;
    };

    unsigned int c = RM_<18, 23>::result;
  • Evo 2009-07-23 11:21
    The only real solution:


    <?php
    function ymhoxntb($n1, $n2)
    {
    $written = "$n1 x $n2";

    // Create the next line, dividing the left number by two and
    // doubling the right.
    do {
    // Get the last line
    $lines = split("\n", $written);
    $line = $lines[count($lines)-1];
    preg_match("/([0-9]*)\s+[x]?\s*([0-9]*)/", $line, $matches);
    $a1 = intval($matches[1]);
    $a2 = intval($matches[2]);

    // Make the next line
    $a1 = floor($a1/2);
    $a2 *= 2;
    $written .= "\n$a1 $a2";
    }
    while($a1 > 1);
    echo $written."\n\n";

    // Cross out the even numbers on the left side
    $docrossout = TRUE;
    for($i = 0; $i < strlen($written); $i++) {
    if($written[$i] == "\n") {
    $docrossout = FALSE;
    if(intval(substr($written, $i)) % 2 == 0)
    $docrossout = TRUE;
    continue;
    }

    if($docrossout)
    $written[$i] = "-";
    }
    echo $written."\n\n";

    // Add the remaining right columns
    $lines = split("\n", $written);
    $result = "";
    foreach($lines AS $line) {
    if(!preg_match("/([0-9]*)\s+[x]?\s*([0-9]*)/", $line, $matches))
    continue;

    if($result == "")
    $result .= $matches[2];
    else
    $result .= " + ".$matches[2];
    }
    echo $result." = ";
    eval("echo ".$result.";");
    echo "\n";
    }
    ymhoxntb(18, 23);
  • Coyne 2009-07-23 11:25
    This is in Java. It was tested and works for negatives.

    public static int doRussianMultiply(int a, int b)
    {
    if (a < 0) return -doRussianMultiply(-a,b);

    int sum = 0;
    while (a > 1) {
    if ((a & 1) == 1) sum += b;
    a >>= 1;
    b += b;
    }
    if (a == 1) sum += b;

    return sum;
    }
  • markwhi 2009-07-23 11:48
    Late to the game, I guess. Replying without viewing comments, wonder if mine is original :)

    http://pastebin.com/f50d7e6d5
  • markwhi 2009-07-23 11:51
    I guess I should post the code, not just a link to it:

    /**
    * Submission for TDWTF Programming Praxis 1: Russian Peasant Multiplication
    * July 23, 2009
    */
    #include <stdio.h>
    #include <stdlib.h>

    void
    usage (void)
    {
    printf ("usage: rmult <int> <int>\n") ;
    exit (-1) ;
    }

    int
    main (int argc, char **argv)
    {
    int a, b, total = 0 ;

    if (argc != 3)
    usage () ;

    a = atoi (argv[1]) ;
    b = atoi (argv[2]) ;
    if (a <= 0 || b <= 0)
    usage () ;

    printf ("%i * %i = ", a, b) ;

    while (1) {
    if (a % 2)
    total += b ;

    if (a == 1)
    break ;

    a /= 2 ;
    b *= 2 ;
    }

    printf ("%i\n", total) ;

    return 0 ;
    }
  • HCGL 2009-07-23 11:54
    public static double RussianMultiply(int left, int right)
    {
    var columns = new Dictionary<int, int> {{left, right}};
    var product=0;
    while (left > 1)
    columns.Add(left /= 2, right *= 2);

    foreach (var row in columns)
    product += row.Value * (row.Key % 2);

    return product;
    }
  • Jeremy Burns 2009-07-23 12:01

    uint multiplyIntegers( uint a, uint b ) // C#
    {
    uint up, down, res = 0;

    if( a > b ) { up = a; down = b; }
    else { up = b; down = a; }

    do
    {
    if( (down & 1) != 0 ) res += up;
    up <<= 1;
    down >>= 1;
    }
    while( down > 0 );

    return res;
    }
  • Evo 2009-07-23 12:16
    Oops... bugfix:


    function ymhoxntb($n1, $n2)
    {
    $written = "$n1 x $n2";

    // Create the next line, dividing the left number by two and
    // doubling the right.
    do {
    // Get the last line
    $lines = split("\n", $written);
    $line = $lines[count($lines)-1];
    preg_match("/([0-9]*)\s+[x]?\s*([0-9]*)/", $line, $matches);
    $a1 = intval($matches[1]);
    $a2 = intval($matches[2]);

    // Make the next line
    $a1 = floor($a1/2);
    $a2 *= 2;
    $written .= "\n$a1 $a2";
    }
    while($a1 > 1);
    echo $written."\n\n";

    // Cross out the even numbers on the left side
    $docrossout = FALSE;
    for($i = -1; $i < strlen($written); $i++) {
    if($i == -1 || $written[$i] == "\n") {
    $docrossout = FALSE;
    if(intval(substr($written, $i + 1)) % 2 == 0)
    $docrossout = TRUE;
    continue;
    }

    if($docrossout)
    $written[$i] = "-";
    }
    echo $written."\n\n";

    // Add the remaining right columns
    $lines = split("\n", $written);
    $result = "";
    foreach($lines AS $line) {
    if(!preg_match("/([0-9]*)\s+[x]?\s*([0-9]*)/", $line, $matches))
    continue;

    if($result == "")
    $result .= $matches[2];
    else
    $result .= " + ".$matches[2];
    }
    echo $result." = ";
    eval("echo ".$result.";");
    echo "\n";
    }
    ymhoxntb(18, 23);
  • iggy 2009-07-23 12:19
    My solution in haskell:


    rpm :: Int -> Int -> Int
    rpm a b = sum $ aux a b [] where
    aux 1 b xs = b:xs
    aux a b xs | odd a = aux (a`div`2) (b*2) (b:xs)
    | otherwise = aux (a`div`2) (b*2) xs


    P.S. Does not terminate for a<=0
  • AngeloR. 2009-07-23 13:12
    Simple PHP version. No array lists.

    function rpm($val1,$val2){
    echo $val1.' x '.$val2.' = ';

    while($val1 >= 1){
    if($val1%2 != 0)
    $done += $val2;
    $val1 = floor($val1/2);
    $val2 *= 2;
    }
    echo $done;
    }
  • juancn 2009-07-23 13:20
    Simple recursive implementation in scala (first version):

    def peasant(a : Int, b : Int) : Int =
    if (a < 0 && b > 0) -peasant(-a, b)
    else if (a < 0 && b < 0) peasant(-a, -b)
    else if (a > 0 && b < 0) -peasant(a, -b)
    else if (a > b) peasant(b, a)
    else if (a == 0) 0
    else if (a == 1) b
    else if (a % 2 != 0) a+b+peasant(a/2, b*2)
    else peasant(a/2, b*2)

    It's not too pretty, but supports all edge cases (since the naive algorithm only works for positive integers).

    This one, is a bit denser (but more obscure):

    def peasant(a : Int, b : Int) : Int =
    if (a.abs > b.abs) peasant(b, a)
    else if (a.abs < 2) a*b
    else if (a % 2 != 0) a+b+peasant(a/2, b*2)
    else peasant(a/2, b*2)

    Also note that the multiplications can be removed (either changed by shifts or by an additional if clause).

    It can probably be simplified. I don't like the first if very much, and my gut tells me that it's probably a more elegant way to solve this.

    I haven't read other solutions yet and I'm eagerly waiting for the winning entries :D


    Addendum (2009-07-23 14:51):
    OoopS! That's what happens when you post without properly testing:

    def peasant1(a : Int, b : Int) : Int =
    if (a < 0 && b > 0) -peasant1(-a, b)
    else if (a < 0 && b < 0) peasant1(-a, -b)
    else if (a > 0 && b < 0) -peasant1(a, -b)
    else if (a > b) peasant1(b, a)
    else if (a == 0) 0
    else if (a == 1) b
    else if (a % 2 != 0) b+peasant1(a/2, b*2)
    else peasant1(a/2, b*2)

    for{ a <- -100 to 100
    b <- -100 to 100 }
    assert (a*b == peasant1(a,b), "peasant1 a: " + a + ", b: " + b + " => " + peasant1(a,b) )


    And the (not much) denser version:

    def peasant(a : Int, b : Int) : Int =
    if (a < 0) -peasant(-a,b)
    else if(b < 0) -peasant(a,-b)
    else if(a < 2) a*b
    else if (a % 2 != 0) b+peasant(a/2, b*2)
    else peasant(a/2, b*2)

    for{ a <- -100 to 100
    b <- -100 to 100 }
    assert (a*b == peasant(a,b), "peasant a: " + a + ", b: " + b + " => " + peasant(a,b) )


    (I might still have one or two WTFs in this code, but that's life ;) )
  • Pony Princess 2009-07-23 13:35
    In Ruby:

    def mul(a,b)
    (1..a).to_a.reverse.inject(0){|res,i| (i == a) ? ( [res + ((a % 2 == 1) ? b : 0) , ( a >>= 1; b <<= 1 )][0]) : res }
    end
  • PatrickBeebe 2009-07-23 13:59
    C# Recursion:

    public static int RussianMultiplication(int x, int y)
    {
    if (x == 0 || y == 0) return 0;
    int sign = (x >> 31 | 1) * (y >> 31 | 1);
    x *= (x >> 31 | 1);
    y *= (y >> 31 | 1);
    if (y < x)
    return sign*RecursiveRussianMultiplication(y, x);
    else
    return sign*RecursiveRussianMultiplication(x, y);
    }

    public static int RecursiveRussianMultiplication(int x, int y)
    {
    if (x ==-1 || x == 1) return y;
    return (x % 2 == 0 ? 0 : y) + RecursiveRussianMultiplication(x /= 2, y += y);
    }
  • workmad3 2009-07-23 13:59
    Here's mine, in python, with doctests, in 4 variations... it was a slow day at work :P

    """
    Russian peasant multiplication functions.

    >>> russian_mult(18, 23)
    414
    >>> russian_mult(2, 4)
    8
    >>> russian_mult(-2, 4)
    -8
    >>> russian_mult(-2, -4)
    8
    >>> russian_mult_gen(18, 23)
    414
    >>> russian_mult_gen(2, 4)
    8
    >>> russian_mult_gen(-2, 4)
    -8
    >>> russian_mult_gen(-2, -4)
    8
    >>> russian_mult_opt(18, 23)
    414
    >>> russian_mult_opt(2, 4)
    8
    >>> russian_mult_opt(-2, 4)
    -8
    >>> russian_mult_opt(-2, -4)
    8
    >>> russian_mult_rec(18, 23)
    414
    >>> russian_mult_rec(2, 4)
    8
    >>> russian_mult_rec(-2, 4)
    -8
    >>> russian_mult_rec(-2, -4)
    8
    """

    def correct_values(func):
    """
    This decorator function 'corrects' the inputs of the
    other functions. It does this in two ways:
    1) It ensures that the numerically lowest absolute value is the lhs. This is to minimise the looping as this is the loop control
    2) It ensures negative multiplication can take place. It does this by multiplying both sides by -1 if the lhs is less than -1.
    This can be removed by taking away the '@correct_values' line before a function to return to a 'pure' russian peasant multiplication algorithm
    >>> def echo(lhs, rhs):
    ... print lhs, rhs
    >>> correct_values(echo)(-23, -18)
    18 23
    >>> correct_values(echo)(-43245, 2)
    2 -43245
    """
    def corrector(lhs, rhs):
    lhs, rhs = (rhs, lhs) if abs(rhs) < abs(lhs) else (lhs, rhs)
    lhs, rhs = (lhs * -1, rhs * -1) if lhs < 0 else (lhs, rhs)
    return func(lhs, rhs)
    corrector.__doc__ = func.__doc__
    return corrector

    @correct_values
    def russian_mult(lhs, rhs):
    """
    Simplest, most exact conversion of 'russian peasant multiplication'.
    Builds a list of pairs and then iterates over them to find the result

    >>> russian_mult(18, 23)
    414
    """
    mult_list = [(lhs, rhs)]
    while mult_list[-1][0]:
    mult_list.append( (mult_list[-1][0] / 2,
    mult_list[-1][1] * 2) )
    result = 0
    for line in mult_list:
    result += line[1] if line[0] % 2 else 0
    return result

    @correct_values
    def russian_mult_opt(lhs, rhs):
    """
    'Optimised' version of the first algorithm. It removes the
    need to store the results by calculating the result in a
    single pass.

    >>> russian_mult_opt(18, 23)
    414
    """
    result = 0
    while lhs:
    result += rhs if lhs % 2 else 0
    lhs /= 2
    rhs *= 2
    return result

    @correct_values
    def russian_mult_gen(lhs, rhs):
    """
    Generator version of the russian_mult_opt function.
    Uses a python generator to get values. This is then
    given to a reduce which iterates over the generator
    and produces the result.

    >>> russian_mult_gen(18, 23)
    414
    """
    def build_list(lhs, rhs):
    while lhs:
    yield rhs if lhs % 2 else 0
    lhs /= 2
    rhs *= 2
    return reduce(lambda x, y: x + y, build_list(lhs, rhs))
    @correct_values
    def russian_mult_rec(lhs, rhs):
    """
    'Russian peasant multiplication' reduced to a recursive one-liner.
    Returns 0 when lhs is 0, otherwise recursion, adding the rhs to the resu
    lt
    when called with an odd lhs value.
    The recursion is done within the inline _russian_mult_rec function so as
    to
    avoid issues with the @correct_values decorator. If this isn't done then
    infinite
    recursion can occur and correct values aren't obtained.

    >>> russian_mult_rec(18, 23)
    414
    """
    def _russian_mult_rec(lhs, rhs):
    return 0 if not lhs else (rhs if lhs % 2 else 0) + _russian_mult
    _rec(lhs / 2, rhs * 2)
    return _russian_mult_rec(lhs, rhs)

    if __name__ == '__main__':
    import doctest
    doctest.testmod()

    I also added a 'correction' decorator to allow multiplication with negatives and to switch the inputs if the larger one is first (minor optimisation)
  • Paul N 2009-07-23 14:19
    Here is a C# version that multiplies two text numbers

    private static string Multiply(string number1, string number2)
    {
    string[,] multiplicationSteps = {{ number1, number2 }};
    while (CanAddStep(multiplicationSteps))
    {
    multiplicationSteps = AddStep(multiplicationSteps);
    }
    multiplicationSteps = RemoveEvenFactor1Steps(multiplicationSteps);
    string result = AddAllFactor2Steps(multiplicationSteps);
    return result;
    }

    private static string AddAllFactor2Steps(string[,] multiplicationSteps)
    {
    string lastStep = string.Empty;
    string result = string.Empty;
    for (int index = 0; index < multiplicationSteps.GetLength(0); index++)
    {
    lastStep = result;
    result = AddNumbers(lastStep, multiplicationSteps.GetValue(index, 1).ToString());
    }
    return result;
    }

    private static string AddNumbers(string number1, string number2)
    {
    string addendum1 = number1.PadLeft(number2.Length, '0');
    string addendum2 = number2.PadLeft(number1.Length, '0');
    StringBuilder result = new StringBuilder();
    string lastStep = string.Empty;
    string currentStep = string.Empty;
    for (int index = addendum1.Length - 1; index >= 0; index--)
    {
    lastStep = currentStep;
    currentStep = AddDigits(addendum1[index], addendum2[index]);
    if (string.IsNullOrEmpty(currentStep))
    {
    currentStep = "0";
    }
    if (lastStep.Length > 1)
    {
    currentStep = AddNumbers(lastStep[0].ToString(), currentStep);
    }
    int lastDigitOfCurrentStep = currentStep.Length - 1;
    result.Insert(0, currentStep[lastDigitOfCurrentStep]);
    }
    if (currentStep.Length > 1)
    {
    result.Insert(0, currentStep[0]);
    }
    return result.ToString();
    }

    private static string[,] RemoveEvenFactor1Steps(string[,] multiplicationSteps)
    {
    int newArraySize = multiplicationSteps.GetLength(0);
    string[,] result = new string[newArraySize, 2];
    Array.Copy(multiplicationSteps, result, multiplicationSteps.Length);
    int indexStop = result.GetLength(0) - 1;
    for (int index = 0; index < indexStop; index++)
    {
    string lastValue = result.GetValue(index, 0).ToString();
    int lastDigitOfLastValue = lastValue.Length - 1;
    string halfLastDigit = GetHalfOfDigit(lastValue[lastDigitOfLastValue]);
    if (halfLastDigit.Length == 1)
    {
    result.SetValue(string.Empty, index, 0);
    result.SetValue(string.Empty, index, 1);
    }
    }
    return result;
    }

    private static string[,] AddStep(string[,] multiplicationSteps)
    {
    int newArraySize = multiplicationSteps.GetLength(0) + 1;
    string[,] result = new string[newArraySize, 2];
    Array.Copy(multiplicationSteps, result, multiplicationSteps.Length);
    int index = multiplicationSteps.GetLength(0) - 1;
    string nextNumber1 = GetHalfOfNumber(multiplicationSteps.GetValue(index, 0).ToString());
    string nextNumber2 = DoubleNumber(multiplicationSteps.GetValue(index, 1).ToString());
    int nextArrayLocation = multiplicationSteps.GetLength(0);
    result.SetValue(nextNumber1, nextArrayLocation, 0);
    result.SetValue(nextNumber2, nextArrayLocation, 1);
    return result;
    }

    private static string DoubleNumber(string number)
    {
    StringBuilder result = new StringBuilder();
    string lastStep = string.Empty;
    string currentStep = string.Empty;
    for (int index = number.Length - 1; index >= 0 ; index--)
    {
    lastStep = currentStep;
    currentStep = DoubleDigit(number[index]);
    if (string.IsNullOrEmpty(currentStep))
    {
    currentStep = "0";
    }
    if (lastStep.Length > 1)
    {
    currentStep = AddNumbers(lastStep[0].ToString(), currentStep);
    }
    int lastDigitOfCurrentStep = currentStep.Length - 1;
    result.Insert(0, currentStep[lastDigitOfCurrentStep]);
    }
    if (currentStep.Length > 1)
    {
    result.Insert(0, currentStep[0]);
    }
    return result.ToString();
    }

    private static string DoubleDigit(char digit)
    {
    switch (digit)
    {
    case '0':
    return "0";
    case '1':
    return "2";
    case '2':
    return "4";
    case '3':
    return "6";
    case '4':
    return "8";
    case '5':
    return "10";
    case '6':
    return "12";
    case '7':
    return "14";
    case '8':
    return "16";
    case '9':
    return "18";
    }
    return string.Empty;
    }

    private static bool CanAddStep(string[,] multiplicationSteps)
    {
    int index = multiplicationSteps.GetLength(0) - 1;
    string halfValue = GetHalfOfNumber(multiplicationSteps.GetValue(index, 0).ToString());
    if (string.IsNullOrEmpty(halfValue))
    { return false; }
    else
    { return true; }
    }

    private static string GetHalfOfNumber(string number)
    {
    StringBuilder result = new StringBuilder();
    string lastStep = string.Empty;
    string currentStep = string.Empty;
    for (int index = 0; index < number.Length; index++)
    {
    lastStep = currentStep;
    currentStep = GetHalfOfDigit(number[index]);
    if (string.IsNullOrEmpty(currentStep))
    {
    currentStep = "0";
    }
    if (lastStep.Length > 1)
    {
    int lastDigitOfLastStep = lastStep.Length - 1;
    currentStep = AddNumbers(lastStep[lastDigitOfLastStep].ToString(), currentStep);
    }
    if (currentStep[0] != '0')
    {
    result.Insert(0, currentStep[0]);
    }
    }
    return result.ToString();
    }

    private static string GetHalfOfDigit(char digit)
    {
    switch (digit)
    {
    case '0':
    return "0";
    case '1':
    return "05";
    case '2':
    return "1";
    case '3':
    return "15";
    case '4':
    return "2";
    case '5':
    return "25";
    case '6':
    return "3";
    case '7':
    return "35";
    case '8':
    return "4";
    case '9':
    return "45";
    }
    return string.Empty;
    }

    private static string AddDigits(char digit1, char digit2)
    {
    switch (digit1)
    {
    case '0':
    switch (digit2)
    {
    case '0':
    return "0";
    case '1':
    return "1";
    case '2':
    return "2";
    case '3':
    return "3";
    case '4':
    return "4";
    case '5':
    return "5";
    case '6':
    return "6";
    case '7':
    return "7";
    case '8':
    return "8";
    case '9':
    return "9";
    }
    break;
    case '1':
    switch (digit2)
    {
    case '0':
    return "1";
    case '1':
    return "2";
    case '2':
    return "3";
    case '3':
    return "4";
    case '4':
    return "5";
    case '5':
    return "6";
    case '6':
    return "7";
    case '7':
    return "8";
    case '8':
    return "9";
    case '9':
    return "10";
    }
    break;
    case '2':
    switch (digit2)
    {
    case '0':
    return "2";
    case '1':
    return "3";
    case '2':
    return "4";
    case '3':
    return "5";
    case '4':
    return "6";
    case '5':
    return "7";
    case '6':
    return "8";
    case '7':
    return "9";
    case '8':
    return "10";
    case '9':
    return "11";
    }
    break;
    case '3':
    switch (digit2)
    {
    case '0':
    return "3";
    case '1':
    return "4";
    case '2':
    return "5";
    case '3':
    return "6";
    case '4':
    return "7";
    case '5':
    return "8";
    case '6':
    return "9";
    case '7':
    return "10";
    case '8':
    return "11";
    case '9':
    return "12";
    }
    break;
    case '4':
    switch (digit2)
    {
    case '0':
    return "4";
    case '1':
    return "5";
    case '2':
    return "6";
    case '3':
    return "7";
    case '4':
    return "8";
    case '5':
    return "9";
    case '6':
    return "10";
    case '7':
    return "11";
    case '8':
    return "12";
    case '9':
    return "13";
    }
    break;
    case '5':
    switch (digit2)
    {
    case '0':
    return "5";
    case '1':
    return "6";
    case '2':
    return "7";
    case '3':
    return "8";
    case '4':
    return "9";
    case '5':
    return "10";
    case '6':
    return "11";
    case '7':
    return "12";
    case '8':
    return "13";
    case '9':
    return "14";
    }
    break;
    case '6':
    switch (digit2)
    {
    case '0':
    return "6";
    case '1':
    return "7";
    case '2':
    return "8";
    case '3':
    return "9";
    case '4':
    return "10";
    case '5':
    return "11";
    case '6':
    return "12";
    case '7':
    return "13";
    case '8':
    return "14";
    case '9':
    return "15";
    }
    break;
    case '7':
    switch (digit2)
    {
    case '0':
    return "7";
    case '1':
    return "8";
    case '2':
    return "9";
    case '3':
    return "10";
    case '4':
    return "11";
    case '5':
    return "12";
    case '6':
    return "13";
    case '7':
    return "14";
    case '8':
    return "15";
    case '9':
    return "16";
    }
    break;
    case '8':
    switch (digit2)
    {
    case '0':
    return "8";
    case '1':
    return "9";
    case '2':
    return "10";
    case '3':
    return "11";
    case '4':
    return "12";
    case '5':
    return "13";
    case '6':
    return "14";
    case '7':
    return "15";
    case '8':
    return "16";
    case '9':
    return "17";
    }
    break;
    case '9':
    switch (digit2)
    {
    case '0':
    return "9";
    case '1':
    return "10";
    case '2':
    return "11";
    case '3':
    return "12";
    case '4':
    return "13";
    case '5':
    return "14";
    case '6':
    return "15";
    case '7':
    return "16";
    case '8':
    return "17";
    case '9':
    return "18";
    }
    break;
    }
    return string.Empty;
    }
  • Ted Walther, newLISP fan 2009-07-23 14:30
    An even better newlisp oneliner:

    (define (rmul x y) (if (= x 1) y (+ (* (& x 1) y) (rmul (>> x) (<< y)))))

    Thanks to the poster who noticed that the and operator is of use here, it saved a comparison operation.
  • Whatever 2009-07-23 14:40
    0&&>::+13p\:2/23p:v
    
    ^g31g32 +*%2_$$.@


    Befunge-93. Shortest so far excluding whitespace?
  • Lightnix 2009-07-23 14:53
    C++ :)

    #include <iostream>

    template <typename T>
    class RussianNumerable
    {
    protected:
    T value;
    public:
    bool printoutput;

    RussianNumerable(T val)
    {
    value = (T)val;
    printoutput = false;
    }

    //must maintain compatibility with regular numbers!
    RussianNumerable & operator = (const T &in)
    {
    value = in;
    return *this;
    }

    operator T()
    {
    return value;
    }

    //correct way of multiplying!!!
    T & operator * (const T &in)
    {
    T n1 = value;
    T n2 = in;
    T answer = 0;
    T first = 0;
    T second = 0;
    if(printoutput)
    {
    std::cout<<n1<<" x "<<n2<<"\n";
    }
    for(int i = n2; i != 1;)
    {
    if(i == n2)
    {
    first = n2*2;
    }
    n1/=2;
    n2*=2;
    if(printoutput)
    {
    std::cout<<n1<<" "<<n2<<"\n";
    }
    for(int a=0;a<2000000;a+=3){a-=2;} //executes too fast?
    if((int)n1 == 1 || (int)n1 == -1)
    {
    second = n2;
    break;
    }
    }
    if(printoutput)
    {
    std::cout<<"========\n";
    }
    answer = first+second;

    return answer;
    }
    };

    int main()
    {
    RussianNumerable<float> a = 18;
    RussianNumerable<float> b = 23;
    a.printoutput = true;
    std::cout<<a*b<<"\n";
    std::cin.get();

    return 0;
    }
  • inky 2009-07-23 15:08
    First attempt, in Python.

    def multiply(x, y):
    
    answer = 0
    while x:
    x, odd = divmod(x, 2)
    if odd:
    answer += y
    y += y
    return answer
  • samanddeanus 2009-07-23 15:14
    Scheme with objects represented as higher order functions using message passing and GOTO done with call-with-current-continuation:

    (define (adder x)
    (let ((total x))
    (lambda (op)
    (cond ((eq? op 'total) total)
    ((eq? op 'add) (lambda (x) (set! total (+ total x)) total))
    (else (error "Invalid operation -- ADDER" op))))))

    (define (halver x)
    (let ((value x))
    (lambda (op)
    (cond ((eq? op 'value) value)
    ((eq? op 'halve) (set! value (quotient value 2)) value)
    (else (error "Invalid operation -- HALVER" op))))))

    (define (doubler x)
    (let ((value x))
    (lambda (op)
    (cond ((eq? op 'value) value)
    ((eq? op 'double) (set! value (+ value value)))
    (else (error "Invalid operation -- DOUBLER" op))))))

    (define (mul x y)
    (let ((left (halver (abs x)))
    (right (doubler (if (negative? x)
    (- y)
    y)))
    (result (adder 0)))
    ((call-with-current-continuation
    (lambda (goto)
    (letrec ((ten (lambda ()
    (if (zero? (left 'value))
    (result 'total)
    (goto twenty))))
    (twenty (lambda ()
    (if (odd? (left 'value))
    ((result 'add) (right 'value)))
    (left 'halve)
    (right 'double)
    (goto ten))))
    ten))))))



  • dee 2009-07-23 15:58
    One more; MySQL stored function:


    DELIMITER WTF

    CREATE FUNCTION peasant (argLeft BIGINT, argRight BIGINT)
    RETURNS BIGINT
    DETERMINISTIC
    BEGIN
    DECLARE result BIGINT DEFAULT 0;
    IF argLeft = 0 THEN
    RETURN 0;
    END IF;

    -- negative numbers
    IF argLeft < 0 THEN
    SET argLeft = -argLeft;
    SET argRight = -argRight;
    END IF;

    -- helper table for multiplication rows
    CREATE TEMPORARY TABLE peasant_helper (
    itemLeft BIGINT NOT NULL,
    itemRight BIGINT NOT NULL
    );

    -- insert the multiplication rows
    WHILE argLeft > 0 DO
    INSERT INTO peasant_helper VALUES (argLeft, argRight);
    SET argLeft = argLeft >> 1;
    SET argRight = argRight + argRight;
    END WHILE;

    -- calculate the sum of the right side
    -- of the rows with an odd left side
    SET result = (
    SELECT
    SUM(itemRight)
    FROM
    peasant_helper
    WHERE
    itemLeft & 1
    );

    DROP TEMPORARY TABLE peasant_helper;
    RETURN result;
    END
    WTF

    DELIMITER ;


    ------------------------


    mysql> SELECT peasant(18,23);
    +----------------+
    | peasant(18,23) |
    +----------------+
    | 414 |
    +----------------+
    1 row in set (0.00 sec)



    Addendum (2009-07-23 16:04):
    Accumulators are so non-inventive. Try harder, people!
  • John Stracke 2009-07-23 15:59
    I've seen a couple of Erlang solutions, but neither of them did concurrency, so here:


    -module(peasant).
    -export([mul/2,pairs/3,filter/1,flatten/1,add/1]).

    pairs(0,_,FilterPid) ->
    FilterPid ! over;
    pairs(X,Y,FilterPid) ->
    FilterPid ! [X,Y],
    pairs(X div 2, Y*2, FilterPid).

    filter(FlattenPid) ->
    receive
    over ->
    FlattenPid ! over;
    [X,Y] ->
    if
    (X rem 2)==1 ->
    FlattenPid ! [X,Y]
    end,
    filter(FlattenPid)
    end.

    flatten(AddPid) ->
    receive
    over ->
    AddPid ! over;
    [_,Y] ->
    AddPid ! Y,
    flatten(AddPid)
    end.

    add(MulPid,Total) ->
    receive
    over ->
    MulPid ! Total;
    X ->
    add(MulPid,Total+X)
    end.

    add(MulPid) ->
    add(MulPid,0).

    mul(X, Y) ->
    spawn(peasant,pairs,
    [X,Y,
    spawn(peasant,filter,
    [spawn(peasant,flatten,
    [spawn(peasant,add,[self()])])])]),
    receive
    Res ->
    Res
    end.
  • Scott 2009-07-23 16:11
    Here's a simple recursive algorithm, written in python (I'm a Plone/Zope developer, so it's what I use regularly... plus, it's awesomest). A little colour for that cozy vi feeling ;)

    I thought about handling the negative numbers in the recursive part, which is much more satisfying, algorithmically, but that would mean calculating the sign of left for every recursion, rather than just once. In my solution, calculating the sign takes work on the order of O(1); the alternate would be on the order of O(log(left)). It makes more sense to just pass the magnitudes in for recursion, and slap the sign back on afterwards. I'm sure that's how the Russians are tought to do it, anyway.


    def _russian (left, right):
    result = {}
    if left:
    result[left] = right
    result.update(_russian(left // 2, right * 2))
    return result

    def russian (left, right):
    sign = left * right / abs(left * right)
    return sign * sum([
    r for l, r in _russian(abs(left), abs(right)).items()
    if l % 2
    ])

  • Paul N 2009-07-23 16:22
    I think I am ahead on longest version. ;)

    In the interest of being true to the problem, I used no built in math functions on the numbers passed in (which is why it is all string manipulation). I did use built in math functions with the integers used for indexing, but only addition and subtraction.

    The Multiplication function works just fine with non-negative integers passed in as strings, but will give unpredictable results if anything else is passed in, which is a big WTF.

    I tried to use as many WTFs in the function as possible, but don't know how to count them.

    It is very easy to read, so maybe I should have obfuscated it to make it unmainable.

    I think I have come up with the most WTF version so far (in a commonly used language), and would really like that sticker. ;)

    The real WTF is the amount of time taken to write a simple multiplication function.
  • Queex 2009-07-23 16:35
    I, too, tried to pack mine with any many WTFs as possible, but no-one even seems to have noticed. Hell, mine crashes and burns as written.

    Way to code review, everyone...
  • epv 2009-07-23 16:37
    Qwertyuiopas:
    Any time you use n = n * 2 or n *=2, n += n would work.
    Any time you use n = n * -1 or n *= -1, n = -n would work.

    Anyone using * for 2 or -1 has NO EXCUSE.


    The excuse is called compilers. Code what you mean and not what you want the compiler to do. The compiler knows what is fast better then you do more often then not. If you want a double, double it. 'n*=2' will take an identical number of cycles as 'n+=n' on modern CPUs. All you've done is obfuscate that you wanted to double something to increment something by something else, that happens to be itself, so that it is double what you wanted it to be.

    Same with the left shift and right shift by 1. Do you mean multiply by two or do you actually want to use it as a bit mask? The compiler will probably change it to a bit-wise operator if it is faster anyways. Or as it more likely the case, the arithmetic operator is just as fast as the bit-wise operator. All you've accomplished is made it harder on humans and taken options away from the compiler.
  • TP 2009-07-23 17:20
    My C++ version is here:

    int multiply(int a, int b)
    {
    int aa[32];
    int bb[32];
    int i = 0;
    aa[i] = a;
    bb[i] = b;
    while(a!=1)
    {
    a/=2;
    b*=2;
    i++;
    aa[i]=a;
    bb[i]=b;
    }
    int result = 0;
    for(int ii=0;ii<=i;ii++)
    {
    if ((aa[ii]&1) == 1)
    {
    result += bb[ii];
    }
    }
    return result;
    }
  • The_Assimilator 2009-07-23 17:26
    WTF, no PowerShell yet?

    # begin script
    clear-host

    $left = 18
    $right = 23
    $sum = 0

    if ($left -lt 0)
    {
    $left *= -1
    $right *= -1
    }

    while ($left -gt 0)
    {
    if (($left % 2) -eq 1)
    {
    $sum += $right
    }

    $left = [Math]::Floor($left / 2)
    $right = $right * 2
    }

    write-host $sum
    # end script

    Should handle negative numbers and 0 but haven't tested it too much because I couldn't be arsed. For the same reason, no bitwise operators or recursion.
  • ajp 2009-07-23 17:36
    did this one that handles 0 and negative numbers.

    //F# Version 1.9.6.16
    #light
    let isOdd x =
    (x%2) = 1

    let abs x =
    if x < 0 then -x else x

    let rec mult x y =
    match x with
    | 0 -> 0
    | 1 -> y
    | _ when isOdd x -> y + mult (x/2) (y*2)
    | _ -> mult (x/2) (y*2)

    let Multiply a b =
    match a with
    | _ when ((a < 0) && (b > 0)) or ((a>0) && (b<0)) -> -mult (abs a) (abs b)
    | _ -> mult (abs a) (abs b)
  • DGM 2009-07-23 17:39
    Larry H.:

    unsigned russian(unsigned a, unsigned b)
    {
    return ((a & 1) ? b : 0) + ((a & ~1) ? russian(a>>1, b<<1) : 0);
    }


    Not tested.


    Now that's what I was looking for. No fair using standard multiplication, division or mod operators. This code gets the job done using only shifts. Bravo!
  • TP 2009-07-23 17:53
    1) operations are done in wrong order
    2) not doing correct operations (a & 1 is and-operation, not testing whether it's odd or even -- proper solution tests for decimal number last digit equals 1,3,5,7 or 9 to test if it's odd - otherwise it's different from how you do it by hand)
    3) not following the rules (it said just ONE FUNCTION is allowed)
  • Rusty Nail 2009-07-23 18:27
    The assembly language submissions seemed a little too high level, so I went for Verilog. It compiles, probably synthesizes, but I didn't simulate it...

    Implement it in a CPLD, no processor required :)

    Just saw Ikegami's discrete logic solution for 4-bit numbers. Cool! Mine does 32-bit numbers though :P




    module multiply (
    input clock,
    input reset,

    input start,
    input [31:0] a,
    input [31:0] b,

    output reg finished,
    output reg [63:0] c
    );

    reg [4:0] count;

    reg [31:0] a_latched;
    reg [63:0] b_latched;

    always @(posedge clock or posedge reset)
    begin
    if (reset == 1'b1) begin
    finished <= 1'b0;
    a_latched <= 32'b0;
    b_latched <= 64'b0;
    c <= 64'b0;
    count <= 5'd0;
    end else begin

    finished <= 1'b0;

    if (start == 1'b1) begin
    count[4:0] <= 5'd31;

    a_latched[31:0] <= a[31:0];
    b_latched[63:0] <= { 32'b0, b[31:0] };
    c <= 64'b0;

    end else if (|count) begin
    if ( a_latched[0] == 1'b1 ) begin
    c[63:0] <= c[63:0] + b_latched[63:0];
    end

    a_latched[31:0] <= { 1'b0, a_latched[31:1] };
    b_latched[63:0] <= { b_latched[62:0], 1'b0 };

    count[4:0] <= count[4:0] - 5'd1;

    if (count[4:0] == 5'd1) begin
    finished <= 1'b1;
    end
    end
    end
    end

    endmodule
  • Landei 2009-07-23 18:28
    Scala:

    def russianMultiply(a:Int, b:Int) = {
    def loop(x:Int, y:Int, list:List[(Int,Int)]):List[(Int,Int)] =
    if(x == 0) list else loop(x >> 1, y << 1, (x, y) :: list)
    loop(a, b, Nil).filter(_._1 % 2 == 1).foldLeft(0)(_+_._2)
    }
  • vog 2009-07-23 18:55
    In addition to Python3, there is also a non-recursive, one-line, one-statement solution in Haskell:

    mul a b =
    let (_,_,p) = foldl (\(a,b,p) _ -> (div a 2,b*2,p+b*mod a 2)) (a,b,0) [1..a] in p

    Or, more efficiently:

    mul a b =
    let (_,_,p) = foldl (\(a,b,p) _ -> (div a 2,b*2,p+b*mod a 2)) (a,b,0) [1..ceiling$logBase 2$fromIntegral a+1] in p

    However, recursion (over "interm") makes it more clear:

    mul a b =
    let interm = (a,b) : [ (div a 2,b*2) | (a,b) <- interm ]
    cut_interm = takeWhile ((0<).fst) interm
    in
    sum [ b | (a,b) <- cut_interm, odd a ]
  • Maurits 2009-07-23 18:59
    80 characters, Perl, requires positive whole multiplicands:

    perl -e "($a,$b)=@ARGV;map{$c+=$b<<$_ if$a>>$_&1}(0..log($a)/log 2);print$c" 8 7

    http://blogs.msdn.com/matthew_van_eerde/archive/2009/07/23/bad-perl-russian-peasant-multiplication-algorithm.aspx
  • MichaelWH 2009-07-23 19:02
    In Haskell, dealing with negatives.

    peasant :: Int -> Int -> Int
    
    peasant 1 y = y
    peasant x y
    | x < 0 = -(peasant (-x) y)
    | odd x = y + p
    | otherwise = p
    where
    p = peasant (x `div` 2) (y * 2)
  • andyesslinger 2009-07-23 19:07
    Hopefully this is original enough... Batch file...

    @echo ON
    REM Russian Peasant Multiplication via Batch file

    @echo OFF
    set /A m1 = %1
    set /A m2 = %2
    set /A EvenOdd=0
    set /A EvenOddRet=0
    set /A Calc=0

    REM Cheat so we know if the output is correct.
    set /A mval = %1 * %2

    REM Decide if we're going to use the given numbers...
    Set /A EvenOdd = %m1%
    goto FindEvenOdd

    REM Begin the loop
    :Start

    REM Odd Numbers are added to the accumulator
    REM Even numbers are displayed but not used
    if %EvenOddRet% equ 0 echo '--- %m1% x %m2%'
    if %EvenOddRet% equ 1 echo ' %m1% x %m2%'
    if %EvenOddRet% equ 1 set /A Calc = calc + %m2%

    REM Divide m1; multiply m2
    set /A m1 = (%m1% / 2)
    set /A m2 = %m2% * 2

    REM Reset the storage to the current number
    Set /A EvenOdd = %m1%

    goto FindEvenOdd

    REM Jump back after determining Even/Odd
    :Back

    REM if m1 is zero or less we're done; print the totals...
    if %m1% GTR 0 goto Start

    echo 'Answer: %mval%'
    echo 'Calc : %Calc%'
    pause

    REM Subtract 10 from the current number until we have a single digit
    REM then hit the brute force code to see if it's even/odd
    :FindEvenOdd
    if %EvenOdd% GTR 9 set /A EvenOdd = %EvenOdd% - 10

    if %EvenOdd% GTR 9 goto FindEvenOdd

    if %EvenOdd% EQU 0 Set /A EvenOddRet = 0
    if %EvenOdd% EQU 1 Set /A EvenOddRet = 1
    if %EvenOdd% EQU 2 Set /A EvenOddRet = 0
    if %EvenOdd% EQU 3 Set /A EvenOddRet = 1
    if %EvenOdd% EQU 4 Set /A EvenOddRet = 0
    if %EvenOdd% EQU 5 Set /A EvenOddRet = 1
    if %EvenOdd% EQU 6 Set /A EvenOddRet = 0
    if %EvenOdd% EQU 7 Set /A EvenOddRet = 1
    if %EvenOdd% EQU 8 Set /A EvenOddRet = 0
    if %EvenOdd% EQU 9 Set /A EvenOddRet = 1

    GOTO Back
  • Corpsegrinder 2009-07-23 19:20
    Here´s my solution in PROLOG:

    russian_mul(X,1,Erg):-
    !, Erg = X.

    russian_mul(X,Y,Erg):-
    1 is Y mod 2,
    YHalf is Y // 2,
    XDouble is X * 2,
    russian_mul(XDouble, YHalf, RekErg),
    Erg is X + RekErg.

    russian_mul(X,Y,Erg):-
    0 is Y mod 2,
    YHalf is Y // 2,
    XDouble is X * 2,
    russian_mul(XDouble, YHalf, RekErg),
    Erg = RekErg.
  • Moe 2009-07-23 19:25
    A proper 6502 assembler solution.

    Features:
    - multiplies two 8-bit numbers with 16 bit result
    - inner loop of only 17 clock cycles per iteration
    - worst case behaviour of 40 clock cycles per iteration
    - minimizes number of iterations
    - total execution time: 25 - 320 cycles
    (i.e. only 3x slower (worst case) than MUL on Intel 8088)
    - 43 bytes size
    - relocatable to about anywhere in address space
    - uses C64-friendly memory locations


    ; INPUT = op1 in A, op2 in X
    ; OUTPUT = low byte in X, high byte in Y
    ; memory locations used as temp space = $fb, $fc, $fd
    stx $fc ; save op2
    cmp $fc ; compare both operands
    bcc noswap ; swap them unless op1 < op2
    sta $fc ; save op1 instead of op2
    txa ; swap op2 for op1
    noswap:
    ldx #$00 ; prepare result low byte
    stx $fd ; clear high byte of op2
    ldy #$00 ; prepare result high byte
    beq begin ; skip shift of op2 for first iteration

    loop:
    asl $fc ; multiply op2 by 2, low byte
    rol $fd ; multiply op2 by 2, high byte
    begin:
    lsr ; divide op1 by 2
    bcs add ; if op1 was odd before division, add op2
    bne loop ; if op1 is not zero repeat loop
    rts ; otherwise return result

    add:
    sta $fb ; save current value of op1
    clc ; prepare addition
    txa ; fetch low byte
    adc $fc ; add op2, low byte
    tax ; store low byte
    tya ; fetch high byte
    adc $fd ; add op2, high byte
    tay ; store high byte
    lda $fb ; restore op1
    bne loop ; if op1 is not zero repeat loop
    rts ; otherwise return result
  • mol1111 2009-07-23 20:56
    I created index of all entries. Languages sorted by their name, entries sorted by order in which they appear. If you cannot find your entry, look in the "Other" (for languages with only one entry) or "Unspecified" (if you have not specified language and it was not easily deductable).

    ABAP
    dv 277800
    Someone 277998 278677

    APL
    Captain Obvious 277817
    Steve the Cynic 278029 278054

    Assembler
    Dascandy x86, ARM 277793
    Bosshog 6502 277804 278103
    Stalker x64 277911
    kastein IA64 277930
    Bob Montgomery 6502 278147
    Lunkwill m68k 278154
    flax ARM 278263
    Kevin Kofler m68k 278381
    Gumpy Guss PDP-8 278418
    bd_ Rabbit 2000 278438
    Chris Walton x86 278499
    C x86 278562
    Anonymous ARM 278710
    Moe 6502 279053

    BASIC
    Alex Papadimoulis VBScript 277748
    Kees QB/VB ? 277803
    Takis VB.Net 277814
    RayS VBA 277842 278407
    djjeavons VB.Net 277887
    Slinky VB? 278001
    antelopelovefan VBA 278068
    JoLoCo Sinclair 278126
    Yorick Sinclair 278372
    bluebearr AutoIt 278460
    James VBA 278489
    Don Knisley VBA 278534
    k1 278548 278550
    Takis VB.Net 278799
    some VBA coder VBA 278862

    bc/dc
    Nick Pope 277951 278207

    brainfuck
    Qwertyuiopas 278037
    Eyrieowl 278241
    Philipp 278837

    Brilliant
    Paula 277801

    C/C++
    Tim 277783 277784
    Larry H. 277798
    Stefan 277813
    Zombywuf templates 277815
    darkwraith 277832
    KimmoS 277850
    KnoNoth 277851
    whileloopsareugly 277873
    TerraNova 277876
    YES WE CAN! 277912
    little3lue templates 277914
    GWO 277924 277962 277964 277965
    ponky 277952 278066
    hh10k 277969
    shub 277985 278055
    _flt 278003
    Harleqin 278009
    Zor 278046 278053 278059
    Kman templates 278062 278880
    Fooba 278100
    serg 278113
    hornet 278173 278191
    Bored 278175
    xtremezone 278176 278190 278205
    Haggis 278189
    Ronuk Raval 278209
    Alan Woodland templates 278240
    Михаил 278267
    OmnipotentEntity 278270
    MG 278284
    Resistance Assembler 278321
    Rob Hulswit templates 278329 278331
    mxsscott 278342
    Rob H 278352
    J.I. 278356
    Sam 278391
    spiderlama 278416
    0ffh 278451
    Chris Walton 278499
    demo templates 278528
    khahem 278731
    Mr. Black 278769
    n1L templates 278844
    markwhi 278906 278908
    Lightnix 278994
    TP 279023

    C#
    Jay 277786
    Dopefish 277788
    Brettm 277812
    Dan 277834 277856
    Damien 277843
    Felix Ungman 277867
    GM 277894
    Fabio Lima 277922 277957
    Osno 277972 277997 278021
    groknroll 277980
    campkev 277991 277994 278078 278081
    Sean Handley 277995
    Oliver Klozoff 278000
    WraithShade 278057
    Floyd LINQ 278082
    chriswatson LINQ 278106
    Codism LINQ 278139
    Jared Youtsey 278149
    David C. 278161 278226
    jeff.woodhull LINQ 278201
    It'sMe 278203
    Shiftyness 278236
    stannius LINQ 278261
    blueberry 278286
    VirtualBlackFox LINQ 278292
    nine 278293
    TNProgrammer 278302
    dontera 278324
    The Answer + 2 278328
    hornet threads 278340
    Rob H 278352
    Lernin ur codez 278376
    PatrickBeebe 278393
    Veryth LINQ 278433
    brian 278450
    Thomas Eyde 278456
    Joel 278461
    joeyadams 278471
    jnz 278473
    JXO 278474
    czetts 278846
    HCGL 278911
    Jeremy Burns 278922
    PatrickBeebe 278974
    Paul N 278983

    D
    Rief 278006
    Quxxy 278069

    Erlang
    Mike McNally 278434 278440
    MichaelWH 278877
    John Stracke 279008

    F#
    darklajid 277890 277941 278137
    Patrick Simpson 278127
    ajp 278357 279029
    cmugford 278486

    FORTRAN
    rst 277978
    java.lang.Chris; 278266

    Groovy
    Matt 277949

    Haskell
    freako 277838
    Dave Ingram 277839
    Sebastian Paaske Tørholm 277870
    HypocriteWorld 277878
    Maxim 277889
    Noah Easterly 278130
    semanticprecision 278170
    Andrew Nurse 278198
    Jonas Kramer 278220
    ikorb 278299
    valderman 278405 278406
    Twey 278439
    Joost 278567
    jefu 278838
    dub 278874
    iggy 278935
    vog 279045
    MichaelWH 279047

    Java
    Cookie 277785
    Jay 277786
    Mat Rantell 277802
    Will 277831
    Drew 277844
    Arjan 277879
    Philipp 277903 277919
    Kook 277963 277968
    imhe 278105 278138
    Jannik Jochem 278115
    Thuktun 278124
    idle 278128
    klagdon 278131 278242
    amischiefr 278152
    Greg R 278212 278231
    Davi Cavalcanti 278228
    DeepThought 278230
    bb 278235
    cincinnatvs 278237
    Fred Dagg 278408
    subanark 278537
    Rorick 278749
    Queex 278761
    Coyne 278892

    Javascript
    Zishan 277882
    Jason Knight 277898
    Mestafais 278005
    Markus Persson 278039
    jjs105 278136
    jonnyq 278208
    Phroggy 278221
    astonerbum 278248 278264 278343
    Scott 278294
    Beat by the system 278319
    Rob Hulswit 278329
    Jeb Walter Strate 278345
    Crindigo 278419
    Chris 278484

    LISP
    newlisp.org newLISP 277861 278283
    MP 2778711
    leppie Scheme 277881
    dee Scheme 277900
    Éibhear Emacs 277910
    Dmitri Savichev Scheme 277992 277999
    lyml Scheme 277996
    Harleqin Common Lisp 278009
    Alex Muscar Common Lisp 278090 278096 278160 278514 278516
    Trey Jackson Emacs 278194
    Bob Scheme 278206
    samanddeanus Scheme 278271
    asdfghj Scheme 278311
    guille_ 278317
    Ted Walther, newLISP fan newLISP 278344 278986
    unit3 Common Lisp 278417
    noSignal Scheme 278469
    iamtim2 newLISP 278491
    jvmbsd7 Scheme 278493
    Chris Judge 278868
    samanddeanus Scheme 278998

    LOLCODE
    JaguarOne 277920
    PopeHappyCat 278099

    Lua
    Stefan 277854
    Will 278010
    Tiogshi 278368
    Methuselah 278675

    MSIL
    Osno 278153 278197 278729 278786 278801

    Other
    hydrus Clojure 277792
    db2 HP 48 277857
    Dave Ingram vimscript 277862
    pjt33 SML 277864
    SR ColdFusion 277896
    Will MUSH 277942
    Samuel A. Falvo II Forth 277976
    Sal Postscript 278093
    acsi Spreadsheet 278150
    Cindi Knox mIRC 278174
    MUMPS MUMPS 278211
    Trurl MUMPS 278246 278255
    darkscout Matlab 278298
    treyb Excel 278300
    Roger RPGLE 278337
    Tom Medley - www.tommedley.com ML 278350
    ikegami circuit diagram 278370
    dee COBOL 278403
    yowzer ocaml 278428
    J Mathematica 278467
    StarLite Progress V9 278583
    Ralf Smalltalk 278794
    Rorick Rebol 278810 278873
    Whatever Befunge-93 278988
    Rusty Nail Verilog 279040

    Pascal
    Azeroth 277837
    malach Delphi 277860
    baka0815 277868 277877 278020 278028 278065
    DougB Delphi 278179
    Trevor Dubinsky Delphi 278229
    mol1111 Turbo Vision 278374

    Perl
    Me 277807 277845
    epv 277849
    Steven de B 277884
    WarheadsSE 277944 278061
    Anonymous 277977
    tirerim 278119
    John Evans 278141
    Jim Halfpenny 278143
    Igor V. 278199
    Darren 278223
    Warr regex 278260 278420
    qoo3h 278353
    Andrew Rodland 278358
    H2 278388
    Florent 278401 278404
    Toby Gray 278538 278540
    bugmonkey 278658
    rjp 278714
    Maurits 279046

    PHP
    The Wolf 277787 277799
    Erin 277797
    Clark S 277858 277872
    Ryan 277863
    Daniel 277904 277909
    FatherStorm 277932
    aBase 278036 278214
    John Evans 278141
    HonoredMule 278158 278168 278184
    IcePanther 278195
    Tim 278196
    Paul 278265
    LeCoyote 278396
    mjomble 278413
    mneimeyer 278524
    LatecomerX 278617 278673
    bugmonkey 278658
    Evo 278886 278934
    AngeloR. 278960

    Prolog
    Anonymous Coward 277938
    Mike5 278204
    A.T. 278641 278646
    Corpsegrinder 279051

    Python
    ath 277789 277806 278244
    phihag 277811 277818 277869
    Fenris 277823
    Jeff Kemp 277852 277940
    Tempura 277875
    Stalin 277880
    Jim 277901
    Eutactic 277915
    RECURSIVEMAN 277916
    rob tracey 277917
    krat 277918
    drBeat 277925
    ross 277931
    halber_mensch 277936 277943 277955 277979 278129
    Real russian peasant :) 277974
    Remy 278004
    Billy 278007
    Josh Bohde 278017 278080 278092 278104 278166 278854
    Wulf0r 278024
    Jürgen 278086
    koblas 278101
    Rob W. 278111
    Chad M 278132
    Jörg 278163
    martinp 278172
    JJM 278193
    Ronuk Raval 278209
    lostlogic 278222
    SoaperGEM 278305
    ZzzZZZz 278318
    Lee Crabtree 278355
    sdeek 278359
    opussf 278364
    KukkerMan 278366
    Edinburgh Mike 278375
    mwchase 278395
    Adrian 278402
    Jukka 278412
    tdh 278444
    Mr.'; Drop Database -- 278459
    agrif 278497
    Python 278688
    Lom 278732
    the real wtf fool 278842
    workmad3 278975
    inky 278996
    Scott 279009

    Ruby
    arnemart 277825 277855
    Mike Dotterer 277829
    exo 277926
    Nicholas Laux 277958 277971
    Xthlc 277983 278026
    derula 278050
    Amadan 278071
    Northpole 278072
    jweir77 278079
    Jürgen 278086
    Dave Havlicek 278122
    Jeremy Weathers 278216
    Chewbie 278224
    Jimmy Selgen 278367
    Redredredredredred 278380
    Pony Princess 278967

    Scala
    Alex Ciarlillo 277937
    Ian McLaird 278023
    Matt 278249
    Unlabeled Meat 278332
    juancn 278962
    Landei 279042

    Shell
    mat BASH 277791
    bluebearr Batch 278012 278243
    Ken B Batch 278032
    moltonel BASH 278262 278272 278282
    Julian Calaby BASH 278485
    The_Assimilator PowerShell 279028
    andyesslinger Batch 279049

    SQL
    SQLDork 277795
    KnowOracle Oracle 277816 277822 277824
    Chris Hunt Oracle 277836
    csulli13 277888
    MeesterTurner T-SQL 277959
    wombat T-SQL 278186
    shane blake T-SQL 278210
    Dave Havlicek PL/pgSQL 278322
    Bodestone 278341
    DFHawthorne Oracle 278409
    Paul N T-SQL 278425 278427
    Hidayat Oracle 278526
    SlyEcho 278535
    Boneist Oracle 278555
    EJCorcoran T-SQL 278795
    dee MySQL 279007

    Tcl/Tk
    Albrecht from Germany 278142 278145

    Unspecified
    Z 277796
    Matthew Verleger 277827
    ruckc 277828
    cwink 277899 277905
    Bob 277907
    avl 277929
    Jonathan 277967
    buzkie 277984
    Alex Guzman 278084
    SimonY 278120
    David Young 278185
    Humanoid Life-form 278238
    aef123 278245 278247
    Josue Chi 278303
    Michael Clark (mjac.co.uk) 278360
    Eric 278371
    Wheaties 278426
    astander 278544
    col obvious 278598
    Alex 278628

    XSLT
    Dave van der Brugge 278133
    wombat 278808


    Addendum (2009-07-24 02:26):
    jnz 278473 should be in C/C++ category.
  • mol1111 2009-07-23 21:25
    Yorick:
    Speccy basic, recursive:

    10 DEF FN m(a,b)=VAL ((("FN m(
    "+STR$ a+"*2,INT ("+STR$ b+"/2))
    +("+STR$ b+"-2*INT ("+STR$ b+"/2
    ))*"+STR$ a) AND b<>1)+(STR$ a A
    ND b=1))



    C Nonsense in BASIC, 20:1
  • jnz 2009-07-23 22:20
    mol1111:
    I created index of all entries.

    Wow, that must have taken a lot of work.

    mol1111:
    C#
    ...
    jnz 278473

    My entry should be in the C/C++ section.
  • dysfunctor 2009-07-23 22:44
    This seems like a good opportunity to show the world why Haskell is interesting. I'll write several implementations.

    We'll need some import statements:
    import Control.Monad.State
    
    import Test.QuickCheck

    Unit tests

    Where would we be without unit tests, eh? QuickCheck is a really cool library that automagically generates lots of test-cases for you.

    Here's our generic test case. We write it as a function called prop_russian_multiplication with arguments mul, n1 and n2. mul is the multiply function we want to test. We leave it as a parameter because we will want to test several different implementations. When we run QuickCheck it evaluates prop_russian_multiplication with lots of random numbers for n1 and n2, checking that it is always True:
    prop_russian_multiplication mul n1 n2 =
    
    n1 >= 0 ==> -- Only generate test cases with n1 >= 0
    n1 `mul` n2 == n1 * n2 -- The property to test
    -- This line doesn't do anything, but it gives QuickCheck
    -- some hints.
    where types = (n1 :: Integer, n2 :: Integer)

    Syntax notes: Whitespace (indents and newlines) is significant. "--" marks comments. Backticks (`) are syntactic sugar that let us write a prefix function (mul n1 n2) as an infix (n1 `mul` n2).

    Iterative style

    Haskell is a pure functional language, so it doesn't let you modify variables. If it did, we could write code like:
    russian_multiply n1 n2 =
    
    total := 0
    while (n1 > 0)
    if (odd n1) total += n2
    n1 := n1 `div` 2
    n2 := n2 * 2
    return total

    We can't do that, but we can cheat! We can write an auxiliary function called loop with arguments total, n1 and n2. loop can modify n1, n2 and total by calling itself with modified values, like this:
    russian_multiply_iterative n1 n2 = loop n1 n2 0
    
    where
    -- First the special case where n1 == 0.
    loop 0 n2 total = total -- We're done here. total is the answer
    -- Now the general case.
    loop n1 n2 total = loop (n1 `div` 2) -- new value for n1
    (n2 * 2) -- new value for n2
    (if (odd n1) then total + n2 else total)
    -- new value for total

    Then (here's the cool part) the compiler will notice that this is equivalent to a loop that modifies local variables. After the compiler has worked its magic, we have code exactly the same as the pseudo-code I wrote earlier. loop really is a loop! (This is known as tail-call optimisation, and is a requirement in the Haskell 98 standard.)

    List style

    This most closely matches the way the Russian peasant would really do it. It is also, perhaps, the most Haskell-ish way.

    To solve 18 x 23, we first generate the list [18, 9, 4, 2, 1] (called halves) and the infinite list [23, 46, 92, ...] (called doubles). (Haskell is lazy, so infinite lists are fine. Haskell constructs only as much of the list as is needed.) Haskell's powerful list-processing syntax and libraries can do the rest in a single line:
    russian_multiply_lists n1 n2 =
    
    sum [d | (h, d) <- zip halves doubles, odd h]
    where
    halves = f n1
    where
    f 0 = []
    f n = n : f (n `div` 2)
    doubles = iterate (* 2) n2

    Here's another cool thing. As I said earlier, Haskell constructs the lists on demand, but the elements of the list are consumed as soon as they are produced. A smart compiler will notice that the lists are just intermediaries between a producer and consumer, and cut out the middle man. Ultimately, we end up with object code that is exactly the same as for the iterative version!

    Why does this matter? Well, the "natural" way to do it is the list way. That's how the Russian peasant does it. But the most efficient way to do it is the iterative way. Of course, any half-decent programmer knows this already, and writes his code the efficient way, but if he is a Haskell programmer, he doesn't need to. The compiler is smart enough to figure it out for him.

    This technique for eliminating intermediate data structures is, known as deforestation. It is based on a deep, mathematical relationship between Data Structures (lists, in this case) and Algorithms (iteration) known as a hylomorphism.

    Monadic style

    I told a small lie earlier. Haskell does let you modify variables, but only in carefully controlled circumstances. You have to wrap it all in a thing called a Monad. There's more deep maths involved, and it's hard to get your head round, but here's a simple example using the State Monad.

    This code is similar to the iterative code, except that instead of total we have state. The state only exists within stateful_loop. execState initialises the state of (stateful_loop n1 n2) to 0, runs it, and then returns the final state.
    russian_multiply_monadic n1 n2 =
    
    execState (stateful_loop n1 n2) 0
    where
    stateful_loop n1 n2 =
    -- We're done here.
    -- () is a dummy value; it's the state we want
    if n1 == 0 then return ()
    else do
    -- if n1 is odd modify the state
    when (odd n1) $ modify (n2 +)
    -- repeat the loop with new n1 and n2
    -- but keeping the same state
    stateful_loop (n1 `div` 2)
    (n2 * 2)

    This code might be equivalent to the iterative code ... but I'm not sure. Monads can be tricky. But very powerful. Monads are a principled way to implement things like: non-determinism, really smart parsing libraries, I/O, and much more besides.

    Running it
    main = do
    
    quickCheck $ prop_russian_multiplication russian_multiply_iterative
    quickCheck $ prop_russian_multiplication russian_multiply_lists
    quickCheck $ prop_russian_multiplication russian_multiply_monadic
    putStrLn $ "18 x 23 = " ++ show (18 `russian_multiply_lists` 23)

    Which should give the output:
    OK, passed 100 tests.
    
    OK, passed 100 tests.
    OK, passed 100 tests.
    18 x 23 = 414
  • Moritz 2009-07-23 22:51
    import scala.annotation.tailrec
    
    def rpmul(a : Int, b : Int) : Int = {
    if (a < 0) {
    if (b < 0) rpmul(-a,-b) else -rpmul(-a,b)
    }
    else if (b < 0) -rpmul(a,-b)
    else {
    val (x,y) = if (a > b) (b,a) else (a,b)
    @tailrec def f(a : Int, b : Int, result : Int) : Int =
    if (a == 0) result
    else f(a>>1, b<<1, result + (a & 1) * b)
    f(x, y, 0)
    }
    }


    Scala 2.8 trunk - remove @tailrec and import for 2.7.
  • Greg 2009-07-23 23:14
    didn't look too hard, but didn't see any awk solutions. how about:

    awk 'NF==2{t=0;x=$1;y=$2;while(x>=1){if(x%2==1){t+=y}x=int(x/2);y=y*2}print t}'

    just feed in 2 numbers per input line
  • zcl 2009-07-23 23:22

    Yes ,your article is very good, we have the same belief with you,so let me introduce the area to you.Now Juicy Jewelry become more adn more popular within all kind of people. Juicy couture is a kind of juicy series . It won a good reputation. Juicy sale often held its regular discount juicy activities,such as juicy charms,juicy couture charms and so on.In these activities juicy couture sale got great success. juicy couture consists of two main aspects, juicy couture jewelry and juicy couture accessories
    Juicy couture series are worthwhile than other juicy on sales. They have a lot of discounted jewelry,for example discount Juicy Couture necklaces, juicy earrings , juicy bracelets and rings on sale. Benefit from the discount,you can get juicy jewelry save up to 30%, We assure you of our best services at all times.
  • Kenneth Pullen 2009-07-24 00:01
    It's not much, but here was my solution. Copy this into a .lua and watch the magic!

    -- rpc.lua
    -- the russian peasant calculator
    -- http://thedailywtf.com/Articles/Programming-Praxis-Russian-Peasant-Multiplication.aspx

    function iterate_calculation(num1, num2, racetrack)
    accumulator = 0
    racetrack = racetrack or {}
    table.insert(racetrack, {num1 = num1, num2 = num2})

    num1 = math.floor(num1 / 2)
    num2 = math.floor(num2 * 2)

    if num1 >= 1 then
    iterate_calculation(num1, num2, racetrack)
    else
    for key, value in ipairs(racetrack) do
    if (value.num1 % 2) == 0 then
    value.num2 = 0
    end
    end
    for key, value in ipairs(racetrack) do
    accumulator = accumulator + value.num2
    end
    end
    return accumulator
    end

    if not arg[1] then
    print("Usage: " .. arg[-1] .. " " .. arg[0] .. " num1 num2")
    os.exit()
    end

    print(arg[1] .. " x " .. arg[2] .. " = " .. iterate_calculation(arg[1], arg[2]))
  • DBA_In_OKC 2009-07-24 00:50
    MSSQL 2005/2008. No loops, only CTE recursion.

    CREATE TABLE #operands (leftval int, rightval int);
    INSERT #operands SELECT 18, 23;

    WITH russians (leftval, rightval) AS (
    SELECT leftval / 2, rightval * 2
    FROM #operands
    UNION ALL
    SELECT leftval / 2, rightval * 2
    FROM russians
    WHERE leftval > 0
    )

    SELECT SUM(rightval)
    FROM russians
    WHERE leftval % 2 = 1;

    DROP TABLE #operands;

    Addendum (2009-07-24 00:59):
    Sorry, should be
    ...
    WITH russians (leftval, rightval) AS (
    SELECT leftval, rightval
    FROM #operands
    ...

    in case the first value is odd...
  • derari (was A.T.) 2009-07-24 02:08
    As there were complaints about the maintainability of the solutions, I added some comments.

    %% russian(?A,?B,?P)
    %% Multiplies A and B the russian style and unifies the result with P.
    %% All parameters may be variables.
    russian(A,B,P) :-
    % validate that all args are variables or positive integers
    (var(A);integer(A),A>=0),
    (var(B);integer(B),B>=0),
    (var(P);integer(P),P>=0), !,
    do_crazy_table_stuff(A,B,P).

    %% do_crazy_table_stuff(?A,?B,?P)
    %% does the crazy table stuff
    do_crazy_table_stuff(A,B,P) :-
    % If one of the factors is a variable, I prefer if it's the first one.
    nonvar(A), var(B), !, do_crazy_table_stuff(B,A,P).
    do_crazy_table_stuff(A,B,P) :-
    % A is a value, B as well. Thus, there is exactly one result P.
    nonvar(A), !, row(A,B,P,0,P), !. % <-- Therefore, here is a cut.
    do_crazy_table_stuff(A,B,P) :-
    % A is a variable, B is not -> many results
    nonvar(B), !, row(A,B,P,0,P).
    do_crazy_table_stuff(A,B,P) :-
    % A is a variable, B as well -> even more results
    % make sure P is initialized somehow
    length(_,P), between(0,P,B), row(A,B,P,0,P).

    %% row(?A,+B,?P,+N,?R).
    %% A single row of the multiplication table
    %% A: factor 1 in this row; B: factor 2 in this row
    %% P: Result of the multiplication (only set if provided externally)
    %% N: Number of current row, starting at 0
    %% R: Result so far (sum of rows >= N where A is odd)
    row(_,_,P,N,_) :-
    % if P is provided, end recursion if N is just too big
    nonvar(P), P < 1<<(N-1), !, fail.
    row(0,_,_,_,0). % if A is 0, the result should be 0 as well
    row(A,B,P,N,R) :-
    % before caring about this row, solve the next
    row(Ax,B<<1,P,N+1,Rx),
    % of course, this A should be twice as big
    halve(A,Ax,Rem),
    % add B to result if A is odd
    R is Rx+B*Rem.

    %% halve(-X2,+X,-Rem)
    %% Ensures that X is halve the size of X2,
    %% the remainder is stored in Rem (1 if X2 is odd, 0 else)
    halve(1,0,1) :- !. % X and X2 being zero is not allowed
    halve(X2,X,Rem) :- (Rem=0;Rem=1), X2 is X*2+Rem.
    Examples:

    ?- russian(18,23,Z). % Z = 414;
    ?- russian(18,Y,414). % Y = 23;
    ?- russian(X,23,Z). % X = 1, Z = 23; X = 2, Z = 46; ...
    ?- russian(X,Y,414). % X = 1, Y = 414; X = 2, Y = 207; ...
    ?- russian(X,Y,Z). % X = 0, Y = 0, Z = 0; X = 1, Y = 1, ...
  • mol1111 2009-07-24 02:26
    jnz:

    mol1111:
    C#
    ...
    jnz 278473

    My entry should be in the C/C++ section.

    Sorry for the mistake. I guess it isn't the last one but I had no energy to check the results :-)
  • astander 2009-07-24 02:38
    45 X 76 is uneven, so you add 76 to start with
  • Boombuler 2009-07-24 03:23
    Ok here is one more Brainfuck version. This one has comments ;)

    ++++++> # A=6 (Input 1)
    ++++++++++++< # B=12 (Input 2)
    [ # While (A <> 0) {
    >>>[-]>[-]>[-]>[-]<<<<<< # D = 0; E = 0; F = 0; G = 0;| P = A
    [>>>+>+>+<<<<<-] # D = A; E = A; F = A; A = 0;
    >>>>>[-<<<<<+>>>>>]< # A = F; F = 0;
    [-[->+<[>>+<<-]]>>[<<+>>-]<<] # F = E / 2; E = 0; G = 0;
    >[-<+>]< # E = F; F = 0;
    [>++<-]>[<+>-]< # E = E * 2; F = 0;
    >>[-]<<< # G = 0;
    >[-<->]< # if (D != E)
    [ # {
    [-]<< # D = 0
    [>+>+<<-] # C = C (plus) B; D = B; B = 0;
    >>[-<<+>>] # B = D; D = 0;
    ] # }
    <<[>>++<<-]>>[-<<+>>]>[-] # B = B * 2; D = 0;
    <<<<[-[->>>+<<<[->>>>+<<<<]]>>>>[-<<<<+>>>>]<<<<] # D = A / 2; A = 0; E = 0;
    >>>[-<<<+>>>]<<< # A = D; D = 0;
    ] # }
    >>. # Output as Ascii (H = 66)
  • symcbean 2009-07-24 03:57
    A major shortcoming of all the examples I've looked as the insistence on using base 10 operations - this smacks of a distinct lack of under-engineering and foresight on the part of the developers. My code can use any radix which can be represented by a single character per digit:

    <?php

    // $digits=array('0','1','2','3','4','5','6','7','8','9'); // decimal
    $digits=array('0','1'); // binary
    // $digits=array('0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'); // hexadecimal
    // $digits=array('.','!','$','%','^','*','{','>'); // wtfimal

    $a=$argv[1];
    $b=$argv[2];

    $reverse_digits=array_flip($digits);
    $base=count($digits);
    $pairs=array();
    $even=array();

    for ($offset=0; $offset<count($digits); $offset++) {
    $even[]=$digits[$offset++];
    }

    praxis_gen_pairs($a, $b);
    $out=praxis_reduce_pairs();

    print "$a x $b = $out\n";
    exit;

    function praxis_gen_pairs($a, $b)
    {
    global $pairs, $digits;
    $pairs[]=array($a, $b);
    $a=praxis_half($a);
    $b=praxis_double($b);
    if ($a!=$digits[0]) {
    praxis_gen_pairs($a, $b);
    }
    }

    function praxis_double($x)
    {
    global $digits, $reverse_digits, $base;
    $out='';
    $carry=0;
    for ($i=strlen($x)-1; $i>=0; $i--) {
    $new_offset=$reverse_digits[$x[$i]]+$reverse_digits[$x[$i]]+$carry;
    $carry=0;
    if ($new_offset>=$base) {
    $carry=1;
    $new_offset=$new_offset % $base;
    }
    $out=$digits[$new_offset] . $out;
    }
    if ($carry) $out=$digits[$carry] . $out;
    return praxis_tidy($out);
    }

    function praxis_half($x)
    {
    global $digits, $reverse_digits, $base, $even;
    $out='';
    $carry=0;
    for ($i=0; $i<strlen($x); $i++) {
    $offset=(integer)(($reverse_digits[$x[$i]] + $carry)/2);
    $carry=0;
    if (!in_array($reverse_digits[$x[$i]], $even)) {
    $carry=$base;
    }
    $out.=$digits[$offset];
    }
    return praxis_tidy($out);
    }

    function praxis_reduce_pairs()
    {
    global $pairs, $even, $digits;
    $out=$digits[0];
    foreach($pairs as $offset=>$val) {
    // is it even?
    $digit=substr($val[0],-1);
    if (in_array($digit, $even)) {
    unset($pairs[$offset]);
    } else {
    $out=praxis_add($pairs[$offset][1], $out);
    }
    }
    return $out;
    }

    function praxis_add($a, $b)
    {
    global $digits, $reverse_digits, $base;
    if (strlen($a)<strlen($b)) {
    $x=$a;
    $a=$b;
    $b=$x;
    }
    while (strlen($b)<strlen($a)) {
    $b=$digits[0] . $b;
    }
    $carry=0;
    $out='';
    for ($x=strlen($a); $x>0; $x--) {
    $offset=$reverse_digits[$a[$x-1]] + $reverse_digits[$b[$x-1]] + $carry;
    if ($offset>=$base) {
    $carry=1;
    $offset-=$base;
    } else {
    $carry=0;
    }
    $out=$digits[$offset] . $out;
    }
    if ($carry) $out=$digits[$carry].$out;
    return praxis_tidy($out);
    }

    function praxis_tidy($a)
    {
    global $digits;
    while ((substr($a,0,1)==$digits[0]) && (strlen($a)>1)) {
    $a=substr($a,1);
    }
    return($a);
    }
    ?>
  • Yorick 2009-07-24 05:42
    mol1111:
    C Nonsense in BASIC, 20:1

    Do you mean it didn't work when you tried it? I may have made a mistake when transcribing it from the emulator window, but I think I checked it thoroughly. If you type it in, please take care to use tokens for DEF FN, VAL, FN, STR$, INT, AND and <> instead of spelling them out.
  • Marlon 2009-07-24 05:48
    A False implementation!

    0 23 18 [$0>][$[$1>][2-]#1=[@@$@+@@\]?2/\2*\]#%%.
  • Marlon 2009-07-24 06:17
    And the ugly simple False implementation...

    18a:23b:0[a;$2/2*=~[b;+]?a;1>][a;2/a:b;2*b:]#.
  • Yorick 2009-07-24 06:25
    Perl, entirely without arithmetic.

    ($_,$b)=map{'.'x$_}@ARGV;
    /^(.+)\1(.?)$/,($_,$b,$c)=($1,$b.$b,$c.($2&&$b))while/../;
    print length$b.$c;

  • ClaudeSuck.de 2009-07-24 06:36
    Matthew Verleger:
    int RussianSum( int A, int B ){
    return A ? RussianSum(A>>2,B<<2) + (!!(A&1))*(B): 0;
    }


    "RussianSum(A>>2,B<<2) + (!!(A&1))*(B): 0;" looks more like a swearing Russian @!#&^$
  • Marlon 2009-07-24 06:40
    Finally the most aesthetic esoteric False version:

    0 23 18 [$$2/2*\-[@@$@+\@]?$1>][2/\2*\]#%%.
  • mol1111 2009-07-24 07:02
    Yorick:
    mol1111:
    C Nonsense in BASIC, 20:1

    Do you mean it didn't work when you tried it? I may have made a mistake when transcribing it from the emulator window, but I think I checked it thoroughly. If you type it in, please take care to use tokens for DEF FN, VAL, FN, STR$, INT, AND and <> instead of spelling them out.


    Sorry, it was my mistake, I had not used tokens for keywords inside strings. Now it works perfectly! Great job! And I thought that deffn is useless...
  • cofiem 2009-07-24 08:31
    Javascript version:

    <!DOCTYPE html>
    <html>
    <head>
    <title> Russian Peasant Multiplication</title>
    <script>
    function RussianMultiply(num1, num2){

    var total = 0;
    var easymultiply = num1*num2;

    while(num1 > 0){
    var newNum1 = Math.floor(num1/2);
    var newNum2 = num2*2;
    if(Math.floor(newNum1/2) != newNum1/2){
    total += newNum2;
    }
    num1 = newNum1;
    num2 = newNum2;
    }
    document.getElementById('results').innerHTML += "Russian result: "+total+" ("+easymultiply+")<br>";
    }

    </script>
    </head>
    <body>
    <div id="results"></div>
    <script>
    RussianMultiply(18, 23);
    RussianMultiply(0, 1);
    RussianMultiply(4, 100);
    RussianMultiply(8, 56);
    RussianMultiply(100, 0);
    </script>


    </body>
    </html>
  • Corpsegrinder 2009-07-24 08:44
    And a solution in AppleScript


    set res to 0
    display dialog "First value:" default answer "" buttons {"OK"} default button 1
    set firstVal to text returned of the result
    display dialog "Second value:" default answer "" buttons {"OK"} default button 1
    set secondVal to text returned of the result


    repeat while secondVal is greater than or equal to 1
    if secondVal mod 2 is 1 then
    set res to res + firstVal
    end if
    set firstVal to firstVal * 2
    set secondVal to round secondVal / 2 rounding down
    end repeat

    display dialog res buttons {"OK"} default button 1

  • Corpsegrinder 2009-07-24 08:49
    and to provide negative multipliers add


    if secondVal is less than 0 then
    set firstVal to firstVal * -1
    set secondVal to secondVal * -1
    end if


    after the first two dialogs
  • PopeHappyCat 2009-07-24 09:13
    Another lolcode, this time following the letter of the challenge more than the spirit.

    LOLCODE 1.2X. Extends LOLCODE 1.2, by having a BUKKIT (array) and shift operators:
    SHIFTROFL <x> <y> BTW shift x right y bits
    SHIFTLOL <x> <y> BTW shift x left y bits



    HAI 1.2X
    OBTW THIS IS EXTENSHUN OF 1.2 IT HAS BUKKIT N SHIFT
    TLDR

    CAN HAS STDIO?

    I HAS A X
    I HAS A Y
    I HAS A MULTIPL

    VISIBLE "CAN HAS X?:)"
    GIMMEH X
    VISIBLE "CAN HAS Y?:)"
    GIMMEH Y

    X R MAEK X A NUMBR
    Y R MAEK Y A NUMBR

    HOW DUZ I RPM YR X AN YR Y
    I HAS A THING
    THING IS NOW A BUKKIT
    I HAS A MUTLIPL ITZ 0
    I HAS A DUMMY
    I HAS A COUNTR ITZ 0
    IM IN YR RPMLOOP UPPIN YR COUNTR WILE DIFFRINT X AN 1
    DUMMY R PRODUKT OF COUNTR AN 2
    THING[DUMMY] R X
    THING[SUM OF DUMMY AN 1] R y
    X R SHIFTROFL X AN 1
    Y R SHIFTLOL Y AN 1
    IM OUTTA YR RPMLOOP
    IM IN YR RPMLOOPAGAIN NERFIN YR COUNTR WILE BOTH SAEM COUNTR AN BIGGR OF COUNTR AN 0
    DUMMY R PRODUKT OF COUNTR AN 2
    X R THING[DUMMY]
    Y R THING[SUM OF DUMMY AN 1]
    MOD X AN 2
    BOTH SAEM IT AN 1, O RLY?
    YA RLY, MULTIPL R SUM OF MULTIPL AN Y
    NO WAI, BTW NOTHING HAPPENS
    OIC
    IM OUTTA YR RPMLOOPAGAIN
    FOUND YR MULTIPL
    IF U SAY SO

    MULTIPL R RPM X Y

    VISIBLE "PRODUKT OF " N X N " N " N Y N " IZ " N MULTIPL N ":)"

    KTHXBYE
  • asd 2009-07-24 09:14
    > perl wtf.pl 101 6
    606


    eval eval '"'.


    ('`'| '-'). ('['^'"').('{'^'[').'(' .'\\'.'$'.('`'|'!').','
    .'\\' .'$'. ('`'|'"').')'.('{'^'[') .'='.('{'^'[').'\\'.'@'
    .('`' ^'!') .('{' ^')') .('`'
    ^"'") .("\{"^ '-'). ';'.( "\`"|
    '-'). ('['^'"') .('{' ^'[') .'\\'.'$'.('['
    ^'/') .';'. ('['^ ','). ('`'| '(').('`'|')')
    .('`'|',' ).(('`')| '%'). "\(".
    ('\\'). ('$').( "\`"| '!').
    "\)". '\\'. "\{". '\\'.
    '$'.( "\["^ '/').'+'.'='.'\\'.'$'.( '`'|'"').'*'."\(".'\\'.
    '$'.( "\`"| '!').'&'.('^'^('`'|'/') ).')'.';'.'\\'.'$'.('`'
    |'!') .'>'. "\>". '='.( '^'^(
    "\`"| "\/")). "\;". '\\'. '$'.(
    "\`"| '"').'*'. '='.( '^'^( '`'|',')).'\\'
    .'}'. ('['^ '+'). ('['^ ')'). ('`'|')').('`'
    |('.')).( '['^'/'). ('{'^ '[').
    ('\\'). ('$').( "\["^ '/').
    ';'.( "\!"^ '+'). ('!'^
    '+'). "\""; $:='.'^'~';$~='@'|"\("; $^=')'^'[';$/='`'|"\.";
    ($,)= "\("^ '}';$\='`'|'!';$:="\)"^ '}';$~='*'|'`';$^="\+"^
    "\_"; ($/)= "\&"| "\@"; ($,)=
    "\["& '~';$\= "\,"^ "\|"; ($:)=
    "\."^ ('~');$~= "\@"| "\("; $^=')'^'[';$/=
    "\`"| "\."; ($,)= "\("^ "\}"; $\='`'|'!';$:=
    ')'^"\}"; $~=('*')| "\`"; ($^)=
    '+'^'_' ;$/='&' |'@'; ($,)=
    "\["& "\~"; ($\)= "\,";
  • Dascandy 2009-07-24 09:22
    flax:
    Nobody has submitted ARM code yet that I have seen. Does this win for smallest number of instructions?

    ; multiplicands in r0 and r1

    mov r2,#0
    loop
    movs r0,r0,lsr #1
    addcs r2,r1
    mov r1,r1,asl #1
    bne loop


    Yours is second (I posted mine way too soon) but it is shorter and probably better tested. You don't have a return though, which I do have. IIRC I only have one opcode more though, so that would be the return.
  • Tachyon 2009-07-24 09:29
    Slightly evil asp.net dynamicly created controls version. Why hasn't anyone done an asp.net version (yet)?

    using System;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Data;

    public partial class Default : Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {
    if (IsPostBack)
    {
    TextBox t1 = form1.FindControl("m1") as TextBox;
    TextBox t2 = form1.FindControl("m2") as TextBox;
    if ((t1.Text.Length > 0) && (t2.Text.Length > 0))
    {
    int mu1 = int.Parse(t1.Text);
    int mu2 = int.Parse(t2.Text);
    DataRow dr = d.Tables[0].NewRow();
    dr[0] = mu1;
    dr[1] = mu2;
    d.Tables[0].Rows.Add(dr);
    d.Tables[0].AcceptChanges();
    DoRussian();
    l1.Text = "Result is : ";
    int ret = 0;
    foreach (DataRow dre in d.Tables[0].Rows)
    {
    int fi1 = (int)dre[0];
    double fi = (double)fi1;
    double f = fi / 2;
    if (f != (fi1 / 2))
    {
    ret += (int)dre[1];
    }
    }
    l1.Text += ret.ToString();
    }
    }
    g.DataSource = d;
    g.DataBind();
    }

    protected override void OnInit(EventArgs e)
    {
    base.OnInit(e);
    Panel p2 = new Panel();
    Label m = new Label();
    m.Text = "Enter two numbers: ";
    TextBox m1 = new TextBox();
    m1.ID = "m1";
    m1.MaxLength = 3;
    TextBox m2 = new TextBox();
    m2.ID = "m2";
    m2.MaxLength = 3;
    m1.Text = "4";
    m2.Text = "6";
    Label s = new Label();
    s.Text = " &nbsp; &nbsp; ";
    Label s1 = new Label();
    s1.Text = " &nbsp; &nbsp; ";
    p2.Controls.Add(m);
    p2.Controls.Add(m1);
    p2.Controls.Add(s);
    p2.Controls.Add(m2);
    p2.Controls.Add(s1);
    Button b = new Button();
    b.Text = "Do it!";
    p2.Controls.Add(b);
    d.Tables.Add(new DataTable("Russian"));
    d.Tables[0].Columns.Add("First", typeof(int));
    d.Tables[0].Columns.Add("Second", typeof(int));
    g.CellPadding = 2;
    g.CellSpacing = 2;
    g.BorderWidth = 1;
    Panel p1 = new Panel();
    p1.Controls.Add(l1);
    form1.Controls.Add(p2);
    form1.Controls.Add(g);
    form1.Controls.Add(l1);
    }

    private GridView g = new GridView();
    private DataSet d = new DataSet();
    private Label l1 = new Label();

    private void DoRussian()
    {
    DataRow dr = d.Tables[0].Rows[d.Tables[0].Rows.Count - 1];
    int d1 = (int)dr[0];
    int d2 = (int)dr[1];
    if (d1 > 1)
    {
    int d3 = d1 / 2;
    int d4 = d2 * 2;
    DataRow dn = d.Tables[0].NewRow();
    dn[0] = d3;
    dn[1] = d4;
    d.Tables[0].Rows.Add(dn);
    d.Tables[0].AcceptChanges();
    DoRussian();
    }
    }
    }
  • Jason 2009-07-24 11:19
    one line recursive c# version:

    static int OneLineRussian(int a, int b)
    {
    return (a==0)?0:(a%2==0)?OneLineRussian(a/2,b* 2):b+OneLineRussian(a/2,b*2);
    }
  • Ed 2009-07-24 11:25
    Fairly elegant functional JavaScript 1.8 one-liner:

    function russian(a, b) [d for ([c, d] in function(c, d) {
    do { yield [c, d]; } while (d <<= 1, c >>= 1)
    }(a, b)) if (c & 1)].reduce(function(p, c) p + c, 0);

    Might work in Firefox 3; I just used the JavaScript shell.
  • kramthegram 2009-07-24 11:33
    Here is my pretty schweet python version with a test script!(sorry for any the tabs, I prefer them)

    def peasant(a,b):
    oddnums=[]
    while(a>1):
    if((a%2)!=0):
    oddnums.append(b)
    a=a/2
    b=b*2
    for num in oddnums:
    b=b+num
    return b

    for a in range(1,100):
    for b in range(a,100):
    if(peasant(a,b)!=(a*b)):
    print "fail!", a, b
    else:
    print "schweet!"
  • kramthegram 2009-07-24 11:35
    Drat! Two spaces it is then!
    def peasant(a,b):
    oddnums=[]
    while(a>1):
    if((a%2)!=0):
    oddnums.append(b)
    a=a/2
    b=b*2
    for num in oddnums:
    b=b+num
    return b

    for a in range(1,100):
    for b in range(a,100):
    if(peasant(a,b)!=(a*b)):
    print "fail!", a, b
    else:
    print "schweet!"
  • kramthegram 2009-07-24 11:44
    Double Drat! bbcode, I hates you

    def peasant(a,b):
    oddnums=[]
    while(a>1):
    if((a%2)!=0):
    oddnums.append(b)
    a=a/2
    b=b*2
    for num in oddnums:
    b=b+num
    return b

    for a in range(1,100):
    for b in range(a,100):
    if(peasant(a,b)!=(a*b)):
    print "fail!", a, b
    else:
    print "schweet!"
  • Nix Nada 2009-07-24 12:08
    Got it to one line in a function on VBA. My proudest moment.

    Function RussedRightUp(nr1 As Long, nr2 As Long) As Long

    If nr1 > 0 Then RussedRightUp = RussedRightUp(nr1 \ 2, nr2 * 2) + nr2 * (nr1 Mod 2)

    End Function
  • curtmack 2009-07-24 13:49
    Well, here's mine in Perl. The order of statements in the iterate function is a bit confusing, but it's all to ensure that it works in all of the unusual cases (namely, when 1 or 0 is given as the left operand).

    Also, it doesn't work at all when given negative numbers... but that's a flaw inherent in the method itself, not necessarily in my implementation.


    #!/usr/bin/perl

    use POSIX qw/ceil floor/;
    my ($op1, $op2) = @ARGV;

    sub iterate {

    my ($left, $right, $sum) = @_;
    $sum += $right if $left % 2;

    return $sum if $left <= 1;

    $left = floor($left / 2);
    $right *= 2;

    &iterate ($left, $right, $sum);
    }

    my $product = &iterate ($op1, $op2, 0);
    print "$product\n";

  • Joe 2009-07-24 13:58
    Excel Array Formula:

    =SUM(MOD(INT(A$1/POWER(2,ROW(A1:OFFSET(A1,INT(LN(A1)/LN(2)),0))-1)),2)*POWER(2,ROW(A1:OFFSET(A1,INT(LN(A1)/LN(2)),0))-1)*$B$1)

    When pasting in the formula, instead of hitting enter, you need to press CTRL-SHIFT-ENTER to tell excel it's an array formula.

    First number goes in A1
    Second number goes in B1

  • Cale Gibbard 2009-07-24 14:01
    Here's a Haskell implementation using a list comprehension:

    multiply x y = sum [v | (u,v) <- zip (takeWhile (> 0) $ iterate (`div` 2) x) (iterate (*2) y), odd u]

  • JS ROX! 2009-07-24 14:26
    I LOVE me some js.

    Wait, is this thing on? Is there anybody still here??

    Well, here are my two favorites, in js one-liners :

    function grif(x,y){
    return x>1?(x&1?y:0)+grif(x>>1,y<<1):y;
    }

    function firg(x,y){
    for(var r=0;x&1?r+=y:1;x>>=1,y<<=1)if(!x)return r;
    }
    firg is almost twice as fast as grif. and only half to a third as fast as straight multiplication, depending on the script engine. here's the instrumentation (works in WSH, or browser):]
    //instrumentation
    
    if(typeof(WScript!='undefined'))alert=function(msg){WScript.echo(msg);}

    function straight(x,y){
    return x*y;
    }

    function timeMethod(method,args,loop){
    var start=new Date();
    for(var i=0;i<loop;i++)method.apply(this,args);
    var end=new Date();
    return end-start;
    }

    new function main(){
    var params=[990,990];
    var loopCount=20000;
    var methods=[
    straight,
    grif,
    firg
    ]
    var results=[];
    for(var i=0;i<methods.length;i++){
    var time=timeMethod(methods[i],params,loopCount);
    var result=methods[i].apply(this,params);
    results.push(methods[i].toString().match(/function ([^(]*)/)[1]+" took: "+time+"ms to get "+result);
    }
    alert(results.join('\n'));
    }


    for extra credit, here's the link to run the above in your browser:

    Test Grif and Firg

    Cheers, and thanks for the game!
  • curtmack 2009-07-24 14:37
    For an encore, I did 6502 assembly as well.

    It should work, but I can't test it, because I don't know enough 6502 assembly to make a program that actually does something.

    There's also the issue of whether or not BIT can actually be used the way I use it. The reference I used wasn't clear on the subject. Frankly, if BIT can't use constants as operands, I am going to invent a time machine, go back to 1975, and storm into MOS Technology with a pitchfork demanding to know why the hell it can't.

    PHA
    
    LDA #00
    STA $03
    LDA $00

    _ITER BIT #01
    BNE _ROLL

    CLC

    STA $00
    LDA $03

    ADC $02
    STA $03
    LDA $00

    _ROLL ASL $02
    LSR A
    BNE _ITER

    PLA
    RTS
  • raony 2009-07-24 15:26
    python:

    f = lambda x,y, h = lambda x,y: x%2 != 0 and y or 0, g = lambda x,y: x > 1 and f(x/2, y*2) or 0: h(x,y) + g(x,y)
  • Joel Klein 2009-07-24 16:04
    Mathematica version that tries to match the algorithm as described:

    RussianPeasantMultiply[i_, j_] :=
    Total@Map[#[[2]]&,
    DeleteCases[
    NestWhileList[
    Function[args, {Floor[args[[1]]/2.], args[[2]]*2}],
    {i, j},
    First[#] =!= 1 &],
    {_?EvenQ, _}]]

    The innermost call is NestWhileList, having the form NestWhileList[f, {i,j}, test].

    If you use the NestWhileList expression with {12,23} as in the example you get a matrix representing the rows and columns:
    {{12, 23}, {6, 46}, {3, 92}, {1, 184}}

    Next is the DeleteCases expression, which uses a pattern {_?EvenQ, _} to delete rows where the first element is even.

    Next out from that is Map[#[[2]]&, rows], which gives us just the 2nd column.

    Finally, the numbers from the 2nd column are passed to Total.
  • Just another Russian peasant 2009-07-24 17:07
    Just a bit on the "curious" nature of the algorithm: doubling or halving a number using abacus is fast, even faster than adding or subtracting two numbers.

    For example, here is the doubling algorithm:

    for every digit from the least significant to the most do:
    if digit >=5 do
    subtract 5 from this digit
    carry 1 to next digit (propagate if needed)
    end if
    double this digit
    continue to next digit

    It may look complex, but actually doesn't involve counting beads (due to the most types of abaci being bi-quinary, including the Russian one), and therefore as fast as one could move his hand.

    Addition or subtraction requires either counting beads, or messing with decimal half-carry (that is 4-bead wire on Russian abacus is really for; counting quarter-copecs is a marginal use).
  • Bob 2009-07-24 18:16
    This is exercise 1.18 in Structure and Interpretation of Computer Programs
  • ikegami 2009-07-24 20:31
    curtmack:
    For an encore, I did 6502 assembly as well.


    Wow, that's very similar to Varian72 (as in 1972). I helped write a number of control programs in Varian72 assembler. They're used to control CANDU nuclear power reactors and the 100s of valves of the attached boiler system. This is what's being used today!

    Varian72 has a richer instruction set, and supports constants (bit 15 of the address field = 1: constant; bit 15 of the address field = 0: address)

    For common constants, we used low memory which could be addressed using a single-word instructions.


    * RMUL - Russion Multiply
    *
    * Inputs:
    * A-REG: Multiplier
    * B-REG: Multiplicand
    * X-REG: Anything
    *
    * Outputs:
    * A-REG: Product
    * B-REG: Destroyed
    * X-REG: Unchanged

    RMUL ENTR
    STA MULTER Save the multiplier

    TZA A-REG = 0
    STA PROD Init the product to zero.

    LDA MULTER A-REG = Multiplier
    RMUL01 BTA0 BT0,RMUL02 Jump over add if multiplier is even or zero

    TBA A-REG = Multiplicand
    ADD PROD A-REG = Product
    STA PROD Save product.

    LDA MULTER A-REG = Multiplier
    RMUL02 LSLB 1 Double the multiplicand
    LSRA 1 Half the multiplier
    STA MULTER Save the multiplier
    JANZ RMUL01 Loop if multiplier is non-zero

    RMULEX LDA PROD A-REG = Product
    RETU* RMUL

    PROD BSS 1

  • Dale King 2009-07-24 20:31
    Features:
    - excessive use of goto
    - no bitwise operations
    - no mul/div/mod operations


    #include <stdio.h>

    int peasantiply(int a, int b) {

    int r = 0;
    int h, d;

    firstodd:
    h = a;
    while (h > 1) {
    h -= 2;
    }
    d = b;
    if (h == 1)
    goto addodd;

    start:
    if (a == 0)
    goto done;

    halve:
    h = 0;
    while (a > 1) {
    h++;
    a -= 2;
    }
    a = h;

    doubleup:
    d = b;
    while (d > 0) {
    d--;
    b++;
    }
    d = b;

    addodd:
    h = a;
    while (h > 1) {
    h -= 2;
    }
    if (h == 1) {
    while (d >0) {
    d--;
    r++;
    }
    }

    goto start;

    done:
    return r;
    }

    int main() {
    printf("%d\n", peasantiply(18, 23));
    }
  • mol1111 2009-07-24 20:34
    Updated version of index. Added entries from yesterday, fixed jnz's entry, resolved most entries without specified language, removed duplicates.

    ABAP
    dv 277800
    Someone 277998 278677

    APL
    Captain Obvious 277817
    Steve the Cynic 278029 278054

    Assembler
    Dascandy x86, ARM 277793
    Bosshog 6502 277804 278103
    Stalker x64 277911
    kastein IA64 277930
    Bob Montgomery 6502 278147
    Lunkwill m68k 278154
    flax ARM 278263
    Kevin Kofler m68k 278381
    Gumpy Guss PDP-8 278418
    bd_ Rabbit 2000 278438
    Chris Walton x86 278499
    C x86 278562
    Anonymous ARM 278710
    Moe 6502 279053
    curtmack 6502 279343

    BASIC
    Alex Papadimoulis VBScript 277748
    Kees QB/VB ? 277803
    Takis VB.Net 277814 278799
    RayS VBA 277842 278407
    djjeavons VB.Net 277887
    Slinky VB? 278001
    antelopelovefan VBA 278068
    JoLoCo Sinclair 278126
    Yorick Sinclair 278372
    bluebearr AutoIt 278460
    James VBA 278489
    Don Knisley VBA 278534
    k1 278548 278550
    some VBA coder VBA 278862
    Nix Nada VBA 279306

    bc/dc
    Nick Pope 277951 278207

    brainfuck
    Qwertyuiopas 278037
    Eyrieowl 278241
    Philipp 278837
    Boombuler 279204

    Brilliant
    Paula 277801

    C/C++
    Tim 277783 277784
    Larry H. 277798
    Stefan 277813
    Zombywuf templates 277815
    Matthew Verleger 277827
    darkwraith 277832
    KimmoS 277850
    KnoNoth 277851
    whileloopsareugly 277873
    TerraNova 277876
    YES WE CAN! 277912
    little3lue templates 277914
    GWO 277924 277962 277964 277965
    avl 277929
    ponky 277952 278066
    hh10k 277969
    buzkie 277984
    shub 277985 278055
    _flt 278003
    Harleqin 278009
    Zor 278046 278053 278059
    Kman templates 278062 278880
    Alex Guzman 278084
    Fooba 278100
    serg 278113
    hornet 278173 278191
    Bored 278175
    xtremezone 278176 278190 278205
    David Young 278185
    Haggis 278189
    Ronuk Raval 278209
    Humanoid Life-form 278238
    Alan Woodland templates 278240
    Михаил 278267
    OmnipotentEntity 278270
    MG 278284
    Resistance Assembler 278321
    Rob Hulswit templates 278329 278331
    mxsscott 278342
    Rob H 278352
    J.I. 278356
    Sam 278391
    spiderlama 278416
    0ffh 278451
    jnz 278473
    Chris Walton 278499
    demo templates 278528
    khahem 278731
    Mr. Black 278769
    n1L templates 278844
    markwhi 278906 278908
    Lightnix 278994
    TP 279023

    C#
    Jay 277786
    Dopefish 277788
    Brettm 277812
    ruckc 277828
    Dan 277834 277856
    Damien 277843
    Felix Ungman 277867
    GM 277894
    cwink 277899 277905
    Fabio Lima 277922 277957
    Jonathan 277967
    Osno 277972 277997 278021
    groknroll 277980
    buzkie 277984
    campkev 277991 277994 278078 278081
    Sean Handley 277995
    Oliver Klozoff 278000
    WraithShade 278057
    Floyd LINQ 278082
    Alex Guzman 278084
    chriswatson LINQ 278106
    Codism LINQ 278139
    Jared Youtsey 278149
    David C. 278161 278226
    jeff.woodhull LINQ 278201
    It'sMe 278203
    Shiftyness 278236
    Humanoid Life-form 278238
    aef123 278245 278247
    stannius LINQ 278261
    blueberry 278286
    VirtualBlackFox LINQ 278292
    nine 278293
    TNProgrammer 278302
    Josue Chi 278303
    dontera 278324
    The Answer + 2 278328
    hornet threads 278340
    Rob H 278352
    Lernin ur codez 278376
    PatrickBeebe 278393 278974
    Veryth LINQ 278433
    brian 278450
    Thomas Eyde 278456
    Joel 278461
    joeyadams 278471
    JXO 278474
    astander 278544
    col obvious 278598
    Alex 278628
    czetts 278846
    HCGL 278911
    Jeremy Burns 278922
    Paul N 278983
    Tachyon ASP.Net 279255
    Jason 279280

    D
    Rief 278006
    Quxxy 278069

    Erlang
    Mike McNally 278434 278440
    MichaelWH 278877
    John Stracke 279008

    F#
    darklajid 277890 277941 278137
    Patrick Simpson 278127
    ajp 278357 279029
    cmugford 278486

    FORTRAN
    rst 277978
    java.lang.Chris; 278266

    Groovy
    Matt 277949

    Haskell
    freako 277838
    Dave Ingram 277839
    Sebastian Paaske Tørholm 277870
    HypocriteWorld 277878
    Maxim 277889
    Noah Easterly 278130
    semanticprecision 278170
    Andrew Nurse 278198
    Jonas Kramer 278220
    ikorb 278299
    valderman 278405 278406
    Twey 278439
    Joost 278567
    jefu 278838
    dub 278874
    iggy 278935
    vog 279045
    MichaelWH 279047
    dysfunctor 279081
    Cale Gibbard 279334

    Java
    Cookie 277785
    Jay 277786
    Mat Rantell 277802
    ruckc 277828
    Will 277831
    Drew 277844
    Arjan 277879
    Philipp 277903 277919
    Kook 277963 277968
    buzkie 277984
    Alex Guzman 278084
    imhe 278105 278138
    Jannik Jochem 278115
    Thuktun 278124
    idle 278128
    klagdon 278131 278242
    amischiefr 278152
    Greg R 278212 278231
    Davi Cavalcanti 278228
    DeepThought 278230
    bb 278235
    cincinnatvs 278237
    Humanoid Life-form 278238
    aef123 278245 278247
    Josue Chi 278303
    Fred Dagg 278408
    subanark 278537
    astander 278544
    col obvious 278598
    Alex 278628
    Rorick 278749
    Queex 278761
    Coyne 278892

    Javascript
    Z 277796
    Zishan 277882
    Jason Knight 277898
    Mestafais 278005
    Markus Persson 278039
    jjs105 278136
    jonnyq 278208
    Phroggy 278221
    astonerbum 278248 278264 278343
    Scott 278294
    Beat by the system 278319
    Rob Hulswit 278329
    Jeb Walter Strate 278345
    Crindigo 278419
    Chris 278484
    cofiem 279233
    Ed 279287
    JS ROX! 279340

    LISP
    newlisp.org newLISP 277861 278283
    MP 2778711
    leppie Scheme 277881
    dee Scheme 277900
    Bob Scheme 277907 278206
    Éibhear Emacs 277910
    Dmitri Savichev Scheme 277992 277999
    lyml Scheme 277996
    Harleqin Common Lisp 278009
    Alex Muscar Common Lisp 278090 278096 278160 278514 278516
    Trey Jackson Emacs 278194
    samanddeanus Scheme 278271 278998
    asdfghj Scheme 278311
    guille_ 278317
    Ted Walther, newLISP fan newLISP 278344 278986
    unit3 Common Lisp 278417
    noSignal Scheme 278469
    iamtim2 newLISP 278491
    jvmbsd7 Scheme 278493
    Chris Judge 278868

    LOLCODE
    JaguarOne 277920
    PopeHappyCat 278099 279245

    Lua
    Stefan 277854
    Will 278010
    Tiogshi 278368
    Methuselah 278675
    Kenneth Pullen 279099

    Mathematica
    J 278467
    Joel Klein 279356

    MSIL
    Osno 278153 278197 278729 278786 278801

    MUMPS
    MUMPS 278211
    Trurl 278246 278255

    Other
    hydrus Clojure 277792
    db2 HP 48 277857
    Dave Ingram vimscript 277862
    pjt33 SML 277864
    SR ColdFusion 277896
    Will MUSH 277942
    Samuel A. Falvo II Forth 277976
    Sal Postscript 278093
    Cindi Knox mIRC 278174
    darkscout Matlab 278298
    Roger RPGLE 278337
    Tom Medley - www.tommedley.com ML 278350
    ikegami circuit diagram 278370
    dee COBOL 278403
    yowzer ocaml 278428
    StarLite Progress V9 278583
    Ralf Smalltalk 278794
    Rorick Rebol 278810 278873
    Whatever Befunge-93 278988
    Rusty Nail Verilog 279040
    Greg awk 279087
    Marlon False 279219 279220 279225
    Corpsegrinder AppleScript 279236 279237

    Pascal
    Azeroth 277837
    malach Delphi 277860
    baka0815 277868 277877 278020 278028 278065
    DougB Delphi 278179
    Trevor Dubinsky Delphi 278229
    mol1111 Turbo Vision 278374

    Perl
    Me 277807 277845
    epv 277849
    Steven de B 277884
    WarheadsSE 277944 278061
    Anonymous 277977
    tirerim 278119
    John Evans 278141
    Jim Halfpenny 278143
    Igor V. 278199
    Darren 278223
    Warr regex 278260 278420
    qoo3h 278353
    Andrew Rodland 278358
    H2 278388
    Florent 278401 278404
    Toby Gray 278538 278540
    bugmonkey 278658
    rjp 278714
    Maurits 279046
    Yorick 279222
    asd 279246
    curtmack 279331

    PHP
    The Wolf 277787 277799
    Erin 277797
    Clark S 277858 277872
    Ryan 277863
    Daniel 277904 277909
    FatherStorm 277932
    aBase 278036 278214
    John Evans 278141
    HonoredMule 278158 278168 278184
    IcePanther 278195
    Tim 278196
    Paul 278265
    LeCoyote 278396
    mjomble 278413
    mneimeyer 278524
    LatecomerX 278617 278673
    bugmonkey 278658
    Evo 278886 278934
    AngeloR. 278960
    symcbean 279208

    Prolog
    Anonymous Coward 277938
    Mike5 278204
    A.T. 278641 278646 279196
    Corpsegrinder 279051

    Python
    ath 277789 277806 278244
    phihag 277811 277818 277869
    Fenris 277823
    Jeff Kemp 277852 277940
    Tempura 277875
    Stalin 277880
    Jim 277901
    Eutactic 277915
    RECURSIVEMAN 277916
    rob tracey 277917
    krat 277918
    drBeat 277925
    ross 277931
    halber_mensch 277936 277943 277955 277979 278129
    Real russian peasant :) 277974
    Remy 278004
    Billy 278007
    Josh Bohde 278017 278080 278092 278104 278166 278854
    Wulf0r 278024
    Jürgen 278086
    koblas 278101
    Rob W. 278111
    Chad M 278132
    Jörg 278163
    martinp 278172
    JJM 278193
    Ronuk Raval 278209
    lostlogic 278222
    SoaperGEM 278305
    ZzzZZZz 278318
    Lee Crabtree 278355
    sdeek 278359
    opussf 278364
    KukkerMan 278366
    Edinburgh Mike 278375
    mwchase 278395
    Adrian 278402
    Jukka 278412
    tdh 278444
    Mr.'; Drop Database -- 278459
    agrif 278497
    Python 278688
    Lom 278732
    the real wtf fool 278842
    workmad3 278975
    inky 278996
    Scott 279009
    kramthegram 279290 279292 279297
    raony 279352

    Ruby
    arnemart 277825 277855
    Mike Dotterer 277829
    exo 277926
    Nicholas Laux 277958 277971
    Xthlc 277983 278026
    derula 278050
    Amadan 278071
    Northpole 278072
    jweir77 278079
    Jürgen 278086
    Dave Havlicek 278122
    Jeremy Weathers 278216
    Chewbie 278224
    Jimmy Selgen 278367
    Redredredredredred 278380
    Pony Princess 278967

    Scala
    Alex Ciarlillo 277937
    Ian McLaird 278023
    Matt 278249
    Unlabeled Meat 278332
    juancn 278962
    Landei 279042
    Moritz 279082

    Shell
    mat BASH 277791
    bluebearr Batch 278012 278243
    Ken B Batch 278032
    moltonel BASH 278262 278272 278282
    Julian Calaby BASH 278485
    The_Assimilator PowerShell 279028
    andyesslinger Batch 279049

    Spreadsheet
    acsi 278150
    treyb Excel 278300
    Joe Excel 279333

    SQL
    SQLDork 277795
    KnowOracle Oracle 277816 277822 277824
    Chris Hunt Oracle 277836
    csulli13 277888
    MeesterTurner T-SQL 277959
    wombat T-SQL 278186
    shane blake T-SQL 278210
    Dave Havlicek PL/pgSQL 278322
    Bodestone 278341
    DFHawthorne Oracle 278409
    Paul N T-SQL 278425 278427
    Hidayat Oracle 278526
    SlyEcho 278535
    Boneist Oracle 278555
    EJCorcoran T-SQL 278795
    dee MySQL 279007
    DBA_In_OKC T-SQL 279145

    Tcl/Tk
    Albrecht from Germany 278142 278145

    Unspecified
    SimonY 278120
    Michael Clark (mjac.co.uk) 278360
    Eric 278371
    Wheaties 278426

    XSLT
    Dave van der Brugge 278133
    wombat 278808


    Addendum (2009-07-24 20:53):
    BTW If anybody (Alex?) interested, here are sources for the index generator (datafile + python script).
  • iamtim2 2009-07-25 01:33
    ;Done in Newlisp without using variables to store calculations. Making it purely functional, I believe.

    (define (odd? x)
    (= (& x 1) 1))

    (define (half! x)
    (>> x 1))

    (define (double! x)
    (<< x 1))

    (define (b x y)
    (cond
    ((= 1 x) y)
    ((and (< 1 x) (odd? x)) (+ y (b (half! x) (double! y))))
    ((< 1 x) (b (half! x) (double! y)))))
  • Serpardum 2009-07-25 06:00
    This is what I slapped together. It's fairly simply actually. This is C++ code but the only thing I notice right away keeping it from becoming C code is the use of bool.

    A friend are I were discussing the fact he would use a & 1 to check for odd/even where I would use a % 2 == 1. just because I think it's more self explanitory.

    #include <iostream>
    

    int russianMultiply( int a, int b ) {
    // Multiplication on the chip may be innaccurate.
    // Lets use the manual way to multiply to ensure we
    // receive accurate results
    bool aneg = a < 0;
    if ( aneg )
    a = -a;

    int result = 0;
    if ( a % 2 == 1 ) {
    result += b;
    }
    while ( a > 1 ) {
    a /= 2;
    b <<= 1; // I don't even trust *2 to be accurate
    if ( a % 2 == 1 ) { // is a odd?
    result += b; // It is so add our current multicant
    }
    }

    if ( aneg )
    result = -result;
    return result;
    }

    int main() {

    std::cout << russianMultiply( 18, 23 ) << "\n";
    std::cout << russianMultiply( -18, 23 ) << "\n";
    std::cout << russianMultiply( 18, -23 ) << "\n";
    std::cout << russianMultiply( -18, -23 ) << "\n";
    }
  • mr.DUDA 2009-07-25 06:00
    Did anyone try High-Level Shader Language? With modern video cards the program can run entirely on GPU and take no CPU time at all.

    Here it goes (uncomment mul operation to apply results to any 3D model; leave it commented out for screen-aligned quad):

    uniform float A = 37;
    
    uniform float B = 258;

    uniform float4x4 worldViewProj;

    float3 numbers[] =
    {
    { 0, 1, 0 }, { 1, 0, 1 }, { 1, 0, 1 }, { 1, 0, 1 }, { 0, 1, 0 },
    { 0, 1, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 1, 0 }, { 1, 1, 1 },
    { 0, 1, 0 }, { 1, 0, 1 }, { 0, 0, 1 }, { 0, 1, 0 }, { 1, 1, 1 },
    { 1, 1, 1 }, { 0, 0, 1 }, { 0, 1, 0 }, { 0, 0, 1 }, { 1, 1, 1 },
    { 1, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 0, 1 }, { 0, 0, 1 },
    { 1, 1, 1 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 0, 1 }, { 1, 1, 0 },
    { 0, 1, 1 }, { 1, 0, 0 }, { 1, 1, 0 }, { 1, 0, 1 }, { 1, 1, 0 },
    { 1, 1, 1 }, { 0, 0, 1 }, { 0, 1, 0 }, { 0, 1, 0 }, { 0, 1, 0 },
    { 0, 1, 0 }, { 1, 0, 1 }, { 0, 1, 0 }, { 1, 0, 1 }, { 0, 1, 0 },
    { 0, 1, 0 }, { 1, 0, 1 }, { 0, 1, 1 }, { 0, 0, 1 }, { 1, 1, 0 }
    };

    void vs_main(float4 pos : POSITION, float2 t : TEXCOORD0, out float4 oPos : POSITION, out float3 oT : TEXCOORD0)
    {
    // russian multiplication goes here
    float a = A, b = B, c = 0;
    do
    {
    float a2 = a / 2;
    float a2f = floor(a2);
    c += b * (1 - step(a2, a2f));
    a = a2f;
    b *= 2;
    } while (a > 0);

    // pass outputs to pixel shader, convert pos to 0..1 up-down left-right
    oPos = pos;// mul(pos, worldViewProj); --- TODO: leave commented out for screen-space quad
    oT = float3(t, c);
    }

    float4 ps_main (float3 t : TEXCOORD0) : COLOR
    {
    // # of digits in result
    float x = t.x, y = t.y, result = t.z;
    float maxDigits = 1 + floor(log10(result));

    // determine value and index of digit in result
    float idigit = (maxDigits - 1) - floor(x * maxDigits);
    float digit = floor(result * pow(10, -idigit));
    float nonempty = digit > 0;
    digit -= 10 * floor(digit * 0.1);

    // get row and column of output number
    float3 row = numbers[floor((y + digit) * 5)];
    float col = row[4 * fmod(x * maxDigits, 1)] * nonempty;

    return float4(col.xx, 1, 1);
    }

    technique
    {
    pass
    {
    VertexShader = compile vs_3_0 vs_main();
    PixelShader = compile ps_3_0 ps_main();
    ZEnable = false;
    ZWriteEnable = false;
    CullMode = NONE;
    AlphaBlendEnable = false;
    }
    }


    P.S. the graphic is ASCII-style but is capable to display numbers of any width
  • Stalker 2009-07-25 07:01
    No hardware implementations yet? Oh well, VHDL isn't really my field (haven't done anything real in it ever) but this actually seem to work.

    Put factors on input and then pulse start, the result can then be read from prod on rising edge of done.


    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;
    use ieee.numeric_std.all;

    entity RusMulUnit is
    port
    (
    clk : in std_logic;
    fac0 : in std_logic_vector( 19 downto 0 );
    fac1 : in std_logic_vector( 19 downto 0 );
    start : in std_logic;

    prod : out std_logic_vector( 39 downto 0 ) := (others => '0');
    done : out std_logic := '0'
    );
    end RusMulUnit;

    architecture bdf_type of RusMulUnit is
    signal fac0i : std_logic_vector( 19 downto 0 ) := (others => '0');
    signal fac1i : std_logic_vector( 19 downto 0 ) := (others => '0');
    signal sumi : std_logic_vector( 39 downto 0 ) := (others => '0');
    begin
    process( clk )
    begin
    if rising_edge( clk ) then
    if start = '1' then
    fac0i <= fac0;
    fac1i <= fac1;
    sumi <= (others => '0');
    done <= '0';
    else
    fac0i <= '0' & fac0i(19 downto 1); -- shift right
    fac1i <= fac1i(18 downto 0) & '0'; -- shift left
    if fac0i(0) = '1' then
    sumi <= sumi + fac1i;
    end if;
    if fac0i = 0 then
    done <= '1';
    end if;
    end if;
    end if;

    if falling_edge( clk ) then
    if start = '1' then
    prod <= (others => '0');
    else
    if fac0i = 0 then
    prod <= sumi;
    end if;
    end if;
    end if;
    end process;
    end bdf_type;
  • The_Assimilator 2009-07-25 07:41
    Was going to submit a HLSL version as well but I thought I'd leave it up to someone more competent in HLSL than myself. :)
  • mr.DUDA 2009-07-25 10:51
    Hey, feel free to submit your version as well!

    My code isn't well optimized, e.g. some calculations can be moved into vertex pipeline rather than perform per-pixel; also, if еру screen quad geometry is highly tesselated, everything can perform at per-vertex basis; also, by using a texture with baked numbers we can just tex2D instead of messing with ASCII-like-grid-symbols etc.

    :)
  • Kennie Nybo Pontoppidan 2009-07-25 13:18
    fun peasantAdder(n,m) =
    let
    fun adder(1,m,acc) = m+acc
    | adder(n,m,acc) = adder(div(n,2),2*m,mod(n,2)*n+acc)
    in
    adder(n,m)
    end
  • Rusty Nail 2009-07-25 15:11
    No hardware implementations yet?


    There's a schematic version and a verilog version way back in the flood of posts :)
  • mol1111 2009-07-25 15:25
    Rusty Nail:
    No hardware implementations yet?


    There's a schematic version and a verilog version way back in the flood of posts :)

    ikegami circuit diagram 278370
    Rusty Nail Verilog 279040
  • Ben 2009-07-25 16:49
    A bit late to this party, but here's my take:

    #include <assert.h>

    #define is_odd(num) (num % 2 != 0)

    /* Multiply two numbers together, in the manner of Russian peasants. */
    /* This method expects and accepts only non-negative integers. */
    int multiply(int lh, int rh)
    {
    assert(lh >= 0 && rh >= 0);

    int total = 0;

    while (lh > 0)
    {
    if (is_odd(lh))
    total += rh;

    lh /= 2;
    rh *= 2;
    }

    return total;
    }
  • mol1111 2009-07-25 19:20
    Does anybody has some idea in what language is this entry:
    Wheaties 278426
    written?

    I was able to indentify all others, but this one remains mystery.
  • Stalker 2009-07-25 20:05
    Oops. Guess I fell asleep after a few hundred posts. Anyway, here's an implementation in a language having some neat functions but otherwise severely lacking (no bitwise and, no shift etc).


    function integer mul: integer f0, integer f1
    begin
    mul = 0;
    while f0 > 0 do

    // Just because we can
    function boolean isEven: integer n
    begin
    isEven = n == (n / 2) + (n / 2);
    end;

    if !isEven( f0 ) then
    mul = mul + f1;
    end;

    f0 = f0 / 2;
    f1 = f1 + f1;
    end;
    end;

    procedure main:
    begin
    // Test it
    for x = 0 to 100 do
    for y = 100 to 0 step -1 do
    output x * y;
    output mul( x, y );
    end;
    end;
    end;
  • Paul Marfleet 2009-07-25 20:34
    Solution in F#:

    let multiply a b =
    let rec getWorkings a b lst =
    match a with
    | 1 -> lst
    | _ ->
    let c, d = a / 2, b * 2
    getWorkings c d (lst @ [(c, d)])

    let result =
    getWorkings a b []
    |> Seq.filter (fun (a, b) -> a % 2 = 1)
    |> Seq.map (fun (a, b) -> b)
    |> Seq.fold (fun acc b -> acc + b) 0
    result

    printf "%d" (multiply 18 23)
  • fuggit 2009-07-26 00:40
    Haskell!

    mul 0 y = 0
    mul x y | x < 0 = -(mul (- x) y)
    mul x y = mul (x `div` 2) (y * 2) + if (even x) then 0 else y
  • Paul Marfleet 2009-07-26 05:43
    Refined F# solution:

    let multiply a b =
    let rec getResult a b sum =
    match a with
    | 1 -> sum
    | _ ->
    let c, d = (a / 2), (b * 2)
    match c with
    | x when c % 2 = 1 -> getResult c d (sum + d)
    | _ -> getResult c d sum

    match a with
    | 0 -> 0
    | 1 -> b
    | _ -> getResult a b 0
  • f_ranek 2009-07-26 06:25
    Writen in Java, works for both nonnegative and negative numbers. Int type can be used as well as long.

    long multiply(long a1, long a2)
    {
        long res = 0;
        for (; a1 != 0; a1 >>>= 1, a2 <<= 1)
            if ((a1&1) != 0)
                res += a2;
        return res;
    }
  • f_ranek 2009-07-26 09:28
    @echo off

    :: WindowsXP CMD script
    :: Usage: save to file multiply.cmd, call multiply.cmd -13 56
    :: Correct negative numbers handling

    set result=0
    set a=%1
    set b=%2

    if %a% lss 0 (
    set /a a = -a
    set /a b = -b
    )

    :loop
    if %a% equ 0 goto :endx
    set /a tmp = "a & 1"
    if not %tmp% equ 0 set /a result += b
    set /a "a >>= 1"
    set /a "b <<= 1"
    goto loop
    :endx

    echo %result%
  • Alex Muscar 2009-07-26 10:28
    Common Lisp:

    This is a long one :). Assuming that function composition and unfold are provided by a library (eventually sigfun too, but it's not such a useful function after all) the implementation would be made out of rpm5-aux and rpm5. This is just because i wanted the implementation to be functional (sorta').


    (declaim (inline comp))
    (defun comp (f g)
    (lambda (&rest args)
    (funcall f (apply g args))))

    (defun unfold* (f &rest s)
    (multiple-value-bind (c s) (apply f s)
    (when c
    (cons c (apply #'unfold* f s)))))

    (declaim (inline sigfun))
    (defun sigfun (n)
    (if (minusp n)
    #'-
    #'+))

    (defun rpm5-aux (m n)
    (when (> m 0)
    (values (list m n)
    (list (ash m -1) (ash n 1)))))

    (defun rpm5 (m n)
    (let* ((ns (unfold* #'rpm5-aux (abs m) n)))
    (reduce (sigfun m) (delete-if (comp #'evenp #'car) ns)
    :initial-value 0 :key #'cadr)))
  • Alex Muscar 2009-07-26 10:46
    This is so nice :).
  • Alex Muscar 2009-07-26 11:55
    Common Lisp:

    Corrected version of the tail recursive variant:

    (defun rpm7 (m n)
    (labels ((rec (m n acc)
    (if (= m 0)
    acc
    (rec (ash m -1) (ash n 1) (if (oddp m) (+ acc n) acc)))))
    (funcall (sigfun m) (rec (abs m) n 0))))
  • Михаил 2009-07-26 13:25
    ehrm, forgot.

    квас<<=1;

    after the пиво>>=1;.
  • curtmack 2009-07-26 13:33
    I had to cheat a little bit here. I don't know of any way to make this algorithm work in Befunge without very advanced trickery. So, it doesn't actually print the result of the multiplication - it just prints out the values that would be added together if Befunge could actually handle such a thing.

    &&v
    
    v < \.:\<
    >2/\2*\:2%|
    ^ <:
    @ ^_
  • Karol Urbanski 2009-07-26 14:02
    Here's mine in perl:
    sub k{($a,$b)=@_,$a%2&&($_+=$b),$a&&k($a>>1,$b*2)}

    (50 chars)

    And the one liner to use that:
    $ perl -E'sub k{($a,$b)=@_,$a%2&&($_+=$b),$a&&k($a>>1,$b*2)}k(@ARGV),say' 18 23
    
    414
    $ perl -E'sub k{($a,$b)=@_,$a%2&&($_+=$b),$a&&k($a>>1,$b*2)}k(@ARGV),say' 7 7
    49

    (71 chars + args; also a true one-liner - no semicolons :))
    That's making a function, as said in the article. Without using a subroutine, the algorithm by itself:
    $a%2&&($_+=$b),$b*=2,$a>>=1while $a

    (35 chars! though $a and $b have to be initialised, if
    ($a,$b)=@ARGV;
    is used it becomes 49 chars)
    And the one liners for that (slightly cheaty because semicolons):
    $ perl -E'($a,$b)=@ARGV;$a%2&&($_+=$b),$b*=2,$a>>=1while $a;say' 7 3
    
    21
    $ perl -E'($a,$b)=@ARGV;$a%2&&($_+=$b),$b*=2,$a>>=1while $a;say' 135 975
    131625

    This is 62 chars + args.

    Also, the above Befunge program is awesome and I fully endorse it, even if it doesn't fully work ;).
  • djhworld 2009-07-26 14:10
    I enjoy these tasks, they give me something to do whilst I'm feeling a bit of a blackout on the "programming ideas" but still want to write some code.

    My solution isn't as elegant or "efficient" as everyone elses seems to be but it was fun none the less.


    public static int doPeasantMaths(int left, int right)
    {
    int leftColumn[] = new int[20];
    int rightColumn[] = new int[20];

    int product = 0;
    int i = 0;

    leftColumn[i] = left;
    rightColumn[i] = right;

    if( (leftColumn[i] % 2) != 0 )
    {
    product = product + rightColumn[i];
    }

    while(leftColumn[i] != 1)
    {
    if(leftColumn[i] != 1)
    {
    i++;
    }

    leftColumn[i] = leftColumn[i-1] / 2;
    rightColumn[i] = rightColumn[i-1] * 2;

    if( (leftColumn[i] % 2) != 0 )
    {
    product = product + rightColumn[i];
    }
    <