Calculating a leap year without the leap year function - c#

I need to calculate if the current year at the runtime of the program is a leap year (divisible by 4, not divisible by 100 but divisible by 400) but without using the DateTime.LeapYear property. Can anyone suggest anything?
//DateTimePicker code
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
DateTime now;
int[] months = {31,28,31,30,31,30,31,31,30,31,30,31};
now = DateTime.Now.Date;
if (now.Year / 4 == 0 && now.Year / 400 == 0)
{
months(1) = 29;
}
}

I think this covers the three criteria:
var year = now.Year;
if (year % 4 == 00 && !(year % 100 == 0 && year % 400 != 0))
{
....
}

Use the modulus operator % when checking divisibility. Also, when changing an array, use array indexers [], not parentheses:
if (now.Year % 4 == 0 && now.Year % 400 == 0)
{
months[1] = 29;
}

Related

C# trying to solve a Project Euler problem 5

I'm new at C# and trying to solve:
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
This is what I wrote
int i = 1;
while (i % 2 != 0 || i % 3 != 0 || i % 4 != 0 || i % 5 != 0 || i % 6 != 0 || i % 7 != 0 || i % 8 != 0
|| i % 9 != 0 || i % 10 != 0 || i % 11 != 0 || i % 12 != 0 || i % 13 != 0 || i % 14 != 0
|| i % 15 != 0 || i % 16 != 0 || i % 17 != 0 || i % 18 != 0 || i % 19 != 0 || i % 20 != 0)
{
i++;
}
It works the answer is right, but can I optimize it
Thank you!
approach with Linq
while (Enumerable.Range(2,19).Any(x => i % x != 0))
{
i++;
}
The simplest next step is to take your long list of i % x != 0 tests and turn it into a loop:
bool IsEvenlyDivisible(int value, int range)
{
for (int i = 2; i <= range; i++)
{
if (value % i != 0)
{
return false;
}
}
return true;
}
int i = 1;
while (!IsEvenlyDivisible(i, 20))
{
i++;
}
You can even turn this while loop into a for loop:
for (int i = 1; IsEvenlyDivisible(i, 20); i++)
{
}
You can then make the IsEvenlyDivisible method simpler using linq, see fubo's answer.

VB to C# conversion error (assign and if statements)

what is the proper way to convert
if((year mod 4=0 and year mod 100<>0) or (year mod 400=0), “Leap Year”, “Not a Leap Year”)
To C#
I was able to successfully convert the first part if ((year % 4 == 0 & year % 100 != 0) | (year % 400 == 0)) but when I add the messages, I get an error.
Any help would be greatly appreciated.
The equivalent of that VB If operator is the C# ternary operator (?:), i.e.
If(x, y, z)
is equivalent to:
x ? y : z;
For the record, there's another If operator like this:
If(x, y)
which evaluates to x if x is not null, otherwise it evaluates to y. The C# equivalent is called the null coalescing operator (??):
x ?? y;
The original VB code should have used the DateTime.IsLeapYear(Int32) Method, so that in C# it would become:
DateTime.IsLeapYear(year) ? "Leap Year" : "Not a Leap Year";
The answer in compilable code is:
private string LeapYearResponse(int year)
{
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
return "Leap Year";
else
return "Not a Leap Year";
}
Or more concisely:
private string LeapYearResponse(int year)
{
return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) ? "Leap Year" : "Not a Leap Year";
}

repeat a if else statement

How do I make it after the if statement comes true it will not execute and I can re-enter another set of numbers?... to stop it though i will have it to enter -1 to exit.
static void Main(string[] args)
{
{
// first enter 2016, then 2000, then 2015 and get multiple results
int Year;
Console.WriteLine("Please enter a year: ");
Year = Convert.ToInt32(Console.ReadLine());
if ((Year % 4 == 0) && (Year % 100 != 0 || Year % 400 != 0)) // <--- entered 2016
{
Console.WriteLine("The Year you have entered is a Leap Year {0}.", Year);
}
if ((Year % 4 == 0) && (Year % 100 == 0)) // <--- year 2000
{
Console.WriteLine("the 2000 works", Year);
}
if ((Year % 5 == 0) && (Year % 100 != 0)) // <--- year 2015
{
Console.WriteLine("2015 works", Year);
}
else
{
// startover
}
Console.ReadLine();
}
}
It is bit unclear, since you want to recur the process until you press -1, you could do something like this .
int Year;
do
{
Console.WriteLine("Please enter a year: ");
if(!int.TryParse(Console.ReadLine(), out Year))
{
Console.WriteLine("invalid input");
continue;
}
if ((Year % 4 == 0) && (Year % 100 != 0 || Year % 400 != 0)) // <--- entered 2016
{
Console.WriteLine("The Year you have entered is a Leap Year {0}.", Year);
}
if ((Year % 4 == 0) && (Year % 100 == 0)) // <--- year 2000
{
Console.WriteLine("the 2000 works", Year);
}
if ((Year % 5 == 0) && (Year % 100 != 0)) // <--- year 2015
{
Console.WriteLine("2015 works", Year);
}
} while(Year != -1);
//Console.ReadLine(); not required.
Working Code
If you are just testing to see if the year entered is a leap year, you could just use DateTime.IsLeapYear()
if(DateTime.IsLeapYear(Year))
{
Console.WriteLine("The Year you have entered is a Leap Year {0}.", Year);
}
else
{
Console.WriteLine("The Year you have entered is NOT a Leap Year {0}.", Year);
}

Shorten a DateTime condition check

if ((DateTime.Now.DayOfWeek != DayOfWeek.Friday && DateTime.Now.DayOfWeek != DayOfWeek.Saturday) &&
((DateTime.Now.Hour >= 10 && DateTime.Now.Hour < 13) || (DateTime.Now.Hour >= 20 && DateTime.Now.Hour < 23)))
I have to shorten this condition, any suggestions?
You could change the hours to use
(DateTime.Now.Hour % 12) +1 >= 10 && (DateTime.Now.Hour % 12) +1 < 13
Maybe even without the second check.
I don't think you can improve much more than that than looking for other methods like other answers
Update
I tested the above and its wrong, but this is more sadistic and works
var check = (DateTime.Now.Hours - 10 % 12) % 10;
var checkV = (DateTime.Now.Hours >= 10 && check < 3);
Test Code
for (int i = 0; i < 24; i++)
{
var check = (i - 10 % 12) % 10;
bool checkV = (i >= 10 && check < 3);
Console.WriteLine(i.ToString() + ": " + checkV.ToString());
}
Console.ReadKey();
Update 2
Complete shortened code
if( (int)DateTime.Now.DayOfWeek < 5 &&
DateTime.Now.Hours >= 10 &&
((DateTime.Now.Hours - 10 % 12) % 10) < 3)
Well, you could build an extension method:
public static bool BoundsCheck(this DateTime d, int min, int max, int min2, int max2)
{
return (d.DayOfWeek != DayOfWeek.Friday &&
d.DayOfWeek != DayOfWeek.Saturday &&
d.Hour >= min &&
d.Hour < max) ||
(d.Hour >= min2 && d.Hour < max2);
}
and then call it like this:
if (DateTime.Now.BoundsCheck(10, 13, 20, 23))...
Is this shorter? Maybe, but more important in my opinion it's more readable and maintainable:
var now = DateTime.Now;
var notAllowedDays = new[] { DayOfWeek.Friday, DayOfWeek.Saturday };
var allowedHours = Enumerable.Range(10, 3).Concat(Enumerable.Range(20, 3));
if(!notAllowedDays.Contains(now.DayOfWeek) && allowedHours.Contains(now.Hour))
{
}
if (!this.ItsPartyDay() && (this.ItsLunchTime() || this.ItsDinnerTime()))
{
...
}
private bool ItsPartyDay()
{
return (Int32)DateTime.Now.DayOfWeek >= 5;
}
private bool ItsLunchTime()
{
return (DateTime.Now.Hour >= 10 && DateTime.Now.Hour < 13);
}
private bool ItsDinnerTime()
{
return (DateTime.Now.Hour >= 20 && DateTime.Now.Hour < 23);
}
I don't think there is any reasonable solution but here a couple that come to mind. Use aliases for DateTime and DayOfWeek. One other option would be to assign all of those values to variables before the conditional.
So you could do things like;
string fri = DayOfWeek.Friday;
string sat = DayOfWeek.Saturday;
then use those in the conditional. Or;
using dt = DateTime;
Then you could do dt.Now.DayOfWeek
I personally would not recommend doing either of these things. You're not actually shortening the conditional, you're just refactoring. If you have a lot of these in one class it might be worth the trade off, otherwise it's probably not.
EDIT: The extension method suggestion by Michael Perrenoud is a reasonable solution that actually works really well.

Asp with C# Prime Number

I'm a 17 year old student currently in software engineering and web development and im having trouble right now with some of my coding. I need to make a project that will alow the user to input a number anywherefrom 0 to 999 and tell whether it is a prime number or not. The code i have so far is....
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void primeNumber()
{
int primeNumber1 = int.Parse(Request.Form["Text4"]);
if (primeNumber1 % 1 == 0 & ! (primeNumber1 % 2 == 0 &
primeNumber1 % 3 == 0 &
primeNumber1 % 4 == 0 &
primeNumber1 % 5 == 0 &
primeNumber1 % 6 == 0 &
primeNumber1 % 7 == 0 &
primeNumber1 % 8 == 0 &
primeNumber1 % 9 == 0))
{
Response.Write(" This is a prime number! ");
}
else
{
Response.Write(" This is not a prime Number! ");
}
}
}
... but i cannot get this program to display the correct answer. Any help would be greatly appreciated. Thanks!
You have got the concept of prime numbers wrong. Your code would for example report that 3 is not a prime number, because you check if the number divides evenly in three even if the number entered is three.
The simplest solution would be to loop from 2 and up to primeNumber1 - 1 and check if any of those divides evenly with the number. As you are using a loop, you also need a variable to hold what the result was, as you don't have a single expression that returns the result.
Something like:
bool prime = true;
for (int i = 2; i <= primeNumber1 - 1; i++) {
if (primeNumber1 % i == 0) {
prime = false;
}
}
This is of course the simplest possible solution that solves the problem, for reasonably small numbers. You can for example improve on the solution by exiting out of the loop as soon as you know that it's not a prime number.
You also don't need to loop all the way to primeNumber1 - 1, but only as high as the square root of the number, but you can find out about that if you read up on methods for checking prime numbers.
You need to handle the special cases of 1 and 2 also. By definition 1 is not a prime number, but 2 is.
http://en.wikipedia.org/wiki/Prime_number
bool IsPrime(int number) {
if (number == 1) return false;
if (number == 2) return true;
for (int i = 2; i < number; ++i) {
if (number % i == 0) return false;
}
return true;
}
A little google-fu or a little navel-gazing about prime numbers in general, will lead you to the naive algorithm:
For all n such that 0 < n:
There are two "special case" prime numbers, 1 and 2.
All even numbers > 2 are non-prime, by definition
If you think about the nature of factoring, the largest possible factor you have to consider is the square root of n, since above that point, the factors are reflexive (i.e., the possible factorizations of 100 are 1*100 , 2*50 , 4*25 , 5*20 , 10*10 , 20*5 , 25*4, 50*2 and 100*1 — and the square root of 100 is...10).
That should lead you to an implementation that looks something like this:
static bool IsPrime( int n )
{
if ( n < 1 ) throw new ArgumentOutOfRangeException("n") ;
bool isPrime = true ;
if ( n > 2 )
{
isPrime = ( 0 != n & 0x00000001 ) ; // eliminate all even numbers
if ( isPrime )
{
int limit = (int) Math.Sqrt(n) ;
for ( int i = 3 ; i <= limit && isPrime ; i += 2 )
{
isPrime = ( 0 != n % i ) ;
}
}
}
return isPrime ;
}
Anytime you find yourself in programming repeating a test on a sequential range of numbers you're doing the wrong thing. A better construct for this is a loop. This will give you the range of numbers in an identifier which can then be used to write the repetive code one time. For example I could rewrite this code
primeNumber1 % 2 == 0 &
primeNumber1 % 3 == 0 &
primeNumber1 % 4 == 0 &
primeNumber1 % 5 == 0 &
primeNumber1 % 6 == 0 &
primeNumber1 % 7 == 0 &
primeNumber1 % 8 == 0 &
primeNumber1 % 9 == 0))
As follows
bool anyFactors = false;
for (int i = 2; i <= 9; i++) {
if (primeNumber1 % i != 0) {
anyFactors = true;
break;
}
}
At this point I can now substitute the value allTrue for the original condition you wrote.
if (primeNumber1 % 1 == 0 && !anyFactors)
I can also expand the number of values tested here by substiting a different number for the conditional check of the loop. If I wanted to check 999 values I would instead write
for (int i = 2; i <= 999; i++) {
...
}
Additionally you don't want to use & in this scenario. That is for bit level and operations. You are looking for the logical and operator &&
Try the code below:
bool isPrimeNubmer(int n)
{
if (n >=0 && n < 4) //1, 2, 3 are prime numbers
return true;
else if (n % 2 == 0) //even numbers are not prime numbers
return false;
else
{
int j = 3;
int k = (n + 1) / 2 ;
while (j <= k)
{
if (n % j == 0)
return false;
j = j + 2;
}
return true;
}
}

Categories

Resources