Split input with two termination numbers into two arrays c# - c#

Lets assume we have an input from keyboard.
I dont know the length of the input, but I know that the first part is an array of integers, where consecutive groups of three numbers describe assets: type,value,amount.
then termination number is -1 then I have another array of integers and then again termination number -1
For example:
1 500 5 2 25 100 3 10 50 -1 3 9 -1
So I want to have 2 containers to work with first is {(1,500,5),(2,25,100),(3,10,50)} and second is {3,9}.
How I can make this happen?

This will give you a List of structs containing the asset data triples from the first part of the string, and an array of ints from the second part:
public struct assetData {
public int type;
public int value;
public int amount;
};
void Main()
{
string keyboard = "1 500 5 2 25 100 3 10 50 -1 3 9 -1";
string[] parts = keyboard.Split("-1", StringSplitOptions.RemoveEmptyEntries);
int[] assetInput = parts[0].Trim().Split().Select(int.Parse).ToArray();
int[] numbers = parts[1].Trim().Split().Select(int.Parse).ToArray();
// take 3 numbers at a time into assetData structs. Store them.
var assetInfo = new List<assetData>();
for (int i = 0; i < assetInput.Length; i += 3)
{
assetData item;
item.type = assetInput[i];
item.value = assetInput[i+1];
item.amount = assetInput[i+2];
assetInfo.Add(item);
}
}
variant for array input:
public struct assetData {
public int type;
public int value;
public int amount;
};
void Main()
{
string keyboard = "1 500 5 2 25 100 3 10 50 -1 3 9 -1";
int[] input = keyboard.Trim().Split().Select(int.Parse).ToArray();
// 3 numbers at a time into assetData structs. Store them.
var assetInfo = new List<assetData>();
int i;
for (i=0; input[i] != -1; i += 3)
{
assetData item;
item.type = input[i];
item.value = input[i+1];
item.amount = input[i+2];
assetInfo.Add(item);
}
i++; // skip the -1
var numbers = new List<int>();
while (i < input.Length - 1) {
numbers.Add(input[i]);
i++;
}
}

Related

Show a pyramid based on number input

I'm currently stuck on this problem the goal is to be able to print out a pyramid depending on the input number.
Ex: input = 3
It should look like this:
1
23
I'm able to make it work with some numbers but it doesn't work with other inputs.
The current logic that I follow is by dividing the input by 2 then add the remainder to the next one to be divided.
Example input: 10
10 / 2 = 5 remainder: 0
5 / 2 = 2 remainder: 1
2 + 1 (previous remainder)/ 2 = 1 remainder: 1
1
Whereas it would look like this:
5
2
2
1
The rules of the pyramid that I'm trying to make only needs to have one or two differences per row.
That's why I'll be needing to deduct 1 from 5 and add it to the next one:
4
3
2
1
Thus having pyramid like this: 10
****
***
**
*
The problem is this approach isn't applicable on other inputs and I'm having a hard time on finding a different approach for this.
This code works for your example, although it might be improved to detect whenever a number is not suitable to print a piramid.
static void Main(string[] args)
{
while (true)
{
Console.Write("Enter a number:");
int input = int.Parse(Console.ReadLine());
List<List<string>> piramid = new List<List<string>>();
int rowNumber = 1, dotsCount = 0;
while (dotsCount < input)
{
List<string> row = new List<string>();
for (int i = 1; i <= rowNumber && dotsCount < input; i++)
{
row.Add("*");
dotsCount++;
}
piramid.Add(row);
rowNumber++;
}
Console.WriteLine("Piramid");
Print(piramid);
Console.WriteLine("Piramid (inverted)");
PrintInverted(piramid);
}
}
static void Print(List<List<string>> piramid)
{
foreach (var item in piramid)
{
item.ForEach(Console.Write);
Console.Write("\n");
}
}
static void PrintInverted(List<List<string>> piramid)
{
for (int i = piramid.Count - 1; i >= 0; i--)
{
List<string> item = piramid[i];
item.ForEach(Console.Write);
Console.Write("\n");
}
}

Algorithm to get which values make sum of a given number from array

I don't know to search or google it so I ask it here.
I have an array of integers with fixed size and exactly with this logic.
sample [1,2,4,8,16,32]
Now I am given a number for example 26. And I shall find the numbers whose sum will make this number, in this case is [2,8,16]
for a number of 20 it will be [4,16]
for 40 it is [8,32]
and for 63 it is all of these numbers [1,2,4,8,16,32]
What is the proper algorithm for that?
I know strictly that there is always this continuation that the number is double of the previous value.
as well as only the numbers from the given array will sum up to the given number and each number will be used only for once or none
If it will be in C# method that takes array of ints and an int value and returns the array of ints that contains the ints that sum up this number from the given array will be preferred.
Thank you
As you can see, the number are base-2, which means you can easily use shift.
You could try this:
private IEnumerable<int> FindBits(int value)
{
// check for bits.
for (int i = 0; i < 32; i++)
{
// shift 1 by i
var bitVal = 1 << i; // you could use (int)Math.Pow(2, i); instead
// check if the value contains that bit.
if ((value & bitVal) == bitVal)
// yep, it did.
yield return bitVal;
}
}
This method will check what bits are set and return them as an ienumerable. (which can be converted to an array of list)
Usage:
// find the bits.
var res = FindBits(40).ToArray();
// format it using the string.join
var str = $"[{string.Join(",", res)}]";
// present the results
Console.WriteLine(str);
Results in [8,32]
Extra info:
counter
00000001 = 1 = 1 << 0
00000010 = 2 = 1 << 1
00000100 = 4 = 1 << 2
00001000 = 8 = 1 << 3
00010000 = 16 = 1 << 4
00100000 = 32 = 1 << 5
01000000 = 64 = 1 << 6
10000000 = 128 = 1 << 7
Instead of writing all combinations you make a for loop which does the counter.
Some extra non-sense:
If you like lambda's, you could replace the FindBits with this:
private Func<int, IEnumerable<int>> FindBits = (int value) => Enumerable
.Range(0, 31)
.Select(i => 2 << i).Where(i => (value & i) == i);
But it's better to keep it simpel/readable.
First you should notice that
( 1 2 4 8 16 ... ) = (2^0 2^1 2^2 2^3 2^4 ... )
And that this is the same as finding a binary encoding for a decimal number. What you are looking for is an algorithm to transform a decimal or base 10 number to a binary or base 2 number.
The algorithm is pretty simple:
public List<int> dec_to_bin(int num)
{
List<int> return_list = new List<int>();
int index = 0;
int remainder = num;
int bit = 0;
while (remainder > 0)
{
bit = remainder % 2;
if (bit == 1 )
{
return_list.Add((int)Math.Pow(2, index));
}
remainder = remainder / 2;
index = index + 1;
}
return return_list;
}
There is a better way however that just uses the underlying encoding of the number which is already binary.
public List<int> dec_to_bin(int num)
{
List<int> return_list = new List<int>();
int value = 1;
while( value < num )
{
if( (value & num) == value )
{
return_list.Add(value);
}
value = value * 2;
}
return return_list;
}
Another way to state your requirement is "What are the unique powers of 2 that sum to a given integer?" Since computers work with powers of 2 natively, there are built-in goodies in most languages to do this very succinctly.
As a bonus, you can use existing .Net types and methods to eliminate the need to write your own loops.
Here's one approach:
IEnumerable<int> GetCompositePowersOf2(int input) =>
//convert to enumerable of bools, one for each bit in the
//input value (true=1, false=0)
new BitArray(new[] { input }).Cast<bool>()
// get power of 2 corresponding to the position in the enumerable
// for each true value, gets 0 for false values.
.Select((isOne, pos) => isOne ? (1 << pos) : 0)
//filter out the 0 values
.Where(pow => pow > 0);
I don't quite get the " takes array of ints " part, since this creation of sums only works with numbers that are the power of 2.
private int[] count (int num)
{
int factor = 0;
List<int> facts = new List<int>();
while (num > 0)
{
int counter = 0;
int div = num;
int remainder = 0;
while (remainder == 0)
{
remainder = div % 2;
div = div / 2;
counter++;
}
factor = 1;
for (int i = 1; i < counter; i++)
factor *= 2;
num = num - factor;
facts.Add(factor);
}
return (facts.ToArray());
}

How to get the number of elements in an int array?

in this case I want to take the number of elements in the array , but the array is dependent on user input
int first = int.Parse(Console.ReadLine());
int second = int.Parse(Console.ReadLine());
for (int i = first; i <= second; i++)
{
if (i % 5 == 0)
{
int[] some =new int [i];
int c =some.Length;
Console.WriteLine(c);
}
}
I tried several options, but the output is still a list of the numbers divisible by 5 without remainder. How is right to do?
example: first = 15, second = 50.
Expected output = 8.
8 numbers divisible by 5 without remainder(15,20,25,30...50)
You can just loop through the numbers and count how many you find that are divisible by 5:
int first = int.Parse(Console.ReadLine());
int second = int.Parse(Console.ReadLine());
int cnt = 0;
for (int i = first; i <= second; i++) {
if (i % 5 == 0) {
cnt++;
}
}
However, you dont have to generate the numbers to know how many there are. You can just calculate where the last number is (as that is easier than the first) and then calculate how many there are before that but after the first:
int first = int.Parse(Console.ReadLine());
int second = int.Parse(Console.ReadLine());
second -= second % 5;
int cnt = (second - first) / 5 + 1;
For example for the input 3 and 11 you want to count the numbers 5 and 10. The expression 11 % 5 gives 1, so second becomes 10 (the last number). Then second - first is 7, doing integer division with 5 gives 1, and then add 1 gives 2.

C# Linq Dictionary IO

How can I do this with LinQ?
I have a txt file.(Its about 100 lines long.)
6 7
0/3 # ##t#kon tu#i#do#b#n ko#yk####a#s##ttak###lk##ul$$$$#$#$$$####$$$$#$$$$$$#$$#$$$$$#$
I stored it in a Dictionary (The two lines).
alap = File.ReadAllLines("veetel.txt");
Dictionary<string,string> statisztikaDictionary = new Dictionary<string,string>();
for (int z = 1; z < alap.Length; z+=2)
{
statisztikaDictionary.Add(alap[z],alap[z-1]);
}
The first line so in this the 6 is the day of record the 7 is the pesons id who recorded.
I need to create a statistics about it so.
Write it out like this:
Day:Number of persons who made a record.
I counted so the person number and the day value varies from 0-11 but we "don't" know this.
The second line starts with a 0/3 that means 0 adult 3 child. I need to read 2 values a day and an ID and print out how many wolfs the person observed(In this case 3).
I am training for my final exam and I got stuck with this. Any help would be apriciated,
I'd suggest to create custom class which can hold/store related data. Let it be Statisztika with the following fields/properties: Day, PersonId, Visitor and CountOfVisits.
Statisztika class definition:
public class Statisztika
{
private int iday = 0;
private int ipersonid = 0;
private int ivisitor =0;
private int icount =0;
//class constructor
public Statisztika(string[] twolines)
{
iday = Convert.ToInt32(twolines[0].Split(' ')[0]);
ipersonid = Convert.ToInt32(twolines[0].Split(' ')[1]);
//we have to replace these lines:
//ivisitor = Convert.ToInt32(twolines[1].Split('/')[0]);
//icount = Convert.ToInt32(twolines[1].Split('/')[1].Split(' ')[0]);
//with:
//check for single slash
int pos = twolines[1].IndexOf("/");
if (pos>-1)
{
//in case of error TryParse method returns zero
Int32.TryParse(twolines[1].Substring(0,pos)
.Replace("#", "").Trim(), out ivisitor);
Int32.TryParse(twolines[1].Substring(pos+1,2)
.Replace("#","").Trim(), out icount);
}
}
public int Day
{
get {return iday;}
set {iday = value;}
}
public int PersonId
{
get {return ipersonid;}
set {ipersonid = value;}
}
public int Visitor
{
get {return ivisitor;}
set {ivisitor = value;}
}
public int CountOfVisits
{
get {return icount;}
set {icount = value;}
}
}
As you can see, to create Statisztika object, you need to pass two lines of text (from the file) to be able to initiate fields. Now, we need to create List<Statisztika>. Imagine, it's data container. To get data from this list, we can use Linq query.
Usage:
string sFileName = #"D:\veetel.txt";
string[] alap = File.ReadAllLines(sFileName);
List<Statisztika> stat = new List<Statisztika>();
for(int i=0; i<alap.Length; i+=2)
{
//Linq rules!
string[] twolines = alap.Skip(i).Take(2).ToArray();
//create new Statisztika object and add to list
stat.Add(new Statisztika(twolines));
}
//use create linq query, group data by day and visitor type ;)
var qry = stat
.GroupBy(p=>new{p.Day, p.Visitor})
.Select(grp=>new
{
Day = grp.Key.Day,
Visitor = grp.Key.Visitor,
SumOfVisits = grp.Sum(p=>p.CountOfVisits)
})
.OrderBy(a=>a.Day)
.ThenBy(a=>a.Visitor);
Console.WriteLine("Day Visitor SumOfVisits");
foreach(var sta in qry)
{
Console.WriteLine("{0}\t{1}\t{2}", sta.Day, sta.Visitor, sta.SumOfVisits);
}
Sample output:
Day Visitor SumOfVisits
1 0 0
2 0 0
2 1 0
3 0 0
3 2 15
4 0 0
5 0 0
6 0 12
7 0 9
7 1 9
8 0 0
9 0 0
9 1 0
10 0 0
11 0 0
11 1 0
11 3 0
11 13 0
[EDIT]
Note: If \ (slash) does not exists, Statisztika class constructor uses zero's in Visitor and CountOfVisits fields/members.
If you would like to check if code works properly, use this code:
string sFileName = #"D:\veetel.txt";
string[] alap = File.ReadAllLines(sFileName);
for(int i=0; i<alap.Length; i+=2)
{
int one = 0;
int two = 0;
string[] twolines = alap.Skip(i).Take(2).ToArray();
int pos = twolines[1].IndexOf("/");
if(pos>-1)
{
Int32.TryParse(twolines[1].Substring(0,pos)
.Replace("#", "").Trim(), out one);
Int32.TryParse(twolines[1].Substring(pos+1,2)
.Replace("#","").Trim(), out two);
}
Console.WriteLine("{0}\t{1}\t{2}",
twolines[1].Substring(0,8), one, two);
}
Above code produces output as follow:
#abor# # 0 0
ta###t## 0 0
0/# a #a 0 0
a pat#k# 0 0
e#zakrol 0 0
1/3#sot# 1 3
0/# a pa 0 0
#3/0#s#t 3 0
verofe#y 0 0
ta#o#t#v 0 0
eszakro# 0 0
#/3#so## 0 3
...etc.
Cheers, Maciej
I guess you prefer some guidance instead of a working code as the full solution.
To be able to query a dictionary for the amount of persons that recorded observations in certain day, and to query for the amount of wolves observed by a person in certain day, I would create a dictionary with a key composed by day and personId and value as observation data.
See below for an example of 2 classes to hold keys and values for your dictionary.
For keys:
public class ObservationId
{
public int Day;
public int PersonId;
public ObservationId(int day, int personId)
{
this.Day = day;
this.PersonId = personId;
}
public ObservationId(string line)
{
// Add code here to split data in the line to fill day and personId values
}
}
For values:
public class ObservationData
{
public int Adults;
public int Childs;
public int TotalWolves
{
get { return this.Adults + this.Childs; }
}
public ObservationData(int adults, int childs)
{
this.Adults = adults;
this.Childs = childs;
}
public ObservationData(string line)
{
// Add code here to split data in the line to fill values for adults and childs (and optionally the rest of data)
}
}
To fill data from the file:
string[] alap;
alap = File.ReadAllLines("veetel.txt");
Dictionary<ObservationId, ObservationData> statisztikaDictionary = new Dictionary<ObservationId, ObservationData>();
for (int z = 1; z < alap.Length; z += 2)
{
ObservationId id = new ObservationId(alap[z - 1]);
ObservationData data = new ObservationData(alap[z]);
statisztikaDictionary.Add(id, data);
}
To search by day and person ID:
public int GetTotalWolves(int day, int personId)
{
ObservationId id = new ObservationId(day, personId);
if (statisztikaDictionary.ContainsKey(id))
{
return statisztikaDictionary[id].TotalWolves;
}
else
{
return 0;
}
}
To search for a day (using Linq):
public int GetObservationsByDay(int day)
{
return statisztikaDictionary.Where(o => o.Key.Day == day).Count();
}

How can i find the number of 9s in an integer

I have the following method which should found the total number of 9 in an integer, the method is used to retrieve the employees' contract type based on the number of 9. i tried the below class:-
public class EmployeeCreditCards
{
public uint CardNumber(uint i)
{
byte[] toByte = BitConverter.GetBytes(i);
uint number = 0;
for (int n = 0; n < toByte.Length; n++)
{
if (toByte[i] == 9)
{
number = number + 1;
}
}
return number;
}
}
In which i am trying to find how many 9 are in the passed integer, but the above method will always return zero. Any idea what is going wrong?
You can do this simple with a little linq:
public int GetAmountOfNine(int i)
{
return i.ToString().Count(c => c.Equals('9'));
}
But do add using System.Linq; to the cs file.
Your answer isn't working because you are converting to bytes, converting the number to bytes does not generate a byte for each digit (via #Servy). Therefor if you would write every byte in your array to console/debug you wouldn't see your number back.
Example:
int number = 1337;
byte[] bytes = BitConverter.GetBytes(number);
foreach (var b in bytes)
{
Console.Write(b);
}
Console:
57500
You can however convert the int to a string and then check for every character in the string if it is a nine;
public int GetAmountOfNineWithOutLinq(int i)
{
var iStr = i.ToString();
var numberOfNines = 0;
foreach(var c in iStr)
{
if(c == '9') numberOfNines++;
}
return numberOfNines;
}
A classic solution is as follows: (Probably this is the fastest algorithm to find solution, it takes only O(log n) time.)
private int count9(int n)
{
int ret = 0;
if (n < 0)
n = -n;
while (n > 0)
{
if (n % 10 == 9) ++ret;
n /= 10; // divide the number by 10 (delete the most right digit)
}
return ret;
}
How does that work?
Consider an example, n = 9943
now ret = 0.
n % 10 = 3, which != 9
n = n / 10 = 994
n % 10 = 4 != 9
n = 99
n % 10 = 9, so ret = 1
n = 9
n % 10 = 9, so ret = 2
n = 0
Try
int numberOfNines = number.ToString().Where(c => c == '9').Count();
Since a string implements IEnumerable<char>, you can apply LINQ directly to the string without converting it to an enumeration of chars first.
UPDATE
Converting the uint to a byte array won't work the expected way, since the uint does not store the decimal digits of your number directly. The number is stored as a binary number that streches over four bytes. A unit has always four bytes, even if your number has 9 decimal digits.
You can convert the number to a string in order to get its decimal representation.

Categories