Production of strings based on a simple grammar

This is the solution for the problem http://acm.tju.edu.cn/toj/showp1021.html.
The problem deals with the generation of strings based on a very limited grammar. Given the constraints given (only two chars in the allowed alphabet, and the max string length no greater than 15) the problem becomes suitable for a brute-force with few but important optimizations along the way: restrict the search using the length, restrict the search if you have processed that same string before. Note that functional programming seems the ideal tool for this kind of problem (hence, I have changed the coding style to mimic functional programming):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace LSystem
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length != 5)
            {
                Console.WriteLine("LSystem - solution to problem http://acm.tju.edu.cn/toj/showp1021.html");
                Console.WriteLine("Usage: LSystem.exe <'a' production> <'b' production> <init string> <target string> <length limit>");
                Console.WriteLine("Example: LSystem.exe aa bb ab aaabb 15");
                return;
            }
            Hashtable htAlreadyUsed = new Hashtable();
            bool result = IsThereAMatch(args[3],
                                        args[2],
                                        args[0],
                                        args[1],
                                        Convert.ToInt32(args[4]),
                                        ref htAlreadyUsed);
            Console.WriteLine("{0}", result?"YES":"NO");
        }
        static bool IsThereAMatch(string target,
                                  string current,
                                  string aProduction,
                                  string bProduction,
                                  int lengthLimit,
                                  ref Hashtable htAlreadyUsed)
        {
            if (target == null || current == null) return false;
            if (current == target) return true;
            if (current.Length > lengthLimit || current.Length > target.Length) return false;
            if (htAlreadyUsed.ContainsKey(current)) return false;
            if (!htAlreadyUsed.ContainsKey(current)) htAlreadyUsed.Add(current, true);
            for (int i = 0; i < current.Length; i++)
            {
                string firstPart = (i == 0) ? "" : current.Substring(0, i);
                string secondPart = (i == current.Length - 1) ? "" : current.Substring(i + 1);
                if(current[i] == 'a')
                    if(IsThereAMatch(target, firstPart + aProduction + secondPart, aProduction, bProduction, lengthLimit, ref htAlreadyUsed))
                        return true;
                if(current[i] == 'b')
                    if(IsThereAMatch(target, firstPart + bProduction + secondPart, aProduction, bProduction, lengthLimit, ref htAlreadyUsed))
                        return true;
            }
            return false;
        }
    }
}

Comments

Popular posts from this blog

Advent of Code - Day 6, 2024: BFS and FSM

Golang vs. C#: performance characteristics (simple case study)

Advent of Code - Day 7, 2024: Backtracking and Eval