Category Archives: Math

Ancient Egyptian Multiplication

Actionscript:
  1. egyptianMultiply(12, 99);
  2.  
  3. // trace(12 * 99) // test to make sure it works
  4.  
  5. /* outputs:
  6. /64 768
  7. /32 384
  8.  16 192
  9.  8 96
  10.  4 48
  11. /2 24
  12. /1 12
  13. ---
  14. 1188
  15. */
  16.  
  17.  
  18. function egyptianMultiply(valueA:Number, valueB:Number):void {
  19.    
  20.     var left:Array = [];
  21.     var right:Array = []
  22.    
  23.     // swap if valueB is smaller than value A
  24.     if (valueB <valueA){
  25.         var swap:int = valueB;
  26.         valueB = valueA;
  27.         valueA = swap;
  28.     }
  29.    
  30.     // create left and right columns
  31.     var currentLeft:int = 1;
  32.     var currentRight:int = valueA;
  33.    
  34.     while (currentLeft <valueB){
  35.         left.push(currentLeft);
  36.         right.push(currentRight);
  37.         currentRight += currentRight;
  38.         currentLeft += currentLeft;
  39.     }
  40.    
  41.    
  42.     // add up the right column based on the left
  43.     currentLeft = 0;
  44.     var rightSum:int;
  45.     var leftSum:int;
  46.     var i:int = left.length - 1;
  47.    
  48.     while (currentLeft != valueB){
  49.      
  50.       leftSum = currentLeft + left[i];
  51.       // if the next number causes the sum
  52.       // to go above valueB, skip it
  53.       if (leftSum <= valueB){
  54.         currentLeft = leftSum;
  55.         rightSum += right[i];
  56.         trace("/" + left[i]  + " " + right[i]);
  57.       } else {
  58.         trace(" " + left[i]  + " " + right[i]);
  59.       }
  60.       i--;
  61.     }
  62.     trace("---");
  63.     trace(rightSum);
  64. }

Someone mentioned egyptian multiplication to me yesterday... So read a little about it here and whipped up this example. For some reason I decided to do it in processing ... once it worked I ported it to ActionScript.

The above link describing the technique I used is from http://www.jimloy.com/... I haven't spent much time digging around the site, but it appears to have some pretty nice stuff on it...

If you're curious, here is the original processing version:

JAVA:
  1. Vector left = new Vector();
  2. Vector right = new Vector();
  3.  
  4. int valueA = 10;
  5. int valueB = 8;
  6.  
  7. if (valueB <valueA){
  8.     int swap = valueB;
  9.     valueB = valueA;
  10.     valueA = swap;
  11. }
  12.  
  13. int currentLeft = 1;
  14. int currentRight = valueA;
  15. while (currentLeft <valueB){
  16.     left.add(currentLeft);
  17.     right.add(currentRight);
  18.     currentRight += currentRight;
  19.     currentLeft += currentLeft;
  20. }
  21.  
  22. currentLeft = 0;
  23.  
  24. int result = 0;
  25. int i = left.size() - 1;
  26. while (currentLeft != valueB){
  27.  
  28.   int temp = currentLeft + (Integer) left.get(i);
  29.   if (temp <= valueB){
  30.    
  31.     currentLeft = temp;
  32.     result += (Integer) right.get(i);
  33.     println("/" + left.get(i) + " " + right.get(i));
  34.   } else {
  35.     println(" " + left.get(i)  + " " + right.get(i));
  36.   }
  37.    
  38.   i--;
  39. }
  40. println("---");
  41. println(result);

After writing, this I took a look at the wikipedia entry... I also found myself on this short page about a scribe called Ahmes. (I recommend reading this if you are interested in PI)

Also posted in misc | Tagged , , , | 1 Comment

Triangular Numbers

Actionscript:
  1. [SWF(width = 500, height = 500)]
  2.  
  3. var txt:TextField = TextField(addChild(new TextField()));
  4. txt.defaultTextFormat = new TextFormat("_sans", 4);
  5. txt.width = stage.stageWidth;
  6. txt.height = stage.stageHeight+4;
  7. txt.z = -1;
  8. txt.x = stage.stageWidth
  9. txt.rotation = 90;
  10. var count:int = 0;
  11. addEventListener(Event.ENTER_FRAME, onLoop);
  12. function onLoop(evt:Event):void{
  13.      count++;
  14.      txt.appendText(triangular(count).toString(2) + "\n");
  15.      txt.scrollV= txt.maxScrollV;
  16. }
  17. function triangular(n:int):int{
  18.        return (n * (n + 1)) / 2;
  19. }

Calculate some triangular numbers... (n * (n + 1)) / 2....

Check out the swf on wonderfl

Also posted in misc | Tagged , , | Leave a comment

Flowing Leaves (optical illusion)


Saw this optical illusion today... figured I'd make a snippet to create a few variations on the illusion...

Actionscript:
  1. [SWF( backgroundColor=0x2E7999, width=780, height = 600) ]
  2.  
  3. var leafNum:Number = 375;
  4. var spacing:Number = 12;
  5. var cols:Number = 25;
  6. var hh:Number = stage.stageHeight / 2;
  7. var hw:Number = stage.stageWidth / 2;
  8.  
  9. for (var i:Number = 0; i<leafNum; i++){
  10.     var leaf:Shape = makeLeaf();
  11.     leaf.scaleX = leaf.scaleY = 0.25;
  12.     leaf.rotation = 90;
  13.     leaf.x = 50 + (i % cols) * (leaf.width + spacing);
  14.     leaf.y = 40 + int(i / cols) * (leaf.height + spacing);
  15.     var dx:Number = leaf.x - hw;
  16.     var dy:Number = leaf.y - hh;
  17.     leaf.rotation = Math.sqrt(dx * dx + dy * dy);
  18. }
  19.  
  20. function makeLeaf():Shape{
  21.     var leaf:Shape = Shape(addChild(new Shape()));
  22.     leaf.graphics.beginFill(0x9DC4D4);
  23.     scaleYcircle(leaf.graphics, 50, .65, false);
  24.     leaf.graphics.endFill();
  25.     leaf.graphics.lineStyle(2, 0x003366, 1, false, "none", CapsStyle.SQUARE, JointStyle.MITER);
  26.     scaleYcircle(leaf.graphics, 50, .65);
  27.     leaf.graphics.lineStyle(2, 0xFFFFFF, 1, false, "none", CapsStyle.SQUARE, JointStyle.MITER);
  28.     scaleYcircle(leaf.graphics, -50, .65);
  29.     return leaf;
  30. }
  31.  
  32.  
  33. // original circle function by senocular (www.senocular.com) from here http://www.actionscript.org/forums/showthread.php3?s=&threadid=30328
  34. // circle that can be scaled on the y axis
  35. function scaleYcircle(g:Graphics, r:Number, s:Number = 1, isHalf:Boolean=true):void {
  36.      
  37.     var c1:Number = r * (Math.SQRT2 - 1);
  38.     var c2:Number = r * Math.SQRT2 / 2;
  39.     var rs:Number = r * s, c1s:Number = c1 * s, c2s:Number = c2 * s;
  40.     var x_r:Number =  -r, y_r:Number = -rs, x_c2:Number =  -c2;
  41.     var y_c2:Number =  -c2s, x_c1:Number =  -c1, y_c1:Number =  -c1s
  42.     g.moveTo(r, 0), g.curveTo(r, c1s, c2, c2s);
  43.     g.curveTo(c1, rs, 0, rs), g.curveTo(x_c1,rs, x_c2, c2s);
  44.     g.curveTo(x_r, c1s, x_r, 0);
  45.     if (!isHalf){
  46.      g.curveTo(x_r,y_c1,x_c2,y_c2);
  47.      g.curveTo(x_c1,y_r,0,y_r), g.curveTo(c1,y_r,c2,y_c2);
  48.      g.curveTo(r,y_c1,r,0);
  49.     }
  50. }

Also posted in Graphics, Vector, misc, motion, pixel manipulation | Tagged , , , | 5 Comments

Bitwise OR | and Variable Function Arguments (bitwise flags)

Actionscript:
  1. const A:uint = 1;
  2. const B:uint = 2;
  3. const C:uint = 4;
  4. const D:uint = 8;
  5. const E:uint = 16;
  6.  
  7. function orArgs(args:uint):void{
  8.     if (args & A){
  9.         trace("A");
  10.     }
  11.     if (args & B){
  12.         trace("B");
  13.     }
  14.     if (args & C){
  15.         trace("C");
  16.     }
  17.     if (args & D){
  18.         trace("D");
  19.     }
  20.     if (args & E){
  21.         trace("E");
  22.     }
  23. }
  24.  
  25. // test out the function:
  26. orArgs(A | B);
  27. trace("--");
  28. orArgs(A | C | E);
  29. trace("--");
  30. orArgs(B | E | D);
  31. trace("--");
  32. orArgs(C | A);
  33.  
  34. /* outputs:
  35. A
  36. B
  37. --
  38. A
  39. C
  40. E
  41. --
  42. B
  43. D
  44. E
  45. --
  46. A
  47. C
  48. */

If you've every used Array.sort(Array.NUMERIC | Array.DESCENDING) you should have at least a vague idea about what this snippet is doing. It shows how you can pass a variable number of arguments to a function using | (bitwise OR) and & (bitwise AND). I believe the correct term for these kind of arguments is "bitwise flags". This snippet works by having a series of constant values... in this case A - E. Each constant is assigned an unsigned integer... now you may not see the significance of the values 1, 2, 4, 8 and 16 until you see them in binary... get ready this is a pretty cryptic description...

A = 00001 = 1
B = 00010 = 2
C = 00100 = 4
D = 01000 = 8
E = 10000 = 16

If we OR all these together we get: 11111... If we do:

A | E
00001 | 10000

we end up with 10001...

...we can then check which values are stored in the resulting unsigned integer by using AND:

check for A... 10001 & 00001 = 00001 = true
check for E... 10001 & 10000 = 10000 = true
check for C... 10001 & 00100 = 00000 = false

That's it... I just guessed at the way this was being done... if you have another way to do the same thing, feel free to post it in the comments....

Also posted in Operators, binary, misc | Tagged , , , | 1 Comment

Bad PI Approximation

Actionscript:
  1. var inside:Number = 0
  2. var precision:Number = 1000000;
  3. for (var i:int = 0; i<precision; i++){
  4.        var xp:Number = 0.5 - Math.random();
  5.        var yp:Number = 0.5 - Math.random();
  6.        if (Math.sqrt(xp * xp + yp * yp) <0.5){
  7.                inside++;
  8.        }
  9. }
  10. trace(inside / precision * 4);
  11. // outputs : 3.143304

Someone described this bad method of a PI approximation to me the other day... figured I'd try it out... pretty funny. I always liked 22/7... but this one is definitely funnier...

Posted in Math | Tagged , , | 3 Comments

JS Sketch Experiment

Actionscript:
  1. [SWF(width=950, height=600)]
  2. with (graphics) beginFill(0xefefef), drawRect(0,0,stage.stageWidth, stage.stageHeight);
  3. var btn:Sprite = Sprite(addChild(new Sprite()));
  4. with (btn.graphics) beginFill(0x666666), drawRect(0,0,100,20);
  5. with(btn)  x=320, y=430, buttonMode = true;
  6. btn.addEventListener(MouseEvent.ROLL_OVER, function():void{
  7.   with(btn.graphics) clear(), beginFill(0x222222), drawRect(0,0,100,20);
  8. });
  9. btn.addEventListener(MouseEvent.ROLL_OUT, function():void{
  10.   with(btn.graphics) clear(), beginFill(0x666666), drawRect(0,0,100,20);
  11. });
  12. btn.addEventListener(MouseEvent.CLICK, function():void{
  13.     var res:*= ExternalInterface.call("function(){ plot=[]; colors=[]; " + txt.text + " return {plot:plot, colors:colors};}");
  14.     render((res == null) ? {plot:[], colors:[]} : res);
  15. });
  16.  
  17. var v:Shape = Shape(addChild(new Shape()));
  18. v.x = 700;
  19. v.y = 220;
  20. function render(obj:Object):void{
  21.     var plot:Array = obj.plot;
  22.     var colors:Array = obj.colors;
  23.     var leng:int = plot.length;
  24.     v.graphics.clear();
  25.     var inc:int = 0;
  26.     v.graphics.moveTo(plot[0], plot[1]);
  27.     for (var i:int = 2; i<leng; i+=2){
  28.         v.graphics.lineStyle(0,colors[inc++]);
  29.         v.graphics.lineTo(plot[i], plot[i + 1]);
  30.     }
  31. }
  32.  
  33.  
  34. var submit:TextField = TextField(btn.addChild(new TextField()));
  35. submit.defaultTextFormat = new TextFormat("_sans", 12);
  36. with(submit) textColor=0xFFFFFF, width=100, autoSize="center";
  37. with(submit) mouseEnabled = false,  text="submit";
  38.  
  39. var txt:TextField = TextField(addChild(new TextField()));
  40. with(txt) x = y = 20, type = "input", multiline=true;
  41. with(txt) width = 400, height = 400, border = true, background = 0xFFFFFF;
  42. txt.defaultTextFormat = new TextFormat("Monaco", 12);
  43. txt.text = "enter text";
  44. txt.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
  45. function onDown(evt:MouseEvent):void{
  46.     txt.text = "";
  47.     txt.removeEventListener(MouseEvent.MOUSE_DOWN, onDown);
  48. }

This snippet is a mini code editor that allows the user to write javascript into a textfield - the javascript is then run using external interface. Optionally the javascript code can populate two arrays (plot and colors). If these arrays are populated flash, will render the data in each array using the Graphics class.

Have a look at the demo:

If you do something nice with this... post your javascript snippet as a comment and I'll add it to the JS Sketch page...

Also posted in Graphics, dynamic, external data, functions | Tagged , , , | Leave a comment

ActionScript Eval (well, not really)

Actionscript:
  1. var txt:TextField = TextField(addChild(new TextField()));
  2. txt.autoSize = TextFieldAutoSize.LEFT;
  3.  
  4. var myVar:Number = 100;
  5. // works as an expression parser
  6. txt.text = js("return (" + myVar + " * 2 + 10) / 2");
  7. txt.appendText("\n\n");
  8.  
  9. // parses javascript
  10. txt.appendText(js("var a = []; for (var i = 0; i<10; i++){ a.push(i) } return a;"));
  11.  
  12. function js( data:String ):*{
  13.    var res:*= ExternalInterface.call("function(){" + data + "}");
  14.    return (res == null) ? "null" : res;
  15. }

This one made my day - CAN'T believe I never thought of it before... haven't done any speed tests yet... but it shows how to use ExternalInterface.call to parse math expressions and javascript code. This will only work when the swf is shown in an html page of course... so if your in flash cmd+f12...

I got the idea from this code snippet... which actually has an error in it... the decode() function should not return void... I found that snippet thanks to this tweet by makc3d.

Also posted in external data, functions, misc, string manipulation, strings | Tagged , , | Leave a comment

E8 Inspired Forms

This doesn't have much to do with E8.. but it is vaguely inspired by it...

View the demo... (source code is below)

Actionscript:
  1. var hw:Number = stage.stageWidth / 2;
  2. var hh:Number = stage.stageHeight / 2;
  3.  
  4. var canvas:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight, false, 0x333333);
  5. addChild(new Bitmap(canvas));
  6. var vector:Shape = Shape(addChild(new Shape()));
  7.  
  8. // contrast
  9. var cm:ColorMatrixFilter = new ColorMatrixFilter([2.6,0,0,0,-101.6,0,2.6,0,0,-101.6,0,0,2.6,0,-101.6,0,0,0,1,0]);
  10. filters = [cm];
  11.  
  12. var over:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight, false, 0x333333);
  13. var frm:Bitmap = Bitmap(addChild(new Bitmap(over)));
  14.  
  15. frm.blendMode = BlendMode.OVERLAY;
  16.  
  17. var dotNum:int = 250;
  18. var dotConnected:int = 0;
  19. var curr:int = 0;
  20. var prevConnected:int = -1;
  21. var dots:Vector.<Point> = new Vector.<Point>(dotNum, true);
  22.  
  23. // consider altering this value manually
  24. var step:Number =  Math.random()*10
  25.  
  26. var theta:Number = -.5234;
  27. for (var i:int= 0; i <dotNum; i++){
  28.     var r:Number = 280
  29.     theta += step;
  30.     var xp:Number = hw + r  * Math.cos(theta);
  31.     var yp:Number = hh + r * Math.sin(theta);
  32.     dots[i] = new Point(xp, yp);
  33. }
  34.  
  35. var col:uint = 0xFFFFFF;
  36. var a:Point, b:Point;
  37. var connections:int = 0;
  38.  
  39. var txt:TextField = TextField(addChild(new TextField()));
  40. txt.defaultTextFormat = new TextFormat("_sans", 12);
  41. txt.textColor = 0x555555, txt.x = 10, txt.y = 10;
  42. txt.autoSize = "left";
  43. txt.text = step.toString();
  44.  
  45. addEventListener(Event.ENTER_FRAME, onLoop);
  46. function onLoop(evt:Event):void{
  47.      
  48.     over.applyFilter(canvas, over.rect, new Point(0,0), new BlurFilter(10,10, 1));
  49.    
  50.     for (var i:int = 0; i<100; i++){
  51.         if (dotConnected <dotNum - 1){
  52.             if (prevConnected != dotConnected){
  53.                 a = dots[dotConnected];
  54.             }
  55.             prevConnected = dotConnected;
  56.             b = dots[curr];
  57.             curr++;
  58.            
  59.             if (a != b){
  60.                 connections++;
  61.                 vector.graphics.clear();
  62.                 vector.graphics.lineStyle(0,col,0.05);
  63.                 vector.graphics.moveTo(a.x, a.y);
  64.                 vector.graphics.lineTo(b.x, b.y);
  65.                 canvas.draw(vector);
  66.             }
  67.             if (curr> dotNum - 1){
  68.                 curr = 0;
  69.                 dotConnected++;
  70.                 col =[0,0xFFFFFF][int(Math.random()*2)];
  71.             }
  72.         }else{
  73.             break;
  74.             trace("done");
  75.             removeEventListener(Event.ENTER_FRAME, onLoop);
  76.         }
  77.     }
  78. }

Also posted in BitmapData, misc | Tagged , , | Leave a comment

Calculate Surface Area and Volume of a Sphere

Actionscript:
  1. var rad:Number = 1;
  2.  
  3. var surfaceArea:Number = sphereSurfaceArea(rad);
  4. var volume:Number = sphereVolume(rad)
  5. trace("surface area: ", surfaceArea);
  6. trace("volume:", volume);
  7. trace("volume / surface area:", volume / surfaceArea);
  8.  
  9. function sphereSurfaceArea(r:Number):Number{
  10.     return 4 * Math.PI * r * r;
  11. }
  12.  
  13. function sphereVolume(r:Number):Number{
  14.     return r * r * r * (4.0/3.0) * Math.PI;
  15. }
  16.  
  17. /*outputs:
  18. surface area:  12.566370614359172
  19. volume: 4.1887902047863905
  20. volume / surface area: 0.3333333333333333
  21. */

Last night I was feeling curious about sphere volume and sphere surface area... I used WolframAlpha to find the neccessary equations and then wrote the above code snippet...

Check out how WolframAlpha does it:
surface area of a sphere
surface area of a sphere with radius 10
sphere volume
sphere volume with radius 10

Also posted in misc | Tagged , , , | 2 Comments

Gumdrop Torus

Actionscript:
  1. var matrix:Matrix3D = new Matrix3D();
  2.  
  3. var verts:Vector.<Number> = new Vector.<Number>();
  4. var pVerts:Vector.<Number> = new Vector.<Number>();
  5. var uvts:Vector.<Number> = new Vector.<Number>();
  6.  
  7. for (var i:Number = -2; i<2; i+=.04){
  8.     for (var j:Number = -2; j<2; j+=.04){
  9.         for (var k:Number = -2; k<2; k+=.04){
  10. // equation from: http://local.wasp.uwa.edu.au/~pbourke/geometry/gumdrop/
  11.             var yz:Number = j * j + k * k;
  12.              var s:Number = 4 * (Math.pow(i,4) + Math.pow(yz,2))
  13.              + 17 * i * i *(yz) - 20 * (yz + i * i) + 17;
  14.             if (s <0 && s> -0.5){
  15.                 verts.push(i * 60);
  16.                 verts.push(j * 60);
  17.                 verts.push(k * 60);
  18.                 pVerts.push(0), pVerts.push(0);
  19.                 uvts.push(0), uvts.push(0), uvts.push(0);
  20.              }
  21.         }
  22.     }
  23. }
  24.  
  25. var tVerts:Vector.<Number> = new Vector.<Number>();
  26. matrix.appendRotation(90, Vector3D.X_AXIS);
  27. matrix.appendRotation(45, Vector3D.Y_AXIS);
  28. matrix.appendScale(1.7, 1.7, 1.7);
  29. matrix.transformVectors(verts, tVerts);
  30.  
  31. var p:Point = new Point();
  32. var brush:BitmapData=new BitmapData(3,3,true,0x41FFFFFF);
  33. var canvas:BitmapData = new BitmapData(500,500,false, 0x000000);
  34. addChild(new Bitmap(canvas));
  35. var dx:Number=0;
  36. var dy:Number=0;
  37. addEventListener(Event.ENTER_FRAME, onLoop);
  38. function onLoop(evt:Event):void {
  39.     dx += (mouseX - dx)/4;
  40.     dy += (mouseY - dy)/4;
  41.     matrix.identity();
  42.     matrix.appendRotation(dy,Vector3D.X_AXIS);
  43.     matrix.appendRotation(dx,Vector3D.Y_AXIS);
  44.     matrix.appendTranslation(250, 250, 0);
  45.     Utils3D.projectVectors(matrix, tVerts, pVerts, uvts);
  46.     canvas.lock();
  47.     canvas.fillRect(canvas.rect, 0x000000);
  48.     var inc:int = 0;
  49.     for (var i:int = 0; i<pVerts.length; i+=2){
  50.      
  51.         p.x = pVerts[i];
  52.         p.y = pVerts[i+1];
  53.         canvas.copyPixels(brush, brush.rect, p, null, null, true);
  54.     }
  55.     canvas.unlock();
  56. }

Felt like revisiting implicit surface plotting today...

Have a look at the swf over at wonderfl.net

Also posted in 3D, BitmapData | Tagged , , | Leave a comment