I have a program that creates a given number of folders named from a text file. I have the following algorithm:
private void button2_Click(object sender, EventArgs e)
{
if (path != null && Directory.Exists(path))
{
Random rnd = new Random();
for (int i = 0; i < value; i++)
{
var lines = File.ReadAllLines(path1);
var randomLineNumber = rnd.Next(0, lines.Length);
var line = lines[randomLineNumber];
StringBuilder b = new StringBuilder();
for (int j = 0; j < line.Length; j++)
{
char c = line[j];
if (rnd.Next(2) == 0)
{
c = Char.ToUpper(c);
}
b.Append(c);
if (j % 2 == 1)
{
b.Append(rnd.Next(10));
}
}
line = b.ToString();
Directory.CreateDirectory(Path.Combine(path, line));
}
}
}
I have a text file with one word on each line. My algorithm should take a random word from it and rename the folders that I create following the next rule:
lldlldll...ll and so on, where:
l - letter (upper case or lower case - it should be random)
d - digit
Real example:
Number of folders: 13
My list:
computer
explore
wireless
dog
love
electrical
phone
alex
andrew
elevator
door
Desired output:
aN5dR0ew7
dO1G6
DO3oR5
CO4mP7uT6er8
pH6ON1e
al9EX5
eX0pl9Or4e
EL5eC0Tr8iC0aL7
lO4vE2
wi1re9le6Ss47
el3eV0AT8oR9
Actual output:
aN5dR0ew7
dO1G6
DO3oR5
DO4G7
DO6g1
Do9G1
eL4Ec6TR5Ic3Al9
EL5eC0Tr8iC0aL7
eX2Pl6OR7E8
wi1re9le6Ss47
Wi8Re7Le6ss54
The problem is the next one:
If I create 20 folders and I also have 20 words in that .txt file, the algorithm will not use all of the words but just some of them ( and it will repeat them 3 times). The digits are ok / the upper-lower letters are ok. I just have to be sure that each word from that txt will be used.
Any help please ?
There is no guarantee that a Random() instance will generate different values each time its Next method is called. 9 (nine) is a perfectly good random number, and it could be all you'll receive until the end of time.
What you want is the Fisher–Yates shuffle algorithm... You shuffle the lines of the txt file and so you guarantee that all the lines are used, and each line is only used once. If you need more lines than the file has, every time you have used all the lines of the file you re-shuffle it and restart.
This should be the full solution:
Random rnd = new Random();
var lines = File.ReadAllLines(path1);
for (int i = 0; i < value; i++)
{
if (i % lines.Length == 0)
{
// We after using all the rows once
// we used all of them (or at the beginning)
// Shuffle, Fischer-Yates
int n = lines.Length;
while (n > 1)
{
n--;
int k = rnd.Next(n + 1);
string value2 = lines[k];
lines[k] = lines[n];
lines[n] = value2;
}
}
var line = lines[i % lines.Length];
StringBuilder b = new StringBuilder();
for (int j = 0; j < line.Length; j++)
{
char c = line[j];
if (rnd.Next(2) == 0)
{
c = Char.ToUpper(c);
}
b.Append(c);
if (j % 2 == 1)
{
b.Append(rnd.Next(10));
}
}
line = b.ToString();
Directory.CreateDirectory(Path.Combine(path, line));
}
I would create a list of integers right after this row
var lines = File.ReadAllLines(path1);
List<int> list = Enumerable.Range(0, lines.Length).ToList<int>();
Shuffle the list: Randomize a List<T>
and loop trought shuffled lines
for (int i = 0; i < list.Count; i++) {
var lineItem = lines[i];
}
Related
When running this program, my first line has 62 digits while the other lines only have 60. How can I place 2 spaces in front of the first line so each line of the array is no more then 60 characters? So basically it would look like ( with two spaces in the beginning)
9999999999999999999999999999999999999999999999999999999999
999999999999999999999999999999999999999999999999999999999999
999999999999999999999999999999999999999999999999999999999999
using System;
namespace BigFactorial
{
class Program
{
static int MAX = 5000;
//This is telling the program what to multiply.
private static void mult(int[] x, int n)
{
int y = 0, i, m;
for (i = 0; i < MAX; i++)
{
m = y + x[i] * n;
x[i] = m % 10000;
y = m / 10000;
}
}
//This is telling the program how to calculate factorial of n.
public static void Factorial(int[] a, int n)
{
a[0] = 1;
for (int i = n; i > 1; i--)
{
mult(a, i);
}
}
//This is displaing the factorial after the calculation.
public static void Display(int[] a)
{
int i;
for (i = MAX - 1; a[i] == 0; i--) ;
Console.Write(a[i]);
for (int j = i - 1, c = 1; j >= 0; j--, c++)
{
string s = "" + a[j];
Console.Write(s.PadLeft(4, '0'));
if (c % 15 == 0)
Console.WriteLine();
}
Console.WriteLine();
}
public static void Main(string[] args)
{
while (true)
{
//Telling user to enter a number.
Console.Write("Enter a number to factor or a negative number to quit: ");
int n = int.Parse(Console.ReadLine());
//Quit function
if (n < 0) break;
int[] arr = new int[MAX];
Factorial(arr, n);
Display(arr);
}
//100000 is the max number it can calculate
}
}
}
You have already demonstrated that you know how to use String.PadLeft(), so cache the strings that you are writing in memory so you can inspect them rather than writing directly out to the console.
using System.Linq;
using System.Text;
public static void Display(int[] a)
{
int i = 0;
// build the string in memory, so we can inspect the length of the lines
StringBuilder output = new StringBuilder();
output.Append(a[i]);
for (int j = i - 1, c = 1; j >= 0; j--, c++)
{
output.Append($"{a[j]}".PadLeft(4, '0'));
if (c % 15 == 0)
output.AppendLine();
}
// get the lines into an array so we can normalise the length,
// although we know the length today, calculating it expresses the intent better
var lines = output.ToString().Split(new string [] { Environment.NewLine }, StringSplitOptions.None);
var maxLength = lines.Max(x => x.Length);
// now write the output to the console
foreach(var line in lines)
Console.WriteLine(line.PadLeft(maxLength, ' '));
}
It is not necessary to use StringBuilder like this, you could have used a List<string> and that would simplify the code further. It is however useful to identify that code written targeting the Console can easily be refactored to write to memory via StringBuilder as the syntax is very similar.
You could also have used a StringWriter instance called Console and the syntax would be identical... But that was a step too far for a logic block as simple as this.
For my problem I am experiencing today comes in the form of a string array. The goal of this assignment is to use Random with a seed value of 243 as a key to access a hidden message from 22 lines. Within these 22 lines are 5 letters that form a word. Here is 22 lines containing 60 characters in each line and the goal is to use the key to pick the 5 letters from each line.
String[] line = { "<?JRrP*h^vtVc^ppOZI#PCAa{ (n1>&VSf~59eI7Tn5We^77O/CEvgdq}gU0",
"G;t#o=#|^ZWV01`a-h{=Js>!z`_j!&7PB9nCgtfHZ:WtWk4e&#k5i7uV{$E/",
"]7zXf&4uA=n8!Sa08IIoKyc~:#d*T8FcOWjB?~QQ =Ch(S37UT>RYobbSz>#",
"w*A)v5gHh>p9vvVeUzvfmMT~tr)8s(nC`11Lz:qhjjN6c$Z ^T,W$VQqUB/#",
"+NSrOLhed*2;)$z#}=;t7FY?z6?e^?cX+nf;6me6Kt|TBpN ZNr7&9j t4c8",
"-N&E2X/:<_k0W$HpH${*f?M0K_Qp##F!)M){nVAu`4bzab_too;m8YPm!tyR",
"s=69 j&*yLRpb2IR[RNg~O!ZfUhr{czx]mbB}Hau]T(CtI-%0}1NFeRV<ZRb",
"!U-]QY4sN&S2pW+JGaenHc?|)KQJ:,&Cu}s'GIp:59U)J~]n&(/^s6:=htS ",
"'iXi 0;qbk#|kn&/-5Q*mbC2|FN_bVp6tk3K_3):bj+#%1 I/+0 ]I6CEFDX",
" [/,2k( 7ZNy,7GlV#,kk$PVEpXKTn&8mPX&[~o9)q2S]6rs!3k$:i$]*WeA",
"3[KGT5+Z^#FWPt aq{y/|2I##!}5Kzz$9M&LFieF*8f_l4RGuBie]UD!2+Dh",
"7u.qDs=#k5:' S$dKiRmMU>)1lFb)%:;EL/4)#:Juu[_'a1)Q_TGWUe`V%QW",
"zZxtz~aOCoZGN(vny]#N[=1IOqbnGN]iQbN;Vtc' od`$-xN^&ex##z]HO )",
"<q(t2VukYZf%yyNzWODBw40wgc!Nfpr&]Yj- oNM6-t#^`h(R %o+s0'af-N",
"Ut$gg#F?/#Bg!v+j>,aedrzekyzhebJpb wo(-:>:hw1]<v3hEgU%&h]J=zm",
"D]uLuP$ ~;b1pBk% usN#f #ytk[6:Di1Lx[hK;,7u4mbVca:b[` bk]]qQ ",
"dHicvw De/<SM{7+QR#n0iAR^bUe_;}uy;Fr,PUiV?8*F(37a`++Q.nZ&6%3",
"Bcc-1EY1UG} {a on6,UN=P~/rDjKkguKBG<[*xsM#akb+/zA}gn*Nc$hc}>",
" ndhw'TX-O4f=* LZc<#cHIL#xk|]BSv+Z!^<s-ZUUlpi!Q~F7IimyZVD7de",
":Vzi{=[b)HEaV`M-[Wb#FlVFxNN0 I9. G?}Z#tKDmu|'gM LLzlT->M TpL",
"mKb^.+i/#NRXa7]XuX>1!gbR LOQ(q}%1H]x+.mz:=D}xB*<$eWDj_J%g/0a",
"[{&NOLF9YcL^iCvcBcY+A2LB:UoQ|V1{s,?>7krK{pb#8w]pgfa#U$tHNbay" };
For the chunk of code that I am working on comes here.
String[] decrypted = new String[22];
var randNum = new Random(243);
int i, k;
for (i = 0; i < 22; i++)
{
String currentLine = line[i];
for (k = 0; k < 5; k++)
{
decrypted[i] = Convert.ToString(currentLine[randNum.Next(0, 60)]);
}
}
printIt(decrypted);
Console.ReadLine();
}
static void printIt(string[] decrypted)
{
var build = new StringBuilder();
for (int h = 0; h < 22; h++)
{
build.Append(Convert.ToString(decrypted[h]));
}
Console.WriteLine(build);
The help I am looking for is to understand how I can store the 5 characters from each line successfully within the decrypted array.
I can gain the correct answer if I insert directly in my nested for loop the Console.WriteLine(decrypted[i]);
However, if I try to pull the same line anywhere after the for loop containing random, I only am able to pull the first letter of each line.
Change your loop to:
String[] decrypted = new String[110];
for (i = 0; i < 22; i++)
{
String currentLine = line[i];
for (k = 0; k < 5; k++)
{
decrypted[k + i * 5] = Convert.ToString(currentLine[randNum.Next(0, 60)]);
}
}
And Print:
static void printIt(string[] decrypted)
{
var build = new StringBuilder();
for (int h = 0; h < decrypted.Length; h++)
{
build.Append(Convert.ToString(decrypted[h]));
}
Console.WriteLine(build);
}
I was able to solve my own problem after doing a bit more research and deduction of what I could possibly be missing. Here is the solution.
for (i = 0; i < 22; i++)
{
String currentLine = line[i];
for (k = 0; k < 5; k++)
{
decrypted[i] = decrypted[i] + Convert.ToString(currentLine[randNum.Next(0, 60)]);
//Adding the previous character to the new character to help build up the string.
}
It was after I realized I wasn't building up the characters properly I chose to add the previous character and it solved my problem.
I am trying to count how many times a number appears in an array 1 (a1) and then trying to print out that number by storing it in array 2 (a2) just once and then try to print array 2. But first using for loop and a function, I will check that if a number already exist in array 2 then move to next index in array 1, unfortunateley this code is not working; can someone please help me in trying to fix it, I don't need some complex solutions like dictionaries or lists athe moment, although it might be helpful too. thanks, I am not an expert in programming and I try to practise it in my free time, so please help me.
I just want this code to be fixed for my understanding and knowledge
class Program
{
static void Main(string[] args)
{
int i, j;
int[] a1 = new int[10];
int[] a2 = new int[10];
int[] a3 = new int[10];
//takes an input
for (i = 0; i < a1.Length; i++)
{
a1[i] = Convert.ToInt32(Console.ReadLine());
}
for (i = 0; i < a1.Length; i++)
{
Cn(a1, a2); //calls in function
i++; //increments is if true
int count = 0;
for (j = 0; j < a1.Length; j++)
{
//if a number matches with a number in second array
if (a1[i] == a1[j])
{
//do count ++
count++;
// store that number into second array
a2[i] = a1[i];
}
}
//store the number of counts in third array
a3[i] = count;
}
for (i = 0; i < a2.Length; i++)
{
if (a2[i] != 0)
{
Console.WriteLine(a2[i]);
}
}
Console.ReadLine();
}
//function to check if element at current index of array 1 exists in array 2 if yes than break
public static void Cn (int[] aa1, int [] aa2)
{
int k, j;
for ( k = 0; k < aa1.Length; k++)
{
for (j = 0; j < aa2.Length; j++)
{
if (aa1[k] == aa2[j])
break;
}
}
}
}
You probably want to do a group by count:
int[] a1 = new int[10];
var rnd = new Random();
//takes an input
for (int i = 0; i < a1.Length; i++)
{
a1[i] = Convert.ToInt32(rnd.Next(0, 11)); // or Console.ReadLine()
}
var grouped = a1
.GroupBy(x => x)
.Select(g => new
{
Item = g.Key,
Count = g.Count()
}).ToList(); // ToList() is optional, materializes the IEnumerable
foreach (var item in grouped)
{
Console.WriteLine($"number: {item.Item}, count: {item.Count}");
}
This uses a Hash algorithm internally.
You can solve this without a Hash or Dictionary but it wouldn't be very efficient because you need to do lots of linear searches through the arrays.
The advantage of a Hash algorithm is that your lookups or groupings are much faster than if you loop over a complete array to find / increment an item.
I have a list of names (msfuncionarios), with name, RFID-MAC (6 pairs of hexadecimal digits) and others.
When I read the RFID (output in 6 decimal digits), I need to check the name with that MAC.
I have the folowing code, but I think that breaks for memory fault.
The list has 2666 items.
I'm running the program on a Raspberry PI 2 v.B.
string ConvertUidToName(string uid)
{
int j, h;
int k = 0;
string final="";
string[] separators = { "-" };
for (k=0;k <= msfuncionarios.count;k++)
{
TextBox_produto.Text = k.ToString();
string[] words = msfuncionarios[k].MAC.Split(separators, StringSplitOptions.RemoveEmptyEntries);
i = 0;
h = 0;
for (h = 2; h <= 5; h++)
{
j = Convert.ToInt32(words[h], 16);
final = final + j;
}
j = 0;
if (final == uid )
{
return msfuncionarios[k].Nome.ToString();
}
final = "";
}
return uid.ToString();
}
The problem is in your for condition:
for (k=0; k <= msfuncionarios.count; k++)
You are using the <= operator, so the loop runs 2667 times, even for non-existing item msfuncionarios[2666] which is out of bounds. You can fix it by using < operator.
for (k=0; k < msfuncionarios.count; k++)
Solved!
I found a bugg in the API that writes in the list. The list contains empty MAC's and the convertion breaks.
I am trying to write a program that replaces even numbers with the word "EVEN". So far, I have:
List<int> num = new List<int>();
for (int num1 = 0; num < 101; num++)
{
num.add(num1)
}
foreach(int n in num1)
{
if (n/3)
{
num.Replace("EVEN")
}
}
Is this close or am I far off?
var list = new List<string>();
for (int i = 0; i < 101; i++)
{
string value = (i % 2 == 0) ? "EVEN" : i.ToString();
list.Add(value);
}
In one line:
var list = Enumerable.Range(1, 100).Select(i => (i % 2 == 0) ? "EVEN" : i.ToString()).ToList();
not sure why you are trying to do this, but this should work..:
var num = new List<string>();
for (int n = 0; n < 101; n++)
{
num.Add(n % 2 == 0 ? "EVEN" : n.ToString());
}
Solutions have been provided for constructing a list of strings where each element of the list will be the number if it's odd or "EVEN" if it's even.
If, for some reason, you actually need to take an existing list of int and perform such a replacement, make sure you understand a fundamental problem: You can't insert the string "EVEN" into a strongly-typed list of int.
If you do start with a List<int>, you'll have to iterate over it and insert the results into a new List<string>, replacing even numbers with "EVEN" as per #CMP or #Can Gencer's answers.
Enumerable.Range(1, 100)
.Select(n => (n % 2) == 0 ? "EVEN" : n.ToString())
.ToList();
The list of numbers probably should be string if you want to replace with "even".
List<string> numbers = new List<string>();
numbers.Add("1");
numbers.Add("2");
numbers.Add("3");
for (int i = 0; i < numbers.Count; i++)
{
int n = 0;
bool success = int.TryParse(numbers[i], out n);
if (success && n % 2 == 0)
{
numbers[i] = "Even";
}
}
//Output Test Results
foreach (string number in numbers)
{
Console.WriteLine(number);
}