How to output numbers - c#

I have a program that requests the user enter as many floating points as they wish to. I need to output these values on the console and apply the following return values as well: I need to find the sum of the numbers
The average of the numbers
The lowest value number
The highest value number
I can't figure out how to get an output
Here is my current code:
bool charactersFound = false;
List<float> allNumbers = new List<float>();
while (charactersFound == false)
{
while (charactersFound == false)
{
String textEntered = Console.ReadLine();
if (textEntered.ToUpperInvariant().Contains("STOP"))
{
charactersFound = true;
}
break;
allNumbers.Add(float.Parse(textEntered));
}
float max = array.Max();
float min = array.Min();
float total = array.Sum();
}
How can I output this on the console with each of the above values on separate lines?

Extract method (inputArray in your case), please, do not put everything into single routine:
private static float[] inputArray() {
List<float> list = new List<float>();
while (true) {
string textEntered = Console.ReadLine();
if (textEntered.ToUpperInvariant().Contains("STOP"))
return list.ToArray();
if (float.TryParse(textEntered, out var item))
list.Add(item);
else
Console.WriteLine($"\"{textEntered}\" is not a floating point value, ignored");
}
}
...
float[] array = inputArray();
//TODO: you may want to check here if array is not empty
if (array.Length == 0)
Console.WriteLIne("The array is empty");
else {
Console.WriteLine($"[{string.Join(", ", array)}]");
Console.WriteLine($" Max = {array.Max()}");
Console.WriteLine($" Min = {array.Min()}");
Console.WriteLine($" Total = {array.Sum()}");
}

Related

Making my dice throws produce more throws?

I'm working on an assignment, where I have to make an application where you can throw 1-4 dice. The results are then added to a list.
However, if any of them is a 6, that one isn't added to the list, instead 2 additional dice are thrown.
As long as a die returns a 6, 2 more dice have to be thrown, until no die returns a 6.
Does anyone here know how to solve this? My programming skills are really basic, and I haven't used them much since last year.
for (int i = 0; i < qty; i++)
{
int diceNr = RollDice(random);
dicelist.Add(diceNr);
Console.WriteLine(diceNr);
if (diceNr == 6)
{
dicelist.Remove(diceNr);
Console.WriteLine("You got a six, that means you get 2 extra throws!");
for (int x = 0; x < 2; x++)
{
diceNr = RollDice(random);
dicelist.Add(diceNr);
}
You can try using a while loop as follows:
int i = quantity; #initialize a variable to your maximum number of throws
while(i > 0){ #until you have throws yet
i--; #this is the equivalent of one throw
int diceNr = RollDice(random);
dicelist.Add(diceNr);
Console.WriteLine(diceNr);
if(diceNr == 6){
Console.WriteLine("You got a six, that means you get 2 extra throws!");
i = i + 2; #add your bonus throws
}
}
You can use a while loop that exits once you are out of rolls. If you roll a six, add two more to the remaining quantity otherwise add the rolled value to the list.
int qty = 6;
// decrement remaining quantity each iteration
// until zero rolls remain
while(qty-- > 0)
{
int diceNr = RollDice(random);
Console.WriteLine(diceNr);
if (diceNr == 6)
{
// rolled six, add two more rolls
Console.WriteLine("You got a six, that means you get 2 extra throws!");
qty += 2;
}
else
{
// not six, add to list
dicelist.Add(diceNr);
}
}
// output all the non-six values
var allRolls = string.Join(",", diceList);
Console.WriteLine("All rolls: " + allRolls);
You could also do this with recursion (though I don't recommend it for this problem):
private static void Play(List<int> diceList, Random random, int rolls)
{
// base case, no rolls remain
if (rolls == 0)
return;
int diceNr = RollDice(random);
Console.WriteLine(diceNr);
if (diceNr == 6)
{
Console.WriteLine("You got a six, that means you get 2 extra throws!");
// add one to rolls since we are "reusing" this slot
// adding two would give us one more roll than we really want
rolls++
}
else
{
diceList.Add(diceNr);
// decrement rolls by one
rolls--;
}
// recursively call Play with updated roll count
// which is either original + 1 OR original - 1
Play(diceList, random, rolls);
}
private static int RollDice(Random r)
{
return r.Next(1, 7);
}
public static void Main()
{
var diceList = new List<int>();
var random = new Random();
int qty = 6;
Play(diceList, random, qty);
// output all the non-six values
var allRolls = string.Join(",", diceList);
Console.WriteLine("All rolls: " + allRolls);
}
My (readable) solution would look like:
class Program
{
static void Main(string[] args)
{
var game = new Game(4);
game.Play();
}
}
public class Game
{
private readonly int _noOfDices;
private readonly List<int> _result;
private readonly Random _random = new Random();
public Game(int noOfDices)
{
_noOfDices = noOfDices;
_result = new List<int>();
}
public void RollDice()
{
var no = _random.Next(1, 7);
if (no == 6)
{
RollDice();
RollDice();
}
else
{
_result.Add(no);
}
}
public void Play()
{
for (var i = 1; i <= _noOfDices; i++)
{
RollDice();
}
Console.WriteLine($"Output: {string.Join(',',_result)}");
}
}
Output:

Nearest value from user input in an array C#

so in my application , I read some files into it and ask the user for a number , in these files there a lot of numbers and I am trying to find the nearest value when the number they enter is not in the file. So far I have as following
static int nearest(int close_num, int[] a)
{
foreach (int bob in a)
{
if ((close_num -= bob) <= 0)
return bob;
}
return -1;
}
Console.WriteLine("Enter a number to find out if is in the selected Net File: ");
int i3 = Convert.ToInt32(Console.ReadLine());
bool checker = false;
//Single nearest = 0;
//linear search#1
for (int i = 0; i < a.Length; i++)//looping through array
{
if(a[i] == i3)//checking to see the value is found in the array
{
Console.WriteLine("Value found and the position of it in the descending value of the selected Net File is: " + a[i]);
checker = true;
}
else
{
int found = nearest(i3,a);
Console.WriteLine("Cannot find this number in the Net File however here the closest number to that: " + found );
//Console.WriteLine("Cannot find this number in the Net File however here the closest number to that : " + nearest);
}
}
When a value that is in the file is entered the output is fine , but when it comes to the nearest value I cannot figure a way. I can't use this such as BinarySearchArray for this. a = the array whilst i3 is the value the user has entered. Would a binary search algorithm just be simpler for this?
Any help would be appreciated.
You need to make a pass over all the elements of the array, comparing each one in turn to find the smallest difference. At the same time, keep a note of the current nearest value.
There are many ways to do this; here's a fairly simple one:
static int nearest(int close_num, int[] a)
{
int result = -1;
long smallestDelta = long.MaxValue;
foreach (int bob in a)
{
long delta = (bob > close_num) ? (bob - close_num) : (close_num - bob);
if (delta < smallestDelta)
{
smallestDelta = delta;
result = bob;
}
}
return result;
}
Note that delta is calculated so that it is the absolute value of the difference.
Well, first we should define, what is nearest. Assuming that,
int nearest for given int number is the item of int[] a such that Math.Abs(nearest - number) is the smallest possible value
we can put it as
static int nearest(int number, int[] a)
{
long diff = -1;
int result = 0;
foreach (int item in a)
{
// actual = Math.Abs((long)item - number);
long actual = (long)item - number;
if (actual < 0)
actual = -actual;
// if item is the very first value or better than result
if (diff < 0 || actual < diff) {
result = item;
diff = actual;
}
}
return result;
}
The only tricky part is long for diff: it may appear that item - number exceeds int range (and will either have IntegerOverflow exceprion thrown or *invalid answer), e.g.
int[] a = new int[] {int.MaxValue, int.MaxValue - 1};
Console.Write(nearest(int.MinValue, a));
Note, that expected result is 2147483646, not 2147483647
what about LINQ ?
var nearestNumber = a.OrderBy(x => Math.Abs(x - i3)).First();
Just iterate through massive and find the minimal delta between close_num and array members
static int nearest(int close_num, int[] a)
{
// initialize as big number, 1000 just an example
int min_delta=1000;
int result=-1;
foreach (int bob in a)
{
if (Math.Abs(bob-close_num) <= min_delta)
{
min_delta = bob-close_num;
result = bob;
}
}
return result;
}

Find Minimum and Maximum values within a multi dimensional struct array

For a school project in learning c# I am making a data collection console application which saves floating point entries for 4 different locations along with the time/date, and user who recorded the entry. I am required to use a multi dimensional struct array.
I need to have a view that displays the average of the values, along with the minimum and maximum values and the first and last date. I've got the average figured out by counting through the values and adding cumulatively but I can't figure out how to find the minimum and maximum values.
I tried searching and came across this page: http://www.dotnetperls.com/max
I tried to implement this syntax into my code to no avail due to it being a much more complex array.
It worked in my test with integers:
class Program
{
static int[][] intarray = new int[4][] { new int[10], new int[10], new int[10], new int[10] };
static void Main(string[] args)
{
intarray[0][0] = 5;
intarray[0][1] = 3;
intarray[0][2] = 10;
intarray[0][3] = 4;
intarray[0][4] = 2;
Console.WriteLine(intarray[0].Max());
Console.ReadLine();
}
}
The above code perfectly displays the number 10! :)
But when I tried to implement this in to my program with a struct array, it doesn't work:
class Program
{
static byte location = 0;
static float entriesmin;
static float entriesmax;
static Entry[][] entriesarray = new Entry[4][] { new Entry[10], new Entry[10], new Entry[10], new Entry[10] };
struct Entry
{
public float value;
public string user;
public DateTime datetime;
}
static byte LoopEntries(bool display)
{
float runningtotal = 0;
byte entrycount = 0;
foreach (Entry entry in entriesarray[0])
{
if (entry.user != null)
{
if (display)
{
string ten;
if (entrycount == 9)
{
ten = " #";
}
else
{
ten = " #";
}
Console.WriteLine(ten + (entrycount + 1) + " " + entry.datetime + " " + entry.user + new string(' ', 16 - entry.user.Length) + entry.value);
}
runningtotal += entry.value;
entrycount += 1;
}
}
entriesmin = (entriesarray[location]).value.Min();
entriesmax = (entriesarray[location]).value.Max();
if (entrycount == 0 && display)
{
Console.WriteLine("No entries to show!");
}
return entrycount;
}
I need to hand this project in on Monday! I really hope someone can help me! ;)
What you have is not a multidimensional array, it's an array of array (a.k.a. a jagged array), but you work with them in a similar way.
To loop through the array of arrays you need a loop in a loop:
foreach (Entry[] arr in entriesarray) {
foreach (Entry entry in arr) {
// ...
}
}
You could use the Min and Max extension methods to get the minimum and maximum value of each inner array, but you still would have to find the minimum and maximum between those values. As you are already looping through all the entries anyway to get the average you can just keep a record of the smallest and largest values found:
float runningtotal = 0;
int entrycount = 0;
float min = float.MaxValue;
float max = float.MinValue;
foreach (Entry[] arr in entriesarray) {
foreach (Entry entry in arr) {
runningtotal += entry.value;
entrycount++;
if (entry.value < min) {
min = entry.value;
}
if (entry.value > max) {
max = entry.value;
}
}
}

What's a good algorithm for checking if a given list of values alternates up and down?

Assuming the function takes in a list of double and an index to perform the check from, I need to check if the values alternates up and down consecutively.
For example, a list of [14.0,12.3,13.0,11.4] alternates consecutively but a list of [14.0,12.3,11.4,13.0] doesn't.
The algorithm doesn't have to be fast, but I'd like it to be compact to write (LINQ is totally fine). This is my current method, and it looks way too crude to my taste:
enum AlternatingDirection { Rise, Fall, None };
public bool CheckConsecutiveAlternation(List<double> dataList, int currDataIndex)
{
/*
* Result True : Fail
* Result False : Pass
*/
if (!_continuousRiseFallCheckBool)
return false;
if (dataList.Count < _continuousRiseFallValue)
return false;
if (currDataIndex + 1 < _continuousRiseFallValue)
return false;
AlternatingDirection direction = AlternatingDirection.None;
int startIndex = currDataIndex - _continuousRiseFallValue + 1;
double prevVal = 0;
for (int i = startIndex; i <= currDataIndex; i++)
{
if (i == startIndex)
{
prevVal = dataList[i];
continue;
}
if (prevVal > dataList[i])
{
prevVal = dataList[i];
switch (direction)
{
case AlternatingDirection.None:
direction = AlternatingDirection.Fall;
continue;
case AlternatingDirection.Rise:
direction = AlternatingDirection.Fall;
continue;
default:
//Two falls in a row. Not a signal.
return false;
}
}
if (prevVal < dataList[i])
{
prevVal = dataList[i];
switch (direction)
{
case AlternatingDirection.None:
direction = AlternatingDirection.Rise;
continue;
case AlternatingDirection.Fall:
direction = AlternatingDirection.Rise;
continue;
default:
//Two rise in a row. Not a signal.
return false;
}
}
return false;
}
//Alternated n times until here. Data is out of control.
return true;
}
Try this:
public static bool IsAlternating(double[] data)
{
var d = GetDerivative(data);
var signs = d.Select(val => Math.Sign(val));
bool isAlternating =
signs.Zip(signs.Skip(1), (a, b) => a != b).All(isAlt => isAlt);
return isAlternating;
}
private static IEnumerable<double> GetDerivative(double[] data)
{
var d = data.Zip(data.Skip(1), (a, b) => b - a);
return d;
}
Live demo
The idea is:
If the given list of values is alternating up and down, mathematically it means that it's derivative keeps changing its sign.
So this is exactly what this piece of code does:
Get the derivative.
Checks for sign fluctuations.
And the bonus is that it will not evaluate all of the derivative / signs arrays unless it is necessary.
I'd do it with a couple of consecutive zips, bundled in an extension method:
public static class AlternatingExtensions {
public static bool IsAlternating<T>(this IList<T> list) where T : IComparable<T>
{
var diffSigns = list.Zip(list.Skip(1), (a,b) => b.CompareTo(a));
var signChanges = diffSigns.Zip(diffSigns.Skip(1), (a,b) => a * b < 0);
return signChanges.All(s => s);
}
}
Edit: for completeness, here's how you'd use the feature:
var alternatingList = new List<double> { 14.0, 12.3, 13.0, 11.4 };
var nonAlternatingList = new List<double> { 14.0, 12.3, 11.4, 13.0 };
alternatingList.IsAlternating(); // true
nonAlternatingList.IsAlternating(); // false
I also changed the implementation to work on more types, making use of generics as much as possible.
Here is a small pseudo code. Assuming no repeated elements (can be handled easily though by few tweaks)
Idea is to have a sign variable which is alternating 1,-1,... that is multipled by the difference of two consecutive pairs, the difference multipled by this sign variable must always be positive. If it's not at some point, return false.
isUpAndDown(l):
if size(l) < 2: // empty,singleton list is always good.
return true
int sign = (l[0] < l[1] ? 1 : -1)
for i from 0 to n-1 (exclusive):
if sign * (l[i+1] - l[i]) < 0:
return false //not alternating
sign = sign * -1
end for
return true //all good
You may create kind of a signed array first:
double previous = 0;
var sign = myList.Select(x => {
int s = Math.Sign(x - previous);
previos = x;
return s;
});
This gives you a list similar to
{ -1, 1, -1, ... }
Now you can take a similar appraoch as the previos Select-statement to check if a -1 follows a 1:
var result = sign.All(x => {
bool b = x == -previous;
previous = x;
return b;
});
Now result is true if your list alternates, false otherwise.
EDIT: To ensure that the very first check within the second query also passes add previous = -sign[0]; before the second query.
Assuming that two equal values in a row are not acceptable (if they are, just skip over equal values):
if (dataList[0] == dataList[1])
return false;
bool nextMustRise = dataList[0] > dataList[1];
for (int i = 2; i < dataList.Count; i++) {
if (dataList[i - 1] == dataList[i] || (dataList[i - 1] < dataList[i]) != nextMustRise)
return false;
nextMustRise = !nextMustRise;
}
return true;
public double RatioOfAlternations(double[] dataList)
{
double Alternating = 0;
double Total = (dataList.Count()-2);
for (int (i) = 0; (i) < Total; (i)++)
{
if (((dataList[i+1]-dataList[i])*(dataList[i+2]-dataList[i+1]))<0)
// If previous change is opposite sign to current change, this will be negative
{
Alternating++;
}
else
{
}
}
return (Alternating/Total);
}

Combination Algorithm

Length = input Long(can be 2550, 2880, 2568, etc)
List<long> = {618, 350, 308, 300, 250, 232, 200, 128}
The program takes a long value, for that particular long value we have to find the possible combination from the above list which when added give me a input result(same value can be used twice). There can be a difference of +/- 30.
Largest numbers have to be used most.
Ex:Length = 868
For this combinations can be
Combination 1 = 618 + 250
Combination 2 = 308 + 232 + 200 +128
Correct Combination would be Combination 1
But there should also be different combinations.
public static void Main(string[] args)
{
//subtotal list
List<int> totals = new List<int>(new int[] { 618, 350, 308, 300, 250, 232, 200, 128 });
// get matches
List<int[]> results = KnapSack.MatchTotal(2682, totals);
// print results
foreach (var result in results)
{
Console.WriteLine(string.Join(",", result));
}
Console.WriteLine("Done.");
}
internal static List<int[]> MatchTotal(int theTotal, List<int> subTotals)
{
List<int[]> results = new List<int[]>();
while (subTotals.Contains(theTotal))
{
results.Add(new int[1] { theTotal });
subTotals.Remove(theTotal);
}
if (subTotals.Count == 0)
return results;
subTotals.Sort();
double mostNegativeNumber = subTotals[0];
if (mostNegativeNumber > 0)
mostNegativeNumber = 0;
if (mostNegativeNumber == 0)
subTotals.RemoveAll(d => d > theTotal);
for (int choose = 0; choose <= subTotals.Count; choose++)
{
IEnumerable<IEnumerable<int>> combos = Combination.Combinations(subTotals.AsEnumerable(), choose);
results.AddRange(from combo in combos where combo.Sum() == theTotal select combo.ToArray());
}
return results;
}
public static class Combination
{
public static IEnumerable<IEnumerable<T>> Combinations<T>(this IEnumerable<T> elements, int choose)
{
return choose == 0 ?
new[] { new T[0] } :
elements.SelectMany((element, i) =>
elements.Skip(i + 1).Combinations(choose - 1).Select(combo => (new[] { element }).Concat(combo)));
}
}
I Have used the above code, can it be more simplified, Again here also i get unique values. A value can be used any number of times. But the largest number has to be given the most priority.
I have a validation to check whether the total of the sum is greater than the input value. The logic fails even there..
The algorithm you have shown assumes that the list is sorted in ascending order. If not, then you shall first have to sort the list in O(nlogn) time and then execute the algorithm.
Also, it assumes that you are only considering combinations of pairs and you exit on the first match.
If you want to find all combinations, then instead of "break", just output the combination and increment startIndex or decrement endIndex.
Moreover, you should check for ranges (targetSum - 30 to targetSum + 30) rather than just the exact value because the problem says that a margin of error is allowed.
This is the best solution according to me because its complexity is O(nlogn + n) including the sorting.
V4 - Recursive Method, using Stack structure instead of stack frames on thread
It works (tested in VS), but there could be some bugs remaining.
static int Threshold = 30;
private static Stack<long> RecursiveMethod(long target)
{
Stack<long> Combination = new Stack<long>(establishedValues.Count); //Can grow bigger, as big as (target / min(establishedValues)) values
Stack<int> Index = new Stack<int>(establishedValues.Count); //Can grow bigger
int lowerBound = 0;
int dimensionIndex = lowerBound;
long fail = -1 * Threshold;
while (true)
{
long thisVal = establishedValues[dimensionIndex];
dimensionIndex++;
long afterApplied = target - thisVal;
if (afterApplied < fail)
lowerBound = dimensionIndex;
else
{
target = afterApplied;
Combination.Push(thisVal);
if (target <= Threshold)
return Combination;
Index.Push(dimensionIndex);
dimensionIndex = lowerBound;
}
if (dimensionIndex >= establishedValues.Count)
{
if (Index.Count == 0)
return null; //No possible combinations
dimensionIndex = Index.Pop();
lowerBound = dimensionIndex;
target += Combination.Pop();
}
}
}
Maybe V3 - Suggestion for Ordered solution trying every combination
Although this isn't chosen as the answer for the related question, I believe this is a good approach - https://stackoverflow.com/a/17258033/887092(, otherwise you could try the chosen answer (although the output for that is only 2 items in set being summed, rather than up to n items)) - it will enumerate every option including multiples of the same value. V2 works but would be slightly less efficient than an ordered solution, as the same failing-attempt will likely be attempted multiple times.
V2 - Random Selection - Will be able to reuse the same number twice
I'm a fan of using random for "intelligence", allowing the computer to brute force the solution. It's also easy to distribute - as there is no state dependence between two threads trying at the same time for example.
static int Threshold = 30;
public static List<long> RandomMethod(long Target)
{
List<long> Combinations = new List<long>();
Random rnd = new Random();
//Assuming establishedValues is sorted
int LowerBound = 0;
long runningSum = Target;
while (true)
{
int newLowerBound = FindLowerBound(LowerBound, runningSum);
if (newLowerBound == -1)
{
//No more beneficial values to work with, reset
runningSum = Target;
Combinations.Clear();
LowerBound = 0;
continue;
}
LowerBound = newLowerBound;
int rIndex = rnd.Next(LowerBound, establishedValues.Count);
long val = establishedValues[rIndex];
runningSum -= val;
Combinations.Add(val);
if (Math.Abs(runningSum) <= 30)
return Combinations;
}
}
static int FindLowerBound(int currentLowerBound, long runningSum)
{
//Adjust lower bound, so we're not randomly trying a number that's too high
for (int i = currentLowerBound; i < establishedValues.Count; i++)
{
//Factor in the threshold, because an end aggregate which exceeds by 20 is better than underperforming by 21.
if ((establishedValues[i] - Threshold) < runningSum)
{
return i;
}
}
return -1;
}
V1 - Ordered selection - Will not be able to reuse the same number twice
Add this very handy extension function (uses a binary algorithm to find all combinations):
//Make sure you put this in a static class inside System namespace
public static IEnumerable<List<T>> EachCombination<T>(this List<T> allValues)
{
var collection = new List<List<T>>();
for (int counter = 0; counter < (1 << allValues.Count); ++counter)
{
List<T> combination = new List<T>();
for (int i = 0; i < allValues.Count; ++i)
{
if ((counter & (1 << i)) == 0)
combination.Add(allValues[i]);
}
if (combination.Count == 0)
continue;
yield return combination;
}
}
Use the function
static List<long> establishedValues = new List<long>() {618, 350, 308, 300, 250, 232, 200, 128, 180, 118, 155};
//Return is a list of the values which sum to equal the target. Null if not found.
List<long> FindFirstCombination(long target)
{
foreach (var combination in establishedValues.EachCombination())
{
//if (combination.Sum() == target)
if (Math.Abs(combination.Sum() - target) <= 30) //Plus or minus tolerance for difference
return combination;
}
return null; //Or you could throw an exception
}
Test the solution
var target = 858;
var result = FindFirstCombination(target);
bool success = (result != null && result.Sum() == target);
//TODO: for loop with random selection of numbers from the establishedValues, Sum and test through FindFirstCombination

Categories

Resources