Category Archives: Math

Polar Coordinates Distribution

If you're at all interested in watching me free from code. I recorded a video of me coding this snippet (which is about 11 minutes long or so).

In the video I create a few functions that allow you to draw shapes like these:

Mathematically this stuff is really simple ... the free form nature of the video takes a less technical perspective as you'll see (I even made a few funny mistakes).



Actionscript:
  1. [SWF(width = 600, height = 600)]
  2. var dotNum:int = 1000;
  3. var dotRad:Number = 0.5;
  4.  
  5. x = 120
  6. y = 100;
  7.  
  8. // extra stuff to display what the functions can do
  9. stage.addEventListener(MouseEvent.CLICK, onDrawAll);
  10.  
  11. function onDrawAll(evt:Event):void{
  12.     graphics.clear();
  13.     for (var i:int = 0; i<16; i++){
  14.         var m:Number;
  15.    
  16.         var rad:Number = 120;
  17.         var xp:Number = i % 4 * rad
  18.         var yp:Number = int(i / 4) * rad
  19.    
  20.         var type:int = int(Math.random() * 4);
  21.         if (type == 0){
  22.           makeShape(xp, yp, rad-60, Math.random() , 1);
  23.         }else if (type == 1){
  24.            makeShape(xp, yp, rad-60, 1,  Math.random());
  25.         }
  26.         else if (type == 2){
  27.            m = Math.random() * 2;
  28.            makeShape(xp, yp, rad-Math.random()*120, m, m);
  29.         }
  30.         else if (type == 3){
  31.            m = Math.random() * 2;
  32.            makeShape(xp, yp, rad-Math.random()*120, m, m/2);
  33.         }
  34.     }
  35. }
  36.  
  37. // main part from the video
  38. function makeShape(xp:Number, yp:Number,
  39.                    maxRad:Number = 100,m0:Number=1,
  40.                    m1:Number=1):void{
  41.     var polarX:Number;
  42.     var polarY:Number;
  43.     var radius:Number;
  44.     graphics.lineStyle(0, 0);
  45.     var theta:Number = Math.random() * Math.PI * 2;
  46.     for (var i:int = 0; i<dotNum; i++){
  47.         radius = Math.random() * maxRad
  48.         polarX = xp + radius * Math.cos(theta * m0);
  49.         polarY = yp + radius * Math.sin(theta * m1);
  50.         theta += 0.1;
  51.          
  52.         makeDot(polarX, polarY);
  53.        
  54.     }
  55. }
  56.  
  57. function makeDot(xp:Number, yp:Number, fillColor:uint = 0x000000):void{
  58.     graphics.beginFill(fillColor);
  59.     graphics.drawCircle(xp, yp, dotRad);
  60.     graphics.endFill();
  61. }

Here it is over at wonderf:

Also posted in Graphics, functions, misc | Tagged , , | 4 Comments

Prefix Notation (Lisp Style)

Today's quiz is not multiple choice. Instead, your task is to write a lisp style math parser. This may sound tricky, but it's surprisingly simple. (well... not simple exactly, it's just simple compared to what one might assume).

Lisp uses prefix notation... where the operator is placed before the operands:

10 * 10

becomes:

* 10 10

You could think of this as a function "*" with two arguments (10, 10). In Lisp this is enclosed with parens:

(* 10 10)

Let's see a few more examples:

100 / 2 + 10

becomes:

(+ (/ 100 2) 10)

...
2 * 4 * 6 * 7

becomes:

(* 2 4 6 7)

...

(2 + 2) * (10 - 2) * 2

becomes

(* (+ 2 2) (- 10 2) 2)

Remember, thinking "functions" really helps. The above can be though of as:

multiply( add(2, 2), subtract(10 , 2), 2)

You should create a function called parsePrefix() that takes a string and returns a number:

Here is some code to test if your parser works properly:

Actionscript:
  1. trace(parsePrefix("(* 10 10)"));
  2.  
  3. trace(parsePrefix("(* 1 (+ 20 2 (* 2 7) 1) 2)"));
  4.  
  5. trace(parsePrefix("(/ 22 7)"));
  6.  
  7. trace(parsePrefix("(+ (/ 1 1) (/ 1 2) (/ 1 3) (/ 1 4))"));
  8.  
  9. /* Should trace out:
  10. 100
  11. 74
  12. 3.142857142857143
  13. 2.083333333333333
  14. */

I highly recommend giving this a try, it was one of those cases where I assumed it would be much trickier than it was.

I've posted my solution here.

Also posted in Quiz | Tagged , , , , | 4 Comments

Float as a Fraction

Actionscript:
  1. // print some floats as fractions
  2. printFraction(0.5);
  3. printFraction(0.75);
  4. printFraction(0.48);
  5.  
  6. // try something a little more complex
  7. var float:Number = 0.98765432;
  8. trace("\na more complex example:");
  9. printFraction(float);
  10. var frac:Array = asFraction(float);
  11. trace("double check it:");
  12. trace(frac[0] + "/" + frac[1] +" = " + frac[0] / frac[1]);
  13.  
  14. /* outputs:
  15. 0.5 = 1/2
  16. 0.75 = 3/4
  17. 0.48 = 12/25
  18.  
  19. a more complex example:
  20. 0.98765432 = 12345679/12500000
  21. double check it:
  22. 12345679/12500000 = 0.98765432
  23. */
  24.  
  25.  
  26. function printFraction(n:Number):void{
  27.     var frac:Array = asFraction(n);
  28.     trace(n + " = " + frac[0] + "/" + frac[1]);
  29. }
  30.  
  31. // takes any value less than one and returns an array
  32. // with the numerator at index 0 and the denominator at index 1
  33. function asFraction(num:Number):Array{
  34.     var decimalPlaces:int = num.toString().split(".")[1].length;
  35.     var denom:Number = Math.pow(10, decimalPlaces);
  36.     return reduceFraction(num * denom, denom);
  37. }
  38.  
  39. // divide the numerator and denominator by the GCF
  40. function reduceFraction(numerator:int, denominator:Number):Array{
  41.     // divide by the greatest common factor
  42.     var divisor:int = gcf(numerator, denominator);
  43.     if (divisor){
  44.         numerator /= divisor;
  45.         denominator /= divisor;
  46.     }
  47.     return [numerator, denominator];
  48. }
  49.                    
  50. // get the greatest common factor of two integers
  51. function gcf(a:int, b:int):int{
  52.     var remainder:int;
  53.     var factor:Number = 0;
  54.     var maxIter:int = 100;
  55.     var i:int = 0;
  56.     while (1){
  57.         if (b> a){
  58.            var swap:int = a;
  59.            a = b;
  60.            b = swap;
  61.         }
  62.         remainder = a % b;
  63.         a = b;
  64.         b = remainder
  65.         if (remainder == 0){
  66.             factor = a;
  67.             break;
  68.         }else if (remainder==1){
  69.             break;
  70.         }else if (i> maxIter){
  71.             trace("failed to calculate gcf");
  72.             break;
  73.         }
  74.         i++;
  75.     }
  76.     return factor;
  77. }

This snippet contains a few functions for calculating fractions based on float values. Writing this brought back some memories from grade school math.

Also posted in misc | Tagged , , | 4 Comments

Greatest Common Factor (divisor)

Actionscript:
  1. trace(gcf(75,145));
  2.  
  3. // outputs 5
  4.  
  5. function gcf(a:int, b:int):int{
  6.     var remainder:int;
  7.     var factor:Number = 0;
  8.     while (1){
  9.         if (b> a){
  10.            var swap:int = a;
  11.            a = b;
  12.            b = swap;
  13.         }
  14.         remainder = a % b;
  15.         a = b;
  16.         b = remainder
  17.         if (remainder == 0){
  18.             factor = a;
  19.             break;
  20.         }else if (remainder==1){
  21.          
  22.             break;
  23.         }
  24.     }
  25.     return factor;
  26. }

I was messing around with Egyptian Fractions and found myself in need of some interesting functions. The first function I realized I would be needing was for a greatest common factor (GCF or GCD).

The above snippet is a quick implementation of Euclid's algorithm. It will return 0 if no GCF is found...

I wrote a few helper functions while working with Egyptian fractions... will post them over the next few days.

Posted in Math | Tagged , , | 4 Comments

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