Next Bigger Than - c#

Implement the NextBiggerThan method that returns the nearest largest integer consisting of the digits of the given positive integer number and null if no such number exists. The method should return -1, if there is no nearest largest number.
Use iteration and selection statements. Extract digits using the remainder operator %. Don't use strings, collections or arrays.
At first, I thought it would be enough to swap the last 2 digits of the number. But now I see that it is crucial to use selection and iteration. Unfortunately, I have no clue how to correctly implement them here.
using System.Collections.Generic;
using System;
namespace NextBiggerTask
{
public static class NumberExtension
{
/// <summary>
/// Finds the nearest largest integer consisting of the digits of the given positive integer number; return -1 if no such number exists.
/// </summary>
/// <param name="number">Source number.</param>
/// <returns>
/// The nearest largest integer consisting of the digits of the given positive integer; return -1 if no such number exists.
/// </returns>
/// <exception cref="ArgumentException">Thrown when source number is less than 0.</exception>
public static int NextBiggerThan(int number)
{
int lastdigit = number % 10;
int lastdigits = number % 100;
int prelastdigit = (lastdigits - lastdigit) / 10;
int nearestnumber = number - lastdigits;
nearestnumber += 10 * lastdigit + prelastdigit;
return nearestnumber;
}
}
}

Let D be a list of the digits, in order, of number.
Let i be the smallest value such that D[i..] is non-increasing. (If i is 0, then there is no next value.)
Let j be index of the smallest value in D[i..] that is larger than D[i-1]
Then your answer is D[..i-2]+D[j]+sorted_ascending(D[i..] with D[j] replaced by D[i-1])
Example:
number = 114232, so D=[1,1,4,2,3,2]
i is 4 (for [3,2])
j is also 4 (for the 3)
So the result is [1,1,4] + [3] + [2,2]

Related

Program to determine total stops taken by elevator

I was asked a question to write a optimal program that would determine the total number of stops a elevator has taken to serve X number of people. Question description is as below.
There is a elevator in a building with M floors, this elevator can take a max of X people at a time or max of total weight Y. Given that a set of people has arrived and their weight and the floor they need to stop given how many stops has the elevator taken to serve all the people. Consider elevator serves in the first come first serve basis.
E.g. Let Array A be the weight of people to be considered
A[] = {60, 80, 40 }
Let Array B be the floors where person needs to be dropped respectively
B[] = {2, 3, 5}
Total building floors be 5,max allowed person in elevator be 2 at a time with max weight capacity being 200
For this example the elevator would take total of 5 stops floors ground, 2, 3,ground, 5 , ground
What would be the optimal code for this?
One of my solution is as below. Is there any other better solutions?
class Solution
{
/// <summary>
/// Return total stops used
/// </summary>
/// <param name="A">weight of people</param>
/// <param name="B">floors they need to get down</param>
/// <param name="M">total floors in the building</param>
/// <param name="X">Max people to carry at a time</param>
/// <param name="Y">max weight to carry at a time</param>
/// <returns></returns>
public int solution(int[] A, int[] B, int M, int X, int Y)
{
// write your code in C# 6.0 with .NET 4.5 (Mono)
int totalStops = 0;
long totalWeightPerRound = 0;
int maxPersonsCount = 0;
List<int> lstFloors = new List<int>();
int currPerson = 0;
bool startLift = false;
while (currPerson < A.Length)
{
if ((totalWeightPerRound + A[currPerson]) <= Y && (maxPersonsCount+1) <= X)
{
totalWeightPerRound += A[currPerson];
maxPersonsCount++;
lstFloors.Add(B[currPerson]);
if (currPerson == A.Length - 1)
startLift = true;
currPerson++;
}
else
{
startLift = true;
}
if (startLift)
{
totalStops += lstFloors.Distinct().Count() + 1;
lstFloors.Clear();
maxPersonsCount = 0;
totalWeightPerRound = 0;
startLift = false;
}
}
return totalStops;
}
}
Maybe a little off topic, but as someone said above, it`s a math not a programming question. To be on the safe side, you should construct a functional describing the cost function you want to minimize, add constraints to include boundary conditions and finally calculate the variation to get the extremum.
Putting it another way, it is a non trivial mathematical task and you should REALLY concentrate on getting the math right before even trying to write a line of code. To optimize means to get the optimal solution, not just some solution ;)

Converting / Rounding a number to the closest match within a range where they all offset by 30 by getting its upperbound and lowerbound values?

First of all, I'm not really sure if I have framed my question correctly, but what I'm looking for can be better explained by looking at the below visual representation:
I have a method which returns an int within the range of 0 and 360.
Now, for further manipulation, I would like to round? or get the closest match from the numbers which are offset by 30. So how can I achieve this. Also, is there a specific term for the function that I'm looking for?
You may also edit the question if you think it can be written better.
Best Regards,
Navik.
This should work for any list where the items are an equal distance apart (i.e. 30, 60, 90).
EDIT
I've updated the code to use AlexD's elegant solution so that it will work with lists of any 'step' value, and with any starting (or ending) value (i.e. it could start with a negative number, like: -20, -15, -10, -5, 0, 5, 10, 15, 20):
/// <summary>
/// Gets the value of the item in the list of
/// numbers that is closest to the given number
/// </summary>
/// <param name="number">Any number</param>
/// <param name="numbers">A list of numbers, sorted from lowest to highest,
/// where the difference between each item is the same</param>
/// <returns>The value of the list item closest to the given number</returns>
public static int GetClosestNumber(int number, List<int> numbers)
{
if (numbers == null) throw new ArgumentNullException("numbers");
if (numbers.Count == 0)
throw new
ArgumentException("There are no items to compare against.", "numbers");
if (numbers.Count == 1) return numbers[0]; // Short-circuit for single-item lists
var step = Math.Abs(numbers[1] - numbers[0]);
// Get closest number using a slight modification of AlexD's elegant solution
var closestNumber = (Math.Abs(number) + (step / 2)) / step *
step * (number < 0 ? -1 : 1);
// Ensure numbers is within min/max bounds of the list
return Math.Min(Math.Max(closestNumber, numbers[0]), numbers[numbers.Count - 1]);
}

Most evenly distribute letters of the alphabet across sequence

I'm wondering if there is a sweet way I can do this in LINQ or something but I'm trying to most evenly distribute the letters of the alphabet across X parts where X is a whole number > 0 && <= 26. For example here might be some possible outputs.
X = 1 : 1 partition of 26
X = 2 : 2 partitions of 13
X = 3 : 2
partitions of 9 and one partition of 8
etc....
Ultimately I don't want to have any partitions that didn't end up getting at least one and I'm aiming to have them achieve the most even distribution that the range of difference between partition sizes is as small as posssible.
This is the code I tried orginally:
char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
int pieces = (int)Math.Round((double)alphabet.Count() / numberOfParts);
for (int i = 0; i < numberOfParts.Count; ++i) {
char[] subset = i == numberOfParts.Count - 1 ? alphabet.Skip(i * pieces).ToArray()
: alphabet.Skip(i * pieces).Take(pieces).ToArray();
... // more code following
This seemed to be working fine at first but I realized in testing that there is a problem when X is 10. Based on this logic I'm getting 8 groups of 3 and one group of 2, leaving the 10th group 0 which is no good as I'm going for the most even distribution.
The most ideal distribution for 10 in this case would be 6 groupings of 3 and 4 groupings of 2. Any thoughts on how this might be implemented?
In general, the easiest way to implement the logic is using the modulo operator, %. Get familiar with this operator; it's very useful for the situations where it helps. There are a number of ways to write the actual code to do the distribution of letters, using arrays or not as you wish etc., but this short expression should give you an idea:
"ABCDEFGHIJKLMNOPQRSTUVWXYZ".IndexOf(letter) % partitionCount
This expression gives the zero-based index of the partition in which to deposit an upper-case letter. The string is just shown for convenience, but could be an array or some other way of representing the alphabet. You could loop over the alphabet, using logic similar to the above to choose where to deposit each letter. Up to you would be where to put the logic: inside a loop, in a method, etc.
There's nothing magical about modular arithmetic; it just "wraps around" after the end of the set of usable numbers is reached. A simple context in which we've all encountered this is in division; the % operator is essentially just giving a division remainder. Now that you understand what the % operator is doing, you could easily write your own code to do the same thing, in any language.
Putting this all together, you could write a utility, class or extension method like this one--note the % to calculate the remainder, and that simple integer division discards it:
/// <summary>
/// Returns partition sized which are as close as possible to equal while using the indicated total size available, with any extra distributed to the front
/// </summary>
/// <param name="totalSize">The total number of elements to partition</param>
/// <param name="partitionCount">The number of partitions to size</param>
/// <param name="remainderAtFront">If true, any remainder will be distributed linearly starting at the beginning; if false, backwards from the end</param>
/// <returns>An int[] containing the partition sizes</returns>
public static int[] GetEqualizedPartitionSizes(int totalSize, int partitionCount, bool remainderAtFront = true)
{
if (totalSize < 1)
throw new ArgumentException("Cannot partition a non-positive number (" + totalSize + ")");
else if (partitionCount < 1)
throw new ArgumentException("Invalid partition count (" + partitionCount + ")");
else if (totalSize < partitionCount)
throw new ArgumentException("Cannot partition " + totalSize + " elements into " + partitionCount + " partitions");
int[] partitionSizes = new int[partitionCount];
int basePartitionSize = totalSize / partitionCount;
int remainder = totalSize % partitionCount;
int remainderPartitionSize = basePartitionSize + 1;
int x;
if (remainderAtFront)
{
for (x = 0; x < remainder; x++)
partitionSizes[x] = remainderPartitionSize;
for (x = remainder; x < partitionCount; x++)
partitionSizes[x] = basePartitionSize;
}
else
{
for (x = 0; x < partitionCount - remainder; x++)
partitionSizes[x] = basePartitionSize;
for (x = partitionCount - remainder; x < partitionCount; x++)
partitionSizes[x] = remainderPartitionSize;
}
return partitionSizes;
}
I feel like the simplest way to achieve this is to perform a round robin distribution on each letter. Cycle through each letter of the alphabet and add to it, then repeat. Have a running count that determines what letter you will be putting your item in, then when it hits >26, reset it back to 0!
What I did in one app I had to distribute things in groups was something like this
var numberOfPartitions = GetNumberOfPartitions();
var numberOfElements = GetNumberOfElements();
while (alphabet.Any())
{
var elementsInCurrentPartition = Math.Ceil((double)numberOfPartitions / numberOfElements)
for (int i = 0; i < elementsInCurrentPartition; i++)
{
//fill your partition one element at a time and remove the element from the alphabet
numberOfElements--;
}
numberOfPartitions--;
}
This won't give you the exact result you expected (i.e. ideal result for 10 partitions) but it's pretty close.
p.s. this isn't tested :)
A pseudocode algorithm I have now tested:
Double count = alphabet.Count()
Double exact = count / numberOfParts
Double last = 0.0
Do Until last >= count
Double next = last + exact
ranges.Add alphabet, from:=Round(last), to:=Round(next)
last = next
Loop
ranges.Add can ignore empty ranges :-)
Here is a LinqPad VB.NET implementation of this algorithm.
So a Linq version of this would be something like
Double count = alphabet.Count();
Double exact = count / numberOfParts;
var partitions = Enumerable.Range(0, numberOfParts + 1).Select(n => Round((Double)n * exact));
Here is a LinqPad VB.NET implementation using this Linq query.
(sorry for formatting, mobile)
First, you need something like a batch method:
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int groupSize)
{
var tempSource = source.Select(n => n);
while (tempSource.Any())
{
yield return tempSource.Take(groupSize);
tempSource = tempSource.Skip(groupSize);
}
}
Then, just call it like this:
var result = alphabet.Batch((int)Math.Ceiling(x / 26.0));

Find best case scenario C# [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have the following to solve and I'm not sure how to approach this:
There are parking lots that are adjacent to each other and their placement resembles a straight line. Each parking lot has a value (profit) assigned to it. You can purchase as many lots as you want BUT they have to be adjacent to each other (in a contiguous set).
INPUT (THIS IS GIVEN/WHAT YOU WOULD TYPE IN):
Number of lots: 9
Value for each parking lot: ie: -5, 0, 7, -6, 4, 3, -5, 0, 2
Representation (for easier viewing)
Each box contains profit of a each lot:
OUTPUT:
Should be:
3 6 8
meaning:
3 - start lot #,
6 - ending lot #,
8 - total profit (7 - 6 + 4 + 3)
If there is more than one answer, program should write the one that contains the smallest number of parking lots. If there is still more than one possible answer, your program can write any of them.
Please help. thanks in advance.
EDIT:
I got it working:
/// <summary>
/// The problem 2.
/// </summary>
public class MySuperAwesomeClass
{
#region Constants and Fields
/// <summary>
/// The seq end.
/// </summary>
private static int seqEnd = -1;
/// <summary>
/// The seq start.
/// </summary>
private static int seqStart;
#endregion
// Quadratic maximum contiguous subsequence sum algorithm.
#region Public Methods and Operators
/// <summary>
/// The max sub sum 2.
/// </summary>
/// <param name="a">
/// The a.
/// </param>
/// <returns>
/// The max sub sum 2.
/// </returns>
public static int maxSumSub(int[] a)
{
int maxSum = 0;
for (int i = 0; i < a.Length; i++)
{
int thisSum = 0;
for (int j = i; j < a.Length; j++)
{
thisSum += a[j];
if (thisSum > maxSum)
{
maxSum = thisSum;
seqStart = i;
seqEnd = j;
}
}
}
return maxSum;
}
#endregion
#region Methods
/// <summary>
/// The main.
/// </summary>
private static void Main()
{
Console.WriteLine("Enter N:");
string stringInput = Console.ReadLine();
int[] a = new int[Convert.ToInt16(stringInput)];
Console.WriteLine("Enter profit values:");
for (int i = 0; i < Convert.ToInt16(stringInput); i++)
{
string value = Console.ReadLine();
a[i] = Convert.ToInt16(value);
}
int maxSum = maxSumSub(a);
Console.WriteLine(string.Format("{0} {1} {2}", seqStart, seqEnd, maxSum));
Console.ReadKey();
}
#endregion
}
Except I can't figure out this part:
If there is more than one answer, program should write the one that contains the smallest number of parking lots.
This is the classic Maximum subset sum problem. No code as this is homework, but here is the general solution. I'm sure you can find code online by searching the title if you still get stuck.
Make first/last index variables for the max subset. These will hold the parking spaces of our answer. 3 and 6 respectively in your example.
Make a sum variable for the sum of the max subset. This will hold the sum of our answer. 8 in your example.
Make another set of first/last/sum variables which we will be our "current" variables.
Start at the beginning of the parking spaces. Place the current first and current last variable at the start and update the sum.
Now you're going to loop through each parking space by moving the current last variable and updating the sum.
If the current sum is greater then the max-so-far sum, save all the current variables into the max-so-far variables.
If at any point our current sum dips into the negative or becomes zero, our subset is not helping us get a max anymore, so restart it by moving the current first to where current last is and resetting current sum to zero.
Once we get to the end return the max-so-far variables
Here's a hint for a way you can make the algorithm more efficient: look at how the totals from each end add up. For example, from what you provided, from the left side the totals would be -5, -5, 2, -4, 0, 3, -2, -2, 0, and from the right side they would be 2, 2, -3, 0, 4, -2, 5, 5, 0.

How to use integer RowKeys in Azure Table Storage?

I have consecutively numbered entities that I want to persist with the Azure Table Service, however the type of the RowKey column is problematic.
The number of the entity should be stored in the RowKey column, so I can query entities fast (PK = '..' && RowKey = 5), get newest entities (RowKey > 10) and query a certain set of entities (RowKey > 5 && RowKey < 10).
Since RowKey must be a string, lower-than comparisons are problematic ("100" < "11").
I thought about prepending zeros to the numbers (so that "100" > "011"), but I can't predict the number of entities (and thus the number of zeros).
I know I could just create an integer column, but I would loose the performance advantage of the indexed RowKey column (plus I don't have any other information suitable for RowKey).
Did anyone have this problem before?
I had a similar problem, with the added caveat that I also wanted to support having the RowKey sorted in descending order. In my case I did not care about supporting trillions of possible values because I was correctly using the PartitionKey and also using scoping prefixes when needed to further segment the RowKey (like "scope-id" -> "12-8374").
In the end I settled on an specific implementation of the general approach suggested by enzi. I used a modified version of Base64 encoding, producing a four character string, which supports over 16 million values and can be sorted in ascending or descending order. Here is the code, which has been unit tested but lacks range checking/validation.
/// <summary>
/// Gets the four character string representation of the specified integer id.
/// </summary>
/// <param name="number">The number to convert</param>
/// <param name="ascending">Indicates whether the encoded number will be sorted ascending or descending</param>
/// <returns>The encoded string representation of the number</returns>
public static string NumberToId(int number, bool ascending = true)
{
if (!ascending)
number = 16777215 - number;
return new string(new[] {
SixBitToChar((byte)((number & 16515072) >> 18)),
SixBitToChar((byte)((number & 258048) >> 12)),
SixBitToChar((byte)((number & 4032) >> 6)),
SixBitToChar((byte)(number & 63)) });
}
/// <summary>
/// Gets the numeric identifier represented by the encoded string.
/// </summary>
/// <param name="id">The encoded string to convert</param>
/// <param name="ascending">Indicates whether the encoded number is sorted ascending or descending</param>
/// <returns>The decoded integer id</returns>
public static int IdToNumber(string id, bool ascending = true)
{
var number = ((int)CharToSixBit(id[0]) << 18) | ((int)CharToSixBit(id[1]) << 12) | ((int)CharToSixBit(id[2]) << 6) | (int)CharToSixBit(id[3]);
return ascending ? number : -1 * (number - 16777215);
}
/// <summary>
/// Converts the specified byte (representing 6 bits) to the correct character representation.
/// </summary>
/// <param name="b">The bits to convert</param>
/// <returns>The encoded character value</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
static char SixBitToChar(byte b)
{
if (b == 0)
return '!';
if (b == 1)
return '$';
if (b < 12)
return (char)((int)b - 2 + (int)'0');
if (b < 38)
return (char)((int)b - 12 + (int)'A');
return (char)((int)b - 38 + (int)'a');
}
/// <summary>
/// Coverts the specified encoded character into the corresponding bit representation.
/// </summary>
/// <param name="c">The encoded character to convert</param>
/// <returns>The bit representation of the character</returns>
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
static byte CharToSixBit(char c)
{
if (c == '!')
return 0;
if (c == '$')
return 1;
if (c <= '9')
return (byte)((int)c - (int)'0' + 2);
if (c <= 'Z')
return (byte)((int)c - (int)'A' + 12);
return (byte)((int)c - (int)'a' + 38);
}
You can just pass false to the ascending parameter to ensure the encoded value will sort in the opposite direction. I selected ! and $ to complete the Base64 set since they are valid for RowKey values. This algorithm can be easily amended to support additional characters, though I firmly believe that larger numbers do not make sense for RowKey values as table storage keys must be efficiently segmented. Here are some examples of output:
0 -> !!!! asc & zzzz desc
1000 -> !!Dc asc & zzkL desc
2000 -> !!TE asc & zzUj desc
3000 -> !!is asc & zzF5 desc
4000 -> !!yU asc & zz$T desc
5000 -> !$C6 asc & zylr desc
6000 -> !$Rk asc & zyWD desc
7000 -> !$hM asc & zyGb desc
8000 -> !$x! asc & zy0z desc
9000 -> !0Ac asc & zxnL desc
I found an easy way but the previous solution is more efficient (regarding key length).
Instead of using all alphabets we can use just the numbers and the key is to make the length fixed (0000,0001,0002,.....):
public class ReadingEntity : TableEntity
{
public static string KeyLength = "000000000000000000000";
public ReadingEntity(string partitionId, int keyId)
{
this.PartitionKey = partitionId;
this.RowKey = keyId.ToString(KeyLength); ;
}
public ReadingEntity()
{
}
}
public IList<ReadingEntity> Get(string partitionName,int date,int enddate)
{
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
// Create the CloudTable object that represents the "people" table.
CloudTable table = tableClient.GetTableReference("Record");
// Construct the query operation for all customer entities where PartitionKey="Smith".
TableQuery<ReadingEntity> query = new TableQuery<ReadingEntity>().Where(TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionName),
TableOperators.And,TableQuery.CombineFilters(
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, enddate.ToString(ReadingEntity.KeyLength)), TableOperators.And,
TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThanOrEqual, date.ToString(ReadingEntity.KeyLength)))));
return table.ExecuteQuery(query).ToList();
}
Hope this helps.
you can post-append a guid to an integer. that should help with sorts.
http://blogs.southworks.net/fboerr/2010/04/22/compsition-in-windows-azure-table-storage-choosing-the-row-key-and-simulating-startswith/
I solved this problem by creating a custom RowKey class that wraps around a String and provides an Increment method.
I can now define a range of valid characters (e.g. 0-9 + a-z + A-Z) and "count" within this range (e.g. az9 + 1 = aza, azZ + 1 = aA0). The advantage of this compared to using only numbers is that I have a far greater range of possible keys (62^ninstead of 10^n).
I still have to define the length of the string beforehand and mustn't change it, but now I can store pretty much any number of entities while keeping the string itself much shorter. For example, with 10 digits I can store ~8*10^17 keys and with 20 digits ~7*10^35.
The number of valid characters can of course be increased further to use the number of digits even more effectively, but in my case the above range was sufficient and is still readable enough for debugging purposes.
I hope this answer helps others who run into the same problem.
EDIT: Just as a side note in case anyone wants to implement something similar: You will have to create custom character ranges and can't just count from 0 upwards, because there are illegal characters (e.g. /, \) between the numbers (0-9) and the lowercase letters.
I found a potential solution if you're using Linq to query against Azure Table Storage.
You add something like this to your model for the table...
public int ID
{
get
{
return int.Parse(RowKey);
}
}
And then you can do this in your Linq query...
.Where(e => e.ID > 1 && e.ID < 10);
With this technique you're not actually adding the "ID" column to the table since it has no "set" operation in it.
The one thing I'm unsure about is what's happening behind the scenes exactly. I want to know what the query to Azure Table Storage looks like in its final form, but I'm not sure how to find that out. I haven't been able to find that information when debugging and using quickwatch.
UPDATE
I still haven't figured out what's happening, but I have a strong feeling that this isn't very efficient. I'm thinking the way to go is to create a sortable string as the OP did. Then you can use the RowKey.CompareTo() function in your Linq where clause to filter by a range.

Categories