I'm stuck at this. I`m beginner into software development. You get a list of N students and then a list of ratings for each student. A student which has bigger rating than his neighbour from list gets more coins than both of them. For example:
Data input:
3
John
Dan
Sam
9
10
8
Data output:
John 1
Dan 3
Sam 1
My output is just the names of the students.
I wrote this code:
using System;
class Program
{
private static void Main(string[] args)
{
int n = Convert.ToInt32(Console.ReadLine());
var numberCoins = new int[n];
string[] studentNames = new string[n];
numberCoins[0] = 1;
for (int i = 0; i < n; i++)
{
studentNames[i] = Console.ReadLine();
}
int[] grades = new int[n];
for (int i = 0; i < n; i++)
{
grades[i] = Convert.ToInt32(Console.ReadLine());
}
for (int i = 1; i < n; i++)
{
if (grades[i] > grades[i - 1])
{
numberCoins[i] = numberCoins[i - 1] + 1;
}
}
for (int i = n - 2; i >= 0; i--)
{
if (grades[i] > grades[i + 1])
{
numberCoins[i] = numberCoins[i + 1] + 1;
}
}
for (int i = 0; i < n; i++)
{
Console.WriteLine(studentNames[i], " ", numberCoins[i]);
}
Console.ReadLine();
}
}
You didn't mention if there is any pattern to give coins to the students. And if we have specific number of coins or not.
If we consider at first no one has any coins the result must be something like the following:
Please specify the number of the students:
3
Please write students' name (after each name hit the ENTER):
John
Dan
Sam
Please write students' ratings (after each rating hit the ENTER):
9
10
8
The result:
John: 0
Dan: 2
Sam: 0
I wrote a piece of code which might help you approach the functionality you want.
using System;
class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Please specify the number of the students:");
int n = int.Parse(Console.ReadLine());
string[] studentNames = new string[n];
int[] studentRatings = new int[n];
int[] studentCoins = new int[n];
Console.WriteLine();
Console.WriteLine("Please write students' name (after each name hit the ENTER):");
for (int i = 0; i < n; i++)
{
studentNames[i] = Console.ReadLine() ?? string.Empty;
}
Console.WriteLine();
Console.WriteLine("Please write students' ratings (after each rating hit the ENTER):");
for (int i = 0; i < n; i++)
{
studentRatings[i] = int.Parse(Console.ReadLine());
}
Console.WriteLine();
Console.WriteLine("The result:");
for (int i = 0; i < n; i++)
{
int coins = 1;
studentCoins[i] = 0;
if (i != 0)
if (studentRatings[i] > studentRatings[i - 1])
coins++;
if (i != n - 1)
if (studentRatings[i] > studentRatings[i + 1])
coins++;
studentCoins[i] = coins;
}
for (int i = 0; i < n; i++)
{
Console.WriteLine($"{studentNames[i]}: {studentCoins[i]}");
}
}
}
using System;
namespace MoveFirst
{
class Program
{
static void Main(string[] args)
{
int[] values = ReadValuesList();
int[] positionsToMove = ReadPositions();
for (int i = 0; i < positionsToMove.Length; i++)
MoveFirst(values, positionsToMove[i]);
PrintValuesList(values);
Console.WriteLine(CheckIfSortedAscending(values));
Console.Read();
}
static bool CheckIfSortedAscending(int[] values)
{
for (int i = 1; i < values.Length; i++)
if (values[i - 1] > values[i])
return false;
return true;
}
public static void MoveFirst(int[] values, int index)
{
var temp = values[0];
values[0] = values[index];
values[index] = temp;
}
static int[] ReadPositions()
{
int positionsNumber = Convert.ToInt32(Console.ReadLine());
int[] positions = new int[positionsNumber];
for (int i = 0; i < positionsNumber; i++)
positions[i] = Convert.ToInt32(Console.ReadLine());
return positions;
}
static int[] ReadValuesList()
{
string[] inputValues = Console.ReadLine().Split(' ');
int[] values = new int[inputValues.Length];
for (int i = 0; i < values.Length; i++)
values[i] = Convert.ToInt32(inputValues[i]);
return values;
}
static void PrintValuesList(int[] valuesList)
{
for (int i = 0; i < valuesList.Length; i++)
Console.Write(valuesList[i] + " ");
Console.Write('\n');
}
}
}
This is my whole code, but I have a problem with the result..Can I get some suggestions how to correct the code within the MoveFirst method ?
There are given a series of numbers on a single line, separated by a space. There are N operations to move a string element to the first position.. Each move is specified on one line (the index of the element which has to be moved to the first position), but all other elements of the string remain in the same order.
For example if the user inputs : 1 2 3 4 5 6
1
5
the result should be : 6 2 1 3 4 5
my result is : 6 1 3 4 5 2
Here is working example, using LinkedList<int>
Input:
1 2 3 4 5 6
2
1
5
Result:
6 2 1 3 4 5
using System;
using System.Collections.Generic;
using System.Linq;
namespace MoveFirst
{
class Program
{
static void Main(string[] args)
{
LinkedList<int> values = ReadValuesList();
int[] positionsToMove = ReadPositions();
for (int i = 0; i < positionsToMove.Length; i++)
MoveFirst(values, positionsToMove[i]);
PrintValuesList(values);
Console.WriteLine(CheckIfSortedAscending(values));
Console.Read();
}
static bool CheckIfSortedAscending(IEnumerable<int> valuesList)
{
var prevValue = int.MinValue;
foreach (int value in valuesList)
{
if (prevValue > value)
return false;
prevValue = value;
}
return true;
}
public static void MoveFirst(LinkedList<int> values, int index)
{
if (index == 0 || index >= values.Count)
return;
var node = values.First;
for (var i = 0; i < index; i++)
node = node.Next;
values.Remove(node);
values.AddFirst(node);
}
static int[] ReadPositions()
{
int positionsNumber = Convert.ToInt32(Console.ReadLine());
int[] positions = new int[positionsNumber];
for (int i = 0; i < positionsNumber; i++)
positions[i] = Convert.ToInt32(Console.ReadLine());
return positions;
}
static LinkedList<int> ReadValuesList()
{
return new LinkedList<int>(Console.ReadLine().Split(' ').Select(Int32.Parse));
}
static void PrintValuesList(IEnumerable<int> valuesList)
{
foreach (int value in valuesList)
Console.Write(value + " ");
Console.Write('\n');
}
}
}
Update:
MoveFirst method for situation when you forced to use array.
public static void MoveFirst(int[] values, int index)
{
if (index == 0 || index >= values.Length)
return;
var temp = values[index];
for (int i = index - 1; i >=0; i--)
values[i + 1] = values[i];
values[0] = temp;
}
I have this problem from school:
You get a list of N students and a list of grades for each student. Every student gets coins. A student which has bigger grade than his neighbours from list earns more coins than them. Find the coins which every student must recieve.
Input:
6
Ionel
Mihai
Elena
Maria
George
Irina
9
10
8
6
9
10
Output:
Ionel 1
Mihai 3
Elena 2
Maria 1
George 2
Irina 3
Here is my code:
static void Main()
{
int number = Convert.ToInt32(Console.ReadLine());
string[] studentsList = FillTheList(number);
int[] studentsGrades = ConvertList(FillTheList(number));
PrintResult(studentsList, CalculateCoins(studentsGrades, number));
}
static string[] FillTheList(int number)
{
string[] result = new string[number];
for (int i = 0; i < number; i++)
{
result[i] = Console.ReadLine();
}
return result;
}
static int[] ConvertList(string[] array)
{
int[] result = new int[array.Length];
for (int i = 0; i < array.Length; i++)
{
result[i] = Convert.ToInt32(array[i]);
}
return result;
}
static int[] GiveEachStudentCoins(int number)
{
int[] result = new int[number];
result[0] = 1;
return result;
}
static void CheckArray(int[] array, int[] theResult, int number, int counter)
{
int i = number;
int count = counter;
int[] result = theResult;
for (int j = 0; j < array.Length; j++)
{
if (array[i] < array[j])
{
result[j] += count;
}
else
{
break;
}
}
}
static int[] CalculateCoins(int[] array, int number)
{
int[] result = GiveEachStudentCoins(number);
const int count = 1;
for (int i = 1; i < array.Length; i++)
{
if (array[i - 1] < array[i])
{
result[i] += result[i - 1] + count;
}
else
{
result[i] += count;
CheckArray(array, result, i, count);
}
}
return result;
}
static void PrintResult(string[] array, int[] array2)
{
for (int i = 0; i < array.Length; i++)
{
array[i] += " " + array2[i];
}
foreach (string student in array)
{
Console.WriteLine(student);
}
}
It works for ascending and descending order of grades, and also for equal grades. But it doesn't work for mixed order. Here is the result I get:
Ionel 3
Mihai 4
Elena 2
Maria 1
George 2
Irina 3
My problem is on the CheckArray method I think, and I don't know how to change the logic for this thing to work.
We can access the neighboring elements while walking through the array in a for loop by subtracting or adding 1 to the index of the current item. Of course before we do this, we have to make sure that the neighbor we want to check actually exists (if i == 0 then we can't access index i - 1, and if i == array.Length - 1, then we can't access index i + 1).
Given this knowledge, we can follow a simple formula, just as if we were doing it "by hand" on a piece of paper:
Start all values in the coins array with 1
Loop through each item in the input array.
If there's an item to the left and it's smaller than this item, then set the corresponding coins item to be one more than the coins item to it's left
If there's an item to the right and it's smaller than this item, and if the corresponding coins item is equal to the coins item to its right, then increment this item by 1
If we incremented this item after comparing to the right, then we need to re-check the item to the left and increment it if necessary (based on the corresponding values in the items array).
If that didn't make complete sense, try it on paper and it may be more obvious. Otherwise, hopefully this code sample will help:
public static int[] GetCoins(int[] input)
{
int[] coins = new int[input.Length];
// Initialize coins array with all '1's (similar to 'GiveEachStudentCoins')
for (int i = 0; i < coins.Length; i++)
{
coins[i] = 1;
}
// Examine the neighbors of each item in the array
for (int i = 0; i < input.Length; i++)
{
// Check left neighbor (if there is one)
if (i > 0 && (input[i] > input[i - 1]))
{
if (coins[i] <= coins[i - 1])
{
coins[i] = coins[i - 1] + 1;
}
}
// Check right neighbor (if there is one)
if (i < input.Length - 1 && input[i] > input[i + 1])
{
if (coins[i] == coins[i + 1])
{
coins[i]++;
// Recheck left since we incremented this one
if (i > 0 && input[i - 1] > input[i])
{
coins[i - 1]++;
}
}
}
}
return coins;
}
Here's some sample code that can be used for testing, so you don't have to manually enter numbers into the console each time (this requires adding using System.Linq to the top of the file):
public static void Main(string[] args)
{
// Populate the grades you want to test here
int[] studentsGrades = {9, 10, 8, 6, 9, 10};
// Student names are automatically generated
string[] studentsList = Enumerable.Range(1, studentsGrades.Length)
.Select(i => $"Student #{i} grade: {studentsGrades[i - 1]}\tcoins: ")
.ToArray();
// Call the new method to get the coins array
int[] coins = GetCoins(studentsGrades);
// Show the results
PrintResult(studentsList, coins);
Console.WriteLine("Done! Press any key to exit...");
Console.ReadKey();
}
i have a deal with a hackerrank algorithm problem.
It works at all cases, except 6-7-8-9. It gives timeout error. I had spent so much time at this level. Someone saw where is problem?
static long[] climbingLeaderboard(long[] scores, long[] alice)
{
//long[] ranks = new long[scores.Length];
long[] aliceRanks = new long[alice.Length]; // same length with alice length
long lastPoint = 0;
long lastRank;
for (long i = 0; i < alice.Length; i++)
{
lastPoint = scores[0];
lastRank = 1;
bool isIn = false; // if never drop in if statement
for (long j = 0; j < scores.Length; j++)
{
if (lastPoint != scores[j]) //if score is not same, raise the variable
{
lastPoint = scores[j];
lastRank++;
}
if (alice[i] >= scores[j])
{
aliceRanks[i] = lastRank;
isIn = true;
break;
}
aliceRanks[i] = !isIn & j + 1 == scores.Length ? ++lastRank : aliceRanks[i]; //drop in here
}
}
return aliceRanks;
}
This problem can be solved in O(n) time, no binary search needed at all. First, we need to extract the most useful piece of data given in the problem statement, which is,
The existing leaderboard, scores, is in descending order.
Alice's scores, alice, are in ascending order.
An approach that makes this useful is to create two pointers, one at the start of alice array, let's call it "i", and the second is at the end of scores array, let's call it "j". We then loop until i reaches the end of alice array and at each iteration, we check for three main conditions. We increment i by one if alice[i] is less than scores[j] because the next element of alice may be also less than the current element of scores, or we decrement j if alice[i] is greater than scores[j] because we are sure that the next elements of alice are also greater than those elements discarded in scores. The last condition is that if alice[i] == scores[j], we only increment i.
I solved this question in C++, my goal here is to make you understand the algorithm, I think you can easily convert it to C# if you understand it. If there are any confusions, please tell me. Here is the code:
// Complete the climbingLeaderboard function below.
vector<int> climbingLeaderboard(vector<int> scores, vector<int> alice) {
int j = 1, i = 1;
// this is to remove duplicates from the scores vector
for(i =1; i < scores.size(); i++){
if(scores[i] != scores[i-1]){
scores[j++] = scores[i];
}
}
int size = scores.size();
for(i = 0; i < size-j; i++){
scores.pop_back();
}
vector<int> ranks;
i = 0;
j = scores.size()-1;
while(i < alice.size()){
if(j < 0){
ranks.push_back(1);
i++;
continue;
}
if(alice[i] < scores[j]){
ranks.push_back(j+2);
i++;
} else if(alice[i] > scores[j]){
j--;
} else {
ranks.push_back(j+1);
i++;
}
}
return ranks;
}
I think this may help you too:
vector is like an array list that resizes itself.
push_back() is inserting at the end of the vector.
pop_back() is removing from the end of the vector.
Here is my solution with c#
public static List<int> climbingLeaderboard(List<int> ranked, List<int> player)
{
List<int> result = new List<int>();
ranked = ranked.Distinct().ToList();
var pLength = player.Count;
var rLength = ranked.Count-1;
int j = rLength;
for (int i = 0; i < pLength; i++)
{
for (; j >= 0; j--)
{
if (player[i] == ranked[j])
{
result.Add(j + 1);
break;
}
else if(player[i] < ranked[j])
{
result.Add(j + 2);
break;
}
else if(player[i] > ranked[j]&&j==0)
{
result.Add(1);
break;
}enter code here
}
}
return result;
}
Here is a solution that utilizes BinarySearch. This method returns the index of the searched number in the array, or if the number is not found then it returns a negative number that is the bitwise complement of the index of the next element in the array. Binary search only works in sorted arrays.
public static int[] GetRanks(long[] scores, long[] person)
{
var defaultComparer = Comparer<long>.Default;
var reverseComparer = Comparer<long>.Create((x, y) => -defaultComparer.Compare(x, y));
var distinctOrderedScores = scores.Distinct().OrderBy(i => i, reverseComparer).ToArray();
return person
.Select(i => Array.BinarySearch(distinctOrderedScores, i, reverseComparer))
.Select(pos => (pos >= 0 ? pos : ~pos) + 1)
.ToArray();
}
Usage example:
var scores = new long[] { 100, 100, 50, 40, 40, 20, 10 };
var alice = new long[] { 5, 25, 50, 120 };
var ranks = GetRanks(scores, alice);
Console.WriteLine($"Ranks: {String.Join(", ", ranks)}");
Output:
Ranks: 6, 4, 2, 1
I was bored so i gave this a go with Linq and heavily commented it for you,
Given
public static IEnumerable<int> GetRanks(long[] scores, long[] person)
// Convert scores to a tuple
=> scores.Select(s => (scores: s, isPerson: false))
// convert persons score to a tuple and concat
.Concat(person.Select(s => (scores: s, isPerson: true)))
// Group by scores
.GroupBy(x => x.scores)
// order by score
.OrderBy(x => x.Key)
// select into an indexable tuple so we know everyones rank
.Select((groups, i) => (rank: i, groups))
// Filter the person
.Where(x => x.groups.Any(y => y.isPerson))
// select the rank
.Select(x => x.rank);
Usage
static void Main(string[] args)
{
var scores = new long[]{1, 34, 565, 43, 44, 56, 67};
var alice = new long[]{578, 40, 50, 67, 6};
var ranks = GetRanks(scores, alice);
foreach (var rank in ranks)
Console.WriteLine(rank);
}
Output
1
3
6
8
10
Based on the given constraint brute-force solution will not be efficient for the problem.
you have to optimize your code and the key part here is to look up for exact place which can be effectively done by using binary search.
Here is the solution using binary search:-
static int[] climbingLeaderboard(int[] scores, int[] alice) {
int n = scores.length;
int m = alice.length;
int res[] = new int[m];
int[] rank = new int[n];
rank[0] = 1;
for (int i = 1; i < n; i++) {
if (scores[i] == scores[i - 1]) {
rank[i] = rank[i - 1];
} else {
rank[i] = rank[i - 1] + 1;
}
}
for (int i = 0; i < m; i++) {
int aliceScore = alice[i];
if (aliceScore > scores[0]) {
res[i] = 1;
} else if (aliceScore < scores[n - 1]) {
res[i] = rank[n - 1] + 1;
} else {
int index = binarySearch(scores, aliceScore);
res[i] = rank[index];
}
}
return res;
}
private static int binarySearch(int[] a, int key) {
int lo = 0;
int hi = a.length - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (a[mid] == key) {
return mid;
} else if (a[mid] < key && key < a[mid - 1]) {
return mid;
} else if (a[mid] > key && key >= a[mid + 1]) {
return mid + 1;
} else if (a[mid] < key) {
hi = mid - 1;
} else if (a[mid] > key) {
lo = mid + 1;
}
}
return -1;
}
You can refer to this link for a more detailed video explanation.
static int[] climbingLeaderboard(int[] scores, int[] alice) {
int[] uniqueScores = IntStream.of(scores).distinct().toArray();
int [] rank = new int [alice.length];
int startIndex=0;
for(int j=alice.length-1; j>=0;j--) {
for(int i=startIndex; i<=uniqueScores.length-1;i++) {
if (alice[j]<uniqueScores[uniqueScores.length-1]){
rank[j]=uniqueScores.length+1;
break;
}
else if(alice[j]>=uniqueScores[i]) {
rank[j]=i+1;
startIndex=i;
break;
}
else{continue;}
}
}
return rank;
}
My solution in javascript for climbing the Leaderboard Hackerrank problem. The time complexity of the problem can be O(i+j), i is the length of scores and j is the length of alice. The space complexity is O(1).
// Complete the climbingLeaderboard function below.
function climbingLeaderboard(scores, alice) {
const ans = [];
let count = 0;
// the alice array is arranged in ascending order
let j = alice.length - 1;
for (let i = 0 ; i < scores.length ; i++) {
const score = scores[i];
for (; j >= 0 ; j--) {
if (alice[j] >= score) {
// if higher than score
ans.unshift(count+1);
} else if (i === scores.length - 1) {
// if smallest
ans.unshift(count+2);
} else {
break;
}
}
// actual rank of the score in leaderboard
if (score !== scores[i-1]) {
count++;
}
}
return ans;
}
Here is my solution
List<int> distinct = null;
List<int> rank = new List<int>();
foreach (int item in player)
{
ranked.Add(item);
ranked.Sort();
ranked.Reverse();
distinct = ranked.Distinct().ToList();
for (int i = 0; i < distinct.Count; i++)
{
if (item == distinct[i])
{
rank.Add(i + 1);
break;
}
}
}
return rank;
This can be modified by removing the inner for loop also
List<int> distinct = null;
List<int> rank = new List<int>();
foreach (int item in player)
{
ranked.Add(item);
ranked.Sort();
ranked.Reverse();
distinct = ranked.Distinct().ToList();
var index = ranked.FindIndex(x => x == item);
rank.Add(index + 1);
}
return rank;
This is my solution in c# for Hackerrank Climbing the Leaderboard based on C++ answer here.
public static List<int> climbingLeaderboard(List<int> ranked, List<int> player)
{
List<int> _ranked = new List<int>();
_ranked.Add(ranked[0]);
for(int a=1; a < ranked.Count(); a++)
if(_ranked[_ranked.Count()-1] != ranked[a])
_ranked.Add(ranked[a]);
int j = _ranked.Count()-1;
int i = 0;
while(i < player.Count())
{
if(j < 0)
{
player[i] = 1;
i++;
continue;
}
if(player[i] < _ranked[j])
{
player[i] = j+2;
i++;
}
else
if(player[i] == _ranked[j])
{
player[i] = j+1;
i++;
}
else
{
j--;
}
}
return player;
}
My solution in Java for climbing the Leaderboard Hackerrank problem.
// Complete the climbingLeaderboard function below.
static int[] climbingLeaderboard(int[] scores, int[] alice) {
Arrays.sort(scores);
HashSet<Integer> set = new HashSet<Integer>();
int[] ar = new int[alice.length];
int sc = 0;
for(int i=0; i<alice.length; i++){
sc = 1;
set.clear();
for(int j=0; j<scores.length; j++){
if(alice[i] < scores[j] && !set.contains(scores[j])){
sc++;
set.add(scores[j]);
}
}
ar[i] = sc;
}return ar;
}
I have a list with 10 items in it. I am trying to output to console every possible pairing of 2. But it cannot pair with itself. For example
1,2
1,3
1,4 etc...
I found this to find all possible combinations within a list. Can someone help me modify it please?
private static void GetCombination(IList list)
{
var count = Math.Pow(2, list.Count);
for (var i = 1; i <= count - 1; i++)
{
var str = Convert.ToString(i, 2).PadLeft(list.Count, '0');
for (var j = 0; j < str.Length; j++)
{
if (str[j] == '1')
{
Console.Write(list[j]);
}
}
Console.WriteLine();
}
}
So if you have a list with 1 to 10, you need 1,2 1,3 1,4...1,10 - 2,1 2,3..2,10 and so on.
You just have to use bubble and check if the first index is different from the second.
For more clarification, here is an example:
List<int> mylist = new List<int>(new int[] { 1,2,3,4,5,6,7,8,9 });
GetCombination(mylist);
private static void GetCombination(IList<int> values)
{
for (int i = 0; i < values.Count; i++)
{
for (int j = 0; j < values.Count; j++)
{
if (i != j)
{
Console.WriteLine(values[i] + " " + values[j]);
}
}
}
}
This is such a easy question.Adding to the answer of #FirstOne
you can also return the List containing all the combinations from the function:
List mylist = new List(new int[] { 1,2,3,4,5,6,7,8,9 });
GetCombination(mylist);
public static IList<Tuple<int,int>> GetCombination(IList<int> values)
{
List<Tuple<int,int>> _temp=new List<Tuple<int, int>>();
for (int i = 0; i < values.Count; i++)
{
for (int j = 0; j < values.Count; j++)
{
if (i != j)
{
_temp.Add(Tuple.Create(i, j));
}
}
}
return _temp;
}