Exemplo n.º 1
0
        }//GenerateStringSimple_Stack

        //REF tex original recursion version, supersceded by GenerateStrings
        static void GenerateString_r(HashInfo hashInfo, List <string>[] allWordsList, int currentDepth, int currentWordListIndex, string currentString, List <int> recurseState, int batchSize, ref int batchCount, string resumeStatePath, StreamWriter sw)
        {
            //tex completed whole string
            if (currentDepth == allWordsList.Length)
            {
                if (hashInfo.inputHashes != null)
                {
                    var hash = hashInfo.HashFunc(currentString);
                    if (hashInfo.inputHashes.Contains(hash))
                    {
                        sw.WriteLine(currentString);
                    }
                }
                else
                {
                    sw.WriteLine(currentString);
                }
                batchCount++;

                //tex write/flush current strings and write resume_state
                if (batchCount >= batchSize)
                {
                    batchCount = 0;

                    sw.Flush();

                    string jsonStringOut = JsonConvert.SerializeObject(recurseState);
                    File.WriteAllText(resumeStatePath, jsonStringOut);

                    string rs = "";
                    foreach (int index in recurseState)
                    {
                        rs += " " + index;
                    }
                    Console.WriteLine(rs + "          : " + currentString);
                }

                return;
            }
            else
            {
                recurseState[currentDepth] = currentWordListIndex;

                List <string> wordList = allWordsList[currentDepth];
                for (int wordListIndex = 0; wordListIndex < wordList.Count; wordListIndex++)
                {
                    string word          = wordList[wordListIndex];
                    string partialString = currentString + word;

                    GenerateString_r(hashInfo, allWordsList, currentDepth + 1, wordListIndex, partialString, recurseState, batchSize, ref batchCount, resumeStatePath, sw);
                }
            }
        }//GenerateString_r
Exemplo n.º 2
0
        /// <summary>
        /// Parallel test a batch of generated strings
        /// </summary>
        /// <param name="hashInfo"></param>
        /// <param name="batch"></param>
        /// <param name="outputStringsStream"></param>
        private static void BatchTest(HashInfo hashInfo, List <string> batch, StreamWriter outputStringsStream)
        {
            ConcurrentBag <string> matches = new ConcurrentBag <string>();

            Parallel.ForEach(batch, currentString => {
                if (hashInfo.inputHashes == null)  //tex if no inputhashes then we just write every generated string
                {
                    matches.Add(currentString);
                }
                else
                {
                    var hash = hashInfo.HashFunc(currentString);
                    if (hashInfo.inputHashes.Contains(hash))
                    {
                        matches.Add(currentString);
                    }
                }
            });//foreach batch

            foreach (string match in matches)
            {
                outputStringsStream.WriteLine(match);
            }
        }//BatchTest
Exemplo n.º 3
0
        }//BatchTest

        //REF CULL Old stack based
        static void GenerateStringsStack(Stack <RecurseStep> resumeState, List <string>[] allWordsLists, HashInfo hashInfo, int batchSize, bool testOnBatch, string resumeStatePath, string stringsOutPath)
        {
            var totalStopwatch = new System.Diagnostics.Stopwatch();

            totalStopwatch.Start();

            int loopCount = 0;

            bool isResume = resumeState != null;

            List <string> batch = new List <string>();

            List <int> recurseState = new List <int>(new int[allWordsLists.Length]);//tex purely for user to get an idea of how it's progressing

            //tex using a custom stack instead of the usual nested loops for generating strings, this allows the whole state to be saved of so program can be quit and resumed later.
            //tex initialize stack
            Stack <RecurseStep> stack = new Stack <RecurseStep>();

            if (resumeState == null)
            {
                RecurseStep startState = new RecurseStep();
                startState.currentDepth         = 0;
                startState.currentWordListIndex = 0;
                startState.currentString        = "";

                stack.Push(startState);
            }
            else
            {
                // tex more stack order shenanigans, dont ask me why
                while (resumeState.Count > 0)
                {
                    stack.Push(resumeState.Pop());
                }
            }//init stack

            if (!isResume)
            {
                Console.WriteLine("Starting GenerateStrings");
            }
            else
            {
                Console.WriteLine("Resuming GenerateStrings");
            }

            using (StreamWriter sw = new StreamWriter(stringsOutPath, isResume)) {//tex StreamWriter append = isResume
                while (stack.Count > 0)
                {
                    loopCount++;
                    RecurseStep state = stack.Pop();

                    //tex you can output currentString here if you want to catch each stage of generation instead of just complete string below
                    //but I currently prefer just having empty strings in the word lists for per word control

                    if (state.currentDepth == allWordsLists.Length)  //tex generated whole test-string
                    {
                        string currentString = state.currentString;

                        if (!testOnBatch)
                        {
                            //tex if no inputhashes then we just write every generated string
                            if (hashInfo.inputHashes == null)
                            {
                                sw.WriteLine(currentString);
                            }
                            else
                            {
                                var hash = hashInfo.HashFunc(currentString);
                                if (hashInfo.inputHashes.Contains(hash))
                                {
                                    sw.WriteLine(currentString);
                                }
                            }
                        }//testOnBatch
                        batch.Add(currentString);

                        //tex write/flush current strings and write resume_state
                        if (batch.Count >= batchSize)
                        {
                            //tex write resume state
                            string jsonStringOut = JsonConvert.SerializeObject(stack);
                            File.WriteAllText(resumeStatePath, jsonStringOut);

                            //tex give user feedback
                            string rs = "";
                            foreach (int wordIndex in recurseState)
                            {
                                rs += " " + wordIndex;
                            }
                            Console.WriteLine(rs + "          : " + currentString);//TODO: order is shifted by one in comparison to wordcounts output earlier in the program, figure out what's up.

                            //tex test batch
                            if (testOnBatch)
                            {
                                BatchTest(hashInfo, batch, sw);
                            }//testOnBatch

                            //tex clear batch and flush/write matches streamwriter
                            batch = new List <string>();
                            sw.Flush();
                        }//batchSize
                    }
                    else    //tex recurse
                    {
                        recurseState[state.currentDepth] = state.currentWordListIndex;

                        List <string> wordList = allWordsLists[state.currentDepth];
                        //tex due to stack the order is actually reversed compared to recursion
                        // for (int wordListIndex = 0; wordListIndex < wordList.Count; wordListIndex++)
                        for (int wordListIndex = wordList.Count - 1; wordListIndex >= 0; wordListIndex--)
                        {
                            //tex this is where we'd normally recursively call the generation function with the current state of the partially generated string
                            //instead we're just seting up our stack of that state, for the next loop
                            RecurseStep nextState = new RecurseStep();
                            nextState.currentDepth         = state.currentDepth + 1;
                            nextState.currentWordListIndex = wordListIndex;
                            nextState.currentString        = state.currentString + wordList[wordListIndex];

                            stack.Push(nextState);
                        }
                    } //if generated whole word
                }     //while stack

                //tex need to process incomplete batch
                if (batch.Count > 0)
                {
                    //tex test batch
                    if (testOnBatch)
                    {
                        BatchTest(hashInfo, batch, sw);
                    }//testOnBatch

                    //tex clear batch and flush/write matches streamwriter
                    batch = new List <string>();
                    sw.Flush();
                } //batch.Count > 0
            }     //using sw

            totalStopwatch.Stop();
            var timeSpan = totalStopwatch.Elapsed;

            Console.WriteLine($"GenerateStrings completed in {timeSpan.Hours}:{timeSpan.Minutes}:{timeSpan.Seconds}:{timeSpan.Milliseconds}");
            Console.WriteLine($"LoopCount: {loopCount}");
        }//GenerateStrings
Exemplo n.º 4
0
        }         //BuildLockstepInfo

        /// <summary>
        /// Main work loop function
        /// A common string generation method is to use depth first recursion, with a depth cut-off, this is to allow partial completions to cover all combinations.
        /// Thus the current state is tied up in the stack.
        /// However if you shift empty strings to the words lists it becomes simpler to maintain a state of the current word indexes for each word list,
        /// build the string from each wordlist/wordIndex, then just advance the wordIndexes.
        /// This also makes it simpler to save off that state so a run can be quit and resumed.
        /// Also (with a bit more complicated advance function) allows for lists to advance in lockstep.
        /// </summary>
        /// IO-IN: Resume state .json
        /// IO-OUT: Resume state .json
        /// IO-OUT: Generated/matched strings .txt
        static void GenerateStrings(List <string>[] wordsLists, int[] lockstepIds, int[] lockstepHeads, HashInfo hashInfo, int maxStringLength, int batchSize, bool testOnBatch, string resumeStatePath, string stringsOutPath)
        {
            var totalStopwatch = new System.Diagnostics.Stopwatch();

            totalStopwatch.Start();
            int loopCount = 0;

            RunState runState = ReadResumeState(resumeStatePath, wordsLists.Length);//tex IO-IN
            bool     isResume = File.Exists(resumeStatePath);

            List <string> batch = new List <string>();

            int[] listSizes = new int[wordsLists.Length];

            for (int i = 0; i < wordsLists.Count(); i++)
            {
                listSizes[i] = wordsLists[i].Count();
            }

            if (!isResume)
            {
                Console.WriteLine("Starting GenerateStrings");
            }
            else
            {
                Console.WriteLine("Resuming GenerateStrings");
            }

            StringBuilder stringBuilder = new StringBuilder(maxStringLength);

            using (StreamWriter outputStringsStream = new StreamWriter(stringsOutPath, isResume)) {//tex IO-OUT StreamWriter append = isResume
                do
                {
                    loopCount++;

                    string currentString = "";
                    stringBuilder.Clear();
                    for (int listIndex = 0; listIndex < wordsLists.Length; listIndex++)
                    {
                        int    wordIndex = runState.recurseState[listIndex];
                        var    wordList  = wordsLists[listIndex];
                        string word      = wordList[wordIndex];
                        stringBuilder.Append(word);//tex appending to a string is slower than stringbuilder at the rate/amount of strings we're using.
                    }
                    currentString = stringBuilder.ToString();

                    if (!testOnBatch)
                    {
                        //tex if no inputhashes then we just write every generated string
                        if (hashInfo.inputHashes == null)
                        {
                            outputStringsStream.WriteLine(currentString);
                        }
                        else
                        {
                            var hash = hashInfo.HashFunc(currentString);
                            if (hashInfo.inputHashes.Contains(hash))
                            {
                                outputStringsStream.WriteLine(currentString);
                            }
                        }
                    }//testOnBatch
                    batch.Add(currentString);

                    //tex write/flush current strings and write resume_state
                    if (batch.Count >= batchSize)
                    {
                        //tex IO-OUT: write resume state
                        string jsonStringOut = JsonConvert.SerializeObject(runState);
                        File.WriteAllText(resumeStatePath, jsonStringOut);

                        //tex give user feedback
                        string rs = " ";
                        foreach (int wordIndex in runState.recurseState)
                        {
                            rs += wordIndex + "\t";
                        }
                        Console.WriteLine(rs + "\t\t: " + currentString);

                        //tex test batch
                        if (testOnBatch)
                        {
                            BatchTest(hashInfo, batch, outputStringsStream);
                        }//testOnBatch

                        //tex clear batch and flush/write matches
                        batch = new List <string>();
                        outputStringsStream.Flush();
                    }//batchSize
                } while (AdvanceState_r(wordsLists.Length - 1, listSizes, lockstepIds, lockstepHeads, ref runState));

                //tex need to process incomplete batch
                if (batch.Count > 0)
                {
                    //tex test batch
                    if (testOnBatch)
                    {
                        BatchTest(hashInfo, batch, outputStringsStream);
                    }//testOnBatch

                    //tex clear batch and flush/write matches streamwriter
                    batch = new List <string>();
                    outputStringsStream.Flush();
                } //batch.Count > 0
            }     //using sw

            //tex print stats
            totalStopwatch.Stop();
            var timeSpan = totalStopwatch.Elapsed;

            Console.WriteLine($"GenerateStrings completed in {timeSpan.Hours}:{timeSpan.Minutes}:{timeSpan.Seconds}:{timeSpan.Milliseconds}");
            Console.WriteLine($"LoopCount: {loopCount}");//tex should match the product of wordsLists counts.
            Console.WriteLine("Completion count:");
            string cs = " ";

            foreach (int completionCount in runState.completionState)
            {
                cs += completionCount + "\t";
            }
            Console.WriteLine(cs);
        }//GenerateStrings