I have a list of object.
class Student
{
int age;
int height;
int weight;
int marksInMath;
int marksInScience;
.
.
.
.
.
.
int marksIn...;
}
List<Student> lst = new List<Student>();
I want to calculate median and average of this List.
I am aware of
lst.Average(x=>x.Age);
lst.Average(x=>x.height);
.
.
Similarly for Median I can sort and then get median
lst.OrderBy(x=>x.Age);
//median logic on lst
But I don't want to repeat this code for every field(age, height, weight, marks, etc) in the object. Is there a way to do this in a loop or any other way so I don't have to get average for each field individually?
Here's the one pass way to compute averages:
var averages =
lst
.Aggregate(
new
{
N = 0,
Age = 0,
Height = 0,
Weight = 0,
MarksInMath = 0,
MarksInScience = 0
},
(a, x) =>
new
{
N = a.N + 1,
Age = a.Age + x.Age,
Height = a.Height + x.Height,
Weight = a.Weight + x.Weight,
MarksInMath = a.MarksInMath + x.MarksInMath,
MarksInScience = a.MarksInScience + x.MarksInScience,
},
a =>
new
{
Age = (double)a.Age / a.N,
Height = (double)a.Height / a.N,
Weight = (double)a.Weight / a.N,
MarksInMath = (double)a.MarksInMath / a.N,
MarksInScience = (double)a.MarksInScience / a.N,
});
If you're after sums, stddev, etc, it's done the same way.
However, you're not going to be able compute the median without doing so on each property, one at a time.
I am at work so haven't been able to run this to see if it works. But if you can retrieve the values of each field using Student.fieldName then should be good. Not 100% on the studentStats.Add, whether that's how to add it or not. Just know I've done it before without needing the Tuple.
public List<(decimal avg, decimal med)> StudentScores(List<Student> students)
{
var fieldNames = typeof(Student).GetFields().Select(field=>field.Name).ToList();
var studentStats = new List<(decimal avg, decimal med)>();
foreach(var field in fieldNames)
{
var average = 0;
var count = 0;
List<decimal> fieldMedian = new List<decimal>();
foreach(var student in students)
{
count++
totalScore = average + student.field;
fieldMedian.Add(student.field);
}
average = totalScore / count;
var sorted = fieldMedian.Sort();
if(count%2 = 0)
{
var middle1 = count/2;
var middle2 = (count/2)+1;
var median = (sorted[middle1] + sorted[middle2]) / 2;
studentStats.Add(average, median);
}
else
{
var middle = (count+1)/2;
var median = sorted[middle];
studentStats.Add(average, median);
}
}
return studentStats;
}
Related
How can I filter a list into distinct values by a specific field and where the values weren’t distinct take their averages. Please see example
{
Public int Time;
Public float Voltage;
Public float Current;
Public Resistance(int time, float voltage, float current)
{
Time = time;
Voltage = voltage;
Current = current;
}
Public List<Resistance> _resistances = new List<Resistance>();
_resistances.Add(new Resistance(Time = 1, Voltage =3.2, Current = 1);
_resistances.Add(new Resistance(Time = 1, Voltage =4.0, Current = 2);
_resistances.Add(new Resistance(Time = 1, Voltage =6.5, Current = 6);
_resistances.Add(new Resistance(Time = 2, Voltage =3.2, Current =4);
_resistances.Add(new Resistance(Time =2, Voltage =3.2, Current = 2);
_resistances.Add(new Resistance(Time = 3, Voltage 5, Current = 1);
Aim is to have a list with:
_resistance[0]{ Time =1,, Voltage = Average(3.2,4,6.5), Current = Average(1,2,6))
_resistance[1]{ Time =2,, Voltage = Average(3.2,3.2,5), Current = Average(4,2,1))
}
For any arbitrary values and quantity of entries
I have tried the following
int divisor = 1;
double voltageSum = 0;
double currentSum = 0;
while (j >= 1)
{
while (_resistances[j].Time== _resistances[j - 1].Time)
{
divisor++;
voltageSum += _resistances[j].Voltage;
currrentSum += _resistances[j].Current;
_resistances.RemoveAt(j);
j -= 1;
}
var averageVoltage = voltageSum / divisor;
var averageCurrent = currentSum / divisor;
_rawDataList[j].Voltage = (float)averageVoltage;
_rawDataList[j].Current= (float)averageCurrent;
j -= 1;
}
I know this is wrong but I cant seem to figure out the logic to modifying a list, I think creating a new list and appending in a forloop maybe the way forward but I cant work it out. I think Linq may help, but not too experienced with Lambda expressions. Thanks in advance
You can accomplish this using Linq, group your records by Time and use the Average function to compute the values for Voltage and Current for the Time groups:
_resistances
.GroupBy(r => r.Time)
.Select(g => new {
Time = g.Key,
Voltage = g.Average(r => r.Voltage),
Current = g.Average(r => r.Current)
});
This question already has answers here:
Divide x into y parts by decreasing amount
(3 answers)
Closed 3 years ago.
If I had $1000(variable) and I want to split that amount up and give it to 20(variable) people, but rather than give it evenly to each person, I want to give more to the 1st person, and the 2nd person, etc.
So the 20th person gets the least, and the 5th person gets the 5th most.
People are sorted into a list by score, how could i check to make sure people with the same score are awarded the same amount of the prize while still giving out the prize total to all people?
Formula thus far:
int people = 20;
float prize = 1000;
List<int> list = new List<int>();
for( int i = 0; i < people; ++i )
{
list.add(Random.Range(0,100));
}
list.Sort();
float k = (2 * prize) / ((people) * (people - 1));
float sum = 0;
for (int i = 1; i < list.Count-1; ++i)
{
var personsPrize = i * k;
sum += personsPrize;
Console.WriteLine(personsPrize);
}
Console.WriteLine("sum = " + sum);
First place would get 25% of the total prize pool. Second place gets 20% and third place gets 15% then the rest is divided between the remaining people, with people on the same score getting the same amount.
What should happen for people getting tied first equal? They shouldn't get less than anybody else, but shouldn't double the first prize value.
I'd do it by splitting out the prize fractions first, and determining which prizes should be merged due to ties. Then, sum up the merged fractions and divide that merged amount equally to all the tied participants.
This ensures that the amount received for each tied participant is less than or equal to the greatest prize amount merged in and greater than or equal to the least prize amount merged in.
public class Person
{
public Person(string name, int position)
{
Name = name;
Position = position;
}
public string Name { get; set; }
public int Position { get; set; }
}
static void Main(string[] args)
{
var winners = new Person[]
{
new Person("Test 1", 1),
new Person("Test 2", 1),
new Person("Test 3", 1),
new Person("Test 4", 1),
new Person("Test 5", 5),
new Person("Test 6", 6),
new Person("Test 7", 7),
new Person("Test 8", 8),
new Person("Test 9", 9),
new Person("Test 10", 9),
new Person("Test 11", 11),
new Person("Test 12", 11),
new Person("Test 13", 13),
new Person("Test 14", 14),
new Person("Test 15", 15),
new Person("Test 16", 16),
new Person("Test 17", 17),
new Person("Test 18", 18),
new Person("Test 19", 19),
new Person("Test 20", 19)
};
var prizes = SplitPrizeFund(1000, winners.Length);
AllocatePrizes(winners, prizes);
}
private static void AllocatePrizes(IEnumerable<Person> positions, double[] prizes)
{
var orderedPositions = positions.OrderBy(f => f.Position).ToArray();
for (var pos = 0; pos < orderedPositions.Length;)
{
var currentPerson = orderedPositions[pos];
// Find equally placed people (if any)
var comList = orderedPositions.Skip(pos).Where(f => f.Position == currentPerson.Position).ToList();
// We should now have one or more people in our list
var splitWays = comList.Count;
// Total the prize fund over the places found
double splitFund = prizes.Skip(pos).Take(splitWays).Sum();
// Allocate the total winnings equally between winners of this place
bool first = true;
foreach (var person in comList)
{
if (first)
{
Console.WriteLine($"{person.Name,-20} {(splitFund / splitWays),10:C2}");
first = false;
}
else
{
// Identify equal placed winners
Console.WriteLine($"{person.Name,-19}= {(splitFund / splitWays),10:C2}");
}
}
pos += splitWays;
}
}
private static double[] SplitPrizeFund(double totalFund, int numberOfPrizes)
{
var prizes = new double[numberOfPrizes];
var remainingFund = totalFund;
int remainingPrizes = numberOfPrizes;
// Special handling for top three places
int pos = 0;
prizes[pos] = Math.Round(remainingFund * 0.25, 2, MidpointRounding.AwayFromZero);
pos += 1;
prizes[pos] = Math.Round(remainingFund * 0.20, 2, MidpointRounding.AwayFromZero);
pos += 1;
prizes[pos] = Math.Round(remainingFund * 0.15, 2, MidpointRounding.AwayFromZero);
pos += 1;
remainingPrizes -= 3;
remainingFund -= prizes[0] + prizes[1] + prizes[2];
// Linear reducing split from 4th (replace this with whatever you want)
int totalPortions = 0;
for (int i = 1; i <= remainingPrizes; i++)
totalPortions += i;
for (int i = remainingPrizes; i >= 1; i--)
{
prizes[pos] = Math.Round(remainingFund * i / totalPortions, 2, MidpointRounding.AwayFromZero);
remainingFund -= prizes[pos];
totalPortions -= i;
pos++;
}
return prizes;
}
This can be a solution :
class People
{
public int ID { get; set; }
public int Rank { get; set; }
public float? Prize { get; set; }
}
//Reserves 60% of the prize for the first, second and the third person.
//Imageine that there are 5 people have the highest rank 20 for exemple.
in this case the total of the first place makes 125%. It can't be possible.
For me, you should have another parameter to choose the first places.
Or, you should modify your rank logic: like if the total of percentages is over 100% or 90%, (or a percentage that you will decide), reduce the percentage of the first place, second and third places etc.
Imagene that you have 4 first place, 1 second place and 1 thirt place.
In this case you have (4 * 25%) + 20% + 15% = 135%. It means you have to reduce your 25% to for exemple 15 %, second place to 10% and the third place to 5%.
in this case you will have (4 * 15%) + 10% + 5% = 75 percent for your highest places and you will distribute 25% to other users.
private void CheckPrices()
{
float prize = 1000;
Random rnd = new Random(1);
var peopleList = new List<People>();
for (int i = 0; i < 20; i++)
{
peopleList.Add(new Test.People() { ID = i + 1, Rank = rnd.Next(5, 100) });
}
var firstPrize = prize * 25 / 100;
var secondPrize = prize * 20 / 100;
var thirstPrize = prize * 15 / 100;
int i = 0;
//Sets first places prizes.
foreach (var person in peopleList.OrderByDescending(ro => ro.Rank))
{
i++;
if (i == 1)
person.Prize = firstPrize;
else if (i == 2)
person.Prize = secondPrize;
else if (i == 3)
person.Prize = thirstPrize;
else
break;
}
var totalRank = peopleList.Sum(ro => ro.Rank);
float prizePerRank = (prize - (firstPrize + secondPrize + thirstPrize)) / totalRank;
foreach (var person in peopleList.Where( ro=> ro.Prize == null))
{
person.Prize = person.Rank * prizePerRank;
}
//
var totalPrizeDistributed = peopleList.Sum(ro => ro.Prize); //= 1000
}
}
Im working on a heatmap where i have to display zones on a map filled by a color calculated by a range of values.
I got the zone color part figgured out, but i also have to display 5 steps, each step providing a color and a value, explaining what the color means.
So, lets say i have a minimum value of 2654 and a maximum value of 6947.
This provides me with a range of 5 numbers, which are:
2654
3727,25
4800,5
5873,75
6947
Now what i want is to display these values as nice intervals, like this:
0 - 3000
3000 - 4000
4000 - 5000
5000 - 6000
> 6000
These values are ofcourse dynamic.
So it could be either huge numbers or small numbers.
Is there any way to do this?
Update
#roberto-carlos i tried your example below:
var min = 900;
var max = 12541;
var steps = 5;
var range = Enumerable.Range(0, steps).Select(i => min + (max - min) * ((double)i / (steps - 1)));
foreach (var d in range)
{
var power = Math.Floor(Math.Log10(d));
var inf = d - d % Math.Pow(10, power);
var sup = d + (Math.Pow(10, power) - d % Math.Pow(10, power));
if (d == min)
{
Console.WriteLine("0-" + sup);
}
else if (d == max)
{
Console.WriteLine(">" + sup);
}
else
{
Console.WriteLine(inf + "-" + sup);
}
}
However, this provides me with a result like this:
0-1000
3000-4000
6000-7000
9000-10000
>20000
Is there any way to make the intervals "stick together" numberwise?
You can try this:
var list = new List<double> { 2654, 3727.25, 4800.5, 5873.75, 6947 };
foreach (var d in list)
{
var power = Math.Floor(Math.Log10(d));
var min = d - d % Math.Pow(10, power);
var max = d + (Math.Pow(10, power) - d % Math.Pow(10, power));
Console.WriteLine(min + "-" + max);
}
/*
Result:
2000 - 3000
3000 - 4000
4000 - 5000
5000 - 6000
6000 - 7000
/*
Version 2:
var list = new List<double> { 2654, 3727.25, 4800.5, 5873.75, 6947 };
var min = list.Min();
var max = list.Max();
foreach (var d in list)
{
var power = Math.Floor(Math.Log10(d));
var inf = d - d % Math.Pow(10, power);
var sup = d + (Math.Pow(10, power) - d % Math.Pow(10, power));
if (d == min)
{
Console.WriteLine("0-" + sup);
}
else if (d == max)
{
Console.WriteLine(">" + sup);
}
else
{
Console.WriteLine(inf + "-" + sup);
}
}
/*
Result:
0-3000
3000-4000
4000-5000
5000-6000
>7000
/*
Using linq putting into predetermined groups
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ConsoleApplication42
{
class Program
{
static void Main(string[] args)
{
int[] intervals = {3000, 4000, 5000,6000};
List<List<int?>> data = new List<List<int?>>() {
new List<int?>() {2654},
new List<int?>() {3727,25},
new List<int?>() {3730,25},
new List<int?>() {4800,5},
new List<int?>() {5873,75},
new List<int?>() {6947}
};
var results = data.Select(x => new { index = intervals.Select((y, i) => new { index = i, max = y }).Where(z => x[0] < z.max).FirstOrDefault(), data = x }).ToList();
var groups = results.GroupBy(x => x.index != null ? x.index.index : intervals.Length).Select(x => new { key = x.Key, data = x.Select(y => y.data).ToList() }).ToList();
}
}
}
Ok, I initially misunderstood your problem.
The following implementation should do:
static IEnumerable<Interval> GetIntervals(IEnumerable<double> values, int intervalsCount)
{
if (values == null)
throw new ArgumentNullException(nameof(values));
if (intervalsCount <= 1)
yield break;
var orderedValues = values.OrderBy(v => v);
var frontiers = orderedValues.Select(
v =>
{
var scale = Math.Pow(10, (int)Math.Log10(v));
return Math.Floor(v / scale) * scale;
}).ToArray();
for (var i = 0; i < frontiers.Length - 1; i++)
{
yield return new Interval(frontiers[i], frontiers[i + 1]);
}
yield return new Interval(frontiers[frontiers.Length - 1], double.PositiveInfinity);
}
And Interval is a simple helper struct:
struct Interval
{
public Interval(double lower, double upper)
{
if (upper <= lower)
throw new ArgumentException("The upper bound must be greater than the specified lower bound", nameof(upper));
LowerBound = lower;
UpperBound = upper;
}
public double LowerBound { get; }
public double UpperBound { get; }
public override string ToString()
{
if (UpperBound == double.PositiveInfinity)
return $" > {LowerBound}";
return $"{LowerBound} - {UpperBound}";
}
}
This outputs for 2654.0, 3727.25, 4800.5, 5873.75, 6947:
2000 - 3000
3000 - 4000
4000 - 5000
5000 - 6000
> 6000
And for example, in case of a logarithmic scaled input 2.0, 56, 321, 5674, 12764 the output is:
2 - 50
50 - 300
300 - 5000
5000 - 10000
> 10000
Note that this implementation will not create uniform intervals, it will create intervals, such that each one includes one concrete input value. I'm not really sure if this is what you want, your requirements aren't all that clear.
I need to replicate this Excel graph in code
Given a list of [x, y] values, how can I obtain a new list of values to graph the power trendline?
I've found people referring to this http://mathworld.wolfram.com/LeastSquaresFittingPowerLaw.html formula. But don't know how to generate a new list of values from this.
Follow the formula from the link:
function getFittedPoints(data) {
var log = Math.log,
pow = Math.pow,
sums = [
0, // sum of the logarithms of x ( sum(log(x)) )
0, // sum of the logarithms of y ( sum(log(y)) )
0, // sum of the logarithms of the products of x and y ( sum(log(x) * log(y)) )
0 // sum of the powers of the logarithms of x ( sum((log(x))^2 )
],
fittedPoints = [], // return fitted points
a, // a coefficient
b, // b coefficient
dataLen = data.length,
i,
logX,
logY;
for (i = 0; i < dataLen; i++) {
sums[0] += logX = log(data[i][0]);
sums[1] += logY = log(data[i][1]);
sums[2] += logX * logY;
sums[3] += pow(logX, 2);
}
b = (i * sums[2] - sums[0] * sums[1]) / (i * sums[3] - pow(sums[0], 2));
a = pow(Math.E, (sums[1] - b * sums[0]) / i);
for (i = 0; i < dataLen; i++) {
fittedPoints.push([
data[i][0],
a * pow(data[i][0], b)
]);
}
return fittedPoints;
}
And then apply the function to the data.
example: http://jsfiddle.net/fa3m4Lvf/
Of course if your data are not clean then you can improve the function with handling null values,etc.
And for those like me who are looking for the C# version of morganfree's answer above, here it is translated:
public static IEnumerable<double> GetPowerTrendline(IList<double> knownY, IList<double> knownX, IList<double> newX)
{
var sums = new double[4];
var trendlinePoints = new List<double>();
var dataLen = knownX.Count;
for (var i = 0; i < dataLen; i++)
{
var logX = Math.Log(knownX[i]);
var logY = Math.Log(knownY[i]);
sums[0] += logX;
sums[1] += logY;
sums[2] += logX * logY;
sums[3] += Math.Pow(logX, 2);
}
var b = (dataLen * sums[2] - sums[0] * sums[1]) / (dataLen * sums[3] - Math.Pow(sums[0], 2));
var a = Math.Pow(Math.E, (sums[1] - b * sums[0]) / dataLen);
foreach (var x in newX)
{
var pointY = a * Math.Pow(x, b);
trendlinePoints.Add(pointY);
}
return trendlinePoints;
}
Note that it is modified so that it takes a list of desired x points instead of using the provided ones.
I followed the example calculation based on this: http://www.statisticshowto.com/how-to-find-a-linear-regression-equation/
Modified Adams example based on this and came upp with this solution for C#. This is assumes you have all the existing scatter plots. The result is a number of arraylists with the all the x and y values for the trendline that you can directly insert into highcharts.
public static List<ArrayList> GetPowerTrendline(List<KeyValuePair<int,double>> xyValues)
{
var trendlinePoints = new List<ArrayList>();
var dataLen = xyValues.Count;
var xSum = xyValues.Sum(h => h.Key);
var ySum = xyValues.Sum(h => h.Value);
var XYSum = xyValues.Sum(h => h.Key * h.Value);
var xp2Sum = xyValues.Sum(x => Math.Pow(x.Key, 2));
var a = (ySum * xp2Sum - xSum * XYSum) / (dataLen * xp2Sum - Math.Pow(xSum, 2));
var b = ((dataLen * XYSum) - (xSum * ySum)) / (dataLen * xp2Sum - Math.Pow(xSum,2));
foreach (var x in xyValues.OrderBy(h => h.Key))
{
var pointY = a + b * x.Key;
var rounded = Math.Round(pointY, 2);
trendlinePoints.Add(new ArrayList { x.Key, rounded });
}
return trendlinePoints;
}
And in my HighCharts method like this:
series: [
{
type: 'line',
name: 'Trendlinje',
data: data.RegressionLine,
color: '#444444',
marker: {
enabled: false
},
states: {
hover: {
lineWidth: 0
}
},
enableMouseTracking: false
},
I'm studying coding and I'm on project 8 of project euler.
I was able to show the product "5832" for four adjacent digits when I'm using my code however when I use it on 13 digits, it doesn't work. My code is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace practice
{
class Program
{
static void Main(string[] args)
{
const string number = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
string input1, input2, input3, input4, input5;
string input6, input7, input8, input9, input10;
string input11, input12, input13;
int convert1, convert2, convert3, convert4, convert5;
int convert6, convert7, convert8, convert9, convert10;
int convert11, convert12, convert13;
convert1 = convert2 = convert3 = convert4 = convert5 = convert6 = convert7 = convert8 = 0;
convert9 = convert10 = convert11 = convert12 = convert13 = 0;
int counter;
int product = 0;
int largest = 0;
int length = number.Length - 13;
for (counter = 1; counter <= length; counter++)
{
input1 = number.Substring(counter, 1);
input2 = number.Substring(counter+1, 1);
input3 = number.Substring(counter+2, 1);
input4 = number.Substring(counter+3, 1);
input5 = number.Substring(counter+4, 1);
input6 = number.Substring(counter+5, 1);
input7 = number.Substring(counter+6, 1);
input8 = number.Substring(counter+7, 1);
input9 = number.Substring(counter+8, 1);
input10 = number.Substring(counter+9, 1);
input11 = number.Substring(counter+10, 1);
input12 = number.Substring(counter+11, 1);
input13 = number.Substring(counter+12, 1);
convert1 = Convert.ToInt32(input1);
convert2 = Convert.ToInt32(input2);
convert3 = Convert.ToInt32(input3);
convert4 = Convert.ToInt32(input4);
convert5 = Convert.ToInt32(input5);
convert6 = Convert.ToInt32(input6);
convert7 = Convert.ToInt32(input7);
convert8 = Convert.ToInt32(input8);
convert9 = Convert.ToInt32(input9);
convert10 = Convert.ToInt32(input10);
convert11 = Convert.ToInt32(input11);
convert12 = Convert.ToInt32(input12);
convert13 = Convert.ToInt32(input13);
product = convert1 * convert2 * convert3 * convert4 * convert5 * convert6
* convert7 * convert8 * convert9 * convert10 * convert11
* convert12 * convert13;
if (largest < product) { largest = product; }
}
Console.WriteLine("The largest number is {0}", largest);
Console.ReadKey();
}
}
}
It doesn't show the correct answer which I find daunting. The next steps
I did is:
1. Check the last 13 digits of my variables to check if it loops and multiplies correctly "0420420752963450".
2. Check if it works with the first four numbers and first five numbers which are surprisingly correct.
3. Studied how others have done it.
4. Links used:
Homework in Java. Find the largest product of five consecutive digits
http://www.mathblog.dk/solution-to-problem-8-of-project-euler/
I seem to not get it. Please guide me on seeing my mistake. Thank you.
Your product variable is int and you parse your consecutive numbers to int. Max value for integer is 2,147,483,647. So when you multiply 13 numbers it's quite possible you will exceed the limit and the value will overflow giving incorrect result. Perhaps, consider using BigInteger instead.
What about something like this:
[Test]
public void Test()
{
const string number = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
int index = 0;
int largest = 0;
var largestString = "";
const int length = 13;
while (index + length <= number.Length)
{
var substring = number.Substring(index, length);
var product = ProductOfEachNumber(substring);
if (product > largest)
{
largestString = substring;
largest = product;
}
index++;
}
Console.WriteLine("The largest number is {0}", largest);
Console.WriteLine("The largest number string is {0}", largestString);
}
[Test]
public void TestSubstring()
{
var res = ProductOfEachNumber("9989");
res.Should().Be(5832);
}
private static int ProductOfEachNumber(string substring)
{
return substring.Aggregate(1, (current, c) => current*Int32.Parse(c.ToString()));
}
Gives output:
The largest number is 2091059712
The largest number string is 9781797784617
Try this one, let me know. You have to modify it.
static void Main(string[] args)
{
Stopwatch sw = Stopwatch.StartNew();
int x = Largest();
Console.WriteLine(x);
Console.WriteLine("Time used (float): {0} ms", sw.Elapsed.TotalMilliseconds);
Console.WriteLine("Time used (rounded): {0} ms", sw.ElapsedMilliseconds);
Console.ReadKey();
}
public static int Largest()
{
string p = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
int largest = 0;
int numm = 0;
for (int i = 0; i < p.Length - 4; i++)
{
numm = int.Parse(p.Substring(i, 1)) *
int.Parse(p.Substring(i + 1, 1)) *
int.Parse(p.Substring(i + 2, 1)) *
int.Parse(p.Substring(i + 3, 1)) *
int.Parse(p.Substring(i + 4, 1));
if (numm > largest)
{
largest = numm;
}
}
return largest;
}