-4

Hey i want to generate Random Texts from 4 different Textfiles. The first File have 2 Textslines, the secound have 2 Textline the thrid have 3 textlines and the fourth have 1 textline. With that it should be possible to generate 2x2x3x1 different texts.

I dont know why but the programm altimes just generate 2 different texts and then it runs in a endless loop.

Any idea what i can do to avoid this? - Normaly it should end with 4 different texts.

If i add to the other textfiles with just 2 lines 1 additional line, so that all files have 3 lines and just the last textfile have 1 line it works.

But normaly it should work with 2 lines too.

the Lists count 2 Lines and randam should generate random number between 0 and 2 minus 1 so its alltimes random between 0 and 1 and should select a random index in the list 0 or 1. But with 2 elements in the list it alltimes select the same index.

I use the following code:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace VKTextGenerator
{
    class Program
    {
        string sFullText = "";
        string sFirstTextPart = "";
        string sSecoundTextPart = "";
        string sThirdTextPart = "";
        string sLinkText = "";
        int iAnzahlTexte = 4;



        static void Main(string[] args)
        {
            Random rnd = new Random();
            Program self = new Program();

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

            self.deleteFullTextFile();

            for (int i = 0; i < self.iAnzahlTexte; i++)
            {

                self.ReadFirstTextPart();
                Thread.Sleep(rnd.Next(10, 5000));
                self.ReadSecoundTextPart();
                Thread.Sleep(rnd.Next(10, 5000));
                self.ReadThirdTextPart();
                self.ReadLinkText();

                self.sFullText = self.sFirstTextPart + " " + self.sSecoundTextPart + " " + self.sThirdTextPart + " " + self.sLinkText;


                if (!allTexts.Contains(self.sFullText))
                {
                    allTexts.Add(self.sFullText);
                    self.AppendTextToFile();
                }
                else
                {
                    i--;
   
                }
            }
        }

        internal static string GetStringSha256Hash(string text)
        {
            if (String.IsNullOrEmpty(text))
                return String.Empty;

            using (var sha = new System.Security.Cryptography.SHA256Managed())
            {
                byte[] textData = System.Text.Encoding.UTF8.GetBytes(text);
                byte[] hash = sha.ComputeHash(textData);
                return BitConverter.ToString(hash).Replace("-", String.Empty);
            }
        }

        public void deleteFullTextFile()
        {
            string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
            path = removeExeFromPathChar(path);
            path = path + @"\FinishedText\";
            VerifyDir(path);
            string fileName = "FullTexts.txt";

            if (File.Exists(path + fileName))
            {
                File.Delete(path + fileName);
            }
        }

        public void ReadFirstTextPart()
        {
            List<string> textList = new List<string>();
            Random rnd = new Random();

            string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
            path = removeExeFromPathChar(path);
            path = path + @"\Config\";
            string fileName = "FirstTextPart.txt";

            textList = ReadTextFile(path + fileName);
            if (textList.Count > 0)
            {
                sFirstTextPart = textList[rnd.Next(0, textList.Count - 1)];
            }
        }

        public void ReadSecoundTextPart()
        {
            List<string> textList = new List<string>();
            Random rnd = new Random();

            string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
            path = removeExeFromPathChar(path);
            path = path + @"\Config\";
            string fileName = "SecoundTextPart.txt";

            textList = ReadTextFile(path + fileName);
            if (textList.Count > 0)
            {
                sSecoundTextPart = textList[rnd.Next(0, textList.Count - 1)];
            }
        }

        public void ReadThirdTextPart()
        {
            List<string> textList = new List<string>();
            Random rnd = new Random();

            string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
            path = removeExeFromPathChar(path);
            path = path + @"\Config\";
            string fileName = "ThirdTextPart.txt";

            textList = ReadTextFile(path + fileName);
            if (textList.Count > 0)
            {
                sThirdTextPart = textList[rnd.Next(0, textList.Count - 1)];
            }
        }

        public void ReadLinkText()
        {
            List<string> textList = new List<string>();
            Random rnd = new Random();

            string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
            path = removeExeFromPathChar(path);
            path = path + @"\Config\";
            string fileName = "LinkText.txt";

            textList = ReadTextFile(path + fileName);
            if (textList.Count > 0)
            {
                sLinkText = textList[rnd.Next(0, textList.Count - 1)];
            }
        }

        private static List<String> ReadTextFile(string path)
        {
            List<String> lines = new List<String>();
            using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
            {
                while (sr.Peek() != -1)
                    lines.Add(sr.ReadLine());
            }
            return lines;
        }

        public void AppendTextToFile()
        {
            string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
            path = removeExeFromPathChar(path);
            path = path + @"\FinishedText\";
            VerifyDir(path);
            string fileName = "FullTexts.txt";

            try
            {
                System.IO.StreamWriter file = new System.IO.StreamWriter(path + fileName, true);
                file.WriteLine(sFullText);
                file.Close();
            }
            catch (Exception) { }
        }

        public static String removeExeFromPathChar(String s)
        {
            int exeLength = "VKTextGenerator.exe".Length;

            return (s == null || s.Length == 0)
              ? null
              : (s.Substring(0, s.Length - exeLength));
        }

        public void VerifyDir(string path)
        {
            try
            {
                DirectoryInfo dir = new DirectoryInfo(path);
                if (!dir.Exists)
                {
                    dir.Create();
                }
            }
            catch { }
        }
    }
}

Here is a minified version of the problem. I realized now, that the problem is, if i have just 2 lines of text in my textfile where i want to select random index between 0 and 1. I got alltimes the same result for the random index of thy line rnd.Next(0, xxx.count -1) if the xxx.count are just 2 if its 3 or 4 its ok but with 2 it have problems and i dont understand why. the code is below.

Please help

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace VKTextGenerator
{
    class Program
    {

        string sFullText = "";
        string sFirstTextPart = "";
        int iAnzahlTexte = 200;

        Random rnd = new Random();

        static void Main(string[] args)
        {

            Program self = new Program();

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

            self.deleteFullTextFile();

            for (int i = 0; i < self.iAnzahlTexte; i++)
            {

                self.ReadFirstTextPart();
                Thread.Sleep(self.rnd.Next(10, 200));

                self.sFullText = self.sFirstTextPart + " " + self.sSecoundTextPart + " " + self.sThirdTextPart + " " + self.sLinkText;

                allTexts.Add(self.sFullText);
                self.AppendTextToFile();

            }
        }

        public static String removeExeFromPathChar(String s)
        {
            int exeLength = "VKTextGenerator.exe".Length;

            return (s == null || s.Length == 0)
                ? null
                : (s.Substring(0, s.Length - exeLength));
        }
        
        public void deleteFullTextFile()
        {
            string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
            path = removeExeFromPathChar(path);
            path = path + @"\FinishedText\";
            string fileName = "FullTexts.txt";

            if (File.Exists(path + fileName))
            {
                File.Delete(path + fileName);
            }
        }

        public void ReadFirstTextPart()
        {
            List<string> textList = new List<string>();

            string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
            path = removeExeFromPathChar(path);
            path = path + @"\Config\";
            string fileName = "FirstTextPart.txt";

            textList = ReadTextFile(path + fileName);
            if (textList.Count > 0)
            {
                sFirstTextPart = textList[rnd.Next(0, textList.Count - 1)];
            }
        }

        private static List<String> ReadTextFile(string path)
        {
            List<String> lines = new List<String>();
            using (StreamReader sr = new StreamReader(path, Encoding.UTF8))
            {
                while (sr.Peek() != -1)
                    lines.Add(sr.ReadLine());
            }
            return lines;
        }

        public void AppendTextToFile()
        {
            string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
            path = removeExeFromPathChar(path);
            path = path + @"\FinishedText\";
            string fileName = "FullTexts.txt";

            try
            {
                System.IO.StreamWriter file = new System.IO.StreamWriter(path + fileName, true);
                file.WriteLine(sFullText);
                file.Close();
            }
            catch (Exception) { }
        }

    }
}
Alkadir
  • 3
  • 3
  • 1
    all that self stuff is very odd and not needed – pm100 Mar 04 '22 at 01:18
  • Probably a duplicate of [this question](https://stackoverflow.com/questions/1654887/random-next-returns-always-the-same-values) about `Random` always returning the same value. – DiplomacyNotWar Mar 04 '22 at 01:18
  • ReadTExtFile does the same job as File.ReadAllLines – pm100 Mar 04 '22 at 01:20
  • you are assuming that using Random will get you all possible combinations, thats not true. – pm100 Mar 04 '22 at 01:22
  • @pm100 yes i know but i just wanted it qick and dirty :) no need for perfection with just so low number of codelines – Alkadir Mar 04 '22 at 01:25
  • @DiplomacyNotWar i thinked this first to and so i added Thread.Sleep(rnd.Next(10, 20000)); between my functioncalls but with the same result. just 2 different. – Alkadir Mar 04 '22 at 01:26
  • @pm100 no i dont think that random give me all combinations? why you think this i just use random to select 1 element from the list at a random index – Alkadir Mar 04 '22 at 01:27
  • your question is not very clear. You have 4 files each with varying number of lines (is that what you mean by 'texts'?) and you want to assemble a set of files (4?) with a random combination of one line from each file. Is that correct? – pm100 Mar 04 '22 at 01:30
  • @pm100 yes this is correct – Alkadir Mar 04 '22 at 01:31
  • Iam woundering why it works for 2 generated strings - with different text on the thridTextPart. The other 3 are the same and after this 2 strings generated - alltimes endless loop – Alkadir Mar 04 '22 at 01:33
  • 1
    You posted a lot of code here. This is probably a sign that you haven't actually debugged the code. Do you know how to use your IDE's debugger? Assuming you're using Visual Studio, [start here](https://docs.microsoft.com/en-us/visualstudio/debugger/debugger-feature-tour?view=vs-2022). By stepping through the code line by line with the debugger attached, you'll be able to see exactly where the execution of the app deviates from your expectations. – mason Mar 04 '22 at 01:54
  • @mason i know how to debug. if your read the code above you can see that i have debugged and added the results for the indexes and the counts ..... – Alkadir Mar 04 '22 at 11:33

2 Answers2

0

here is a short and sweet one. I am not going to debug your original, you should be able to do it with a debugger

using System;
using System.Collections.Generic;
using System.Text;

class Program {

    public static void Main() {
        string[] files = new string[] { "one.txt" , "two.txt", "three.txt", "four.txt" };
        List<string[]> contents = new();
        foreach (string file in files) {
            var lines = File.ReadAllLines(file);
            contents.Add(lines);
        }
        var rand = new Random();
   
        for (int k = 0; k < 4; k++) {
            var final = new StringBuilder();
            for (int i = 0; i < files.Length; i++) {
                int lineNo = rand.Next(contents[i].Length - 1);
                final.AppendLine(contents[i][lineNo]);
            }
            Console.WriteLine(final.ToString());
        }

    }
}
pm100
  • 42,706
  • 22
  • 76
  • 135
  • looks nice but do totaly different stuff lke my code. – Alkadir Mar 04 '22 at 11:31
  • i added a real minified version at the top. Maybe you can test with it wou.ld be realy nice. The problem is descriped now more in detail too on the top – Alkadir Mar 04 '22 at 11:48
0

the answer is in the docs https://docs.microsoft.com/en-us/dotnet/api/system.random.next?view=net-6.0

32-bit signed integer that is greater than or equal to 0 and less than MaxValue.

rand.Next(0,1) will always generate 0. I have the same error in my code.

int lineNo = rand.Next(contents[i].Length - 1);

should be

 int lineNo = rand.Next(contents[i].Length);

BTW I wrote my code in order to show that yours is waay way too long

pm100
  • 42,706
  • 22
  • 76
  • 135
  • @Alkadir you really need to learn the C# IO library. `removeExeFromPathChar` is exactly Path.GetDirectory`, `AppendTextToFile` is `File.AppendAllText` , you dont need to test if a file exists before calling File.Delete,...... – pm100 Mar 04 '22 at 20:05
  • @Alkadir and please do that GetExecutingAssembly stuff once – pm100 Mar 04 '22 at 22:02
  • @Alkadir you have 2 implementations in the question now. Hard for me to help since I dont know what you are running. The first one has a very strange loop in it so it might be that. But honestly your code is very messy so its hard to help you (I mean why is there a Peek loop in the read function) Where is it looping, break in with the debugger and see. – pm100 Mar 04 '22 at 23:54
  • @Alkadir I mean - why do you have sleeps in there, why does the first loop decrement `i` under some conditions. Why not just take my code – pm100 Mar 04 '22 at 23:57