C# Algorithm Time Complexity - c#

I have this code and I am trying to work out the time complexity of it when n=2, n=4 and n=6. Can anyone help me? I'm confused as how I do it? Big-O Notation please.
using System;
class TimeComplexityTest
{
public static void Main( string[] args)
{
int n;
Console.WriteLine("Please enter the value of n");
n = Int32.Parse(Console.ReadLine());
Console.Write("\n");
for (int i = 1; i <= 1.5*n; i++)
Console.WriteLine(i);
for (int i = n; i >= 1; i--)
Console.WriteLine(i);
Console.Read();
}
}

You have 2 loops: one running 1.5n times, and the other running 1n times.
The time complexity for that is 2.5n, which is O(n).

Related

C# Find every number divisible by 3, in a string of numbers

this is my first post here, I'm new to C# and I have some problems with my code.
class Program
{
static void Main(string[] args)
{
#region FindAllNumbersDivisibleBy3
Console.Write("Enter a string of numbers: ");
string Nums = Console.ReadLine();
List<long> arr = new List<long>();
for (int i = 0; i < Nums.Length; i++)
{
for(int j = Nums.Length - 1; j >= i; j--)
{
try
{
string substring = Nums.Substring(i, j);
if (Convert.ToInt64(substring) % 3 == 0)
{
arr.Add(Convert.ToInt64(substring));
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
Console.WriteLine("The following numbers are divisble by 3: ");
for (int i = 0; i < arr.Count; i++)
{
Console.WriteLine(arr[i]);
}
Console.ReadLine();
#endregion
}
}
The problem is the following: I'm given a series of numbers, probably too big and inefficient to be stored as an integer, so it's recommended to use a string, and you have to find every single number divisible by three. That could be the entire string, or some sub-strings, or just single digit numbers, etc. I get some conversion errors from the catch exception, as well as something else regarding some length parameter and I don't really understand what's the problem. It's also possible that the for loops' arguments have some errors too, but as far as I'm concerned the problems start in the try block.
Sorry if this is a very dumb question, I'm still in high school so I'm not very good at programming yet. Thank you for your help in advance.
This is still vulnerable to overflows, but it would take a very long string indeed to reach that point:
class Program
{
static void Main(string[] args)
{
Console.Write("Enter a string of numbers: ");
string Nums = Console.ReadLine();
Console.WriteLine("The following numbers are divisble by 3: ");
foreach(var result in DivisibleByThree(Nums))
{
Console.WriteLine(result);
}
Console.ReadKey(true);
}
public static IEnumerable<string> DivisibleByThree(string input)
{
for (int i = 0; i < input.Length; i++)
{
for(int j = input.Length; j > i; j--)
{
string segment = input.Substring(i, j-i);
if (SumOfDigits(segment) % 3 == 0)
{
yield return segment;
}
}
}
}
public static int SumOfDigits(string digits)
{
return digits.Where(c => char.IsDigit(c)).Select(c => c-'0').Sum();
}
}
See it work here:
https://dotnetfiddle.net/KacyAD
And since someone suggested recursion, I thought that'd be fun to try. I didn't quite get as far as I wanted (removing both loops and using recursion as the only repetition mechanism), but this does work:
public static IEnumerable<string> DivisibleByThree(string input)
{
if (input.Length > 1)
{
foreach(var item in DivisibleByThree(input.Substring(0, input.Length-1)))
{
yield return item;
}
}
while(input.Length > 0)
{
if ( SumOfDigits(input) % 3 == 0) yield return input;
input = input.Substring(1);
}
}
But that's the boring recursion. From a pure performance standpoint, it still spends a lot of time summing the same sequences of digits. There's a probably a way to use recursion to preserve prior work on each recursive call, and in that way make this run significantly faster.
That is, rather than start with a big string and check progressively smaller segments, start with the small string and with each check add the sum for the just the additional digit:
public static IEnumerable<string> DivisibleByThree(string input)
{
for(int i = input.Length - 1; i>=0; i--)
{
foreach(var item in DivisibleByThreeR(input.Substring(i, input.Length - i), 0, 0, 0)) yield return item;
}
}
public static IEnumerable<string> DivisibleByThreeR(string input, int startPos, int nextPos, int sum)
{
sum += input[nextPos] - '0';
if (sum % 3 == 0) yield return input.Substring(startPos, nextPos - startPos + 1);
if (++nextPos < input.Length)
{
foreach (var item in DivisibleByThreeR(input, startPos, nextPos, sum)) yield return item;
}
}
I'm not sure this is really any faster. I didn't benchmark or test at all beyond getting the right result. In fact, I suspect the iterators will eat up any improvements over the pure-loop version.
There's also probably a way to move the loop in the outer method also into the recursive function thereby optimize even further. But it was a nice exercise.
Here's my final fiddle if anyone else wants to play:
https://dotnetfiddle.net/dGFWNx
Here's a solution close to your code that uses BigInteger (you need .NET5+). This shall eliminate the risk of running into OverflowException. Please note that there can be duplicates in the output (you didn't say if you want to see them).
using System.Numerics;
class Program
{
static void Main(string[] args)
{
#region FindAllNumbersDivisibleBy3
Console.Write("Enter a string of numbers: ");
string Nums = Console.ReadLine();
List<BigInteger> results = new();
for (int i = 0; i < Nums.Length; i++)
{
for (int j = Nums.Length; j >= i; j--)
{
try
{
string substring = Nums.Substring(i, j - i);
if (BigInteger.TryParse(substring, out var bi) && BigInteger.ModPow(bi, 1, 3).IsZero)
{
results.Add(bi);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
Console.WriteLine("The following numbers are divisible by 3:");
for (int i = 0; i < results.Count; i++)
{
Console.WriteLine(results[i]);
}
Console.ReadLine();
#endregion
}
}
Something that will work even with numbers other than 3 and 9 would be to implement long division and only keep track of the carry remainder (added a Linq version since it seemed like an appropriate problem for it):
static bool IsDivisibleBy(string input, long divBy = 3)
{
long remainder = 0;
foreach (char c in input)
{
var num = Convert.ToInt64(c);
remainder = ((remainder * 10) + num) % divBy;
}
return remainder == 0;
}
static bool IsDivisibleByLinq(string input, long divBy = 3)
{
return input.Select(c => Convert.ToInt64(c))
.Aggregate(0L, (remainder, num) =>
((remainder * 10) + num) % divBy) == 0;
}

Printing square with non repetitive character

I want to print a rectangle like this :
&#*#
#*#&
*#&#
#&#*
But problem is that i can't find the algorithm to print this.
I only know how to print a simple rectangle/square
public static void Main(string[] args)
{
Console.Out.Write("Saisir la taille : ");
int taille = int.Parse(Console.In.ReadLine());
int i;
int j;
for(i = 0; i < taille; i++){
for(j = 0; j < taille; j++){
Console.Write("*");
}
Console.WriteLine("");
}
}
Thank you !
First things first unless you need your iterators outside of your loop, just declare them in the for declaration
public static void Main(string[] args)
{
Console.Out.Write("Saisir la taille : ");
int taille = int.Parse(Console.In.ReadLine());
for(int i = 0; i < taille; i++){
for(int j = 0; j < taille; j++){
Console.Write("*");
}
Console.WriteLine("");
}
}
Second you'll need a list of the characters you want to use, given your example
char[] chars = { '&', `#`, `*`, '#' };
and we'll need a way to know which character we want to use at any given time, say an iterator we can call characterIndex for simplicity. We will increment it each iteration. If incrementing it puts it out of the range of our character array, if characterIndex == 4, we set it back to zero.
int characterIndex;
To get the scrolling effect you have, before each line we must select a characterIndex that is offset by the row
characterIndex = i % chars.Length;
Tying it all together
public static void Main(string[] args)
{
char[] chars = { '&', `#`, `*`, '#' };
int characterIndex;
Console.Out.Write("Saisir la taille : ");
int taille = int.Parse(Console.In.ReadLine());
for(int i = 0; i < taille; i++){
characterIndex = i % chars.Length;
for(int j = 0; j < taille; j++){
Console.Write(chars[characterIndex]);
characterIndex++;
if(characterIndex == chars.Length)
characterIndex = 0;
}
Console.WriteLine("");
}
}
Getting the permutations by nesting for loops will only work if you know exactly how many elements there will be. Basically you need to write a for-loop for every element after the 1st.
The proper way to deal with this is Recursion. While there are cases where Recursion and nested for-loops are interchangeable. And in cases where they are, for loops have a potential speed advantage. While normally the speed rant applies to such differences, with the sheer amount of data both Recursion and Loops might have to deal with, it often maters - so best to prefer loops where possible.
Permutations is AFAIK not a case where loops and recursion are interchangeable. Recurions seems to be mandatory. Some problem as simply inherently recursive. As the recursion version is fairly well known, I will not post any example code.
You should defiitely use Recursion. With your example code I basically asume you are:
In a learning environment
You just learned recursion
A input variant recurions can effortless solve (like a 6 or 20 size input), is the next assignment

Program to guess number gets incredibly slow

So, I decided to have some fun and make a program that will come up with a number and you have to guess it with it telling you if you're too high/too low. However, I decided it would be more fun if the computer could come up with the random numbers itself.
I use a simple method here which basically has the program check if a value is in an array, and if it is, come up with another random number. And when a number is too high, start from the size of how large the number can be and go down to that number (that way if it's too high of a number, it never guesses that high or higher again).
So, this works great for small numbers. I think when doing a number like 1,000 or something, it guessed it within 15 tries. However, when I did a 10,000,000 (I know, it's a bit extreme, but I wanted to see C#'s power since I'm fairly new to the language).
The program got about 10 guesses in and it started slowing down incredibly. I had put in a 250ms sleep timer to make it look more like it was guessing (since it is instant for things like 1,000 or 10,000), but when taking it out, it still slowed down. I think this is probably because if it guesses a number like 3 million, it has to add 7 million values to an array (I'm using a List so that it has an "infinite" value).
So what exactly can I do at this point? I want it to be able guess big numbers, but it doesn't really seem possible at this point. How could I do this?
Here's my code:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Program {
class Program {
static void Main(string[] args) {
Random random = new Random();
int selectedNumber = random.Next(1, 101);
int maxNumber;
int guessNumber = 0;
int inputNumber = 0;
// Intro
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine("Welcome to the High Low - Computer version program!");
System.Threading.Thread.Sleep(4000);
Console.WriteLine("\n--------------------------------------------------------");
Console.ForegroundColor = ConsoleColor.DarkYellow;
// This way the computer guesses rather than you
char who = 'C';
Console.Write("\nHow high do you want the computer's number to be max > ");
maxNumber = Convert.ToInt32(Console.ReadLine());
List<int> guessedNumbers = new List<int>();
selectedNumber = random.Next(1, maxNumber);
do {
// System.Threading.Thread.Sleep(250);
Console.ForegroundColor = ConsoleColor.DarkYellow;
if (who == 'M') {
Console.Write("\nPlease enter your guess > ");
guessNumber = Convert.ToInt32(Console.ReadLine());
}
else {
while (true) {
guessNumber = random.Next(1, maxNumber);
if (!(guessedNumbers.Contains(guessNumber))) {
guessedNumbers.Add(guessNumber);
inputNumber++;
break;
}
}
Console.WriteLine("Please enter your guess > {0}", guessNumber);
}
Console.ForegroundColor = ConsoleColor.DarkGreen;
if (guessNumber < selectedNumber) {
Console.WriteLine("\nYou're guessing too low!\n");
for (int i = 0; i < guessNumber; i++) {
guessedNumbers.Add(i);
inputNumber++;
}
}
else if (guessNumber > selectedNumber) {
Console.WriteLine("\nYou're guessing too high!\n");
for (int i = maxNumber; i > guessNumber; i--) {
guessedNumbers.Add(i);
inputNumber++;
}
}
} while (guessNumber != selectedNumber);
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine("\nCongratulations! You correctly guessed that {0} is the computer's number!", selectedNumber);
Console.ReadKey();
}
}
}
Edit: I think I'll try a way to make it so that it only adds the numbers that are higher or lower if they aren't already in there, to keep from having duplicate numbers.
The way you're trying to find the number using the computer's power isn't really efficient, why don't you just change the ranges of the possible guessing numbers based on if the previously guessed number is higher or lower than the correct number like so:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Highest number:");
int maxNumber = Convert.ToInt32(Console.ReadLine());
Random rand = new Random();
int correctNumber = rand.Next(0, maxNumber);
Console.WriteLine("Trying to guess number now..");
int guessedNumber = 0;
int lowBound = 0;
int highBound = maxNumber;
int guesses = 0;
while(guessedNumber != correctNumber)
{
guessedNumber = rand.Next(lowBound, highBound);
if(guessedNumber > correctNumber)
{
highBound /= 2;
lowBound /= 2;
}
else if(guessedNumber < correctNumber)
{
lowBound *= 2;
highBound *= 2;
}
++guesses;
}
Console.WriteLine($"Took me {guesses} guesses.");
Console.ReadKey();
}
}
This takes less than a second for 10,000,000 entries on my machine.
for (int i = 0; i < guessNumber; i++)
{
guessedNumbers.Add(i);
inputNumber++;
}
Everytime you enter these types of loops, you add 'guessnumber' items to the list, possibly millions.
Consider re-reading your code and understanding what it does.
Also, you should consider encapsulating your code to avoid making a behemoth of your main()
Another way is to use a Binary Search approach to guess the number and avoid the additional overhead caused by writing and searching for guess values.
This should run in O(log n).
int minGuess = 0;
int maxGuess = 1000000;
Random random = new Random();
int selectedNumber = random.Next(minGuess, maxGuess);
Console.WriteLine($"Selected number: {selectedNumber}");
int guess;
int count = 0;
do
{
count++;
guess = (minGuess + maxGuess) / 2;
Console.WriteLine($"Guess: {guess}");
if (selectedNumber < guess)
maxGuess = guess - 1;
else
minGuess = guess + 1;
} while (guess != selectedNumber);
Console.WriteLine($"Guessed it in {count} tries");
Console.ReadLine();

issue with nested for loops c#

it seems that I'm kinda stuck with an assignment.
I need to use nested for loops to get this outcome:
0****
01***
012**
0123*
01234
but whatever I do I just don't seem to get there.
this is what I coded :
int i , j;
for (i=0; i<=5;i++)
{
for (j=3; j>= 0; j--)
{
Console.Write(j);
Console.Write("*");
}
Console.WriteLine();
}
Console.WriteLine("Press any key to continue");
Console.ReadKey();
but that gives me this outcome :
0*0*0*0*
1*1*1*1*
2*2*2*2*
3*3*3*3*
4*4*4*4*
5*5*5*5*
and it needs to be a nested loop
You can do this with only one loop:
string numbers = "01234";
string stars = "*****";
for (int i = 1; i <= numbers.Length; i++)
Console.WriteLine($"{numbers.Substring(0, i)}{stars.Substring(i)}");

how to generate for loop

Hello had a pretty simple problem, I'm trying to create a console program in C# that gets 3 inputs from the user. The start, stop and number of steps.
It's supposed to be a for loop but I don't really get how I can put user input in the for loop, I tried making int's of the user input and then placing the names of the int's in the for loop but it's giving me errors.
The program is supposed to look like the following program in "Ovning 1" site is in Swedish but I hope you guys will get it, tried searching the site but there was never an explanation given. http://csharpskolan.se/showarticle.php?id=119
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ovning12
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Mata in Start");
int startNummer = int.Parse(Console.ReadLine());
Console.WriteLine("Mata in Stop");
int stopNummer = int.Parse(Console.ReadLine());
Console.WriteLine("Mata in Steg");
int stegNummer = int.Parse(Console.ReadLine());
for (int startNummer; startNummer >= stopNummer; startNummer + stegNummer)
{
Console.WriteLine();
}
}
}
}
static void Main(string[] args)
{
Console.WriteLine("Mata in Start");
int startNummer = int.Parse(Console.ReadLine());
Console.WriteLine("Mata in Stop");
int stopNummer = int.Parse(Console.ReadLine());
Console.WriteLine("Mata in Steg");
int stegNummer = int.Parse(Console.ReadLine());
for (int n = startNummer; n < stopNummer; n += stegNummer)
{
Console.Write(n + " ");
Console.Write("{0} ", n); //(Alternative)
}
}
a for loop should look like this
for (int i = startNummer; i <= stopNummer; i += stegNummer)
{
Console.Write(i + " ");
}
there are 3 mistakes in your current code:
for (int startNummer; startNummer >= stopNummer; startNummer + stegNummer)
you can't initialize a variable twice int startNummer; - that won't compile
your comparison heads into the wrong direction (except you're working with negative steps) startNummer >= stopNummer
you're not assigning the calculated new step here startNummer + stegNummer - it should be startNummer += stegNummer or startNummer = startNummer + stegNummer
Most of it looks okay. But couple of things do not make sense,
for (int startNummer; startNummer >= stopNummer; startNummer + stegNummer);
{
Console.WriteLine();
}
there's a semi colon ';' at the end of for loop. This ends for loop, making next curly braces syntax error. Also startNumber >= stopNumber and then startNumber + stegNumber would possibly either not run it at all, or run an infinite loop based on the inputs.
Is this for loop supposed to be like below?
for (int start = startNummer /*have to initialize the start value*/;
start < stopNummer;
start += stegNummer)
{
Console.Write(start + " "); //need Console.Write to print all numbers on same line. Console.WriteLine puts each index on its own line
}

Categories

Resources