I'm trying to create an method to evenly distribute an array into X numbers of new arrays, where there is only allowed 15 items pr array, and you are only allowed to create a new array, if the previous have 10 items, except if the array has less than 10 items.
EDIT
To make my question more understandable for future readers.
This is just like a fabric.
You need to build X number of products.
One product takes T amount to build for an employee.
How many employees do you need and how do you share the work load between them?
END EDIT
Max allowed number in array = 15;
Min allowed number in array = 10;
Number = Numbers of Items in the Collection.
Number 5 => [5]
Number 13 => [13]
Number 16 => [10] [6]
Number 29 => [15] [14]
Number 30 => [15] [15]
Number 31 => [11] [10] [10]
Number 32 => [12] [10] [10]
Number 33 => [11] [11] [11]
I'm trying to solve this in C#.
This is my code so far, but it fails at numbers like 16 = [16], 29 = [19][10], 38 = [18][10][10]
const int maxAllowedOrderLines = 15;
const int minAllowedOrderLines = 10;
var optimalOrderDisp = new List<int>();
Console.WriteLine("Number of OrderLines");
int linjer = Convert.ToInt32(Console.ReadLine());
if (linjer <= maxAllowedOrderLines)
optimalOrderDisp.Add(linjer);
else
{
for (var i = maxAllowedOrderLines; i > 0; i--)
{
var maxOrderLines = linjer%i;
if (maxOrderLines == 0 || i <= minAllowedOrderLines || linjer < maxAllowedOrderLines)
{
Console.WriteLine("Optimal number of order lines {0}--{1}", i, (double) linjer/(double) i);
var optimalNumberOfOrders = linjer/i;
for (var orderNumber = 0; orderNumber < optimalNumberOfOrders; orderNumber++)
{
optimalOrderDisp.Add(i);
}
if (maxOrderLines != 0)
optimalOrderDisp[0] += maxOrderLines;
break;
}
}
}
foreach (var i1 in optimalOrderDisp)
{
Console.Write("[{0}]", i1);
}
Console.WriteLine();
Erm ...
const double bucketSize = 15.0;
var totalItems = (double)linjer;
var optimumBuckets = Math.Ceiling(totalItems / bucketSize);
var itemsPerBucket = (int)Math.Ceiling(totalItems / optimumBuckets);
var buckets = new int[(int)optimumBuckets];
var itemsLeft = (int)totalItems
for (var i = 0; i < buckets.length; i++)
{
if (itemsLeft < itemsPerBucket)
{
buckets[i] = itemsLeft;
}
else
{
buckets[i] = itemsPerBucket;
}
itemsLeft -= itemsPerBucket;
}
seems to do what you want.
Fun question. I've given it a go:
const int maxAllowedOrderLines = 15;
const int minAllowedOrderLines = 10;
static List<int> optimalOrderDisp = new List<int>();
static void Main(string[] args)
{
int Lines = Convert.ToInt32(Console.ReadLine());
int MinNumberOfBuckets = (int) Math.Ceiling((double) Lines / minAllowedOrderLines);
int RemainingLines = Lines;
int BucketLines = Lines / MinNumberOfBuckets;
// Distribute evenly
for (int i = 0; i < MinNumberOfBuckets; i++)
{
optimalOrderDisp.Add(i != MinNumberOfBuckets - 1 ? BucketLines : RemainingLines);
RemainingLines -= BucketLines;
}
// Try to remove first bucket
while (RemoveBucket())
{
}
// Re-balance
Lines = optimalOrderDisp.Sum();
RemainingLines = Lines;
BucketLines = (int) Math.Round((double) Lines / (optimalOrderDisp.Count));
for (int i = 0; i < optimalOrderDisp.Count; i++)
{
optimalOrderDisp[i] = (i != optimalOrderDisp.Count - 1 ? BucketLines : RemainingLines);
RemainingLines -= BucketLines;
}
// Re-balance to comply to min size
for (int i = 0; i < optimalOrderDisp.Count - 1; i++)
if (optimalOrderDisp[i] < minAllowedOrderLines)
{
int delta = minAllowedOrderLines - optimalOrderDisp[i];
optimalOrderDisp[i] += delta;
optimalOrderDisp[optimalOrderDisp.Count - 1] -= delta;
}
Console.WriteLine(String.Join("\n", optimalOrderDisp.ToArray()));
}
static bool RemoveBucket()
{
if (optimalOrderDisp.Sum() > maxAllowedOrderLines * (optimalOrderDisp.Count - 1))
return false;
int Lines = optimalOrderDisp[0];
int RemainingLines = Lines;
int BucketLines = Lines / (optimalOrderDisp.Count - 1);
// Remove bucket and re-distribute content evenly
// Distribute evenly
for (int i = 1; i < optimalOrderDisp.Count; i++)
{
optimalOrderDisp[i] += (i != optimalOrderDisp.Count - 1 ? BucketLines : RemainingLines);
RemainingLines -= BucketLines;
}
optimalOrderDisp.RemoveAt(0);
return true;
}
Related
Is there an algorithm for calculating a factorial without using System.Numerics library? We receive an int number and we need to return factorial of this number as string(if n = 30, we should return "265252859812191058636308480000000", if n = 70, we should return "11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000" ect. Numbers are very big)
I tried to find out, did anyone already write an article about that, but I didn't find anything.
It suffices to implement multiplication of a large number as a string by a small integer.
Illustration: 12! = 11! x 12 is obtained by multiplying every digit by 12 and summing (with shifts):
39916800
36
108
108
12
72
96
0
0
---------
479001600
A lazy solution. It is possible to evaluate the factorial with just BigNum addition, replacing the multiplications by successive additions. (For n!, we will perform 1+2+3+...n-1 additions. This is acceptable for moderate n.)
The computation uses two pre-allocated string (arrays of char), which are initially filled with null bytes (Writeline skips them). When adding from right to left, we stop when we meet a null.
int n = 20;
// Factorial and temporary string; 100! fits in 158 digits
const int N = 158;
char[] f = new char[N], t = new char[N];
f[N - 1] = '1'; // 1!
// Product up to n by successive additions
for (int i = 2; i <= n; i++)
{
// t= f
f.CopyTo(t, 0);
for (int j = 0; j < i - 1; j++)
{
// f+= t, repeated i-1 times
int c = 0; // Carry
for (int k = N - 1; k >= 0; k--)
{
if (t[k] == 0 && c == 0) break; // Significant part exhausted
int d = Math.Max(0, t[k] - '0') + Math.Max(0, f[k] - '0') + c;
c= d / 10; d = d % 10; f[k] = (char)(d + '0'); // Next carry/digit
}
}
Console.WriteLine(f);
}
Output:
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
6227020800
87178291200
1307674368000
20922789888000
355687428096000
6402373705728000
121645100408832000
2432902008176640000
static string FindFactorial(int n)
{
int[] result = new int[500000];
result[0] = 1;
int resultSize = 1;
for (int x = 2; x <= n; x++)
resultSize = Multiply(x, result, resultSize);
string factorial = "";
for (int i = resultSize - 1; i >= 0; i--)
factorial += result[i].ToString();
return factorial;
}
static int Multiply(int x, int[] result, int resultSize)
{
int carry = 0;
for (int i = 0; i < resultSize; i++)
{
int product = result[i] * x + carry;
result[i] = product % 10;
carry = product / 10;
}
while (carry != 0)
{
result[resultSize] = carry % 10;
carry /= 10;
resultSize++;
}
return resultSize;
}
This will work
This question already has answers here:
How to generate random 5 digit number depend on user summary
(2 answers)
Closed 4 years ago.
i have some problem like this.
user(A) enter 500000 to my application and then i want to generate 50 random 5 digit number and when summary 50 random number need to equal 500000, How to do like i tried already but it's not working this is my code
int balane = 500000;
int nums = 50;
int max = balane / nums;
Random rand = new Random();
int newNum = 0;
int[] ar = new int[nums];
for (int i = 0; i < nums - 1; i++)
{
newNum = rand.Next(max);
ar[i] = newNum;
balane -= newNum;
max = balane / (nums - i - 1);
ar[nums - 1] = balane;
}
int check = 0;
foreach (int x in ar)
{
check += x;
}
the result that i tell you not working because in my array list i have value more than 5 digit but the result equal 500000.
How to solve this issue ? Thank you very much.
This works for me
public static void test(int balance = 500000, int nums = 50, int max_digits = 5)
{
int rest = balance;
var max_value = (int)Math.Pow(10, max_digits) - 1;
var rand = new Random();
int[] ar = new int[nums];
for (int i = 0; i < nums - 1; i++)
{
var max = rest / (nums - i);
if (max > max_value) max = max_value;
var newNum = rand.Next(max);
ar[i] = newNum;
rest -= newNum;
}
while (rest > max_value)
{
var all_values_are_max = true;
for (int i = 0; i < nums - 1; i++)
{
if (ar[i] < max_value)
{
var d = (int)((max_value - ar[i]) / 10.0); // 10% increase
ar[i] += d;
rest -= d;
all_values_are_max = false;
}
}
if (all_values_are_max)
throw new Exception("This is not possible at all!");
}
while (rest < 0)
{
for (int i = 0; i < nums - 1; i++)
{
if (ar[i] > 0)
{
var d = (int)(ar[i] / 20.0); // %5 decrease
ar[i] -= d;
rest += d;
}
}
}
ar[nums - 1] = rest;
int check_sum = 0;
foreach (int x in ar)
{
check_sum += x;
if (x > max_value || x < 0)
MessageBox.Show("wrong value");
}
if (check_sum != balance)
MessageBox.Show("Error: sum is " + check_sum);
MessageBox.Show("ok");
}
For example, test(500000,50) works fine all times, but test(500000, 5) throw an exception, because is not possible
Perhaps try this:
var rnd = new Random();
var numbers = Enumerable.Range(0, 50).Select(x => rnd.Next(500_000)).OrderBy(x => x).ToArray();
numbers = numbers.Skip(1).Zip(numbers, (x1, x0) => x1 - x0).ToArray();
numbers = numbers.Append(500_000 - numbers.Sum()).ToArray();
Console.WriteLine(numbers.Count());
Console.WriteLine(numbers.Sum());
This outputs:
50
500000
This works by generating 50 random numbers between 0 and 499,999 inclusively. It then sorts them ascendingly and then gets the difference between each successive pair. This by definition produces a set of 49 values that almost adds up to 500,000. It's then just a matter of adding the one missing number by doing 500_000 - numbers.Sum().
I need to distribute a remainder of items over a fixed number of days. e.g. say I have 197 items and 75 days to distribute them over. If I display 2 items for 75 days then I have 47 items not displayed. How do I distribute the remaining 47 items over the 75 days evenly so that I will get a sequence like 2,3,3,2,3,3,2,2,3.... i.e. the 3's are evenly distributed over the whole display. This is what I have so far
const double num = (double)197/75;
double temp = num;
var list = new List<int>();
for (var t = 1; t <= days; t++)
{
var intPart = int.Parse(Math.Truncate(temp).ToString());
list.Add(intPart);
var remainder = num - intPart;
temp = num + remainder;
}
but I only end up with 187 items displayed. I'm missing 10.
The original answer that turned out to give suboptimal results in some cases, as noted by AlexD:
int numItems = 197;
int numDays = 75;
var list = new List<int>();
for (int t = 0; t < numDays; t++)
{
int numItemsInDay = ((t+1)*numItems+numDays/2)/numDays - (t*numItems+numDays/2)/numDays;
list.Add(numItemsInDay);
}
The idea is that every item goes into the day defined by the rounded value of itemIndex*numDays/numItems, and you can calculate the number of items in a day directly, without keeping track of previous items.
Another approach.
To spread numItems items among numDays days as evenly as possible, you need to group the days into spans of days with floor(numItems/numDays) items and spans of days with ceil(numItems/numDays) items, spreading the spans as evenly as possible. So the problem can be solved by recursively reducing the number of days to the number of spans.
static List<int> Spread(int numDays, int numItems)
{
List<int> result = new List<int>();
if (numDays <= 1)
{
if (numDays == 1)
result.Add(numItems);
return result;
}
int numItemsInDayLower = numItems/numDays;
int numItemsInDayHigher = numItemsInDayLower+1;
int numDaysHigher = numItems - numItemsInDayLower * numDays;
int numDaysLower = numDays-numDaysHigher;
int numSpansLower = numDaysLower > numDaysHigher ? numDaysHigher + 1 : numDaysLower;
int numSpansHigher = numDaysHigher > numDaysLower ? numDaysLower + 1 : numDaysHigher;
bool isStartingFromSpanLower = numDaysLower > numDaysHigher;
List<int> spanLehgthsLower = Spread(numSpansLower, numDaysLower);
List<int> spanLehgthsHigher = Spread(numSpansHigher, numDaysHigher);
for (int iSpan = 0; iSpan < spanLehgthsLower.Count + spanLehgthsHigher.Count; iSpan++)
{
if ((iSpan % 2 == 0) == isStartingFromSpanLower)
{
for (int i = 0; i < spanLehgthsLower[iSpan/2]; i++)
result.Add(numItemsInDayLower);
}
else
{
for (int i = 0; i < spanLehgthsHigher[iSpan/2]; i++)
result.Add(numItemsInDayHigher);
}
}
return result;
}
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;
}
}
I should create two new numbers from a one, the first group will contain digits which are divisible by 2 and the other group will contain the others.
int checkCount = 94321, num1 = 94321, count2 = 0, countRest = 0;
while (checkCount > 0)
{
if (checkCount % 2 == 0)
count2++;
else
countRest++;
checkCount /= 10;
}
int[] a = new int[count2];
int[] b = new int[countRest];
int k2 = 0, kRest = 0;
for (int j = 0; j < a.Length + b.Length; j++)
{
if (num1 % 2 == 0)
{
a[k2] = num1 % 10;
k2++;
}
else
{
b[kRest] = num1 % 10;
kRest++;
}
num1 /= 10;
}
I created two arrays with the numbers I should use, now how can I build two INT varabile when each one contains all of the numbers together from the array?
Example:
If I have this number - 12345 so
var = 24, other var = 135
If you have another solution without arrays I think it will be better.
Thank you.
Why not just:
int decimalMaskA = 1;
int decimalMaskB = 1;
while (checkCount > 0)
{
if (checkCount % 2 == 0)
{
count2 = count2 + (checkCount % 10)*decimalMaskA;
decimalMaskA *= 10;
}
else
{
countRest = countRest + (checkCount % 10)*decimalMaskB;
decimalMaskB *= 10;
}
checkCount /= 10;
}
count2 and countRest will contain those numbers (135 and 24) instead of counts.
This splits number 12345 to numbers 135 and 24.
int checkCount = 12345;
int even = 0;
int odd = 0;
int reverseEven = 0;
int reverseOdd = 0;
while (checkCount > 0) {
int current = checkCount % 10;
if (current % 2 == 0) {
reverseEven = 10 * reverseEven + current;
} else {
reverseOdd = 10 * reverseOdd + current;
}
checkCount /= 10;
}
while (reverseEven > 0) {
even = 10 * even + reverseEven % 10;
reverseEven /= 10;
}
while (reverseOdd > 0) {
odd = 10 * odd + reverseOdd % 10;
reverseOdd /= 10;
}
Console.WriteLine("even: {0}", even);
Console.WriteLine("odd: {0}", odd);
If I understand what you're looking for this will do the trick:
//Setup a sample array
int[] a = new int[2];
a[0] = 2;
a[1] = 4;
//Convert each item to a string, convert that to a string array, join the strings and turn into an int
int output = int.Parse(String.Join("", a.Select(s => s.ToString()).ToArray()));
This works for me:
int number = 12345;
string result1 = "";
string result2 = "";
string numberString = number.ToString();
for (int i = 0; i < numberString.Length; i++ )
{
if (numberString[i] % 2 == 0)
{
result1 = result1 + numberString[i];
}
else
{
result2 = result2 + numberString[i];
}
}
int evenNumbers = int.Parse(result1);
int oddNumbers = int.Parse(result2);
How can I build two INT varabile
when each one contains all of the
numbers together from the array?
I can't say for sure, but I think you're asking how to assemble a number given each of its digits in decreasing order of significance.
To 'append' a digit to a number, you can multiply the number by 10 and then add the digit to that. To create the 'assembled' number, you can perform this operation for each digit in the array,
int[] digits = ...
int num = digits.Aggregate(0, (numSoFar, digit) => 10 * numSoFar + digit);
As a loop, this would look like:
int num = 0;
foreach(int digit in digits)
{
num = 10 * num + digit;
}
Try this with LINQ,
int num = 92345;
string strNum = Convert.ToString(num);
var divisibleby2 = from c in strNum
where int.Parse(c.ToString()) % 2 == 0
select c.ToString();
var notDivisibleby2 = from c in strNum
where int.Parse(c.ToString()) % 2 != 0
select c.ToString();
int int_divisibleby2num = int.Parse(String.Join("", divisibleby2.ToArray()));
int int_Notdivisibleby2num = int.Parse(String.Join("", notDivisibleby2.ToArray()));
Every programmer should write wacky code at least once a day:
int checkCount = 12345, numEven, numOdd;
Boolean result;
result = int.TryParse(checkCount.ToString().Replace("0", "").Replace("2", "").Replace("4", "").Replace("6", "").Replace("8", ""), out numOdd);
result = int.TryParse(checkCount.ToString().Replace("1", "").Replace("3", "").Replace("5", "").Replace("7", "").Replace("9", ""), out numEven);
Another solution could be...
var num1 = 94321;
var oddFinal = 0;
var evenFinal = 0;
var odd = new List<int>();
var even = new List<int>();
while( num1>0 )
{
if( num1 % 2 == 0 )
odd.Add( num1 % 10 );
else
even.Add( num1 % 10 );
num1 = num1 / 10;
}
for (int i = 0; i < odd.Count; i++)
{
oddFinal += odd[i] * (int) Math.Pow(10,i);
}
for (int i = 0; i < even.Count; i++)
{
evenFinal += even[i] * (int) Math.Pow(10,i);
}