C# find highest value in class object array without LINQ - c#

This is for my school project and therefor I need to code without LINQ methods etc.
I'm trying to show which city has the highest temperature by finding the highest temp and then print it together with the city name.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
class City
{
public string name { get; set; }
public int temp { get; set; }
public override string ToString()
{
return $"CITY:\t{name}\nTEMP:\t{temp}°C\n";
}
}
I want to use Tostring() to print.
//=====Highest Temperature=====//
static void HighestTemp(City[] cities)
{
int highest = cities[0].temp;
for (int i = 1; i < cities.Length; i++)
{
if (highest < cities[i].temp)
{
highest = cities[i].temp;
}
}
}
I've found the highest temperature.
But the question is: How do I print it with ToString()?? I want both cities[i].name and cities[i].temp

Your issue is you found the highest temp, not the city with the highest temp.
Without using Linq or any of the shortcut methods like .OrderBy(..) or .OrderByDescending(..), you can simply just store a second variable that tracks your best i
int highestTemp = cities[0].temp;
int highestTempIndex = 0;
for (int i = 1; i < cities.Length; i++)
{
if (highest < cities[i].temp)
{
highest = cities[i].temp;
highestTempIndex = i;
}
}
var highestTempCity = cities[highestTempIndex];
And to stringify the city its as simple as:
$"{highestTempCity}"
Because overriding specifically .ToString() automates this. You also can call highestTempCity.ToString() if you like.
If you utilize the power of Linq though you can simplify this a lot by just doing:
var highestTempCity = cities.OrderByDescending(city => city.temp).First();

SOLVED!
I succeeded by doing like this:
//=====Highest temperature=====//
static int HighestTemp(City[] cities, int n)
{
int highestTemp = cities[0].temp;
var highestTempIndex = 0;
for (int i = 1; i < n; i++)
{
if (highestTemp < cities[i].temp)
{
highestTemp = cities[i].temp;
highestTempIndex = i;
}
}
return highestTempIndex;
}
From what this method return I made int Index and print the result in Main
//----------City with HIGHEST temperature----------//
index = HighestTemp(cities, n);
Console.WriteLine(cities[index].ToString());

Related

Weighted Job Scheduler - Retrieve Job Details

I am learning C# and want to created a weighted job scheduler.
The max profit is working fine. But I need to be able to get the JobIDs associated with it so I am trying to save it in an array jobsId, similar to this implementation in C++: https://onlinegdb.com/a9wx3nHoN.
But then in this snippet, I am getting an error: Wrong number of indices inside []; expected 2
if (profitSum > dp[i-1]) {
dp[i] = profitSum;
jobsId[i,0] = jobsId[task]; // Problem is here
jobsId[i].Append(jobs[i].id).ToArray(); //And here
}
What am I doing wrong? Please help, thanks!
Codes can be accessed here:
https://rextester.com/NXM85235
Alternatively, here is my entire snippet:
using System.IO;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;
class Program
{
public int JobScheduling(int[] startTime, int[] endTime, int[] profit) {
var jobs = startTime
.Select((_, i) => new // create custom obj
{
id = i,
s = startTime[i],
e = endTime[i],
p = profit[i],
}
)
.OrderBy(x => x.e) // sort by end-time
.ToArray();
int[] dp = new int[jobs.Length];
int [,] jobsId = new int[,] {{jobs[0].id}};
int profitSum = jobs[0].p;
int task = -1;
dp[0] = jobs[0].p;
for (var i = 1; i < jobs.Length; i++) {
for (var j = i-1; j >= 0; j--) {
if (jobs[j].e <= jobs[i].s) {
task = j;
break;
}
}
if (task != -1) {
profitSum += dp[task];
}
if (profitSum > dp[i-1]) {
dp[i] = profitSum;
jobsId[i,0] = jobsId[task]; // Problem is here
jobsId[i].Append(jobs[i].id).ToArray();
}
}
// Need to implement this
for (var iter = 0; iter < jobsId.Length; iter++) {
Console.WriteLine(jobsId[iter,0]);
}
return dp[jobs.Length-1];
}
public static void Main(string[] args)
{
int[] startTime = { 1,3,6,2 };
int[] endTime = { 2,5,7,8 };
int[] profit = { 50,20,100,200 };
// Creating object
Program job = new Program();
Console.WriteLine(job.JobScheduling(startTime, endTime, profit));
}
}
int [,] jobsId = new int[,] {{jobs[0].id}};
The multi-dimensional 3d array that you are using has a fixed size .i.e. only one. You can't add any more elements to that array. Instead, try using List< List < int > >.
jobsId[i,0] = jobsId[task]; // problem here
Here jobsId is a 2d-array. You can't access the individual rows. You can only access elements within. For this too you need to create an array of array .i.e List< List < int > >.
And I could not figure out why are trying to get an array here.
jobsId[i].Append(jobs[i].id).ToArray();

How do you get a program to pick a different string from a list each time rather than writing the same string over and over again?

I am having an issue with picking randomly from a list. When I run the program, it keeps writing the same string over and over again when I want it to come up with a different random string each time. Here is an example:
using System;
using System.Collections.Generic;
namespace List
{
class Program
{
static void Main(string[] args)
{
var letterList = new List<string>
{
"A","B","C","D"
};
Random r = new Random();
int letterListIndex = r.Next(letterList.Count);
for (int i = 0; i < 10; i++) {
Console.WriteLine(letterList[letterListIndex]);
}
}
}
}
For Example: When I run this code it would write "B" 10 times. I want it to come up with 10 different letters every time. I know that you could just write:
int letterListIndex1 = r.Next(letterList.Count);
int letterListIndex2 = r.Next(letterList.Count);
int letterListIndex3 = r.Next(letterList.Count);
Console.WriteLine(letterList[letterListIndex1]);
Console.WriteLine(letterList[letterListIndex2]);
Console.WriteLine(letterList[letterListIndex3]);
But I wanted to know if there was an easier way to do so.
Thanks.
You should put your letterListIndex variable inside for loop
for (int i = 0; i < 10; i++) {
int letterListIndex = r.Next(letterList.Count);
Console.WriteLine(letterList[letterListIndex]);
}
Otherwise you get the same index every time.
You need to put
int letterListIndex = r.Next(letterList.Count);
inside the for loop.
you can use below code
for (int i = 0; i < 10; i++) {
Console.WriteLine(letterList[r.Next(letterList.Count)]);
}

No errors in Visual Studio, Code Executes but something not right C# (updated! problem in String.Insert)

I'm writing a program for schoolwork, that's supposed to generate a 10 000 "movie" list. A single "movie" consist of a string in a form "moviename year director". I say "movie" because movie name and director are supposed to be randomly generated with letters from a-z.
I wrote the following logic to generate one such "movie". Movie name and director are random letter combination in length between 4-10 charachters. Code gives no errors in visual studio, executes, but shows blank. If I wrote correctly, then this code should generate one such string and print it, yet console is blank.
Do while loop is there to check if, however unlikely, there is a double item in the List (this is for when I do the 10 000 version).
In short, I dont understand what am I doing wrong?
using System;
using System.Collections.Generic;
using System.Linq;
namespace Experiment
{
class Program
{
static void Main(string[] args)
{
Movies();
Console.ReadKey();
}
public static void Movies()
{
List<string> movieList = new List<string>();
bool check = false;
do
{
string movie = "";
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
movie.Insert(0, " ");
movie.Insert(0, Convert.ToString(GetYear()));
movie.Insert(0, " ");
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
if (movieList.Contains(movie))
{
check = false;
}
else
{
movieList.Add(movie);
check = true;
}
} while (check == false);
Console.WriteLine(movieList[0]);
}
public static Random _random = new Random();
public static char GetLetter()
{
int num = _random.Next(0, 26);
char let = (char)('a' + num);
return let;
}
public static int GetNum()
{
int num = _random.Next(4, 11);
return num;
}
public static int GetYear()
{
int num = _random.Next(1920, 2020);
return num;
}
}
}
Strings are immutable, so calling the Insert() method on the movie string doesn't do anything to the current movie variable. Instead it returns the new string.
You are however better off changing the movie type from string to StringBuilder, which is a dynamically allocated buffer of characters, so your example becomes:
using System;
using System.Text;
using System.Collections.Generic;
namespace sotest
{
class Program
{
static void Main(string[] args)
{
Movies();
Console.ReadKey();
}
public static void Movies()
{
List<string> movieList = new List<string>();
bool check = false;
do
{
StringBuilder movie = new StringBuilder();
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
movie.Insert(0, " ");
movie.Insert(0, Convert.ToString(GetYear()));
movie.Insert(0, " ");
for (int i = 0; i < GetNum(); i++)
{
movie.Insert(0, Convert.ToString(GetLetter()));
}
if (movieList.Contains(movie.ToString()))
{
check = false;
}
else
{
movieList.Add(movie.ToString());
check = true;
}
} while (check == false);
Console.WriteLine(movieList[0]);
}
public static Random _random = new Random();
public static char GetLetter()
{
int num = _random.Next(0, 26);
char let = (char)('a' + num);
return let;
}
public static int GetNum()
{
int num = _random.Next(4, 11);
return num;
}
public static int GetYear()
{
int num = _random.Next(1920, 2020);
return num;
}
}
}
The problem is that you are using movie.Insert incorrectly.
If you read the documentation for String.Insert it says
https://learn.microsoft.com/en-us/dotnet/api/system.string.insert?view=netframework-4.8
Returns a new string in which a specified string is inserted at a
specified index position in this instance
public string Insert (int startIndex, string value);
So it returns a new String, it does not amend the existing one. So you would need to do.
movie = movie.Insert(0, Convert.ToString(GetYear()));
However, I must also say that using String.Insert in this way is not the best approach.
You should instead look at using the StringBuilder class. It is very efficient when you want to amend strings (which are immutable objects).
You might want to read parts of this to help you understand. If you scroll down then it also suggests StringBuilder.
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/strings/
Insert() method is used to return a new string from the specified string at a specified index position. In your case, you are not capturing the updated string.
The best approach to solve this is through using StringBuilder object. Please note that StringBuilder object is much efficient rather than playing with immutable string.

Prefixset on codility using c#

Problem Description:
Given a table A of N integers from 0 to N-1 calculate the smallest
such index P, that that {A[0],...,A[N-1]} = {A[0],...,A[P]}.
My solution
using System;
using System.Linq;
using System.Collections.Generic;
class Solution {
public int solution(int[] A) {
for (int i=A.Length-1;i>=0;i--) {
int[] Am = A.Take(i).ToArray();
int pos = Array.IndexOf(Am, A[i]);
if( pos >- 1 )
{
}
else
{
return i;
}
}
return A.Length-1;
}
}
This works but complexity is O(N**2) and times out when Array has large number of elements
If i use long in place of int, I get the cs0266 cannot implicitly convert long to int error.
Please suggest on how i can improve this. Thanks
You can just keep track of all the elements you have already observed using a set.
public Int32 Solution(Int32[] A)
{
var seenNumbers = new HashSet<Int32>();
var result = 0;
for (var index = 0; index < A.Length; index++)
{
if (seenNumbers.Add(A[index]))
{
result = index;
}
}
return result;
}
Note that HashSet<T>.Add() will return true if the element is not already in the set, false otherwise. When you discover a number for the first time you obviously have to include that number and therefore extend the prefix to the current position. This will run in O(n) and consume O(n) additional space.

Sorting a Queue

I have to simulate a process scheduler using SRTN algorithm and im having trouble within a certain part.
I have a queue of a custom class called 'Process' I need to sort it based on a a field called 'last_prediction'. My code works most of the time, but if you look at time:19 of my output, the output in the ready queue is wrong (it should be: 1004(1.5) 1002(2) 1003(2)).
Here is my code:
int count = ReadyQueue.Count;
// Copy Queue into Vector
ArrayList temp = new ArrayList();
for (int i = 0; i < count; i++)
{
Process p = (Process)ReadyQueue.Dequeue();
temp.Add(p);
}
// Sort Vector
for (int i = 0; i < count; i++)
{
double min = ((Process)temp[i]).last_prediction;
for (int j=i+1; j<count; j++)
{
if ( ((Process)temp[j]).last_prediction < min )
{
min = ((Process)temp[j]).last_prediction;
Process dummy = (Process)temp[j];
temp[j] = temp[i];
temp[i] = dummy;
}
}
}
// Copy Vector back into Queue
for (int i = 0; i < count; i++)
{
Process p = (Process)temp[i];
ReadyQueue.Enqueue(p);
}
EDIT: ok, im trying to use ICompare, similar to what you gave hughdbrown.Now i get a different error:
public class Process
{
public int process_id;
public int arrival_time;
public int total_time;
public int avg_burst;
public int actual_burst;
public int last_burst; // SRTN
public double last_prediction; // SRTN
public int io_delay;
public int context_switch_delay;
public class ProcessSort : IComparer
{
public int Compare(object x, object y)
{
var a = x as Process;
var b = y as Process;
double aNum = a.last_prediction;
double bNum = b.last_prediction;
return Compare(aNum, bNum);
}
}
}
this is the error i get now:
Unhandled Exception: System.InvalidOperationException: Failed to compare two elements in the array. ---> System.NullReferenceException: Object reference not set to an instance of an object.
I would use a real sorting routine on this array, not a hand-crafted insertion/bubble sort. Add a comparison function to your object.
I'd also use a templatized data collection, not ArrayList. You might be interested in using this C# PriorityQueue code from my website. That has Queue semantics and maintains items in a sorted order.
Later: Your IComparable code would be something like this:
public class Process : IComparable
{
int last_prediction;
public int CompareTo(object obj)
{
Process right = obj as Process;
return this.last_prediction.CompareTo(right.last_prediction);
}
}
Later still: here is a complete test program that has a sortable Process. Tested in Mono on ubuntu.
using System;
using System.Collections.Generic;
using System.Text;
namespace Comparer
{
public class Process : IComparable
{
int last_prediction;
public Process(int p)
{
this.last_prediction = p;
}
public int CompareTo(object obj)
{
Process right = obj as Process;
return this.last_prediction.CompareTo(right.last_prediction);
}
public int Prediction { get { return this.last_prediction; } }
}
class MainClass
{
public static void Main (string[] args)
{
List<Process> list = new List<Process>();
for (int i = 0; i < 10; i++)
list.Add(new Process(10 - i));
System.Console.WriteLine("Current values:");
foreach (Process p in list)
System.Console.WriteLine("Process {0}", p.Prediction);
list.Sort();
System.Console.WriteLine("Sorted values:");
foreach (Process p in list)
System.Console.WriteLine("Process {0}", p.Prediction);
}
}
}
Have you considered using the ArrayList.Sort method instead of attempting to write your own sort?
Here's how I would sort the Process objects. Let's use a List<Process> instead of an ArrayList so that we don't have to keep casting it back and forth. I haven't done much with queues in C# so I'm afraid I can't help much with those. And please note that this code is untested. :)
int count = ReadyQueue.Count;
// Copy Queue into Vector
List<Process> listProcesses = new List<Process>();
for(int i = 0; i < count; i++)
{
Process p = (Process)ReadyQueue.Dequeue();
listProcesses.Add(p);
}
// Sort Vector
listProcesses.Sort(CompareProcessesByPrediction);
// Copy Vector back into Queue
foreach(Process p in listProcesses)
ReadyQueue.Enqueue(p);
private static int CompareProcessesByPrediction(Process proc1, Process proc2)
{
//if they're both not-null, figure out which one is greatest/smallest.
//otherwise just pick the one that isn't null
if(proc1 == null)
return proc2 == null ? 0 : -1;
else
return proc1 == null ? 1 : proc1.last_prediction.CompareTo(proc2.last_prediction);
}
yea.. use arraylist.sort
If ur array only got numbers, create a new number array coz.. arraylist.sort for string has some problem.
and use arraylist.sort
take the number of the position you want and convert back to string if u want..

Categories

Resources