Monday, October 10, 2011

String-matching automaton

static void Main(string[] args)
{
    if (args.Length < 2)
    {

        Console.WriteLine("Usage: {0} string_pattern string",
            Environment.GetCommandLineArgs()[0]);
        return;
    }

    string pattern = args[0].ToUpper();
    string str = args[1].ToUpper();

    // The automaton. Simple state machine that contains back-links to self-repeating
    // patterns inside the pattern. This takes a long time to compute:
    // O(pattern size cubed times size of the alphabet). This makes this algorithm
    // not very practical in general.

    const int alphabetLen = 'Z' - 'A' + 1;
    int [,] transitionFunc = new int[alphabetLen, pattern.Length];
    for (int stateIndex = 0; stateIndex < pattern.Length; ++stateIndex)
    {
        for (int ch = 0; ch < alphabetLen; ++ch)
        {
            string suffix = pattern.Substring(0, stateIndex) + (char)('A' + ch);
            int stateTransition = Math.Min(pattern.Length + 1, stateIndex + 2);
            string prefix;
            do
            {
                --stateTransition;
                prefix = pattern.Substring(0, stateTransition);
            }
            while (!suffix.EndsWith(prefix));
            transitionFunc[ch, stateIndex] = stateTransition;
        }
    }

    // The match.
    int state = 0;
    for (int i = 0; i < str.Length; ++i)
    {
        state = transitionFunc[str[i] - 'A', state];

        if (state == pattern.Length)
        {
            Console.WriteLine("Substring found at " + (i - pattern.Length + 1));
            break;
        }
    }
}

Thursday, October 6, 2011

SleepSort

static void SleepSort(int[] args)
{
    int count = 0;
    TimerCallback t = (object o) =>
    {
        Console.WriteLine(o);
        Interlocked.Increment(ref count);
    };

    foreach (int a in args)
        new Timer(t, a, a * 1000, System.Threading.Timeout.Infinite);

    while (count < args.Length)
        Thread.Sleep(1000);
}

static void Main(string[] args)
{
    SleepSort(new int[] {5, 3, 12, 10, 1, 2});
}

Wednesday, October 5, 2011

Code snippet: how to use Windows Task Scheduler from .NET

First, make a reference to TaskScheduler 1.1 Type Library in COM components.

Then:

using System;
using System.IO;
using System.Threading;

using TaskScheduler;

namespace TaskScheduleDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                if (args[0].Equals("bing"))
                {
                    for (int i = 0; i < 10; ++i)
                    {
                        Console.WriteLine("Bing!");
                        Thread.Sleep(1000);
                    }

                    return;
                }
                else if (args[0].Equals("install"))
                {
                    Install();
                    return;
                }
                else if (args[0].Equals("remove"))
                {
                    Remove();
                    return;
                }
            }


            Console.Error.WriteLine("Usage: {0} {bing|install|remove}");
        }


        static private void Remove()
        {
            ITaskService service = new TaskSchedulerClass();
            service.Connect(null, null, null, null);
            ITaskFolder folder = service.GetFolder(@"\");
            try
            {
                folder.DeleteTask(@"\Microsoft\Bing\Bing", 0);
                folder.DeleteFolder(@"\Microsoft\Bing", 0);
            }
            catch (FileNotFoundException)
            {
            }
            catch (DirectoryNotFoundException)
            {
            }
            catch (System.Runtime.InteropServices.COMException cex)
            {
                // Something else is still there

                if ((uint)cex.ErrorCode != 0x80070091)
                    Console.Error.WriteLine("Failed to remove task: {0}", cex.ErrorCode);
            }
        }


        static private void Install()
        {
            ITaskService service = new TaskSchedulerClass();
            service.Connect(null, null, null, null);

            ITaskFolder folder = service.GetFolder(@"\");
            ITaskFolder bing = null;
            try
            {
                bing = folder.GetFolder(@"Microsoft\Bing");
            }
            catch (FileNotFoundException)
            {
            }


            if (bing == null)
                bing = folder.CreateFolder(@"Microsoft\Bing",

                    "D:(A;;FA;;;BA)(A;;FA;;;SY)(A;;GR;;;WD)");

            ITaskDefinition td = service.NewTask(0);
            td.RegistrationInfo.Description = "Bing!";
            td.Settings.Enabled = true;
            td.Principal.LogonType = _TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN;


            IExecAction action = td.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC)
                as IExecAction;
            string executable = System.Reflection.Assembly.GetExecutingAssembly().Location;
            action.Path = executable;
            action.WorkingDirectory = Path.GetDirectoryName(executable);
            action.Arguments = "bing";


            ITrigger trigger = td.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_TIME);
            trigger.StartBoundary = DateTime.Now.AddMinutes(1).ToString("o");
            trigger.Enabled = true;


            bing.RegisterTaskDefinition(@"Bing", td, 6, null, null,
                _TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN, null);
        }
    }
}