Computer Science Canada

Swap function without temp variable

Author:  Insectoid [ Sat Feb 12, 2011 12:14 pm ]
Post subject:  Swap function without temp variable

Found this over on Cprogramming.com. Nice use of the XOR operator to eliminate the temp variable from a swap function.

code:

swap(a, b){
    a = a XOR b;
    b = a XOR b;
    a = a XOR b;
}


This takes advantage of the fact that a XOR b XOR a = b, similar to the way a RAID works.

after a=a XOR b, a hold the data for both a and b, given that another variable is holding a or b (in this case b).
b = a XOR b retrieves the original a value from a. This can be re-written as b=(a XOR b) XOR b which is equal to b = a XOR b XOR b, which equals the original a.
a = a XOR b retrieves the original b value from a. Since b is now equal to the original a, this is the same as a = a XOR b XOR a, which equals the original b.


It's this kind of stuff that makes me love programming and computer science in general. There's always the naive way (in this case, swapping with a temp variable) and then there's a cool way that involves a bit of creativity.

Author:  bbi5291 [ Sat Feb 12, 2011 12:22 pm ]
Post subject:  Re: Swap function without temp variable

This code will fail if a and b initially point to the same memory address...

Author:  Insectoid [ Sat Feb 12, 2011 1:04 pm ]
Post subject:  RE:Swap function without temp variable

Who's to say that a and b are pointers? This is pseudocode, I intentionally kept it very general.

if a = b, then a XOR a = 0 XOR a = a

So this should still hold true, unless XORing pointers works differently than other types.

Author:  md [ Sat Feb 12, 2011 1:33 pm ]
Post subject:  RE:Swap function without temp variable

'Course xor isn't fast except for integer types (pointers, ints, lots, etc.) and it isn't defined for floating point types (so you'd need to cast) and doesn't work with structs.

This is a classic case of premature optimization. There is no good reason for trying to optimize away the swap variable, especially when it's not a universal optimization *and* it decreases readability so much.

Author:  Insectoid [ Sat Feb 12, 2011 1:36 pm ]
Post subject:  RE:Swap function without temp variable

I never said it was more efficient. I said it was cool and creative. I enjoy writing interesting code to make the reader think a bit. Not expressly obfuscated, just contrasting the norm.

Author:  RandomLetters [ Sat Feb 12, 2011 7:04 pm ]
Post subject:  Re: RE:Swap function without temp variable

Insectoid @ Sat Feb 12, 2011 1:04 pm wrote:
Who's to say that a and b are pointers? This is pseudocode, I intentionally kept it very general.

if a = b, then a XOR a = 0 XOR a = a

So this should still hold true, unless XORing pointers works differently than other types.


This is not true.
if a = b,
a = a XOR a = 0;
a = a XOR a = 0;
a = a XOR a = 0;

a = 0

edit: this is if the memory location is the same, not if the values are the same

Author:  Insectoid [ Sat Feb 12, 2011 7:13 pm ]
Post subject:  RE:Swap function without temp variable

You're thinking about this wrong.

Well, I assumed you were XORing the memory addresses themselves. If the compiler didn't throw some sort of error then I would be correct. If you are XORing the values they point to then yeah, you'll end up with zero. I don't see this happening in conventional sorting algorithms or any situation where you'd want to sort though, and if you ever used this in a situation where two pointers could potentially point to the same thing, you shouldn't ever touch a compiler again.

Author:  Tony [ Sat Feb 12, 2011 7:45 pm ]
Post subject:  Re: RE:Swap function without temp variable

Insectoid @ Sat Feb 12, 2011 1:36 pm wrote:
Not expressly obfuscated, just contrasting the norm.

I trust that you have heard of 0x5f3759df? Laughing

Author:  bbi5291 [ Sat Feb 12, 2011 11:28 pm ]
Post subject:  Re: Swap function without temp variable

Also, on the topic of XOR: XOR linked list.

Author:  z_cross_fire [ Sun Feb 13, 2011 2:30 am ]
Post subject:  Re: RE:Swap function without temp variable

Insectoid @ Sat Feb 12, 2011 1:36 pm wrote:
I never said it was more efficient. I said it was cool and creative. I enjoy writing interesting code to make the reader think a bit. Not expressly obfuscated, just contrasting the norm.


You can do this too:

code:
a = a + b;
b = a - b;
a = a - b;


This switches the values of 'a' and 'b'.

Author:  md [ Sun Feb 13, 2011 9:12 pm ]
Post subject:  Re: Swap function without temp variable

bbi5291 @ 2011-02-12, 11:28 pm wrote:
Also, on the topic of XOR: XOR linked list.

Nifty solution to space constraints... but I shudder to think that it might actually be in use somewhere...

Author:  mirhagk [ Wed Feb 16, 2011 2:20 pm ]
Post subject:  Re: Swap function without temp variable

md @ Sun Feb 13, 2011 9:12 pm wrote:
bbi5291 @ 2011-02-12, 11:28 pm wrote:
Also, on the topic of XOR: XOR linked list.

Nifty solution to space constraints... but I shudder to think that it might actually be in use somewhere...


I mean why not, you have to iterate to get to middle elements anyways, so why not? It'll save memory, and minimize cache misses (although linked lists already have major cache misses lol).

Along these lines, I have taken to a three array method of declaring objects in games and such. Say for a particle engine where there is a great deal of adding and removing particles, but you really only need like less than 65535. I use an array of my elements and call new on each element. Then I push all the numbers from 0 to 65535 into a 16bit stack. These are my free elements, unused particles. Then I have a 16bit linked list of used particles. To create a new particle only requires popping a 16bit integer and adding to a linked list, so three memory calls. To delete a particle requires only removing it from the linked list and pushing back onto the stack. so again three memory calls.

This means I never have to allocate memory except after the first one, and if the element is stored in the array by value, then every element is stored together in memory, making sure to absolutely minimize cache misses.

Using regular arrays means re-allocation and copying of every element (lists minimize it to every so often, but removing elements still requires copying every element after it), and most other methods actually uses more memory than my method which requires 2 pointers, and a linked list (which is the only expensive piece)

Author:  DemonWasp [ Wed Feb 16, 2011 3:20 pm ]
Post subject:  RE:Swap function without temp variable

mirhagk: Have you ever actually profiled the performance of that solution against a more naive solution (such as creating a new object each time you need it, or keeping a standard Queue object -- of whatever kind your language likes -- of "free" objects?

I think, in general, you'll find that the performance difference, if there is one, is either negligible or the opposite of what you think. I know I've had this happen to me more than a few times.

Author:  mirhagk [ Thu Feb 17, 2011 8:13 am ]
Post subject:  RE:Swap function without temp variable

Well the thing is how do you store active ones. You kinda need a linked list. My only addition is storing unused ones in a stack. The array thing is not needed, I just though to use it so that the would be in the same spot in memory. I suppose it wouldn't have a performance difference using the array or not. Just use a linked list for active objects, and a stack to store inactive ones though. That would definetly perform better, because garbage collection is SOOOO SLOW. Seriously, garbage collection should be avoided at all costs, and recycling objects is a great way to avoid garbage.

Author:  DemonWasp [ Thu Feb 17, 2011 10:43 am ]
Post subject:  RE:Swap function without temp variable

Garbage collection can be slow, yes. Or it can be astoundingly fast and helpful: in some JVM implementations, memory allocation is purportedly almost free because the JVM can just hand you the space without making a system call (which tends to be expensive). See here: http://www.ibm.com/developerworks/java/library/j-jtp01274.html

Iteration over a linked list is also quite slow. Depending on implementation (and I don't believe any serious implementation would do this), adding to the end of a linked list can involve iterating over the list.

If you know you'll have at most N items, why not have an array of elements of size N, each with a boolean isActive()? Have you tried this approach and found it to be significantly slower than your current approach?

Author:  mirhagk [ Thu Feb 17, 2011 12:10 pm ]
Post subject:  RE:Swap function without temp variable

It's slower when there are only a few active, and faster when there are many active. Say you have 65000 elements, but only 500 active. Then you have to go through 65000 if statements to see if they are alive, while with a linked list you merely have to iterate through 500. Also what really slows down? Instead of i++ you have node=node.next; It still requires 2 memory calls, and eliminates the increment, granted i is most likely in the cache but still, it doesn't really slow down.

Anyways most implementations don't have anywhere near the maximum active most of the time. Say for instance sparks from bullet fire, 90% of the time there is none, then the linked list way costs almost 0 cpu while an array with isActive still costs full.

So in short, linked list costs more in worst case, but much less in best case, so choose based on implementation.

Author:  DemonWasp [ Thu Feb 17, 2011 3:24 pm ]
Post subject:  Re: Swap function without temp variable

I got tired of arguing the point in vague terms, theory and guesswork, and decided to benchmark a portion of the situation. The problem statement I worked against is:

Track some number of objects, N, all of which start alive. For each repetition, iterate over the alive objects and update them. On each update, an item may die (that object's isAlive() method will return false). Dead objects should never have update() called on them again.


Your approach keeps all the alive objects in a linked list, removing them when they die. My solution keeps all the objects, dead or alive, in an array. The code is at the bottom.


You start off well. When there are 100 items:
code:
Running solutions with settings:
        Initial living: 100
        Repeats: 1000
Solution 'Mirhagk': 15 ms
Solution 'DemonWasp': 125 ms


Even at 1000 items, you're much faster:
code:
Running solutions with settings:
        Initial living: 1000
        Repeats: 1000
Solution 'Mirhagk': 15 ms
Solution 'DemonWasp': 172 ms


But the jump to 10000 does you in:
code:
Running solutions with settings:
        Initial living: 10000
        Repeats: 1000
Solution 'Mirhagk': 985 ms
Solution 'DemonWasp': 156 ms


At, say, 32000, you're toast:
code:
Running solutions with settings:
        Initial living: 32767
        Repeats: 1000
Solution 'Mirhagk': 12906 ms
Solution 'DemonWasp': 172 ms


On this particular machine, your solution started losing at around 4000 items:
code:
Running solutions with settings:
        Initial living: 4000
        Repeats: 1000
Solution 'Mirhagk': 172 ms
Solution 'DemonWasp': 140 ms


The total time reported includes both the init() call and the REPEATS * update() calls.


Those results are with a trivial update() method. In a game program, your update() is probably going to have to check some geometry and do a little bit of matrix / vector arithmetic, maybe make a call to OpenGL / DirectX (practically speaking, you wouldn't do that in update(), but you would still need to iterate over active objects at some point to get them drawing). You have limited time per frame to run this update, so every millisecond wasted on iteration cuts into your time to do fancy math and produce nice visuals.


I also tried a variation on your method that uses an ArrayList instead of a LinkedList (I'm working in Java, and those are the two List implementations worth mentioning). As it turns out, it does a lot better than using a LinkedList in all cases. In the source, this is Solution 'Mirhagk2'. Eventually, however, it comes out slower -- slightly -- than just using an array.


If you still aren't convinced, give the clearest possible problem statement you can and I will implement a few different solutions to solve the problem, then benchmark them using that same framework attached. Feel free to play with it yourself: declare a new class for your solution, make sure it implements Solution, then fill in the init() and update() methods. Add it to the solutions list in the main method and run the program again, trying it with different values for ALIVE and REPEATS.



Java:

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;


public class Benchmark {
       
        public static void main(String[] args) {
                final int ALIVE = 30000;
                final int REPEATS = 1000;
                long start, end;
               
                List<Solution> solutions = new ArrayList<Solution>();
                solutions.add ( new Mirhagk() );
                solutions.add ( new Mirhagk2() );
                solutions.add ( new DemonWasp() );
               
                System.out.println ( "Running solutions with settings:" );
                System.out.println ( "\tInitial living: "+ALIVE );
                System.out.println ( "\tRepeats: "+REPEATS );
                System.out.println ();
                for ( Solution s : solutions ) {
                        start = System.currentTimeMillis();
                        s.init ( ALIVE );
                        for ( int repeat = 0; repeat < REPEATS; ++repeat ) {
                                s.update();
                        }
                        end = System.currentTimeMillis();
                       
                        System.out.println ( "Solution '"+s.getClass().getName()+"': "+(end-start)+" ms" );
                }
        }
       
       
}

/**
 * Any solution to the problem must satisfy this interface
 */
interface Solution {
        public void init ( final int alive );
        public void update ();
}

/**
 * mirhagk's suggested solution: keep a linked list of living objects and
 * iterate over them; when they die, remove them from the list of living
 * objects.
 */
class Mirhagk implements Solution {
        protected List<ShortLived> active = null;
       
        public void init ( final int alive ) {
                active = new LinkedList<ShortLived>();

                for ( int i = 0; i < alive; ++i ) {
                        active.add ( new ShortLived() );
                }
        }

        public void update () {
                for ( int i = 0; i < active.size(); ) {
                        ShortLived s = active.get(i);
                        s.update();
                        if ( !s.isActive() ) {
                                active.remove ( i );
                        } else {
                                ++i;
                        }
                }
        }
}

/**
 * A variation on mirhagk's original suggestion that uses ArrayList instead.
 */
class Mirhagk2 extends Mirhagk {

        public void init ( final int alive ) {
                active = new ArrayList<ShortLived>();

                for ( int i = 0; i < alive; ++i ) {
                        active.add ( new ShortLived() );
                }
        }
}

/**
 * The naive solution: use an array of objects; never discard anything.
 */
class DemonWasp implements Solution {

        protected ShortLived[] all = null;
       
        public void init ( final int alive ) {
                all = new ShortLived[Short.MAX_VALUE];
                // Add alive
                for ( int i = 0; i < alive; ++i ) {
                        all[i] = new ShortLived();
                }
                // Add dead
                for ( int i = alive; i < Short.MAX_VALUE; ++i ) {
                        ShortLived s = new ShortLived();
                        s.setActive ( false );
                        all[i] = s;
                }
        }
       
        public void update () {
                for ( int i = 0; i < all.length; ++i ) {
                        if ( all[i].isActive() ) {
                                all[i].update();
                        }
                }
        }
}


/**
 * An example object that doesn't live very long (particle effects, bullets,
 * etc). The update() method should only be called on active objects, and
 * performs some computation (here, almost no computation).
 */
class ShortLived {
        protected boolean active = true;
       
        public void update () {
                if ( Math.random() < 0.1 ) {
                        active = false;
                }
        }

        public boolean isActive() {
                return active;
        }

        public void setActive(boolean active) {
                this.active = active;
        }
}

Author:  mirhagk [ Thu Feb 17, 2011 5:02 pm ]
Post subject:  RE:Swap function without temp variable

um.... you clearly didnt optimize, how does 10000 checks of a boolean take almost 200 milliseconds.

And did you see what I said, I said linked list would be slower with lots of items, but you will almost never have lots of items in game. THink the spark engine, where when you don't shoot your solution takes 100 ms, and mine takes 0.

regardless, one frame should run in less than 16ms so your coding is very poor. And optimzation does matter when we're talking about an optimazation.

edit: also your code checks mine if it's alive regardless.

Also what happens when you need to delete an element from your list, which happens ALOT with something like a particle engine, then you gotta iterate the entire list again looking for a dead one, whereas mine simply grabs from a stack.

Author:  DemonWasp [ Thu Feb 17, 2011 5:41 pm ]
Post subject:  Re: Swap function without temp variable

I'm running a standard JRE 6 environment. Specifically, it runs with full optimizations, using the Hotspot compiler, in 32-bit mode. You need to read more carefully: this is not slow.

It's also not 10000 checks: it's 1000 repetitions * 10000 objects = 10 million checks. I can see that taking about 200ms on a Pentium 4 pretty easily.

The stated run-times are the times for running the update() method for (REPEAT) iterations. As I have that value set to 1000, that's the equivalent of 1000 frames, or about 17 seconds real-time at 60FPS. This is assuming you lock 1 frame = 1 update, which most professional games don't, but amateur games tend to. If you divide the time over the number of frames, you'll discover that this accounts for around 200 microseconds per frame, which is pretty reasonable.


It is necessary to check whether things are alive in your solution: otherwise, how do we know when to remove them? Note that it only checks things that are still in the "active" list, so it isn't re-checking items that have already died and been removed.


There is nothing wrong with this code. You are welcome to try writing your own (equivalent) version of it in any other language you choose, using whatever compiler you like, whatever collections library you like, and whatever optimizations / optimization-flags you want. Just make sure it's doing the same amount of work: N objects, M repetitions.


As I mentioned: post a clear problem statement, like you would see in a programming contest, and that'll give us an even ground to compete on. I'm letting you define the problem because it is a problem you discovered.


I have come up with an even faster solution, entitled 'Clever':
code:
Running solutions with settings:
        Initial living: 30000
        Repeats: 1000

Solution 'Mirhagk': 9172 ms
Solution 'Mirhagk2': 406 ms
Solution 'DemonWasp': 188 ms
Solution 'Clever': 62 ms



For clarity, that's 62ms for 30,000 objects, iterating 1,000 times. If we assume one iteration per frame, that's 62 microseconds. I suspect that the majority of that time is spent in the Math.random() call, though I haven't profiled this to find out.


Clever works by keeping all the items in an ArrayList (which provides fast indexing / iteration) and using a 'next' field, like a linked list, that tracks the index of the next living element. This avoids the garbage collection / resource allocation associated with LinkedList, the remove() cost of ArrayList, and the iterate / dereference / invoke cost of the array. It is somewhat trickier, however, and would require additional thought to allow dead objects to become alive. A similar principle could be applied to the dead objects, however, allowing for easily finding the next dead object to resurrect.


This approach may be close to what you were thinking of, but uses the trick of having an in-place linked-list instead of an external one.


Java:


/**
 * A clever solution: keep all the objects in an array. Use a 'next' field to
 * contain the index of the next active node; update this linking as we iterate
 * (when necessary). This solution could be easily extended to do the same with
 * dead values, which would make finding the next object to reuse quite...fast.
 */
class Clever implements Solution {

        protected List<LinkedShortLived> all = null;
       
        protected int firstAlive = 0;
       
        public void init ( final int alive ) {
                all = new ArrayList<LinkedShortLived>(alive);
                // Add alive
                for ( int i = 0; i < alive; ++i ) {
                        LinkedShortLived s = new LinkedShortLived();
                        s.next = i+1;
                        all.add ( s );
                }
                all.get(all.size()-1).next = -1;
        }
       
        public void update () {
                LinkedShortLived prev = null;
                for ( int i = firstAlive; i < all.size() && i != -1; ) {
                       
                        LinkedShortLived s = all.get(i);
                        if ( s.isActive() ) {
                                s.update();
                                if ( prev == null ) {
                                        firstAlive = i; // update head
                                } else {
                                        prev.next = i;  // update middle
                                }
                                prev = s;
                        }
                       
                        i = s.next;     // advance to next node
                }
        }
}

class LinkedShortLived extends ShortLived {
        public int next = 0;
}

Author:  mirhagk [ Thu Feb 17, 2011 8:03 pm ]
Post subject:  RE:Swap function without temp variable

Clever could push dead ones to a stack, and yes clever is a better version of a linked list, and I will probably use that implementation. Also rather than querying objects for dead/alive, simply have Update return a boolean, which will be true if it's still alive, and false if it dies during update (the only time it does die).

Rather than assigning some random variable, and then having it iterate through all of them to find the one or two that are dead, objects simply tell the calling method if they do die, making removing rather simple.

Even better, if you expose the previous and next values to the update method, it can simply remove itself, eliminating even more unneccassaryness.

I may combine the clever approach with the above addition.


btw i ran my tests with that one addition all iterating 10 000 times

100 objects
array 5 ms
linked list 1 ms

1000 objects
array 87 ms
linked list 5 ms

10 000 objects
array 700 ms
linked list 64 ms

100 000 objects
array 7096 ms
linked list 835 ms

I quit using array for 1 million, looking at the test data, seems pretty linear so I'm guessing it'd be 70 seconds. However linked list was still only 8705. that checking of isalive kinda killed your implementation of linked list. Either that or Java's linked lists suck compared to C#'s. I'm still confused how my version can do 1 million in the same amount of time as yours did 32 thousand (especially with 10x iterations). I didn't see your algorithm implementing adding new elements to the list, maybe it did, mine didn't, although I don't see how that would make that much of a difference, as adding a node to the end of a linked list doesn't cost much.

Here's my code

code:

class Program
    {
        static void TestIterate(int numObjects, int numIterations)
        {
            TestObject[] testArray = new TestObject[numObjects];
            for (int p = 0; p < numObjects; p++)
            {
                testArray[p] = new TestObject();
            }
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            for (int i = 0; i < numIterations; i++)
            {
                for (int p = 0; p < numObjects; p++)
                {
                    if (testArray[p].alive)
                        testArray[p].Update();
                }
            }
            stopWatch.Stop();
            Console.WriteLine(stopWatch.ElapsedMilliseconds);
        }
        static void TestIterate2(int numObjects, int numIterations)
        {
            LinkedList<TestObject2> testLinkedList = new LinkedList<TestObject2>();
            for (int p = 0; p < numObjects; p++)
            {
                testLinkedList.AddLast(new TestObject2());
            }
            LinkedListNode<TestObject2> node;
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            for (int i = 0; i < numIterations; i++)
            {
                node = testLinkedList.First;
                while (node != null)
                {
                    if (!node.Value.Update())
                    {
                        if (node.Next == null)
                        {
                            testLinkedList.Remove(node);
                        }
                        else
                        {
                            node = node.Next;
                            testLinkedList.Remove(node.Previous);
                           
                        }
                    }
                    else
                    {
                        node = node.Next;
                    }

                }
            }
            stopwatch.Stop();
            Console.WriteLine(stopwatch.ElapsedMilliseconds);
        }
        class TestObject2
        {
            static Random rand = new Random();
            public bool Update()
            {
                if (rand.Next(100) == 0)
                    return false;
                return true;
            }
        }
        class TestObject
        {
            public bool alive = false;
            static Random rand = new Random();
            public void Update()
            {
                if (rand.Next(100)==0)
                    alive=false;
            }
        }
        static void Main(string[] args)
        {
            TestIterate(10000, 10000);
            TestIterate2(10000, 10000);
            Console.ReadKey();
        }
    }

Author:  DemonWasp [ Thu Feb 17, 2011 8:31 pm ]
Post subject:  RE:Swap function without temp variable

I'm at home now, so I'm on a more powerful machine. The numbers will change accordingly.


Instead of a stack, simply link the elements the same way you are for the living objects. Then you have two "linked lists" that are just elements in an array (or, array-list). If you don't want to muck up all the objects you're putting in arrays

The thing to note about the way I've implemented death here is that at every iteration, the population will decrease by 10%. So: 100%, 90%, 81%, 72.9%, etc. It converges to 0 pretty quickly, so the difference between 1000 iterations and 10000 iterations here is minimal. Perhaps there's a better death function out there, but I wouldn't know unless I saw your data.

My clever implementation is pretty quick, even with 1,000,000 entries and 10,000 repeats:
code:
Running solutions with settings:
        Initial living: 1000000
        Repeats: 10000

Solution 'Mirhagk': 1098 ms
Solution 'Clever': 739 ms


I tried running solution Mirhagk2, but it didn't complete in the 30 seconds I gave it.


I did figure out why my implementation of your idea was running slowly, though: apparently, calling List<E>.remove ( int index ); is a bad idea, because it has to iterate again to find that element in the list. Instead, I should be using a ListIterator<E>.remove(). Revised code:
Java:


/**
 * mirhagk's suggested solution: keep a linked list of living objects and
 * iterate over them; when they die, remove them from the list of living
 * objects.
 */
class Mirhagk implements Solution {
        protected List<ShortLived> active = null;

        public void init ( final int alive ) {
                active = new LinkedList<ShortLived>();

                for ( int i = 0; i < alive; ++i ) {
                        active.add ( new ShortLived() );
                }
        }

        public void update () {
                ListIterator<ShortLived> i = active.listIterator();
                for ( ShortLived s = i.next(); i.hasNext(); s = i.next() ) {
                        s.update();
                        if ( !s.isActive() ) {
                                i.remove();
                        } else {
                        }
                }
        }
}


Revised scores:
code:
Running solutions with settings:
        Initial living: 100000
        Repeats: 1000

Solution 'Mirhagk': 95 ms
Solution 'Mirhagk2': 1893 ms
Solution 'Clever': 66 ms


(Your settings):
code:
Running solutions with settings:
        Initial living: 10000
        Repeats: 10000

Solution 'Mirhagk': 33 ms
Solution 'Mirhagk2': 39 ms
Solution 'DemonWasp': 849 ms
Solution 'Clever': 14 ms


So...apparently it makes a gigantic difference to performance when you iterate over everything a bajillion times. My bad Sad

Further observations:
1. Changing the REPEAT count seems to have at most a minimal effect on non-array solutions. Setting it to 100 yields the same times as 1000, and setting it to 10 yields times only slightly shorter. This is because of my randomized death function. A better death function would help.
2. ArrayList performs poorly when removing from the middle, as expected.
3. The difference between Mirhagk and Clever is minimal. It may look like it's "twice as long", but I would hope that with a million elements you're spending more time computing things in the elements than iterating. This difference isn't significant.

Author:  mirhagk [ Fri Feb 18, 2011 7:56 am ]
Post subject:  RE:Swap function without temp variable

Okay I'm glad we have that all worked out. I'm glad we had this lol, I think we both learned stuff.

I think the biggest thing was once the lists started to die out, linked list became a whole lot faster, I'm wary about using a second linked list for dead ones, because that's alot more extra space, and all you need is to add or remove dead ones, like a stack. I believe it should be faster, and at the least, save the space from a double linked list

Author:  DemonWasp [ Fri Feb 18, 2011 8:12 am ]
Post subject:  RE:Swap function without temp variable

That depends on the linked list implementation. Many linked lists, including Java's, also implement a Stack interface. Really though, any collection that provides a fast repeated "get first" operation works just fine: List, Stack, Queue, etc. Under the clever solution, having a "second" linked list of dead entries uses almost no extra space: it uses the same "next" field as the list of living entries, except it has a different "head" index. Since you can traverse the elements out of order, removing an element from one list and adding it to another is a very fast operation (assuming you keep a "tail" index for both living and dead).

And yes, we did both learn things. To be honest, I'll probably just keep using ArrayLists, like I always have. I don't mind losing 25ms of run time for hours of debugging time.

Author:  mirhagk [ Sun Feb 20, 2011 6:29 pm ]
Post subject:  RE:Swap function without temp variable

yeah It's not a big change, but I find I'm more comfortable with my way It makes more sense to me that alive ones and dead ones are in seperate lists.


: