- Feature Articles
- CodeSOD
- Error'd
-
Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
My take using Progress V9 (will probably work in most older versions as well) Code:
Admin
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);}
Admin
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; }
Admin
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...
Admin
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...
Admin
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);</pre>Admin
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); }
Admin
Here's some Lua code:
Code only: 189 bytes Code with BBCode coloring: 1190 bytes
Admin
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?
Admin
#! -- 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
if name == "main": selftest()
Admin
OH DEAR!!! LOL!
Admin
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 loopAdmin
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}
Admin
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 }
Admin
BTW, I think I've never seen a post in this site with 12 pages of comments.
Admin
C++ with a 'simple' iterator.
Admin
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)
Admin
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; }Admin
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; // }Admin
Wow, the number of unreadable and unmaintainable examples outweight the readable and maintainable ones by about 50:1! That's the real WTF...
Admin
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> ---------------------
Admin
The C# compiler does tail call optimisation only on x64 afaik.
Admin
Smalltalk
Note that this overwrites the System's definition of * and everything still works.
Admin
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
Admin
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:
Admin
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.
Admin
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???
Admin
There is a 44 character python, and a 40 characther bc, although you still have several characters to go to catch perl :)
Admin
Admin
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>Admin
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:
Admin
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 ;)
Admin
Haskell (with quickCheck to test it) :
Admin
#!/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 ------------- = 414The lines starting with -- should be considered crossed out
Admin
soulution as c++ template:
////////////////////////////// template <int I, int J> struct Pmul { operator int() { return (I%2)?J+Pmul():Pmul(); } }; ////////////////////////////// template <int J> struct Pmul<1, J> { operator int() { return J; } }; //////////////////////////////i.e.:Admin
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!)
Admin
37 using * and /
41 without
Admin
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
Admin
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) )Admin
In rebol with caching of generated code stuff.
Admin
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) (b2) ) | otherwise = (rus (div a 2) (b2) )
Admin
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)).Admin
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;
Admin
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);Admin
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; }Admin
Late to the game, I guess. Replying without viewing comments, wonder if mine is original :)
http://pastebin.com/f50d7e6d5
Admin
I guess I should post the code, not just a link to it:
/**
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 ;
}
printf ("%i\n", total) ;
return 0 ; }
Admin
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);
Admin
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; }Admin
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);