Reputation: 819
Trying to get a summary from my current output. E.g. Hello: 5, World: 8, HelloWorld: 20, integer: 5. Currently this accepts a user input e.g. 1,10, 1 being minimum and 10 being maximum and outputs the following from the for loop. Don't know how to get the output into an array and then aggregate this.
Code so far:
Console.WriteLine("Please enter a range?");
string range = Console.ReadLine();
string first = range.Split(',')[0];
string last = range.Split(',')[1];
int min = Int32.Parse(first);
int max = Int32.Parse(last);
Console.WriteLine("");
Console.WriteLine("Heres the Output");
Console.WriteLine("");
for (int i = min; i < max ; i++ )
{
bool hello = i % 3 == 0;
bool world = i % 5 == 0;
if (hello && world)
Console.WriteLine("HelloWorld");
else if (hello)
Console.WriteLine("Hello");
else if (world)
Console.WriteLine("World");
else
Console.WriteLine(i);
}
string list = Console.ReadLine();
Console.WriteLine(list);
Upvotes: 1
Views: 183
Reputation: 186813
All you have to do is to use modular arithmetics; providing that 0 <= min < max
:
private static int CountDivs(int value, int divisor) {
return value < 0 ? 0 : value / divisor + 1;
}
private static string Solution(int min, int max) {
int hello = CountDivs(max - 1, 3) - CountDivs(min - 1, 3);
int world = CountDivs(max - 1, 5) - CountDivs(min - 1, 5);
int helloWorld = CountDivs(max - 1, 3 * 5) - CountDivs(min - 1, 3 * 5);
// others: Inclusion–exclusion principle
int other = max - min - hello - world + helloWorld;
return $"hello: {hello} world: {world} integer: {other}";
}
// Test (your example)
Console.WriteLine(Solution(1, 10));
// My comment [8..14) i.e. 8, 9, 10, 11, 12, 13
Console.WriteLine(Solution(8, 14));
Outcome:
hello: 3 world: 1 integer: 5
hello: 2 world: 1 integer: 3
Please, notice, that the solution has O(1)
time complexity (loop will be inefficient, on inputs like Solution(100, 1000000000)
)
Edit: if you want to change your current code a bit and have an aggregate solution, you can try to extract the loop into a method and use Linq to aggregate the items:
using System.Linq;
...
private static IEnumerable<string> Generator(int min, int max) {
// Your loop extracted: put "yield return ..." instead of "Console.WriteLine(...)"
for (int i = min; i < max; ++i) {
bool hello = i % 3 == 0;
bool world = i % 5 == 0;
if (hello && world) {
// Or if you want return twice, just do it twice:
// yield return "Hello";
// yield return "World";
yield return "HelloWorld";
}
else if (hello)
yield return "Hello";
else if (world)
yield return "World";
else
yield return "integer";
}
}
...
var data = Generator(1, 10)
.GroupBy(item => item)
.OrderBy(chunk => chunk.Key)
.Select(chunk => $"{chunk.Key}: {chunk.Count()}");
var result = string.Join(" ", data);
Console.WriteLine(result);
Outcome:
Hello: 3 integer: 5 World: 1
Edit 2: No Linq solution, manual grouping
int min = 1;
int max = 10;
Dictionary<string, int> counts = new Dictionary<string, int>() {
{ "HelloWorld", 0},
{ "Hello", 0},
{ "World", 0},
{ "integer", 0},
};
foreach (var item in Generator(1, 10))
counts[item] += 1;
string result =
$"Hello: {counts["Hello"]} World: {counts["World"]} integer: {counts["integer"]}";
Console.Write(result);
Outcome:
Hello: 3 World: 1 integer: 5
Upvotes: 1