Get divisible numbers in a range without certain operators (+, -, /, *, %, += %=, etc) - c#

find numbers in an input range that are evenly divisible by 3. Only =, ++, -- operators can be used.
I've tried to get the remainder using shift operators and other loops but I always require a -= or something similar.
Console.Clear();
int n,
d,
count = 1;
// get the ending number
n = getNumber();
// get the divisor
d = 3;// getDivisor();
Console.WriteLine();
Console.WriteLine(String.Format("Below are all the numbers that are evenly divisible by {0} from 1 up to {1}", d, n));
Console.WriteLine();
// loop through
while (count <= n)
{
// if no remainder then write number
if(count % d == 0)
Console.Write(string.Format("{0} ", count));
count++;
}
Console.WriteLine();
Console.WriteLine();
Console.Write("Press any key to try again. Press escape to cancel");
Expected results:
Enter the ending number: 15
Below are all the numbers that are evenly divisible by 3 from 1 up to 15
3, 6, 9, 12, 15

If the == operator is permitted for the assignment, you can have something like
int remainder = 0; // assumes we always count up from 1 to n, we will increment before test
Inside the loop replace the existing if with
remainder++;
if (remainder == 3) {
Console.Write(string.Format("{0} ", count));
remainder = 0;
}
[EDIT: Typo in code corrected]

Think about the underlying maths:
2 x 3 = 3 + 3
3 x 3 = 3 + 3 + 3
4 * 3 = 3 + 3 + 3 + 3
...and so on.
Also, to be evenly divisible by 3 means that the number multiplying 3 must be even.. So...
public bool EvenlyDivisibleBy3(int aNumber)
{
int even = 2;
int currentMultiple = 0;
while (currentMultiple < aNumber)
{
int xTimes = 0;
for (int x = 1; x <= even; x++)
{
((xTimes++)++)++; // add three to xTimes
}
currentMultiple = xTimes;
(even++)++: // next even number
}
return currentMultiple == aNumber;
}

Related

Sum range using loop, calculate sum of odd and even numbers

Hi I am sick of searching I could not find the exact code for my question.
I need to code the sum of the odd numbers from 1 to 100
and sum of the even numbers from 2 to 100.
This is what i have so far.
Thank you so much
// 1) using for statement to Sum Up a Range of values using Interactive
Console.WriteLine(" Sum Up a Range of values entered by User ");
Console.WriteLine();
// 2) Declare the Variables to be used in the Project
string strFromNumber, strToNumber;
int fromNumber, toNumber;
int sum = 0;
int i, even = 0, odd = 0;
int[] array = new int[10];
// 3) Prompt the User to Enter the From Number to Sum From
Console.Write("Enter the From Number to Sum From: ");
strFromNumber = Console.ReadLine();
fromNumber = Convert.ToInt32(strFromNumber);
// 4) Prompt the User to Enter the To Number to Sum To
Console.Write("Enter the To Number to Sum To: ");
strToNumber = Console.ReadLine();
toNumber = Convert.ToInt32(strToNumber);
// 5) Use for statement to Sum up the Range of Numbers
for (i = fromNumber; i <= toNumber; ++i)
{
sum += i;
}
if //(array[i] % 2 == 0) //here if condition to check number
{ // is divided by 2 or not
even = even + array[i]; //here sum of even numbers will be stored in even
}
else
{
odd = odd + array[i]; //here sum of odd numbers will be stored in odd.
}
Console.WriteLine("The Sum of Values from {0} till {1} = {2}",
fromNumber, toNumber, sum);
Console.ReadLine();
There is no need to write the complex code which you have written.
Problem is to calculate the sum of arithmetic progression. The formula to find the sum of an arithmetic progression is Sn = n/2[2a + (n − 1) × d] where, a = first term of arithmetic progression, n = number of terms in the arithmetic progression and d = common difference.
So in case of odd numbers its a = 1, n = 50 and d = 2
and in case of even numbers its a = 2, n = 50 and d = 2
and if you try to normalize these above formulas, it will be more easy based on your problem.
the sum of the first n odd numbers is Sn= n^2
the sum of the first n even numbers is n(n+1).
and obviously, it's very simple to loop from ( 1 to 99 with an increment of 2 ) and ( 2 to 100 with an increment of 2 )
In the simplest case, you can try looping in fromNumber .. toNumber range while adding
number either to even or to odd sum:
// long : since sum of int's can be large (beyond int.MaxValue) let's use long
long evenSum = 0;
long oddSum = 0;
for (int number = fromNumber; number <= toNumber; ++number) {
if (number % 2 == 0)
evenSum += number;
else
oddSum += number;
}
Console.WriteLine($"The Sum of Values from {fromNumber} till {toNumber}");
Console.WriteLine($"is {evenSum + oddSum}: {evenSum} (even) + {oddSum} (odd).");
Note, that you can compute both sums in one go with a help of arithmetics progression:
private static (long even, long odd) ComputeSums(long from, long to) {
if (to < from)
return (0, 0); // Or throw ArgumentOutOfRangeException
long total = (to + from) * (to - from + 1) / 2;
from = from / 2 * 2 + 1;
to = (to + 1) / 2 * 2 - 1;
long odd = (to + from) / 2 * ((to - from) / 2 + 1);
return (total - odd, odd);
}
Then
(long evenSum, long oddSum) = ComputeSums(fromNumber, toNumber);
Console.WriteLine($"The Sum of Values from {fromNumber} till {toNumber}");
Console.WriteLine($"is {evenSum + oddSum}: {evenSum} (even) + {oddSum} (odd).");
From the code snippet you shared, it seems like the user gives the range on which the sum is calculated. Adding to #vivek-nuna's answer,
Let's say the sum of the first N odd numbers is given by, f(n) = n^2 and
the sum of the first N even numbers is given by, g(n) = n(n + 1).
So the sum of odd numbers from (l, r) = f(r) - f(l - 1).
Similarly, the sum of even numbers from (l, r) = g(r) - g(l - 1).
Hope this helps.

C# For loop index returns ascii instead of current iteration

I need to make a program that calculates the factorial of a number and sums the different numbers.
I'm stuck at the point where I need to take the current number in the for loop to do it's factorial (e.g. the number 145 and I can't take the 5). I've tried the following:
for (int i = length-1; i >= 0; i--)
{
int currentNumber = inputString[i];
currentSum = currentSum * i;
sum += currentSum;
}
inputString is the length of the given number.
The problem is that in this way currentNumber becomes the ascii equivalent (if i = 3 currentSum becomes 51). How do I make currentSum become 3?
Alternatively you could use:
int currentNumber = int.Parse(inputString[i].ToString());
I'd like to suggest an alternative:
int num = int.Parse(inputString); // Convert whole input to int
int sum = 0;
while( num != 0 ) // >0 is not enough, num could be negative.
{
sum += num % 10; // Sum up least significant place
num = num / 10; // "Decimal shift right"
}
With your example "145" this would mean:
Iteration 1:
sum += 145 % 10 => sum = 0 + 5 = 5
num = num / 10 => num = 145 / 10 = 14
Iteration 2:
sum += 14 % 10 => sum = 5 + 4 = 9
num = num / 10 => num = 14 / 10 = 1
Iteration 3:
sum += 1 % 10 => sum = 9 + 1 = 10
num = num / 10 => num = 1 / 10 = 0
num == 0 => end while , sum = 10
Disclaimer: This assumes, the input is in fact a valid integer value. I'd strongly suggest to validate that, first. "Never trust user input."
Assuming inputString is numeric only, you can get away with:
int currentNumber = inputString[i] - '0';
Short explanation: character representation of number '3' is 51, but they are in order (so '0' is 48, '1' is 49, etc.) and you can get the "numerical value" of a character by removing the offset (which is the value of '0').

Pairs of amicable numbers

I have a task to find pairs of amicable numbers and I've already solved it. My solution is not efficient, so please help me to make my algorithm faster.
Amicable numbers are two different numbers so related that the sum of the proper divisors of each is equal to the other number. The smallest pair of amicable numbers is (220, 284). They are amicable because the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110, of which the sum is 284; and the proper divisors of 284 are 1, 2, 4, 71 and 142, of which the sum is 220.
Task: two long numbers and find the first amicable numbers between them. Let s(n) be the sum of the proper divisors of n:
For example:
s(10) = 1 + 2 + 5 = 8
s(11) = 1
s(12) = 1 + 2 + 3 + 4 + 6 = 16
If s(firstlong) == s(secondLong) they are amicable numbers
My code:
public static IEnumerable<long> Ranger(long length) {
for (long i = 1; i <= length; i++) {
yield return i;
}
}
public static IEnumerable<long> GetDivisors(long num) {
return from a in Ranger(num/2)
where num % a == 0
select a;
}
public static string FindAmicable(long start, long limit) {
long numberN = 0;
long numberM = 0;
for (long n = start; n <= limit; n++) {
long sumN = GetDivisors(n).Sum();
long m = sumN;
long sumM = GetDivisors(m).Sum();
if (n == sumM ) {
numberN = n;
numberM = m;
break;
}
}
return $"First amicable numbers: {numberN} and {numberM}";
}
I generally don't write C#, so rather than stumble through some incoherent C# spaghetti, I'll describe an improvement in C#-madeup-psuedo-code.
The problem seems to be in your GetDivisors function. This is linear O(n) time with respect to each divisor n, when it could be O(sqrt(n)). The trick is to only divide up to the square root, and infer the rest of the factors from that.
GetDivisors(num) {
// same as before, but up to sqrt(num), plus a bit for floating point error
yield return a in Ranger((long)sqrt(num + 0.5)) where num % a == 0
if ((long)sqrt(num + 0.5) ** 2 == num) { // perfect square, exists
num -= 1 // don't count it twice
}
// repeat, but return the "other half"- num / a instead of a
yield return num/a in Ranger((long)sqrt(num + 0.5)) where num % a == 0
}
This will reduce your complexity of that portion from O(n) to O(sqrt(n)), which should provide a noticeable speedup.
There is a simple formula giving the sum of divisors of a number knowing its prime decomposition:
let x = p1^a1 * ... * pn^an, where pi is a prime for all i
sum of divisors = (1+p1+...+p1^a1) * ... (1+pn+...+pn^an)
= (1-p1^(a1+1))/(1-p1) * ... ((1-pn^(an+1))/(1-pn)
In order to do a prime decomposition you must compute all prime numbers up to the square root of the maximal value in your search range. This is easily done using the sieve of Erathostenes.

Can somebody explains what happens in this algorithm to check if its a pandigital?

I know that the << operand shifts the left value of the operand with the value on the right with bits. So 1 << 2 would give 4. And the | operand copies a bit if it exists in either value. But I simply can't get my head around the code.
private static bool isPandigital(long n)
{
int digits = 0;
int count = 0;
int tmp;
while (n > 0)
{
tmp = digits;
digits = digits | 1 << (int)((n % 10) - 1);
if (tmp == digits)
{
return false;
}
count++;
n /= 10;
}
return digits == (1 << count) - 1;
}
Why does it say 1 << in line 8? And why is the module - 1?
On top of that I don't know what is happening on the last line when the value is returned. Help would be greatly apreciated. Thanks very much!
Doing
digits = digits | 1 << (int)((n % 10) - 1);
is the same thing as
long temp1 = n % 10; //Divide the number by 10 and get the remainder
long temp2 = temp1 - 1; //Subtract 1 from the remainder.
int temp3 = (int)temp2; //cast the subtracted value to int
int temp4 = 1 << temp3; //left shift 1 to the casted value. This is the same as saying "two to the power of the value of temp3"
int temp5 = digits | temp4; //bitwise or together the values of digits and that leftshifted number.
digits = temp5; //Assign the or'ed value back to digits.
The last line
return digits == (1 << count) - 1;
is just doing the same thing as
int temp1 = 1 << count; //left shift 1 `count` times, this is the same as saying "two to the power of the value of count"
int temp2 = temp1 - 1; //Subtract 1 from the leftshifted number.
bool temp3 = digits == temp2; //test to see if digits equals temp2
return temp3;
I don't know what "pandigital" means, but this break apart can help you understand what is happening.
If pandigital means "contains all possible digits for the given radix"
https://en.wikipedia.org/wiki/Pandigital_number
and the radix == 10, why not just check if the number contains all possible 0..9 digits:
private static bool isPandigital(long n) {
// I assume negative numbers cannot be pandigital;
// if they can, put n = Math.Abs(n);
if (n < 1023456789) // smallest pandigital
return false;
int[] digits = new int[10];
for (; n > 0; n /= 10)
digits[n % 10] += 1;
return digits.All(item => item > 0);
}
Edit: In case of bit array (each bit in digits represent a digit) implementation:
private static bool isPandigital(long n) {
// negative numbers can't be pandigital
if (n < 1023456789) // smallest pandigital
return false;
int digits = 0;
for (; n > 0; n /= 10)
digits |= (1 << (int)(n % 10));
// 0b1111111111
return digits == 1023;
}
I think the writer of the method attempted to do this:
static bool IsPandigital(long n) {
int digits = 0;
while (n > 0) {
//set the bit corresponding to the last digit of n to 1 (true)
digits |= 1 << (int)(n % 10);
//remove the last digit of n
n /= 10;
}
//digits must be equal to 1111111111 (in binary)
return digits == (1 << 10) - 1;
}
The << operator is not that difficult. You just have to think in binary.
1 << 0 is simply a 1 shifted zero places, so 1
1 << 1 is 10
1 << 2 is 100, etc
If you encounter a 2 and a 5 and you 'or' them together you will have 100100.
This means if you encounter all 10 digits, the end result will be ten 1's.
In the return statement, we check if digits equals ten 1's.
1 << 10 means a 10000000000. If you substract 1, you get 1111111111
All this in binary, of course.
He may have had a different definition of pandigital, or just a different requirement. If, for example zeroes are not allowed, you can simply change the last line to: digits == (1 << 10) - 2;

How to get the number of elements in an int array?

in this case I want to take the number of elements in the array , but the array is dependent on user input
int first = int.Parse(Console.ReadLine());
int second = int.Parse(Console.ReadLine());
for (int i = first; i <= second; i++)
{
if (i % 5 == 0)
{
int[] some =new int [i];
int c =some.Length;
Console.WriteLine(c);
}
}
I tried several options, but the output is still a list of the numbers divisible by 5 without remainder. How is right to do?
example: first = 15, second = 50.
Expected output = 8.
8 numbers divisible by 5 without remainder(15,20,25,30...50)
You can just loop through the numbers and count how many you find that are divisible by 5:
int first = int.Parse(Console.ReadLine());
int second = int.Parse(Console.ReadLine());
int cnt = 0;
for (int i = first; i <= second; i++) {
if (i % 5 == 0) {
cnt++;
}
}
However, you dont have to generate the numbers to know how many there are. You can just calculate where the last number is (as that is easier than the first) and then calculate how many there are before that but after the first:
int first = int.Parse(Console.ReadLine());
int second = int.Parse(Console.ReadLine());
second -= second % 5;
int cnt = (second - first) / 5 + 1;
For example for the input 3 and 11 you want to count the numbers 5 and 10. The expression 11 % 5 gives 1, so second becomes 10 (the last number). Then second - first is 7, doing integer division with 5 gives 1, and then add 1 gives 2.

Categories