Music major scale converter - c#

i am trying to create music major scale converter.
Dose anyone have info how do to it
so far i have
rootNote is scale base note like cMajor or gMajor
note is note that i want to convert into major scale 0-126
if i insert rootNote 60 and note 60 the right return would be 0,
if i insert rootNote 60 and note 61 the right return would be 2,
if i insert rootNote 60 and note 62 the right return would be 4,
if i insert rootNote 60 and note 63 the right return would be 5,
if i insert rootNote 61 and note 60 the right return would be 0,
if i insert rootNote 61 and note 61 the right return would be 1,
if i insert rootNote 61 and note 62 the right return would be 3,
if i insert rootNote 61 and note 63 the right return would be 5,
ok i have this other one and it seems to work
i want to map my sequence out put in major scale
but is there some kind of formula what can i use?
.
public int getINMajorScale(int note, int rootNote)
{
List<int> majorScale = new List<int>();
//int bNote = (int)_bNote.CurrentValue;
int bNoteMpl = bNote / 12;
bNote = 12 + (bNote - (12 * bNoteMpl)) - 7;
majorScale.Add(bNote + (12 * bNoteMpl));
int tBnote = bNote;
int res = 0;
for (int i = bNote; i < bNote + 6; i++)
{
//algorytm
res = tBnote + 7;
int mod = 0;
if (res >= 12)
{
mod = res / 12;
res = res - 12 * mod;
}
tBnote = res;
majorScale.Add(res + (bNoteMpl * 12));
}
majorScale.Sort();
int modNuller = 0;
if (nmr >= 7)
{
modNuller = nmr / 7;
nmr = nmr - 7 * modNuller;
}
return (majorScale[nmr] + (modNuller *12));
}
but it's obviously faulty.

Problems with the code as it stands:
modScaling does nothing more than rootNote % 12 as you always pass in 0 and 11
You define mNote but never use it
i is never used in the for loop and so each of the 5 iterations prints the same thing.
OK, lets translate your examples into actual notes to make it easier to understand (numbers presumably correspond to MIDI notes):
rootNote = 60 (C), note = 60 (C) - output 0
rootNote = 60 (C), note = 61 (C#) - output 2
rootNote = 60 (C), note = 62 (D) - output 4
rootNote = 60 (C), note = 63 (D#) - output 5
rootNote = 61 (C#), note = 60 (C) - output 0
rootNote = 61 (C#), note = 61 (C#) - output 1
rootNote = 61 (C#), note = 62 (D) - output 3
rootNote = 61 (C#), note = 63 (D#) - output 5
I might be being really dense but I'm afraid I can't see the pattern there.
A Major scale is of course made up of the sequence Tone, Tone, Semi-tone, Tone, Tone, Tone, Semi-tone, but how does that map to your outputs?

Given your input-outputs, I think I know what you are looking for.
determine steps = note - rootNote
determine interval = number of semi-tones between rootNote and the note steps up the scale
determine phase = rootNote - 60
This algorithm provides accurate results:
static int getINMajorScale(int note, int rootNote)
{
if (note < rootNote) return 0;
var scale = new[] { 2, 2, 1, 2, 2, 2, 1 };
var phase = rootNote - 60;
var steps = note - rootNote;
var interval = steps == 0
? 0 : Enumerable.Range(0, steps).Sum(step => scale[step % scale.Length]);
var number = phase + interval;
return number;
}
yielding:
static void Main(string[] args)
{
//rootNote = 60(C), note = 60(C) - output 0
//rootNote = 60(C), note = 61(C#) - output 2
//rootNote = 60(C), note = 62(D) - output 4
//rootNote = 60(C), note = 63(D#) - output 5
//rootNote = 61(C#), note = 60 (C) - output 0
//rootNote = 61(C#), note = 61 (C#) - output 1
//rootNote = 61(C#), note = 62 (D) - output 3
//rootNote = 61(C#), note = 63 (D#) - output 5
Console.WriteLine(getINMajorScale(60, 60)); // 0
Console.WriteLine(getINMajorScale(61, 60)); // 2
Console.WriteLine(getINMajorScale(62, 60)); // 4
Console.WriteLine(getINMajorScale(63, 60)); // 5
Console.WriteLine(getINMajorScale(60, 61)); // 0
Console.WriteLine(getINMajorScale(61, 61)); // 1
Console.WriteLine(getINMajorScale(62, 61)); // 3
Console.WriteLine(getINMajorScale(63, 61)); // 5
Console.ReadKey();
}

Related

calculate numbers in array (run length decoding)

int[] bytes = new int[9] { 123, 5, 65, 123, 6, 77, 123, 4, 101 };
int count = 1;
for (int i = 1; i < bytes.Length; i++)
{
if (bytes[i] == 123)
{
count++;
}
else
{
Console.WriteLine(bytes[i]);
}
}
Console.ReadLine();
Im a beginner in programming.
The 123 is some type of "marker"
I dont know how to do a console output like this: 65 65 65 65 65 77 77 77 77 77 77 101 101 101 101
I would appreciate any help
To decode anything, you really need a specification of what that something is. In this case, I could speculate that:
123 means "the following two bytes X and Y should be interpreted as X instances (0-255) of the payload Y"
so you would parse one byte, if it isn't 123: give up because you don't have any other rules to follow, but otherwise, read X and Y, and output X copies of the value Y
In pseudo-code:
while(TryTakeByte(out val)))
switch val
123:
if (!TryTakeByte(out x) || !TryTakeByte(out y)) FailEndOfStream()
for (i from 0 to x)
write y
default:
FailNoClueWhatToDo() // refer to protocol specification

Convert SQL query to C# (SQL query converts base36 code to DateTime)

I'd like to be able to encode \ decode id's containing the datetime in a 7 digit \ base36 configuration, but despite having a SQL query that decodes Id's, so far have had no luck.
I have a SQL query that is able to convert the code to a date time.
Using the following ids, I'm hoping to get the corresponding datetimes.
id Date Time
------------------------------------
A7LXZMM 2004-02-02 09:34:47.000
KWZKXEX 2018-11-09 11:15:46.000
LIZTMR9 2019-09-13 11:49:46.000
Query:
DECLARE #xdate DATETIME, #offset INT
DECLARE #recid VARCHAR(20)
SET #recid = 'KWZKXEX'
SET #offset = (SELECT DATEDIFF(ss, GETUTCDATE(), GETDATE())) /************* Number of hours offset from GMT ************/
SELECT
DATEADD(ss, #offset +
(POWER(CAST(36 AS BIGINT), 6) *
CASE
WHEN (SELECT ISNUMERIC(SUBSTRING(#recid, 1, 1))) = 0
THEN (SELECT ASCII(SUBSTRING(#recid, 1, 1))) - 55
ELSE (SELECT ASCII(SUBSTRING(#recid, 1, 1))) - 48
END +
POWER(CAST(36 AS BIGINT), 5) *
case
when(select isnumeric(substring(#recid,2,1))) = 0
then(select ascii(substring(#recid,2,1))) - 55
else (select ascii(substring(#recid,2,1))) - 48
End
+
POWER(cast(36 as bigint),4) *
case
when(select isnumeric(substring(#recid,3,1))) = 0
then(select ascii(substring(#recid,3,1))) - 55
else (select ascii(substring(#recid,3,1))) - 48
End
+
POWER(cast(36 as bigint),3) *
case
when(select isnumeric(substring(#recid,4,1))) = 0
then(select ascii(substring(#recid,4,1))) - 55
else (select ascii(substring(#recid,4,1))) - 48
End
+
POWER(cast(36 as bigint),2) *
case
when(select isnumeric(substring(#recid,5,1))) = 0
then(select ascii(substring(#recid,5,1))) - 55
else (select ascii(substring(#recid,5,1))) - 48
End
+
POWER(cast(36 as bigint),1) *
case
when(select isnumeric(substring(#recid,6,1))) = 0
then(select ascii(substring(#recid,6,1))) - 55
else (select ascii(substring(#recid,6,1))) - 48
End
+
POWER(cast(36 as bigint),0) *
case
when(select isnumeric(substring(#recid,7,1))) = 0
then(select ascii(substring(#recid,7,1))) - 55
else (select ascii(substring(#recid,7,1))) - 48
End
)
/50
,'1/1/1990')
using System;
using System.Globalization;
using System.Text;
using System.Numerics;
public class Program
{
public static void Main()
{
string sRecid = "A7LXZMM";
char c0 = sRecid[0];
char c1 = sRecid[1];
char c2 = sRecid[2];
char c3 = sRecid[3];
char c4 = sRecid[4];
char c5 = sRecid[5];
char c6 = sRecid[6];
double d6, d5, d4, d3, d2, d1, d0, dsecs;
Console.WriteLine("c0 = " + c0.ToString());
Console.WriteLine();
d6 = Math.Pow(36, 6) * ((Char.IsNumber(c0)) ? (byte)c0 - 55 : (byte)c0 - 48);
d5 = Math.Pow(36, 5) * ((Char.IsNumber(c1)) ? (byte)c1 - 55 : (byte)c1 - 48);
d4 = Math.Pow(36, 4) * ((Char.IsNumber(c2)) ? (byte)c2 - 55 : (byte)c2 - 48);
d3 = Math.Pow(36, 3) * ((Char.IsNumber(c3)) ? (byte)c3 - 55 : (byte)c3 - 48);
d2 = Math.Pow(36, 2) * ((Char.IsNumber(c4)) ? (byte)c4 - 55 : (byte)c4 - 48);
d1 = Math.Pow(36, 1) * ((Char.IsNumber(c5)) ? (byte)c5 - 55 : (byte)c5 - 48);
d0 = Math.Pow(36, 0) * ((Char.IsNumber(c6)) ? (byte)c6 - 55 : (byte)c6 - 48);
dsecs = d6 + d5 + d4 + d3 + d2 + d1 + d0 / 50;
DateTime dt = new DateTime(1990, 1, 1, 0, 0, 0,0, System.DateTimeKind.Utc);
dt = dt.AddSeconds( dsecs ).ToLocalTime();
Console.WriteLine("d6 = " + d6.ToString());
Console.WriteLine("d5 = " + d5.ToString());
Console.WriteLine("d4 = " + d4.ToString());
Console.WriteLine("d3 = " + d3.ToString());
Console.WriteLine("d2 = " + d2.ToString());
Console.WriteLine("d1 = " + d1.ToString());
Console.WriteLine("d0 = " + d0.ToString());
Console.WriteLine("dsecs = " + dsecs.ToString());
Console.WriteLine("dt = " + dt.ToString());
}
}
When I use the following Ids in SQL, I get the following dates.
id Date Time
------------------------------------
A7LXZMM 2004-02-02 09:34:47.000
KWZKXEX 2018-11-09 11:15:46.000
LIZTMR9 2019-09-13 11:49:46.000
Unfortunately my C# "conversion" is wildly inaccurate.
Any suggestions as to where I'm going wrong?
you have the Char.IsNumber... checks flipped in your C# code compared to your SQL script.
In your SQL, you're subtracting 55 if the character is not a number, and 48 otherwise.
In your C# code you're subtracting 55 if the character is a number, and 48 otherwise.
You're also not calculating dsecs correctly I don't think. You need to add d6 through d0 then divide by 50. The way you have it now, you'll divide d0 by 50 then add all the other dn variables.
In other words...
dsecs = d6 + d5 + d4 + d3 + d2 + d1 + d0 / 50;
Should be
dsecs = (d6 + d5 + d4 + d3 + d2 + d1 + d0) / 50;

distribute values of list 1 unequal lenth over list 2 in linear/evenly fashion

I have 2 List<float> of unequal length.
Scores and Grades.
Depending on the configuration one or the other list is greater than the other.
There are 2 scenarios:
Use case 1: 60 scores and 50 grades - 1 to 6 with tenth grades -
I have to distribute 60 scores over 50 grades in an even way.
Thus many grades will have multiple related consecutive scores (1:N relation concerning data structure)
Use case 2: 40 scores and 50 grades - 1 to 6 with tenth grades -
I have to distribute 40 scores over 50 grades in an even way.
Thus 10 grades must be removed (50 - 40) evenly to get a 1:1 relation data structure between scores and grades.
What algorithm`s are available to me that I can solve the problem with C#?
I have written down here the result data I would expect to look like when the implemented algorythm is run.
Use case 1 sample result data:
Scores Grade
0 6
1 5,9
2 - 3 5,8
4 5,7
5 5,6
6 5,5
7 5,4
8 - 9 5,3
10 5,2
11 5,1
12 5
13 4,9
14 - 15 4,8
16 4,7
17 4,6
18 4,5
19 4,4
20 - 21 4,3
22 4,2
23 4,1
24 4
25 3,9
26 - 27 3,8
28 3,7
29 3,6
30 3,5
31 3,4
32 - 33 3,3
34 3,2
35 3,1
36 3
37 2,9
38 - 39 2,8
40 2,7
41 2,6
42 2,5
43 2,4
44 - 45 2,3
46 2,2
47 2,1
48 2
49 1,9
50 - 51 1,8
52 1,7
53 1,6
54 1,5
55 1,4
56 - 57 1,3
58 1,2
59 1,1
60 1
Use case 2 sample result data:
Score Grade
0 6
1 5,9
2 5,8
3 5,6
4 5,5
5 5,4
6 5,3
7 5,1
8 5
9 4,9
10 4,8
11 4,6
12 4,5
13 4,4
14 4,3
15 4,1
16 4
17 3,9
18 3,8
19 3,6
20 3,5
21 3,4
22 3,3
23 3,1
24 3
25 2,9
26 2,8
27 2,6
28 2,5
29 2,4
30 2,3
31 2,1
32 2
33 1,9
34 1,8
35 1,6
36 1,5
37 1,4
38 1,3
39 1,1
40 1
C# converted code for y = f(x) ;-)
int x, y, accum;
int scores = 33;
int grades = 51;
float[] gradesArray = new float[grades];
float[] scoresArray = new float[scores];
for (y = 0; y < grades; y++)
gradesArray[y] = 6.0f - y / 10.0f;
accum = scores / 2;
y = 0;
for (x = 0; x < scores; x++)
{
scoresArray[x] = gradesArray[y];
accum += grades;
while (accum >= scores)
{
y++;
accum -= scores;
}
}
Assume gradesArray is an input array indexed by y, and scoresArray is the output array indexed by x. To generate the output array, for each index in the output array, you need to select the corresponding value from the input array. In pseudo-code:
scoresArray[x] = gradesArray[y] where y = f(x)
In words, each output value scoresArray[x] is taken from location y in the input array gradesArray[y], where y is some function of x. And what is that function? Well it's a line.
Here's some sample code that uses a line drawing algorithm to solve use case 1:
int x, y, accum;
int scores = 61;
int grades = 51;
float[] gradesArray = new float[grades];
float[] scoresArray = new float[scores];
for (y = 0; y < grades; y++)
gradesArray[y] = 6.0f - y / 10.0f;
accum = (scores-1) / 2;
y = 0;
for (x = 0; x < scores; x++)
{
scoresArray[x] = gradesArray[y];
accum += (grades-1);
y += accum / (scores-1);
accum %= (scores-1);
}
To adapt the code for use case 2, just change int scores = 61 to int scores = 41.

List update in every loop run - Unexpected behavior

I tried to write simple program, that simulates lottery and I got some behavior I cannot understand, nor fix:
To keep it simple I excluded code that is irrelevant to the problem
PROGRAM: On click it should Get six different numbers (between 1 and 49) entered by user, get six different random numbers (between 1 and 49) compare them and repeat getting random numbers and comparing with entered until there are three matches.
What is relevant, I am calling function GetResults() on button click and passing to it two parameters (method definition below). I simplified it to button click to show you. There are some conditions and function calls there, but they are working and problem exists even without them so that's why image example on the bottom may be a little different.
private void btnCheck_Click(object sender, EventArgs e)
{
lotto.GetResults(3, ref listRndNumLabels);
lblMatches.Text = lotto.CurrentMatches.ToString();
lblTryCounter.Text = lotto.NumberOfTries.ToString();
lblBalance.Text = lotto.Balance.ToString() + " zł";
lblThreesAmmount.Text = lotto.ThreesAmmount.ToString();
lblFoursAmmount.Text = lotto.FoursAmmount.ToString();
lblFivesAmmount.Text = lotto.FivesAmmount.ToString();
lblSixesAmmount.Text = lotto.SixesAmmount.ToString();
}
The method GetResults() takes 3 as number of desired matches and List of Labels which is updated at the end
public void GetResults(int Choice, ref List<Label> listLblRndNum)
{
_currentMatches = 0;
int desiredNumberOfMatches = Choice;
// while we got other ammount of matches than three, go again
while (_currentMatches != desiredNumberOfMatches)
{
_numberOfTries++;
// get list of mutually exclusive 6 numbers betweeen 1 and 49
var tempList = GetRndNums();
// insert random numbers to list
_listLotteryNumbers.Clear();
for (int i = 0; i < 6; i++)
{
_listLotteryNumbers.Insert(i, tempList[i]);
}
_balance -= _ticketCost;
_currentMatches = 0;
// get number of matches
for (int i = 0; i < 6; i++)
{
foreach (int num in _listLotteryNumbers)
{
if (_listSelectedNumbers[i] == num)
{
_currentMatches++;
}
}
}
//FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - _currentMatches: " + _currentMatches.ToString());
//FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - tempList { " + tempList[0] + " " + tempList[1] + " " + tempList[2] + " " + tempList[3] + " " + tempList[4] + " " + tempList[5] + " }");
//FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - _listLotteryNumbers { " + _listLotteryNumbers[0] + " " + _listLotteryNumbers[1] + " " + _listLotteryNumbers[2] + " " + _listLotteryNumbers[3] + " " + _listLotteryNumbers[4] + " " + _listLotteryNumbers[5] + " }");
//FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - _listSelectedNumbers { " + _listSelectedNumbers[0] + " " + _listSelectedNumbers[1] + " " + _listSelectedNumbers[2] + " " + _listSelectedNumbers[3] + " " + _listSelectedNumbers[4] + " " + _listSelectedNumbers[5] + " }");
// update stats
if (_currentMatches == 3)
{
_threesAmmount++;
_balance += 10;
}
else if (_currentMatches == 4)
{
_foursAmmount++;
_balance += 100;
}
else if (_currentMatches == 5)
{
_fivesAmmount++;
_balance += 3500;
}
else if (_currentMatches == 6)
{
_sixesAmmount++;
_balance += 1000000;
}
//FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - Threes Ammount right after updating: " + _threesAmmount);
//FrmLotto.lbResults.Items.Add("");
// this gets out of the loop if user has chosen from ddl to run once, it is irrelevant here
if (desiredNumberOfMatches == -1)
break;
}
// finally update Labels with the desired result
for (int i = 0; i < 6; i++)
{
listLblRndNum[i].Text = _listLotteryNumbers[i].ToString();
}
}
And this is the function which gets random numbers:
public List<int> GetRndNums()
{
List<int> listRndNums = new List<int>();
Random rndNum = new Random();
for (int i = 0; i < 6; i++)
{
int myNum = 0;
do
myNum = rndNum.Next(1, 49);
while (listRndNums.Contains(myNum));
listRndNums.Add(myNum);
}
listRndNums.Sort();
return listRndNums;
}
So program works as expected if loop run once, or if there is delay after each loop, or if I put breakpoint in the loop.
OTHERWISE there is an unexpected behavior, loop run more than once for the same data (for the same lists), I don't understand why.
look at the images:
Program run once, I clicked button five times, to show you that results are fine:
(btw = Sprawdź = Check, raz = once, do pierwszej trójki = until 3 matches)
http://ultraimg.com/jHQY
And when I select until 3 matches (or click button from the code example above) I am receiving wrong result, loop runs multiple times for the same values.
http://ultraimg.com/jHQn
Would be really grateful for help, I am learning, I know that many parts of code could be improved, many parts are for temp debugging purposes only. But this behavior, I simply don't get it.
In order to fix this problem you should try making
Random rndNum = new Random();
a static variable.
See this :
http://msdn.microsoft.com/en-us/library/system.random.aspx
Pseudo-random numbers are chosen with equal probability from a finite set of numbers. The chosen numbers are not completely random because a definite mathematical algorithm is used to select them, but they are sufficiently random for practical purposes. The current implementation of the Random class is based on Donald E. Knuth's subtractive random number generator algorithm. For more information, see D. E. Knuth. "The Art of Computer Programming, volume 2: Seminumerical Algorithms". Addison-Wesley, Reading, MA, second edition, 1981.
The random number generation starts from a seed value. If the same
seed is used repeatedly, the same series of numbers is generated. One
way to produce different sequences is to make the seed value
time-dependent, thereby producing a different series with each new
instance of Random. By default, the parameterless constructor of the
Random class uses the system clock to generate its seed value, while
its parameterized constructor can take an Int32 value based on the
number of ticks in the current time. However, because the clock has
finite resolution, using the parameterless constructor to create
different Random objects in close succession creates random number
generators that produce identical sequences of random numbers. The
following example illustrates that two Random objects that are
instantiated in close succession generate an identical series of
random numbers.
byte[] bytes1 = new byte[100];
byte[] bytes2 = new byte[100];
Random rnd1 = new Random();
Random rnd2 = new Random();
rnd1.NextBytes(bytes1);
rnd2.NextBytes(bytes2);
Console.WriteLine("First Series:");
for (int ctr = bytes1.GetLowerBound(0);
ctr <= bytes1.GetUpperBound(0);
ctr++) {
Console.Write("{0, 5}", bytes1[ctr]);
if ((ctr + 1) % 10 == 0) Console.WriteLine();
}
Console.WriteLine();
Console.WriteLine("Second Series:");
for (int ctr = bytes2.GetLowerBound(0);
ctr <= bytes2.GetUpperBound(0);
ctr++) {
Console.Write("{0, 5}", bytes2[ctr]);
if ((ctr + 1) % 10 == 0) Console.WriteLine();
}
// The example displays the following output to the console:
// First Series:
// 97 129 149 54 22 208 120 105 68 177
// 113 214 30 172 74 218 116 230 89 18
// 12 112 130 105 116 180 190 200 187 120
// 7 198 233 158 58 51 50 170 98 23
// 21 1 113 74 146 245 34 255 96 24
// 232 255 23 9 167 240 255 44 194 98
// 18 175 173 204 169 171 236 127 114 23
// 167 202 132 65 253 11 254 56 214 127
// 145 191 104 163 143 7 174 224 247 73
// 52 6 231 255 5 101 83 165 160 231
//
// Second Series:
// 97 129 149 54 22 208 120 105 68 177
// 113 214 30 172 74 218 116 230 89 18
// 12 112 130 105 116 180 190 200 187 120
// 7 198 233 158 58 51 50 170 98 23
// 21 1 113 74 146 245 34 255 96 24
// 232 255 23 9 167 240 255 44 194 98
// 18 175 173 204 169 171 236 127 114 23
// 167 202 132 65 253 11 254 56 214 127
// 145 191 104 163 143 7 174 224 247 73
// 52 6 231 255 5 101 83 165 160 231
This problem can be avoided by creating a single Random object rather
than multiple ones. To improve performance, create one Random object
to generate many random numbers over time, instead of repeatedly
creating a new Random objects to generate one random number. To
generate a cryptographically secure random number suitable for
creating a random password, for example, use a class derived from
System.Security.Cryptography.RandomNumberGenerator such as
System.Security.Cryptography.RNGCryptoServiceProvider.

Find specific text in a file and replace that

I'm building a WPF program that is editing save-files for a simulation program to make it easier to adjust certain parameters. The structure of that (txt)file looks like this
{Verdieping 1}
A bunch of data
'Max'
15
20
10
]);
More data
{Verdieping 2}
A bunch of data
'Max'
25
10
40
20
]);
More data
{Verdieping 3}
etc.
Because the name of the list I need is always 'Max' i cannot use Replace("Old_Value", "New_Value"); So I need someway to find the header {Verdieping 1} then look for 'Max" and write the values down until it reaches "]);" so i end up with something like this:
Verdieping_1[0] = 15
Verdieping_1[1] = 20
Verdieping_1[0] = 10
Verdieping_2[0] = 25
Verdieping_2[1] = 10
Verdieping_2[2] = 40
Verdieping_2[3] = 20
Then when I change these values I need to write them back into the file in the correct locations. Right now I'm using this code in order to read and ultimately write the new file:
var Model = System.IO.File.ReadAllText(#"C:\Base_Model.txt");
//format code here...
System.IO.File.WriteAllText(#"C:\New_Model.txt", Model);
Could somebody give me some hints or help as to how I could best solve this?
EDIT
This is the actual file structure of the file I want to eddit:
{Atom: Verdieping 2}
int015(0, 64, [
1
2
3
]);
int015(1, 64, [`ActivityID`
20
21
33
]);
int015(2, 64, [`vtp`
139830296
189540320
169919424
]);
int015(3, 64, [`%`
100
100
100
]);
int015(4, 64, [`Max`
15
5
20
]);
int015(5, 64, [`Fill (1 = fill, 0 = empty)`
1
1
0
]);
SetStatus(0);
int018;
{Atom: Verdieping 2}
int015(0, 64, [
1
2
3
]);
int015(1, 64, [`ActivityID`
22
23
24
]);
int015(2, 64, [`vtp`
166058172
165557860
155960564
]);
int015(3, 64, [`%`
100
100
100
]);
int015(4, 64, [`Max`
15
20
10
]);
int015(5, 64, [`Fill (1 = fill, 0 = empty)`
0
1
1
]);
SetStatus(0);
int018;
The 'Max' I was talking about earlier is actually called:
int015(4, 64, [Max
And as you can see that name is identical for each off the layers, the amount of variables are different tho.
Thanks for the help so far!
var result = Regex.Matches(File.ReadAllText(fileName), #"\[`Max`(.*?)\]", RegexOptions.Singleline)
.Cast<Match>()
.Select(m => m.Groups[1].Value.Split(" \t\n\r".ToArray(), StringSplitOptions.RemoveEmptyEntries))
.ToList();
foreach (var v in result)
{
Console.WriteLine(String.Join(", ", v));
}
OUTPUT:
15, 5, 20
15, 20, 10
Regex maybe? I made this fast answer, which shouldn't be copy pasted, however; you can consider the results.
In this answer I am expecting your array to be in chronological order to prevent the source code from being too long and messy.
The file I read for the 'DataContainer' objects look identical with the file below:
{Verdieping 1}
A bunch of data
'Max'
15
20
10
]);
More data
{Verdieping 2}
A bunch of data
'Max'
25
10
40
20
]);
First of all I find each 'Max' in the string
Then I take all the datas below and print them out
The regex used to find this is: \'Max\'.*?\]\);
Try this code out to see the results
// fill our container
string DataContainer = string.Empty;
using (StreamReader sr = new StreamReader(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "TestFile.txt"))) {
DataContainer = sr.ReadToEnd();
}
// print data
Match regMatch = Regex.Match(DataContainer, #"\'Max\'.*?\]\);", RegexOptions.Singleline);
int verdiepc = 0;
while (regMatch.Success) {
string[] Data = regMatch.Value.Replace("\r", "").Split('\n');
for (int I = 1; I < Data.Length - 1; I++) {
Console.WriteLine("Verdieping_{0}[{1}] = {2}"
, verdiepc, I, Data[I]);
}
Console.Write("\n");
verdiepc ++;
regMatch = regMatch.NextMatch();
}
// prevent immidiate exit
Console.ReadKey();
The output will be:
Verdieping_0[1] = 15
Verdieping_0[2] = 20
Verdieping_0[3] = 10
Verdieping_1[1] = 25
Verdieping_2[2] = 10
........ etc..
I hope you can use this answer. It is a sketch of how you can use Regex to parse the file
string LoadedFile = File.ReadAllText(#"C:\Base_Model.txt");
StringBuilder result = new StringBuilder();
for (int i = 1; i < Int32.MaxValue; i++)
{
Match ma = Regex.Match(LoadedFile, "Verdieping " + i.ToString() + ".+?'Max'.*?([0-9].+?)[]][)];", RegexOptions.Singleline);
if(!ma.Success)
{
break;
}
string a = ma.Result("$1");
MatchCollection mc = Regex.Matches(a, "(\\d+?)\r\n", RegexOptions.Singleline);
for (int j = 0; j < mc.Count; j++)
{
result.AppendLine(String.Format("Verdieping_{0}[{1}] = {2}", i, j, mc[j].Result("$1")));
}
result.AppendLine(String.Empty);
}
File.WriteAllText(#"C:\New_Model.txt", result.ToString());
You may initialize a new List of string which will contain the required output. Then, read the file getting the information between the target section and inserting the values between [ and ]); into the List of string.
Example
static List<string> ReadFile(string Path, string Section)
{
#region Declare Variables
string[] Lines = File.ReadAllLines(Path); //Read Path into Lines
int CurrentValue = 1; //Declare CurrentValue as an Integer of value 1
List<string> RequiredValues = new List<string>(); //Initialize a new List of string of name RequiredValues
#endregion
#region Collect Information
//Look through the section getting the data between [ and ]);
for (int i = 0; i < Lines.Length; i++)
{
if (Lines[i].StartsWith("{" + Section + "}"))
{
i++;
while (!Lines[i].StartsWith("{") && !Lines[i].EndsWith("}"))
{
i++;
if (Lines.Length > i)
{
if (Lines[i].Contains('['))
{
while (true)
{
i++;
if (Lines[i].Contains("]);"))
{
break;
}
RequiredValues.Add(Section + "[" + CurrentValue.ToString() + "] = " + Lines[i]);
CurrentValue++;
}
}
RequiredValues.Add("");
}
else
{
break; //Reached the end of the document
}
}
}
}
#endregion
return RequiredValues; //Return RequiredValues
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
List<string> Contents = ReadFile(#"C:\Base_Model.txt", "Atom: Verdieping 2");
foreach (string str in Contents)
{
System.Diagnostics.Debug.WriteLine(str); //Write str to the trace listeners
}
}
Sample Input
{Atom: Verdieping 2}
int015(0, 64, [
4
5
6
]);
int015(1, 64, [`ActivityID`
20
21
33
]);
int015(2, 64, [`vtp`
139830296
189540320
169919424
]);
int015(3, 64, [`%`
100
100
100
]);
int015(4, 64, [`Max`
15
5
20
]);
int015(5, 64, [`Fill (1 = fill, 0 = empty)`
1
1
0
]);
SetStatus(0);
int018;
{Atom: Verdieping 1}
int015(0, 64, [
1
2
3
]);
int015(1, 64, [`ActivityID`
22
23
24
]);
int015(2, 64, [`vtp`
166058172
165557860
155960564
]);
int015(3, 64, [`%`
100
100
100
]);
int015(4, 64, [`Max`
15
20
10
]);
int015(5, 64, [`Fill (1 = fill, 0 = empty)`
0
1
1
]);
SetStatus(0);
int018;
Sample Output
The following was returned from reading Atom: Verdieping 2
Atom: Verdieping 2[1] = 4
Atom: Verdieping 2[2] = 5
Atom: Verdieping 2[3] = 6
Atom: Verdieping 2[4] = 20
Atom: Verdieping 2[5] = 21
Atom: Verdieping 2[6] = 33
Atom: Verdieping 2[7] = 139830296
Atom: Verdieping 2[8] = 189540320
Atom: Verdieping 2[9] = 169919424
Atom: Verdieping 2[10] = 100
Atom: Verdieping 2[11] = 100
Atom: Verdieping 2[12] = 100
Atom: Verdieping 2[13] = 15
Atom: Verdieping 2[14] = 5
Atom: Verdieping 2[15] = 20
Atom: Verdieping 2[16] = 1
Atom: Verdieping 2[17] = 1
Atom: Verdieping 2[18] = 0
The following output was returned from reading Atom: Verdieping 1
Atom: Verdieping 1[1] = 1
Atom: Verdieping 1[2] = 2
Atom: Verdieping 1[3] = 3
Atom: Verdieping 1[4] = 22
Atom: Verdieping 1[5] = 23
Atom: Verdieping 1[6] = 24
Atom: Verdieping 1[7] = 166058172
Atom: Verdieping 1[8] = 165557860
Atom: Verdieping 1[9] = 155960564
Atom: Verdieping 1[10] = 100
Atom: Verdieping 1[11] = 100
Atom: Verdieping 1[12] = 100
Atom: Verdieping 1[13] = 15
Atom: Verdieping 1[14] = 20
Atom: Verdieping 1[15] = 10
Atom: Verdieping 1[16] = 0
Atom: Verdieping 1[17] = 1
Atom: Verdieping 1[18] = 1
NOTICE: Using this method, the application will only collect the information between the first section it meets even if you have two sections with the same name.
Thanks,
I hope you find this helpful :)

Categories