Sorting a jagged array

by david 4. December 2009 17:30

This week, I had a need to sort a jagged array of integers, and this is the solution that I came up with:

 

public class IntArraySorter

{

    public static void ExampleSorting()

    {

        int[] a = new int[5] { 1,2,3,4,0 };

        int[] b = new int[4] { 1,2,3,0 };

        int[] c = new int[3] { 1,2,0 };

        int[] d = new int[2] { 1,0 };

        int[] e = new int[1] { 1 };

 

        // sort a 2 dimensional array of integers

        int[][] multi = new int[5][] {a,b,c,d,e};

        Array.Sort(multi, CompareIntArrays);

 

        // we can also use it to sort a List of integer arrays

        List<int[]> list = new List<int[]>();

        list.AddRange(new int[][] {a,b,c,d,e });

        list.Sort(CompareIntArrays);

        int your_breakpoint_here = 0;

    }

 

    public static int CompareIntArrays(int[] x, int[] y)

    {

        int length = x.Length > y.Length ? x.Length : y.Length;

        int diff = 0;

        for (int t = 0; t < length; t++)

        {

            diff = safeGet(x, t) - safeGet(y, t);

            if (diff != 0) return diff;

        }

        return x.Length - y.Length;

    }

    private static int safeGet(int[] arr, int element)

    {

        return (element > arr.Length - 1) ? 0 : arr[element];

    }

}

 

...this technique will work with 2 dimensional arrays of integers if they are jagged or not.  So I thought that it was the type of thing that was worth posting up here for future reference.

Improved Annoyatron Schematic

by david 2. December 2009 22:10

I have been starting to learn to use Eagle, so that I can document my circuit diagrams.  Being quite new to designing hardware I'm learning that it's not good enough to just keep a copy of the source code anymore!  So, here is the very simple circuit that makes up my improved Annoyatron:

It's very simple to knock this up on a small breadboard, you just need the ATMega168, a speaker and a battery, just like this:

Obviously, the ATmega168 is overspecified, but I have a few of them and it's easier to mess around with one type of processor.  I really will try to post the source code and some notes on how to get the source code onto the processor as a program.  Honest.

New Soldering Iron

by david 28. November 2009 16:08

I've just bought one of these soldering irons.  I don't know why I didn't do it ages ago!  It's been useful since I've been taking things apart again, for example here is an infrared receiver that I've just removed from an old set-top box:

de-soldered IR receiver

The new iron made a nice job of it, I set the temperature to a reasonably high level and heated the pins at the back of the board whilst tugging the otherside with a pair of pliers.  Each pin came away very easily.  I've only had it for a day, but so far it has been fantastic.  Plus it's great to have an iron without a power cable, it's much less fiddly.

Windows 7 has arrived!

by david 21. November 2009 18:31

It's here!  Finally, Lenovo have sent my upgrade.  It installed without a hitch and I'm very pleased with my new OS.  They never did answer any of my recent e-mails chasing it up though.

Lenovo the third

by david 8. November 2009 12:05

OK, so I thought that I was finally making some progress with my "free" Windows 7 upgrade that comes with my new Lenovo PC.  It took a very long time for them to validate my purchase - they check to see that you really have bought a Lenovo PC that qualifies for the free upgrade.  I have no problem with that, but why did it take so long? In the end they validated my purchase 44 days after I registered for the upgrade.

So now they have actually taken my money, yes that’s right there is a £16 "shipping" charge.  Don’t get me started – it does not cost £16 to send out a piece of software.  Anyway, I have paid, they have taken the money off my card.  In fact, they took the money 12 days ago.  Their e-mail confirming the payment said: "A notification email with the shipping details will be sent to you when your order has been shipped".  Guess what?  Nothing.   So they have taken my £16 and not shipped anything.  So I thought that I would drop them a line via their Windows 7 Upgrade website.  So far all I have got is an automated response: "This is to acknowledge the receipt of your enquiry and you will hear from us within 10 business days".  Whoa! Two weeks to answer an e-mail?  What’s interesting is that before they took my money their responses said: "This is to acknowledge the receipt of your enquiry and you will hear from us within 1-3 business days".  Fascinating how they lose interest in you once they have taken your money, eh?

Running the ATmega168

by david 3. November 2009 00:30

...so like me you've gone and got an ATmega168 from somewhere like http://www.sparkfun.com (which is where I get a lot of my stuff).  It probably cost you about £2.50. Obviously you'd like to get it to do something meaningful, so what do you need to do?  Take a look at this pinout for the processor:

Drop the processor into a breadboard, making sure that it straddles the middle row.  All we need to do is connect pins 1, 7 and 20 to a +5v DC supply and pins 8 and 22 to Ground.  That's all there is to it.  It's useful to note that the purpose of supplying power to pin 1 is to tell the microprocessor that it is not being reset.  Not supplying power to this pin will prevent any code from running, it will remain in reset mode.  We could use this pin like a reset button on a PC by adding a button and a resistor, but we won't worry about that right now.  I'm saying use a 5v supply because it's a nice easy voltage to find (for example, USB will supply 5v with 1A current, which is fine), but the processor should work with a supply between 2.7v and 5.5v (see the datasheet here if you're interested).  I often use a spare PC power supply, because they normally have a 5v output and are not expensive.

 

OK, so the processor may be running - but we've not put any code onto it yet.  So that's the next thing on our todo list.

Improved annoyatron

by david 31. October 2009 10:12

I think that it's good to keep your hand in with some plain old C programming once in a while.  So I ocasionally mess around with microprocessors. I've been working on an improved annoyatron, with my version it will pretend to be a mobile phone - by playing a simple ringtone. This is what it currently looks like:

annoyatron 2.0

 I've used an AVR ATmega168 microprocessor, which is over spec, but I had a couple of them lying around.  In fact all of the other components except for the button cell battery and holder were things that I had sitting around.  What tends to happen is that before I throw anything away, I take it to bits to see if I can remove anything.  Even a salvaged switch can be useful one day.  And it's fun to take stuff apart :-)

So ... what I'll try to do is post more about this - what development tools I've used and what I have discovered along the way.  I'll be sure to refer back to it if nobody else does.

Tron Legacy

by david 18. October 2009 12:57

My wife told me that they were making a new Tron movie (the original came out in 1982) but even better than that, Daft Punk are doing the soundtrack. Sounds good, I really hope they don't mess this film up. So of course, I had to try and find a trailer, which I found here:
http://www.youtube.com/watch?v=a1IpPpB3iWI

Looks good so far. But then I also went and found this: http://www.youtube.com/watch?v=TbBH3bNyge4 it's rework but still cool, Daft Punk are probably still fiddling with it anyway.  But I can't wait to hear the other stuff that they come up with, I think I'm gonna like it...

My best friends wedding

by david 15. October 2009 21:30

Umm, this must be the kind of thing that happens at a geeky wedding:

Wedding photo

Yeah, I'm in there somewhere...

Custom wsdl from WCF

by david 14. October 2009 20:35

I wanted my WCF service to export specific metadata.  Essentially I am building it contract-first and I only want the users to see the hand-crafted wsdl and xsd files that have been created.  If the web service was running in IIS that would be easy, I'd simply set the location of the metadata explicitlly in the web.config file, like this:

 

<serviceBehaviors>

  <behavior name="MyBehavior">

    <serviceMetadata httpGetEnabled="true"

    externalMetadataLocation="MyCustomWsdl.wsdl" />

    <serviceDebug includeExceptionDetailInFaults="false" />

  </behavior>

</serviceBehaviors>

 

But this time my WCF service is running inside a Windows Service, so I can't just let IIS serve the wsdl as a page, unless I install the wsdl file on some other web server, which makes for a deployment nightmare.  So I set about finding out how to override the mechanism that WCF uses for sending the auto-generated wsdl.  I was thinking about overriding that.  I found that I could easily add a class that implements the IWsdlExportExtension and IEndpointBehavior interfaces, and it did allow me to do some fiddling with the generated wsdl, but not at the level I wanted.  I wanted total control, essentially streaming the files that had been hand crafted so carefully.  For a minute, I even considered implementing an HttpListener to send out the files :-0

 

The solution that I have settled on is to add another WCF service to my Windows Service.  This is a simple WCF service that responds to http GET commands, the interface looks like this:

 

[ServiceContract]

public interface ICustomWsdl

{

   [OperationContract]

   [WebGet()]

   Stream MetaData(string name, string extension);

}

 

By returning a Stream, we are able to avoid sending the xml decoration around the response, which would happen if we returned a string, for example.  The basic implementation of this service looks like this:

 

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]

public class CustomWsdlService : ICustomWsdl

{

   private string renameXsd(string src)

   {

      XmlDocument xdoc = new XmlDocument();

      xdoc.LoadXml(src);

      XmlNodeList xmlnodes = xdoc.GetElementsByTagName("xsd:include");

      updateNodes(xmlnodes);

      xmlnodes = xdoc.GetElementsByTagName("xsd:import");

      updateNodes(xmlnodes);

      return xdoc.InnerXml;

   }

 

   private void updateNodes(XmlNodeList xmlnodes)

   {

      for (int i = 0; i < xmlnodes.Count; i++)

      {

         string xsdName = xmlnodes[i].Attributes["schemaLocation"].Value as string;

         if (!string.IsNullOrEmpty(xsdName))

         {

            string newName = "MetaData?name="

              + Path.GetFileNameWithoutExtension(xsdName) + "&extension=xsd";

            xmlnodes[i].Attributes["schemaLocation"].Value = newName;

         }

      }

   }

 

   public Stream MetaData(string name, string extension)

   {

      string path =

         Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

      string src =

         renameXsd(File.ReadAllText(path + "\\" + name + "." + extension));

      return new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(src));

   }

}

 

To make it work we need to add these settings in the config file:

 

<system.serviceModel>

  <behaviors>

    <endpointBehaviors>

      <behavior name="WebEndpointBehavior">

        <webHttp/>

      </behavior>

    </endpointBehaviors>

  </behaviors>

 

  <bindings>

    <webHttpBinding>

      <binding name="HttpBindingConfig"/>

    </webHttpBinding>

  </bindings>

 

  <services

    <service name="CustomWsdlService">

      <endpoint address="wsdl"

      behaviorConfiguration="WebEndpointBehavior" binding="webHttpBinding"

      contract="Aggregation.Broker.Core.ICustomWsdl"

      bindingConfiguration="HttpBindingConfig">

        <identity>

          <dns value="localhost" />

        </identity>

      </endpoint>

      <host>

        <baseAddresses>

           <add baseAddress="http://localhost:8731/Test/" />

        </baseAddresses>

      </host>

    </service>

  </services>

</system.serviceModel>

 

It will serve up xsd and wsdl files as long as they are in the same folder as the running assembly.  Since it can be called via http GET, you can test it in a browser, like this:

 

http://localhost:8731/Test/wsdl/MetaData?name=MyWsdlFileName&extension=Wsdl

 

...which would serve up a wsdl file named MyWsdlFileName.wsdl as long as it was in the same folder as the running binaries.  Any import or include statements in the metadata will be automatically remapped to the same serving method, so the wsdl can reference seperate xsd files (indeed, xsd files can also reference other xsd files).  All this means that another WCF service can use this in the config:

 

<serviceMetadata httpGetEnabled="true" externalMetadataLocation="URL_AS_ABOVE" />

 

Job done, I now have total control of my metadata, I just place the wsdl and xsd files in with the binaries of my Windows Service.  Finally, I just need to host this new WCF service in the existing Windows Service, which is easy.  Hopefully, that is not a bad solution.  I've tested it by pointing SoapUI at some metadata presented this way, and it seems fine, happy days.

About the author

David
I'm a C# developer having worked with .Net since it was in beta.  Before that I mainly worked in C and C++.  I have been developing commercial software for more than 20 years.  I also mess around with microprocesors, but that's just for fun.  I live near Cambridge, England and at the moment I'm contracted to one of the departments at Cambridge University.