Calculating minimum/maximum/average ping reponse - c#

So here is an application which tests each server of popular RuneScape game. I am running ping on each of 139 servers and add lag value to array. While looping through list entries I can calculate the average, minimum, and maximum lag for each server.
Now, in my code when one of the unreachable servers is noted the lowest lag displays as 0. I'm not sure how to handle if my ping response has reached it's timeout and posts 0 to array list.
What can I do to avoid that 0 as my lowest ping when server is down?
using System;
using System.Net.NetworkInformation;
using System.Collections.Generic;
namespace RuneScape_Ping_Tool
{
class Program
{
static void Main(string[] args)
{
Console.Write(Environment.NewLine + "Start the test? (y/n): ");
if (Console.Read() == char.Parse("y"))
{
Console.WriteLine();
Ping();
}
}
static void Ping()
{
List<int> lag = new List<int>();
for (int server = 1; server <= 139; server++)
{
string url = "world" + server.ToString() + ".runescape.com";
Console.WriteLine("Checking world " + server + "...");
Ping ping = new Ping();
PingReply reply = ping.Send(url);
lag.Add(int.Parse(reply.RoundtripTime.ToString()));
}
for (int i = 1; i <= 139; i++)
{
Console.WriteLine("World " + i + ": " + lag[i - 1]);
}
int average = 0;
int highest = 1;
int lowest = 1000;
int highestWorld = 0;
int lowestWorld = 0;
for (int i = 1; i <= 139; i++)
{
average = average + lag[i - 1];
}
for (int i = 1; i <= 139; i++)
{
if (highest < lag[i - 1])
{
highest = lag[i - 1];
highestWorld = i;
}
}
for (int i = 1; i <= 139; i++)
{
if (lowest > lag[i - 1])
{
lowest = lag[i - 1];
lowestWorld = i;
}
}
Console.WriteLine();
Console.WriteLine("Average lag: " + average / 139);
Console.WriteLine("Highest lag: " + highest + " in world " + highestWorld);
Console.WriteLine("Lowest lag: " + lowest + " in world " + lowestWorld);
Console.Write(Environment.NewLine + "Start the test? (y/n): ");
if (Console.Read() == char.Parse("y"))
{
Console.WriteLine();
Ping();
}
}
}
}

Can you just skip over zeroes? Also, you might as well put all the calculations inside a single loop.
int n = 0 // number of data points
for (int i = 0; i < 139; ++i) {
if (lag[i] == 0) {
continue; // skip 0 values
}
++n;
sum += lag[i];
if (highest < lag[i]) {
highest = lag[i];
highestWorld = i + 1;
}
if (lowest > lag[i]) {
lowest = lag[i];
lowestWorld = i + 1;
}
average = sum / n; // Note: you may want to round this.
}

First consider running everything in parallel (4 at a time here):
var servers = Enumerable.Range(1, 139).Select(i => String.Format("world{0}.runescape.com",i));
var results = servers.AsParallel()
.WithDegreeOfParallelism(4)
.Select(server => new Ping().Send(server))
.ToList();
Then collect just the valid results, note using PingReply.Status rather than checking for 0:
var validResults = results.Where(r => r.Status == IPStatus.Success)
.Select(r => r.RoundtripTime);
Here's the info you need:
Console.WriteLine("Total Results: {0}", results.Count());
Console.WriteLine("Valid Results: {0}", validResults.Count());
Console.WriteLine("Min from Valid: {0}", validResults.Min());
Console.WriteLine("Max from Valid: {0}", validResults.Max());
Console.WriteLine("Avg from Valid: {0}", validResults.Average());

You can get the min, max and average with these functions.
var nozeros = lag.Where(i => i > 0);
int lowest = nozeros.Min();
int lowestWorld = lag.IndexOf(lowest);
int highest = nozeros.Max();
int highestWorld = lag.IndexOf(highest);
int average = (int)nozeros.Average();

Related

Is there a way to combine 2 or more arrays while also combing duplicate data?

For some context I'm currently doing an assignment for college where i need to create a tournament scoring system, and this is my code so far.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace pointsSystemTest
{
class Program
{
static void Main(string[] args)
{
string[] e1Teams;
int n = 4;
int i;
int pos1 = 20;
int pos2 = 18;
int pos3 = 15;
int pos4 = 10;
{
{
AssigningPointsE1:
e1Teams = new string[n];
Console.WriteLine("Enter the 4 teams in order of rank below");
for (i = 0; i < n; i++)
{
e1Teams[i] = Console.ReadLine();
}
if (e1Teams.Length != e1Teams.Distinct().Count())
{
Console.WriteLine("!CONTAINS DUPLICATES!");
Console.WriteLine("Please re-enter the teams for event 1 again");
Console.ReadLine();
goto AssigningPointsE1;
}
string e1p1 = e1Teams[0] + " - " + pos1 + "points";
string e1p2 = e1Teams[1] + " - " + pos2 + "points";
string e1p3 = e1Teams[2] + " - " + pos3 + "points";
string e1p4 = e1Teams[3] + " - " + pos4 + "points";
Console.WriteLine("-------------------------------------------------");
Console.WriteLine("{0}", e1p1);
Console.WriteLine("{0}", e1p2);
Console.WriteLine("{0}", e1p3);
Console.WriteLine("{0}", e1p4);
Console.ReadLine();
}
string[] e2Teams;
{
AssigningPointsE2:
e2Teams = new string[n];
Console.WriteLine("Enter the 4 teams in order of rank below");
for (i = 0; i < n; i++)
{
e2Teams[i] = Console.ReadLine();
}
if (e2Teams.Length != e2Teams.Distinct().Count())
{
Console.WriteLine("!CONTAINS DUPLICATES!");
Console.WriteLine("Please re-enter the teams for event 1 again");
Console.ReadLine();
goto AssigningPointsE2;
}
string e2p1 = e2Teams[0] + " - " + pos1 + "points";
string e2p2 = e2Teams[1] + " - " + pos2 + "points";
string e2p3 = e2Teams[2] + " - " + pos3 + "points";
string e2p4 = e2Teams[3] + " - " + pos4 + "points";
Console.WriteLine("-------------------------------------------------");
Console.WriteLine("{0}", e2p1);
Console.WriteLine("{0}", e2p2);
Console.WriteLine("{0}", e2p3);
Console.WriteLine("{0}", e2p4);
Console.ReadLine();
}
}
}
}
}
I basically would like to combine the 2 arrays into one array but I would also like to display the points each team has acquired during the tournament, the teams aren't entered in the same order so I'm struggling to combine the arrays and combine the points in one go.
I envisioned the final combination of points to look like:
team 1 - 40 points,
team 4 - ... points,
team 3 - ... points,
team 2 - ... points
Here is what I would do
var events = new List<string[]>() { e1Teams, e2Teams };
var scores = new Dictionary<String, int>();
var pointsTable = new int[] { 20, 18, 15, 10 };
foreach (var ev in events) {
for (int i = 0; i < 4; i++) {
var team = ev[i];
if (scores.ContainsKey(team)) {
scores[team] += pointsTable[i];
}
else
scores[team] = pointsTable[i];
}
}
foreach (var kv in scores) {
Console.WriteLine($"{kv.Key} - {kv.Value}");
}
Note you would be way better off with not having a separate array for each event, have a list of lists

Binary search in C#

I'm trying to make a binary search for a random array which has 10 numbers. When I run my code, and the number I input is a number within the random array, instead of just outputting "Found it" once, it will continuously output "Found it" until I close the program, but I can't understand what I've done to make it keep outputting "Found it".
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Binary_Search
{
class Program
{
static void Main(string[] args)
{
int n = 10; //10 values in array
Random r = new Random();
int b; //value to search
int i; //loop control value
int[] a = new int[n + 1];
a[0] = 0; //starts at 0
for (i = 1; i <= n; i++) // set the array up
a[i] = a[i - 1] + r.Next(1, 10); // + random numbers from 1 to 10
for (i = 1; i <= n; i++)
Console.WriteLine(" a[" + i + "] + " + a[i] + ": "); // outputs the numbers for each value of array
Console.WriteLine();
Console.ReadLine();
Console.WriteLine("What number are you looking for?");
b = int.Parse(Console.ReadLine()); // enter value that you want to find
i = 1;
Console.ReadLine();
int min = 1;
int max = n - 1;
do
{
int mid = (min + max) / 2;
if (a[mid] == b)
{
Console.WriteLine("Found it");
}
else if (a[mid] > b)
max = mid;
else if (a[mid] < b)
min = mid;
} while (min <= max);
Console.ReadLine();
}
}
}
You need to break/stop the loop once you've found it.
if (a[mid] == b)
{
Console.WriteLine("Found it");
break; // add this
}
The "Found it" message keeps getting printed because of your do-while condition. You get into an infinite loop because after several iterations, min equals to max.
Set the condition to while (min < max); instead of while (min <= max); and have the if condition after the loop.
This should do the trick:
do
{
int mid = (min + max) / 2;
if (a[mid] > b)
max = mid;
else if (a[mid] < b)
min = mid;
} while (min < max);
if (a[mid] == b)
{
Console.WriteLine("Found it");
}

Finding employee that made the most from array?

I have managed to get the "least" Calculated however the code for "most" is not working... what I have currently.
for (int i = 0; i < workerGrossIncome.Length; i++)
if (workerGrossIncome[i] > workerGrossIncome[maxIndex])
{
maxIndex = i;
workerMost = workerName[i];
workerRegularPayMost = workersRegularPay[i];
workerGrossIncomeMost = workerGrossIncome[i];
}
edit with full code: (Currently Learning cannot use built in array methods)
Program runs however uses the defaults when calculating for the worker that made the most during the work week.
const double FEDERAL_TAX_DEDUCTION = .10; //10% of Gross Income
const double STATE_TAX_DEDUCTION = .05; //5% of Gross Income
const double workerOvertimePay = 0.00; //If Employee Does No Overtime
static void Main(string[] args)
{
int MAX_LIST_VALUE;
Write("How Many Worker's Are Working? ");
MAX_LIST_VALUE = Convert.ToInt32(ReadLine());
string[] workerName = new string[MAX_LIST_VALUE];
for (int i = 0; i < MAX_LIST_VALUE; i++)
{
WriteLine("Please Enter The Worker's Name: ");
workerName[i] = ReadLine();
}
double[] workerWages = new double[MAX_LIST_VALUE];
for (int i = 0; i < MAX_LIST_VALUE; i++)
{
WriteLine("Please Enter The Worker's Hourly Wage: ");
workerWages[i] = Convert.ToDouble(ReadLine());
}
double[] workerWeeklyHours = new double[MAX_LIST_VALUE];
for (int i = 0; i < MAX_LIST_VALUE; i++)
{
Write("How many hours has {0} worked this week? ", workerName[i]);
workerWeeklyHours[i] = Convert.ToDouble(ReadLine());
}
double[] workersRegularPay = new double[MAX_LIST_VALUE];
double[] workerGrossIncome = new double[MAX_LIST_VALUE];
double[] workerStateTaxAmount = new double[MAX_LIST_VALUE];
double[] workerFederalTaxAmount = new double[MAX_LIST_VALUE];
double[] workerNetIncome = new double[MAX_LIST_VALUE];
for (int i = 0; i < MAX_LIST_VALUE; i++)
{
workersRegularPay[i] = workerWeeklyHours[i] * workerWages[i];
workerGrossIncome[i] = workerWeeklyHours[i] * workerWages[i];
workerStateTaxAmount[i] = workerGrossIncome[i] * STATE_TAX_DEDUCTION;
workerFederalTaxAmount[i] = workerGrossIncome[i] * FEDERAL_TAX_DEDUCTION;
workerNetIncome[i] = workerGrossIncome[i] - workerFederalTaxAmount[i] - workerStateTaxAmount[i];
}
WriteLine("There Are " + MAX_LIST_VALUE + " Workers!");
for (int i = 0; i < MAX_LIST_VALUE; i++)
{
WriteLine("Worker's Name: " + workerName[i]);
WriteLine(workerName[i] + " Hourly Wage: " + workerWages[i].ToString("C"));
WriteLine(workerName[i] + " Hours Wokred This Week: " + workerWeeklyHours[i]);
WriteLine(workerName[i] + " Regular Pay: " + workersRegularPay[i].ToString("C"));
WriteLine(workerName[i] + " Gross Income Pay: " + workerGrossIncome[i].ToString("C"));
WriteLine(workerName[i] + " State Tax Amount: " + workerStateTaxAmount[i].ToString("C"));
WriteLine(workerName[i] + " Federal Tax Amount: " + workerFederalTaxAmount[i].ToString("C"));
WriteLine(workerName[i] + " Net Income: " + workerNetIncome[i].ToString("C"));
}
ForegroundColor = ConsoleColor.Red;
WriteLine("\nPress Enter To Continue For Worker's That Earned The Least & Most.");
ReadLine();
int minIndex = 0;
string workerLeast = "null";
double workerRegularPayLeast = 0,
workerGrossIncomeLeast = 0,
workerOverTimeLeast = 0;
int maxIndex = 0;
string workerMost = "null";
double workerRegularPayMost = 0,
workerGrossIncomeMost = 0,
workerOverTimeMost = 0;
for (int i = 0; i < workerGrossIncome.Length; i++)
if (workerGrossIncome[i] < workerGrossIncome[minIndex])
{
minIndex = i;
workerLeast = workerName[i];
workerRegularPayLeast = workersRegularPay[i];
workerGrossIncomeLeast = workerGrossIncome[i];
}
for (int i = 0; i < workerGrossIncome.Length; i++)
if (workerGrossIncome[i] > workerGrossIncome[maxIndex]) //Doesnt calc the most..... FIX
{
maxIndex = i;
workerMost = workerName[i];
workerRegularPayMost = workersRegularPay[i];
workerGrossIncomeMost = workerGrossIncome[i];
}
ForegroundColor = ConsoleColor.Green;
WriteLine("\nThe Worker That Earned The Least Is {0}!", workerLeast);
WriteLine("{0}'s Gross Income Was {1}.", workerLeast, workerGrossIncomeLeast.ToString("C"));
WriteLine("{0}'s Regular Pay Was {1}.", workerLeast, workerRegularPayLeast.ToString("C"));
WriteLine("{0}'s Overtime Pay Was {1}.", workerLeast, workerOverTimeLeast.ToString("C"));
ForegroundColor = ConsoleColor.Cyan;
WriteLine("\nThe Worker That Earned The Most Is {0}!", workerMost);
WriteLine("{0}'s Gross Income Was {1}.", workerMost, workerGrossIncomeMost.ToString("C"));
WriteLine("{0}'s Regular Pay Was {1}.", workerMost, workerRegularPayMost.ToString("C"));
WriteLine("{0}'s Overtime Pay Was {1}.", workerMost, workerOverTimeMost.ToString("C"));
ReadLine();
}
}
Error is in the loop for worker earning the most. The rest is fine for whats needed.
Without LINQ
If you can't use LINQ, then change your maxIndex variable declaration to:
int? maxIndex = null;
And the start of your loop to:
for (int i = 0; i < workerGrossIncome.Length; i++)
if (maxIndex == null || workerGrossIncome[i] > workerGrossIncome[maxIndex.Value])
to ensure that the code work even when the first element is the largest one.
Your existing code does not work if the first element is the largest since workerGrossIncome[i] > workerGrossIncome[maxIndex] will be false and thus workerMost etc won't be set.
With LINQ
If you add the MoreLINQ Nuget Package then maxIndex can be calculated as follows:
// Sample Data
int[] workerGrossIncome = new[] {1, 2, 4};
var maxIndex = workerGrossIncome
.Select((value, index) => new {index, value})
.MaxBy(z => z.value)
.index;
var workerMost = workerName[i];
var workerRegularPayMost = workersRegularPay[i];
var workerGrossIncomeMost = workerGrossIncome[i];
Select will project the original data and the index. MaxBy will find the item with the largest value. index will return the index of that matching item.

C# dice game logic errors

I'm learning C# are I am writing a program that makes an array fills it with 50 random numbers1-6 like dice and then checks how many times each value or 'side' comes up. I made a dice game in python earlier in the week and I had a lot of trouble so I made i= j= and match= print outs to test if the loops and matching were iterating correctly, so I did the same here and I noticed a few logic errors:
the i loop seems to iterate fine but for every 1 iteration of i, j should iterate 50 times but i only get it once.
The i OR j loops don't iterate at all unless in line 47 it states while j > dice.Length. Writing as it should be j < dice.Length makes it not iterate at all. The 50 random numbers display on screen so i know dice is 50 in length and j is 0.
Thirdly in line 50 if dice[i] == dice[j] I get an error that j isn't valid unless I declare j above the for loop, and if I do that I can't do int j = 0 in the for loop, so I scrapped the for loop and did a while loop, but it still only adds a value for the first match and not the next possible 49.
I am only coding inside the static void since it's a simple console application, thank you for your help.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace wk8hw2
{
class Program
{
static void Main(string[] args)
{//staticvoid
int size = 50;
int diceSides = 7;
int matchAdd = 0;
int[] dice = new int[size];
int[] match = new int[diceSides];
Random rnd = new Random();
int j = 0;
Console.WriteLine("Press any key to roll the dice " + size + " times.");
Console.ReadKey();
for (int i = 0; i < dice.Length; i++)//roll dice
{
dice[i] = rnd.Next(1, diceSides);
}
for (int i = 0; i < dice.Length; i++)//show dice
{
Console.Write(dice[i] + " ");
}
Console.WriteLine("done showing dice");//DEBUG
for (int i = 0; i < dice.Length; i++)//outer match loop
{
Console.Write("i = " + i);//DEBUG
if (match[dice[i]] == 0)//if not matched add to match array
{
Console.WriteLine("not yet matched");
matchAdd = 1;
}
else//if alerady matched add no more
{
Console.WriteLine("already matched");
matchAdd = 0;
}
j = 0;
while (j > dice.Length)//inner match loopSUPPOSED TRO BE LESS THAN
{
Console.WriteLine("j = " + j);
if (dice[i] == dice[j])//if equal add to match array
{
match[dice[i]] = match[dice[i]] + matchAdd;
Console.WriteLine("val " + match[dice[i]]);
}
j++;
}
}//endFORouter
for (int i = 1; i < match.Length; i++)
{
Console.WriteLine(i + " came up " + match[i] + " times.");
}
Console.ReadKey();
}//endstaticvoid
}
}
I agree with the first answer however...you said you are learning C# and based on the namespace this is a homework assignment and you are most likely learning about arrays so I would rewrite it a bit different
You seem to be doing way to many loops and generally doing to much. Make your code as simple as possible and name your variables to tell anyone reading the code what they do.
int numberOfRolls = 50;
int diceSides = 6;
int[] dice = new int[numberOfRolls];
int[] match = new int[diceSides];
Random random = new Random();
Console.WriteLine("Press any key to roll the dice " + numberOfRolls + " times.");
Console.ReadKey();
for (int rollCount = 0; rollCount < numberOfRolls; rollCount++)
{
var rollResult = random.Next(1, diceSides+1);
match[rollResult-1]++;
}
for (int i = 0; i < match.Length; i++)
{
Console.WriteLine(i+1 + " came up " + match[i] + " times.");
}
Console.ReadKey();
I'd rewrite this whole thing as:
Random rnd = new Random();
const int diceSides = 6;
const int numDice = 50;
Console.WriteLine("Press any key to roll the dice {0} times.", numDice);
Console.ReadKey();
var diceByValue = Enumerable.Range(0, numDice)
.Select(_ => rnd.Next(diceSides) + 1)
.GroupBy(v => v)
.OrderBy(g => g.Key);
foreach (var group in diceByValue)
Console.WriteLine("{0} came up {1} times.", group.Key, group.Count());

Creating different arrays: not displaying correct results

I am currently building a sorting program. I have made three different ways to create an array: Random, In Order and Reverse. I am currently undergoing problems with the In Order and Reverse arrays. Every time an In Order array is created it starts with a 1, I am not sure how come is doing so. Also my Reverse array will display digits out of order not every time but after some clicks. How can I fix these two issues?
namespace sortingMachine
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Class Level Variables --------------------------------------------------------------------------------------
Stopwatch sw = new Stopwatch();
Random r = new Random();
OpenFileDialog open1 = new OpenFileDialog();
long operations = 0;
int size;
int max;
int[] createArray;
int[] sortArray;
int[] copyArray;
//Create Array Methods --------------------------------------------------------------------------------------
public void RandomNumber()
{
size = Convert.ToInt32(textBoxSize.Text);
max = Convert.ToInt32(textBoxMax.Text);
createArray = new int[size];
copyArray = new int[size];
sortArray = new int[size];
for (int i = 0; i < size; i++)
{
createArray[i] = r.Next(1, max);
}
textBoxResults.AppendText("-------------------------------------------------------------------------------" + Environment.NewLine + "Random" + Environment.NewLine + Environment.NewLine);
DisplayArrays();
}
public void InOrder()
{
size = Convert.ToInt32(textBoxSize.Text);
max = Convert.ToInt32(textBoxMax.Text);
createArray = new int[size];
copyArray = new int[size];
sortArray = new int[size];
createArray[0] = 1;
for (int i = 1; i < size; i++)
{
createArray[i] = createArray[i - 1] + r.Next(1, max);
}
for (int i = 1; i < size; i++)
{
if (r.Next(1, 101) < Convert.ToInt32(textBoxPercentage.Text))
{
for (int x = 1; x < size; x++)
{
createArray[x] = r.Next(1, createArray[size - 1]);
}
}
}
textBoxResults.AppendText("-------------------------------------------------------------------------------" + Environment.NewLine + "In Order" + Environment.NewLine + Environment.NewLine);
DisplayArrays();
}
public void ReverseOrder()
{
size = Convert.ToInt32(textBoxSize.Text);
max = Convert.ToInt32(textBoxMax.Text);
createArray = new int[size];
copyArray = new int[size];
sortArray = new int[size];
createArray[size - 1] = 1;
for (int i = size - 1; i > 0; i--)
{
createArray[i - 1] = createArray[i] + r.Next(1, max);
}
for (int i = size - 1; i > 0; i--)
{
if (r.Next(1, 101) < createArray[0])
{
for (int x = size - 1; x > 0; x--)
{
createArray[x] = r.Next(1, createArray[0]);
}
}
}
textBoxResults.AppendText("-------------------------------------------------------------------------------" + Environment.NewLine + "Reverse Order" + Environment.NewLine + Environment.NewLine);
DisplayArrays();
}
private void buttonCreateArray_Click(object sender, EventArgs e)
{
if ((textBoxSortKey.Text != "") && (textBoxCreateKey.Text != ""))
{
if (radioButtonRandom.Checked == true)
{
RandomNumber();
}
if (radioButtonInOrder.Checked == true)
{
InOrder();
}
if (radioButtonReverseOrder.Checked == true)
{
ReverseOrder();
}
}
else
{
MessageBox.Show("Type a key into the Key textbox.");
}
}
}
}
Display Results:
The order array I am not sure why it always start with one:
-------------------------------------------------------------------------------
In Order
1
2
4
6
10
There are times the reverse order array will be like this:
-------------------------------------------------------------------------------
Reverse Order
10
2
7
6
5
Windows Form:
If you look at how you are assigning values to the array you'll see that the first element is assigned zero, but in your loop you start at the second element (i.e. 1) so you never re-assign the first element.
createArray[0] = 1;
for (int i = 1; i < size; i++)
{
createArray[i] = createArray[i - 1] + r.Next(1, max);
}
Try writing the first element assignment like this:
createArray[0] = r.Next(1, max);
As for your reverse function, there's too much weirdness in there to really see what you're trying to do. Try thinking thru it a few more times. Especially be careful with code like this: if (r.Next(1, 101) < createArray[0]) - it has random behaviour and also magic numbers in it.
In the function InOrder you initialize your first index of your array to 1. As for the Reverse Order, in the if statement in between the two fors, each time you are comparing a random number between 1-101 with the first number in your array. What you should be doing instead is compare the numbers in your array with each other.

Categories

Resources