This is the background to this question:
Background
Take any integer n greater than 1 and apply the following algorithm
If n is odd then n = n × 3 + 1 else n = n / 2
If n is equal to 1 then stop, otherwise go to step 1
The following demonstrates what happens when using a starting n of 6
6 - 3 - 10 - 5 - 16 - 8 - 4 - 2 - 1
After 8 generations of the algorithm we get to 1.
It is conjectured that for every number greater than 1 the repeated application of this algorithm will
eventually get to 1.
The question is how can I find a number that takes exactly 500 generations to reduce to 1?
The code below is my version but appearntly got some wrong logic. Could you help me correct this? Thanks in advance.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Sequence1
{
class Program
{
static void Main(string[] args)
{
int start = 1;
int flag = 0;
int value;
while(true){
int temp = (start - 1) / 3;
string sta = temp.ToString();
if (Int32.TryParse(sta, out value) )
{
if (((start - 1) / 3) % 2 == 1)
{
start = (start - 1) / 3;
flag++;
if (flag == 500)
{
break;
}
}
else
{
start = start * 2;
flag++;
if (flag == 500)
{
break;
}
}
}
else
{
start = start * 2;
flag++;
if (flag == 500)
{
break;
}
}
}
Console.WriteLine("result is {0}", start);
Console.ReadLine();
}
}
}
Since your question's title is "A recursion related issue", I will give you a recursive solution.
int Process(int input, int maxRecursionDepth)
{
// condition to break recursion
if (maxRecursionDepth == 0 || input == 1)
return input;
if (input % 2 == 1) // odd case
return Process(input * 3 + 1, maxRecursionDepth - 1);
else // even case
return Process(input / 2, maxRecursionDepth - 1);
}
Now to find all number in a specified range, that return 1 after exactly 500 recursions:
int startRange = 1, endRange = 1000;
int maxDepth = 500;
List<int> resultList = new List<int>();
for (int i = startRange; i <= endRange; i++)
{
if (Process(i, maxDepth) == 1)
resultList.Add(i);
}
Your problem is a part of Collatz conjecture (about recursively defined function) which has not been solved yet:
http://en.wikipedia.org/wiki/Collatz_conjecture
so I think brute force is a good way out:
public static int GetMinNumber(int generations) {
if (generations < 0)
throw new ArgumentOutOfRangeException("generations");
// Memoization will be quite good here
// but since it takes about 1 second (on my computer) to solve the problem
// and it's a throwaway code (all you need is a number "1979515")
// I haven't done the memoization
for (int result = 1; ; ++result) {
int n = result;
int itterations = 0;
while (n != 1) {
n = (n % 2) == 0 ? n / 2 : 3 * n + 1;
itterations += 1;
if (itterations > generations)
break;
}
if (itterations == generations)
return result;
}
}
...
int test1 = GetMinNumber(8); // <- 6
int test2 = GetMinNumber(500); // <- 1979515
Observing the problem,
13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1
In the third iteration we hit the number 10, which is smaller than 13
So instead of calculating the sequence count every time we can use a cache.
static int GetMinCollatz(int maxChain)
{
const long number = 1000000;
int minNumber = 0;
// Temporary values
int tempCount = 0;
long temp = 0;
// Cache
int[] sequenceCache = new int[number + 1];
// Fill the array with -1
for (int index = 0; index < sequenceCache.Length; index++)
{
sequenceCache[index] = -1;
}
sequenceCache[1] = 1;
for (int index = 2; index <= number; index++)
{
tempCount = 0;
temp = index;
// If the number is repeated then we can find
// sequence count from cache
while (temp != 1 && temp >= index)
{
if (temp % 2 == 0)
temp = temp / 2;
else
temp = temp * 3 + 1;
tempCount++;
}
sequenceCache[index] = tempCount + sequenceCache[temp];
if (sequenceCache[index] == maxChain)
{
minNumber = index;
}
}
return minNumber;
}
For more details refer project euler and this.
A recursive solution
private void ReduceTo1(int input, ref int totalCount)
{
totalCount++;
if (input % 2 == 0)
{
input = input / 2;
}
else
{
input = input * 3 + 1;
}
if (input != 1)
ReduceTo1(input, ref totalCount);
}
to test
int desireValue = 0;
for (int i = 1; i < 100000; i++)
{
int totalCount = 0;
ReduceTo1(i, ref totalCount);
if (totalCount >= 500)
{
desireValue = i;
break;
}
}
Related
I am stuck in a scenario which is complex for me to implement. Scenario is : I have rows in excel sheet which is dynamic . sometimes it could be 2, sometimes 5, sometimes 12 means any number of rows could be there. i need to assign different unique values to each available row in such a way that their sum should be equal to 100. Example : if i have 2 rows i can assign values 65 and 35 but not 50 to both as the value needs to be unique. similarly if i have 4 rows i need to assign values like 20,30, 27, 23 .Need a c# code for this.
How can i do this?
There are many ways you could generate different random numbers for each row. The way I generated the numbers was with DateTime.Now.Second and DateTime.Now.Minute. To ensure that the numbers never go over 100, you can subtract from the maximum number in the row. This is the general idea:
`
public static ulong CapAtNumber(ulong num, ulong cap) {
while(num>cap)
{
num = (num / 2) - 2;
if (num < 3)
{
num += (Convert.ToUInt64(DateTime.Now.Minute) + Convert.ToUInt64(DateTime.Now.Second) / 2);
}
}
return num;
}
This is an example of how you would find the maximum. I used the Math group to check for maximums among twoulong` numbers. The numbers are A B C D E F, and so on, and I group them into AB CD EF to find the maximum between the groups. The array size gets cut in half each time until the array size is 1. When the array size is 1, the number in the array is the maximum.
public static ulong[] FindTheMaxOfArray(ulong[] arg)
{
bool repeat = true;
ulong checknumber = 100;
while(repeat == true)
{
if (arg.Length % 2 == 0)
{
var halflist = new ulong[arg.Length / 2];
for (int z = 0; z < arg.Length / 2; z += 2)
{
halflist[z] = Math.Max(arg[z], arg[z + 1]);
if (
halflist.Length == 1)
{
repeat = true;
arg = new ulong[halflist.Length];
arg = halflist;
}
else { repeat = false;
checknumber = halflist[0]; }
}
}
else
{
var halflist = new ulong[arg.Length + 1 / 2];
for (int z = 0; z < halflist.Length; z++)
{
if (z % 2 != 0)
{
if (z != halflist.Length - 2)
{
halflist[z] = Convert.ToUInt64(Math.Max(Math.Max(arg[z], arg[z + 1]), arg[z + 2]));
}
else { halflist[z] = Convert.ToUInt64(Math.Max(arg[z], arg[z + 1])); }
}
}
if (halflist.Length == 1)
{
repeat = true;
arg = new ulong[halflist.Length];
arg = halflist;
}
else { checknumber = halflist[0];
repeat = false;
}
}
}
for(int z=0; z<arg.Length; z++)
{
if (arg[z] == checknumber)
{
arg[z] = CapAtNumber(arg[z], arg[z] - 20);
}
}
return arg;
}
if you want to ensure that there are no repeats, you can create a method to check for that. Each number in the foreach loop is checking with the numbers in the for loop. Since these are the same arrays, there has to be at least one repeat that happens naturally. Everything except this part seems to run smoothly. Here is an example
public static ulong[] Checkforrepeats(ulong[] args)
{
ulong repeatednumber = 1000;
int repeat = -1;
foreach( ulong num in args)
{
for(int z = 0; z<args.Length; z++)
{
if(z == 0)
{ repeat = -1; }
if(num ==args[z])
{
repeat += 1; //repeat was set to -1 to counter act the guaranteed repeat that will happen
}
if (repeat == 2)
{
args[z] += 2;
args[z - 1] -= 2;
}
}
}
return args;
}
I want to store integers(in an array or anything) that in range of int "i" and int "j".
eg:-Think, "int i = 1" and "int j = 10".I want to store integers from 1 and 10.
So that (1,2,3,4,5,6,7,8,9,10)
Because I want to answer to HackerRank "Beautiful Days at the Movies".
link below.
https://www.hackerrank.com/challenges/beautiful-days-at-the-movies/problem?isFullScreen=false
here is my code and it a garbage.
static int beautifulDays(int i, int j, int k) {
var total = 0;
for(var a = i; a <= j; a++ )
{
if (a != 0)
{
int ri = Reverse(i);
int rj = Reverse(j);
var ra = Reverse(a);
if((ra/k) % 1 == 0)
{
total++;
}
if((rj/k) % 1 == 0)
{
total++;
}
if((ri/k) % 1 == 0)
{
total++;
}
}
return total;
}
return total;
}
public static int Reverse(int inval)
{
int result = 0;
do
{
result = (result * 10) + (inval % 10);
inval = inval / 10;
}
while(inval > 0);
return result;
}
simply, can you give me the answer of HackerRank "Beautiful Days at the Movies".
link below.
https://www.hackerrank.com/challenges/beautiful-days-at-the-movies/problem?isFullScreen=false
Using Java you can easily stream a range of numbers with IntStream, then map the reverse function for each value, then filter those that fulfils the condition and count. With streams you don't need to store, you can get straight to the answer.
IntUnaryOperator reverse = (opperand) -> {
int reversed = 0;
int num = opperand;
while (num != 0) {
int digit = num % 10;
reversed = reversed * 10 + digit;
num /= 10;
}
return Math.abs(opperand - reversed);
};
return (int) IntStream.rangeClosed(i, j).map(reverse)
.filter(v -> v % k == 0).count();
1/ DateTime before = DateTime.Now;
2/ shellSort(List1);
3/ DateTime after = DateTime.Now;
4/ Console.WriteLine(after - before);
5/
6/ before = DateTime.Now;
7/ insertionSort(List2);
8/ after = DateTime.Now;
9/ Console.WriteLine(after - before);
I am trying to compare the run time of two different sorting algorithms. List1 here is equal to List2. I was expecting shell sort to be faster than insertion sort but although first WriteLine differs, it usually prints something like this = 00:00:00.0035037. The second one however, either prints 00:00:00 or something smaller than the first print. I thought maybe the insertion sort was better suited for List's current state however even when i swap the line 7 and line 2 i still get the same result. What is causing this? Why is the second executed function runs faster? Or am i using the Dates completely wrong?
Edit : I used Stopwatch instead of DateTime Class as advised in another post. The result is pretty much the same. The second one usually runs faster but every now and then it's slower than the first one. I also used a pre-written shellsort code to see if my implementation was bad but that was also a dead end.
As requested, shellsort and insertionsort implementations
static void shellSort(List<int> numbers) // Implementation i found online
{
int i, j, increment, temp;
increment = 3;
while (increment > 0)
{
for (i = 0; i < numbers.Count ; i++)
{
j = i;
temp = numbers[i];
while ((j >= increment) && (numbers[j - increment] > temp))
{
numbers[j] = numbers[j - increment];
j = j - increment;
}
numbers[j] = temp;
}
if (increment / 2 != 0)
increment = increment / 2;
else if (increment == 1)
increment = 0;
else
increment = 1;
}
}
public static void insertionSort(List<int> numbers)
{
int i = 0;
while (i != numbers.Count)
{
int k = i;
while (k != 0 && numbers[k] < numbers[k - 1])
{
int temp = numbers[k - 1];
numbers[k - 1] = numbers[k];
numbers[k] = temp;
k--;
}
i++;
}
}
Also this was my implementation of shellsort
public static void shellSort(List<int> Liste)
{
int n = Liste.Count;
int gap = (Liste.Count - 1) / 2;
while (gap > 0)
{
int i = 0;
for(int k = gap; k < n; k++) {
int p = i;
int m = k;
while (p >= 0)
{
if (Liste[p] > Liste[m])
{
int temp = Liste[p];
Liste[p] = Liste[m];
Liste[m] = temp;
m = p;
}
else
break;
p = p - gap;
}
i++;
}
gap = gap / 2;
}
}
Im currently trying to create a program that prints the prime numbers from 0 to 10,000 using only for,do while and ifs. I created this program but it doesn't runs
static void Main(string[] args)
{
for (int x = 2; x < 10000; x++)
{
for (int y = 1; y < x; y++)
{
if (x % y != 0)
{
Console.WriteLine(x);
}
}
Console.ReadKey();
}
I don't know where the problem is and also if the for inside resets.
Try this with no bool variable!!!:
static void Main(string[] args)
{
for (int x = 2; x < 10000; x++)
{
int isPrime = 0;
for (int y = 1; y < x; y++)
{
if (x % y == 0)
isPrime++;
if(isPrime == 2) break;
}
if(isPrime != 2)
Console.WriteLine(x);
isPrime = 0;
}
Console.ReadKey();
}
Check Console.ReadKey(); it should be after upper for loop, you can even change condition for upper for loot with <= since 10000 also need to check for prime condition.
Below is the efficient way to print prime numbers between 0 and 10000
using System.IO;
using System;
class Program
{
static void Main()
{
Console.WriteLine("Below are prime numbers between 0 and 10000!");
Console.WriteLine(2);
for(int i=3;i<=10000;i++)
{
bool isPrime=true;
for(int j=2;j<=Math.Sqrt(i);j++)
{
if(i%j==0)
{
isPrime=false;
break;
}
}
if(isPrime)
{
Console.WriteLine(i);
}
}
}
}
Is there any reason that you put Console.ReadKey(); inside of loop?
You should put that out of the loop unless press key during loop.
static void Main(string[] args)
{
for (int x = 2; x < 10000; x++)
{
for (int y = 1; y < x; y++)
{
if (x % y != 0)
{
Console.WriteLine(x);
}
}
}
Console.ReadKey();
}
And probably that code is just print lots of x.
You should to fix it.
The first problem is that x % 1 will always be zero, at least for non-zero x. You need to start the test (inner) loop at one and, for efficiency, stop when you've exceeded the square root of the number itself - if n has a factor f where f > sqrt(n), you would have already found the factor n / f.
The second problem is that you will write out a candidate number every time the remainder is non-zero. So, because 15 % 4 is three, it will be output despite the fact that fifteen is very much a non-prime. It will also be output at 15 % 2, 15 % 4, 15 % 6, 15 % 7, and so on.
The normal (naive) algorithm for prime testing is:
# All numbers to test.
foreach number 2..whatever:
# Assume prime, check all numbers up to squareroot(number).
isPrime = true
foreach test 2..infinity until test * test > number:
# If a multiple, flag as composite and stop inner loop.
if number % test == 0:
isPrime = false
exit foreach
end
end
# If never flagged as composite, output as prime.
if isPrime:
output number
end
Here is simple logic to Print Prime No for any upper limit.
Input : 10 Output : 2 , 3 , 5 ,7
namespace PurushLogics
{
class Purush_PrimeNos
{
static void Main()
{
//Prime No Program
bool isPrime = true;
Console.WriteLine("Enter till which number you would like print Prime Nos\n");
int n = int.Parse(Console.ReadLine());
Console.WriteLine("Prime Numbers : ");
for (int i = 2; i <= n; i++)
{
for (int j = 2; j <= n; j++)
{
if (i != j && i % j == 0)
{
isPrime = false;
break;
}
}
if (isPrime)
{
Console.Write("\t" + i);
}
isPrime = true;
}
Console.ReadKey();
}
}
}
Here is my code where you can generate and print the prime numbers between two numbers (in between string_starting_number and string_last_number). The lowest possible value for string_starting_number is 0 and the highest possible value for string_last_number is decimal.MaxValue-1=79228162514264337593543950334 and not 79228162514264337593543950335 because of the decimal_a++ command inside a for loop which will result to an overflow error.
Take note that you should input the values in string type in string_starting_number and in string_last_number.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GeneratingPrimeNumbers
{
class Program
{
static void Main(string[] args)
{
string string_starting_number = "1"; //input here your choice of starting number
string string_last_number = "10"; //input here your choice of last number
decimal decimal_starting_number = Convert.ToDecimal(string_starting_number);
decimal decimal_last_number = Convert.ToDecimal(string_last_number);
string primenumbers = "";
ulong ulong_b;
ulong ulong_c;
if (decimal_starting_number <= ulong.MaxValue)
{
ulong ulong_starting_number = Convert.ToUInt64(decimal_starting_number);
ulong ulong_last_number;
if (decimal_last_number > ulong.MaxValue)
{
ulong_last_number = ulong.MaxValue;
}
else
{
ulong_last_number = Convert.ToUInt64(decimal_last_number);
}
if (ulong_starting_number == 0 || ulong_starting_number == 1 || ulong_starting_number == 2 || ulong_starting_number == 3)
{
primenumbers = 2 + " " + 3;
ulong_starting_number = 5;
}
if (ulong_starting_number % 2 == 0)
{
ulong_starting_number++;
}
ulong ulong_a;
for (ulong_a = ulong_starting_number; ulong_a <= ulong_last_number; ulong_a += 2)
{
ulong_b = Convert.ToUInt64(Math.Ceiling(Math.Sqrt(ulong_a)));
for (ulong_c = 3; ulong_c <= ulong_b; ulong_c += 2)
{
if (ulong_a % ulong_c == 0)
{
goto next_value_of_ulong_a;
}
}
primenumbers = primenumbers + " " + ulong_a;
next_value_of_ulong_a:
{
}
}
}
if (decimal_last_number > ulong.MaxValue)
{
string ulong_maximum_value_plus_two = "18446744073709551617";
if (decimal_starting_number <= ulong.MaxValue)
{
decimal_starting_number = Convert.ToDecimal(ulong_maximum_value_plus_two);
}
if (decimal_starting_number % 2 == 0)
{
decimal_starting_number++;
}
decimal decimal_a;
for (decimal_a = decimal_starting_number; decimal_a <= decimal_last_number; decimal_a += 2)
{
ulong_b = Convert.ToUInt64(Math.Ceiling(Math.Sqrt(ulong.MaxValue) * Math.Sqrt(Convert.ToDouble(decimal_a / ulong.MaxValue))));
for (ulong_c = 3; ulong_c <= ulong_b; ulong_c += 2)
{
if (decimal_a % ulong_c == 0)
{
goto next_value_of_decimal_a;
}
}
primenumbers = primenumbers + " " + decimal_a;
next_value_of_decimal_a:
{
}
}
}
Console.WriteLine(primenumbers);
Console.ReadKey();
}
}
}
I have a code here written in C# that finds the smallest multiple by all numbers from 1 to 20. However, I find it very inefficient since the execution took awhile before producing the correct answer. I would like to know what are the different ways that I can do to improve the code. Thank You.
public static void SmallestMultiple()
{
const ushort ARRAY_SIZE = 21;
ushort[] array = new ushort[ARRAY_SIZE];
ushort check = 0;
for (uint value = 1; value < uint.MaxValue; value++)
{
for (ushort j = 1; j < ARRAY_SIZE; j++)
{
array[j] = j;
if (value % array[j] == 0)
{
check++;
}
}
if (check == 20)
{
Console.WriteLine("The value is {0}", value);
}
else
{
check = 0;
}
}
}
static void Main(string[] args)
{
int[] nums = Enumerable.Range(1, 20).ToArray();
int lcm = 1;
for (int i = 0; i < nums.Length; i++)
{
lcm = LCM(lcm, nums[i]);
}
Console.WriteLine("LCM = {0}", lcm);
}
public static int LCM(int value1, int value2)
{
int a = Math.Abs(value1);
int b = Math.Abs(value2);
// perform division first to avoid potential overflow
a = checked((a / GCD(a, b)));
return checked((a * b));
}
public static int GCD(int value1, int value2)
{
int gcd = 1; // Greates Common Divisor
// throw exception if any value=0
if (value1 == 0 || value2 == 0)
{
throw new ArgumentOutOfRangeException();
}
// assign absolute values to local vars
int a = Math.Abs(value1); // local var1
int b = Math.Abs(value2); // local var2
// if numbers are equal return the first
if (a == b) { return a; }
// if var "b" is GCD return "b"
if (a > b && a % b == 0) { return b; }
// if var "a" is GCD return "a"
if (b > a && b % a == 0) { return a; }
// Euclid algorithm to find GCD (a,b):
// estimated maximum iterations:
// 5* (number of dec digits in smallest number)
while (b != 0)
{
gcd = b;
b = a % b;
a = gcd;
}
return gcd;
}
}
Source : Fast Integer Algorithms: Greatest Common Divisor and Least Common Multiple, .NET solution
Since the result must also be divisible by 19 (which is the greatest prime number) up to 20, you might only cycle through multiples of 19.
This should get to to the result about 19 times faster.
Here's the code that does this:
public static void SmallestMultiple()
{
const ushort ARRAY_SIZE = 21;
ushort[] array = new ushort[ARRAY_SIZE];
ushort check = 0;
for (uint value = 19; value < uint.MaxValue; value += 19)
{
for (ushort j = 1; j < ARRAY_SIZE; j++)
{
array[j] = j;
if (value % array[j] == 0)
{
check++;
}
}
if (check == 20)
{
Console.WriteLine("The value is {0}", value);
return;
}
else
{
check = 0;
}
}
}
On my machine, this finds the result 232792560 in a little over 2 seconds.
Update
Also, please note that the initial program did not stop when reaching a solution; I have added a return statement to make it stop.
You're just looking for the LCM of the numbers from 1 to 20:
Where the GCD can be efficiently calculated with the Euclidean algorithm.
I don't know C#, but this Python solution shouldn't be hard to translate:
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def lcm(a, b):
return (a * b) / gcd(a, b)
numbers = range(1, 20 + 1)
print reduce(numbers, lcm)
It's pretty fast too:
>>> %timeit reduce(lcm, range(1, 20000))
1 loops, best of 3: 258 ms per loop
EDIT: v2.0 - Major speed improvement
Building on w0lf's solution. A faster solution:
public static void SmallestMultiple()
{
// this is a bit quick and dirty
// (not too difficult to change to generate primeProduct dynamically for any range)
int primeProduct = 2*3*5*7*11*13*17*19;
for (int value = primeProduct; ; value += primeProduct)
{
bool success = true;
for (int j = 11; j < 21; j++)
{
if (value % j != 0)
{
success = false;
break;
}
}
if (success)
{
Console.WriteLine("The value is {0}", value);
break;
}
}
}
You needn't check 1-10 since if something is divisible by x (e.g. 12), it is divisible by x/n (e.g. 12/2 = 6). The smallest multiple will always be a multiple of a product of all the primes involved.
Didn't benchmark C# solution, but equivalent Java solution runs in about 0.0000006 seconds.
Well I'm not sure what exactly you are trying to accomplish here but your out side for loop will run approximately 4,294,967,295 time (uint.MaxValue). So that will take some time...
If you have a way to keep from going to uint.MaxValue - like breaking your loop when you have accomplished what you need to - that will speed it up.
Also, since you are setting array[j] equal to j and then apparently never using the array again why not just do:
value % j
instead of
value % array[j]
Using also code written by W0lf (sorry but i cannot comment on your post) I would improve it (only a little) deleting the array that I think is useless..
public static void SmallestMultiple()
{
const ushort ARRAY_SIZE = 21;
ushort check = 0;
for (uint value = 1; value < uint.MaxValue; value++)
{
for (ushort j = 1; j < ARRAY_SIZE; j++)
{
if (value % j == 0)
{
check++;
}
}
if (check == 20)
{
Console.WriteLine("The value is {0}", value);
}
else
{
check = 0;
}
}
}