Remove the last element in a queue - algorithm

I need to remove the last element of a queue.
The only operations I may use are
Peek() - get the first element without removing it
Enqueue(element) - Insert an element to the back of the queue
Dequeue() - Remove the first element
IsEmpty() - true or false whether the queue is empty.
And I can't use arrays or queues, and the number of elements is not available.
I thought of some solutions, but each time I get stuck, since I don't know how to tell if the current element is the last element.

Justin Beal's solution is the more straight forward. But I think it can be done in place, without creating another queue.
object RemoveLast(Queue q) {
object first = q.Peek();
object current = null;
while (true) {
current = q.Dequeue();
if (q.Peek() == first) {
break;
}
q.Enqueue(current);
}
return current;
}

each time I get stuck since I don't know how to tell if the current element is the last element.
Good. Since you don't know of the "current" element is last, you do know of the "previous" element was last.
So, by saving the previous element, you should be able to handle this.

Something like this will work:
public Queue removeLast(Queue queue1){
Queue queue2 = new Queue();
while(!queue1.isEmpty()){
Object o = queue1.dequeue();
if(!queue1.isEmpty()){
queue2.enqueue(o);
}
}
return queue2;
}

I had the same requirement so have created an extension method that others may use if their google reached here.
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// Extensions for <see cref="System.Collections.Generic.Queue{T}"/>.
/// </summary>
public static class QueueExtensionsStatic
{
/// <summary>
/// Removes the last item from the <see cref="System.Collections.Generic.Queue{T}"/>.
/// </summary>
/// <typeparam name="T">Type of object in <see cref="System.Collections.Generic.Queue{T}"/>.</typeparam>
/// <param name="q">Instance of <see cref="System.Collections.Generic.Queue{T}"/> to remove item from.</param>
/// <returns>Item removed from the <see cref="System.Collections.Generic.Queue{T}"/>.</returns>
public static T Pop<T>(this Queue<T> q)
{
for (var i = 1; i < q.Count; i++)
q.Enqueue(q.Dequeue());
return q.Dequeue();
}
/// <summary>
/// Removes the last <see cref="quantity"/> item(s) from the <see cref="System.Collections.Generic.Queue{T}"/>.
/// </summary>
/// <typeparam name="T">Type of object in <see cref="System.Collections.Generic.Queue{T}"/>.</typeparam>
/// <param name="q">Instance of <see cref="System.Collections.Generic.Queue{T}"/> to remove item from.</param>
/// <param name="quantity">Number of items to pop off the end of the <see cref="System.Collections.Generic.Queue{T}"/>.</param>
/// <returns>Item removed from the <see cref="System.Collections.Generic.Queue{T}"/>.</returns>
public static IEnumerable<T> Pop<T>(this Queue<T> q, int quantity)
{
for (var i = quantity; i < q.Count; i++)
q.Enqueue(q.Dequeue());
var poppedItems = new List<T>(quantity);
for (int i = 0; i < quantity; i++)
poppedItems.Add(q.Dequeue());
return poppedItems;
}
/// <summary>
/// Adds an item(<see cref="T"/>) to the start of the <see cref="System.Collections.Generic.Queue{T}"/>.
/// </summary>
/// <typeparam name="T">Type of object in <see cref="System.Collections.Generic.Queue{T}"/>.</typeparam>
/// <param name="q">Instance of <see cref="System.Collections.Generic.Queue{T}"/> to remove item from.</param>
public static void Push<T>(this Queue<T> q, T item)
{
q.Enqueue(item);
for (var i = 1; i < q.Count; i++)
q.Enqueue(q.Dequeue());
}
/// <summary>
/// Adds items(<see cref="T"/>) to the start of the <see cref="System.Collections.Generic.Queue{T}"/>.
/// </summary>
/// <typeparam name="T">Type of object in <see cref="System.Collections.Generic.Queue{T}"/>.</typeparam>
/// <param name="q">Instance of <see cref="System.Collections.Generic.Queue{T}"/> to remove item from.</param>
/// <param name="items">List of items(<see cref="T"/>) to add to the <see cref="System.Collections.Generic.Queue{T}"/>.</param>
public static void Push<T>(this Queue<T> q, IEnumerable<T> items)
{
if (items == null || !items.Any()) return;
foreach (var item in items)
q.Enqueue(item);
for (var i = items.Count(); i < q.Count; i++)
q.Enqueue(q.Dequeue());
}
}

I faced the same problem a couple days ago while implementing a similar requirement for my assignment. The simplest method to this problem i believe is looping through the queue and pushing the 'front' element to the back of the queue and 'pop' it , but when you reach the last element in the queue just 'pop' it and don't 'push' it.

I went through the solution provided by Trinidad, which is the most voted answer so far. I guess this solution works perfectly only if the first element/object in the Queue is unique. If any duplicate of the first element/object is encountered, it fails to give the correct element as the last element.

Related

One controller's actions not appearing in help docs

I have an MVC Web API project which is all working fine, but for some reason the entries in the help docs for just one of the controllers does not appear.
This was all fine until just recently, unfortunately though I don't know at what point it disappeared but it definitely used to be there.
The XML comments all look ok.
The XmlDocument.xml file looks correct.
Is there a way to specify which controllers and methods feature in the help docs?
How can I make sure the actions for this controller appear?
In case it helps, this is a snip with the first action:
public class UserController : ApiController
{
/// <summary>
/// Get details of a user or all users, including accounts and group memberships
/// </summary>
/// <param name="username">The name of the user, if a single result is required</param>
/// <param name="account">The account id, if multiple results are required</param>
/// <param name="offset">The first row to return</param>
/// <param name="limit">The maximum number of rows to return</param>
/// <param name="sortby">The column to sort by, if required</param>
/// <param name="order">The sort order; asc[ending] (default) or desc[ending]</param>
/// <returns>Response structure including status and error message (if appropriate), as well as User structure including account and group details</returns>
[Route("user")]
[CombinedAuthentication(AuthLevel = "2")]
[HttpGet]
[AcceptVerbs("GET")]
public UserGetResponse Get(string username = "", int account = 0, int offset = 0, int limit = 0, string sortby = "", string order = "")
{
if (!string.IsNullOrEmpty(username))
{
return new UserGetResponse(username);
}
else
{
return new UserGetResponse(account, offset, limit, sortby, order);
}
}
}
This bit stops the help docs entry being generated:
[AcceptVerbs("GET")]
I removed that and all was fine!

Visual Studio: Doc Comments that get updated when renaming classes/fields/methods

I have a class (written in C#) with some documentation comments:
/// <summary>
/// Abstract class defining a tolerance-based method for Equals.
/// Tolerance must be defined in a derived class like this:
/// <code>class MyPrec : Precision { private MyPrec() : base(42) {} }</code>
/// (This subclass will have a tolerance of 42.)
/// </summary>
public abstract class Precision
{
protected readonly double TOL;
protected Precision(double tol)
{
TOL = tol;
}
/// <summary>
/// Checks if two doubles are equal up to numerical tolerance given by TOL.
/// </summary>
/// <param name="left">First double.</param>
/// <param name="right">Second double.</param>
/// <returns>True if the absolute value of the difference is at most TOL,
/// false otherwise.</returns>
public bool Equals(double left, double right)
{
return Math.Abs(left - right) <= TOL;
}
/// <summary>
/// Not Equals.
/// </summary>
public bool NotEquals(double left, double right)
{
return !Equals(left, right);
}
}
If I rename the parameter left in the Equals method via Visual Studio's renaming feature, it automatically gets renamed in the documentation comment, too. But it seems that this only works for immediate parameters.
How do I write the documentation comments such that the following words are also updated by Visual Studio when renaming the corresponding class/field/method?
Precision in the code example of the summary comment of the class Precision
/// <code>class MyPrec : Precision { private MyPrec() : base(42) {} }</code>
TOL in the return comment of the method Equals
/// <returns>True if the absolute value of the difference is at most TOL,
Equals in the summary comment of NotEquals
/// Not Equals.
I'm using Visual Studio 2015.
I already tried
/// <returns>True if the absolute value of the difference is at most <paramref name="TOL"/>,
but it does not work. It is no input paramter after all.
Precision, I think this is not possible. The comment inside the <code> tag is a free text.
For TOL and Equals, this is simple. Use the <see> tag when you refer to another code member in your comments. Renaming will be applied to such elements. In your case the comment will be:
/// <returns>True if the absolute value of the difference is at most <see cref="TOL"/>,
and
/// Not <see cref="Equals"/>.

List event receiver to record date, when the workflow status on the item has been updated??

Here is the code I have to record the date when the workflow status on an item has been updated/changed. I created accustom column named Completed Date as a Date type in the list to display the date.
The workflow deploys fine but does not render any data under the Completed Date Column. Am I missing something?
namespace WorkflowDateRecorder.EventReceiver1
{
/// <summary>
/// List Item Events
/// </summary>
public class EventReceiver1 : SPItemEventReceiver
{
/// <summary>
/// An item is being updated.
/// </summary>
public override void ItemUpdating(SPItemEventProperties properties)
{
base.ItemUpdating(properties);
if (properties.BeforeProperties["Wokflowstatus"] != properties.AfterProperties["Wokflowstatus"])
{
properties.ListItem["Completed Date"] = DateTime.Now;
properties.ListItem.Update();
properties.Web.Update();
}
}
}
}
In ItemUpdating method, you should be setting your new field value using
properties.AfterProperties[Completed_x0020_Date] = newFieldValue;
//AfterProperties and BeforeProperties are using internal names of columns.
Also question is then, if your if statement is ever visited? Cause calling ListItem.Update() most probably would result in recursive call on this event receiver.

Telerik MVC Grid : Create custom FilterDescriptor based on lambda expression

Currently I'm using this code to create a custom filter:
var fName = new FilterDescriptor
{
Member = "Name",
MemberType = typeof(string),
Operator = FilterOperator.Contains,
Value = name
};
Which will be added to the GridCommand like this:
gridCommand.FilterDescriptors.Add(fName);
However, would like to create filters based on Linq lambda expression like:
IQueryable<CD> query = ...
if (!string.IsNullOrWhiteSpace(Artist))
{
query = query.Where(cd => cd.Artist.Contains(Artist));
}
if (!string.IsNullOrWhiteSpace(Name))
{
query = query.Where(cd => cd.Name.Contains(Name));
}
How to do this ?
In the QueryableExtensions.cs file from Telerik, this extension method will do the job:
/// <summary>
/// Filters a sequence of values based on a collection of <see cref="IFilterDescriptor"/>.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="filterDescriptors">The filter descriptors.</param>
/// <returns>
/// An <see cref="IQueryable" /> that contains elements from the input sequence
/// that satisfy the conditions specified by each filter descriptor in <paramref name="filterDescriptors" />.
/// </returns>
public static IQueryable Where(this IQueryable source, IEnumerable<IFilterDescriptor> filterDescriptors) { }
Ok so there isnt much wrong with the way you are doing it currently. Except if you were determined to add as linq expression then use the following example.
var query = from t in query where t.Artist.Contains(Artist) && t.Name.Contains(Name) select t;
If both Artist and Name are empty or null then it will return all anyway.

Cannot get to ObjectTrackingEnabled linq

I have had a problem where it appeared as though the second execution of a stored procedure was being ignored.
The first time I call my stored procedure it found 20 records and extracted information for the date range August 2009. The first line was meter id 233 with a data value 200
I then called the stored procedure and 20 records were also returned. This time meter id 233 had a data value of 300.
Linq is detecting that meterid 233 already exists in the context and so doesnt update
I am sure this is something to do with ObjectTrackingEnabled but this does not seem to be available for me to set to false?
I didnt write the context code so I dont really know how it all works, but I have noticed that it seems to inherit from ObjectDataContext
This was generate using Entity Framework and VS 2008
namespace DataServiceDAL
{
/// <summary>
/// There are no comments for dbChildDataContext in the schema.
/// </summary>
public partial class dbChildDataContext : global::System.Data.Objects.ObjectContext
{
/// <summary>
/// Initializes a new dbChildDataContext object using the connection string found in the 'dbChildDataContext' section of the application configuration file.
/// </summary>
public dbChildDataContext() :
base("name=dbChildDataContext", "dbChildDataContext")
{
this.OnContextCreated();
}
/// <summary>
/// Initialize a new dbChildDataContext object.
/// </summary>
public dbChildDataContext(string connectionString) :
base(connectionString, "dbChildDataContext")
{
this.OnContextCreated();
}
/// <summary>
/// Initialize a new dbChildDataContext object.
/// </summary>
public dbChildDataContext(global::System.Data.EntityClient.EntityConnection connection) :
base(connection, "dbChildDataContext")
{
this.OnContextCreated();
}
partial void OnContextCreated();
..............
}
I use the following linq to extract the data
public static List<MeterTotalConsumpRecord> GetTotalAllTimesConsumption(DateTime dtStart, DateTime dtEnd, EUtilityGroup ug, int nMeterSelectionType, int nCustomerID,
int nUserID, string strSelection, bool bClosedLocations, bool bDisposedLocations)
{
dbChildDataContext db = DBManager.ChildDataConext(nCustomerID);
var tbl = from t in db.GetTotalConsumptionByMeter(dtStart, dtEnd, (int) ug, nMeterSelectionType, nCustomerID, nUserID, strSelection, bClosedLocations, bDisposedLocations, 1)
select t;
return tbl.ToList();
}
I need a way of clearing this cache out so that the objects are updated properly or I need a way of refreshing the objects
Can anyone help?
Cheers
Paul
We recommend you to refresh objects using MergeOption.
Here is a simple example:
var query = from d in context.Depts
where d.Deptno < 50
select d;
(query as ObjectQuery).MergeOption = MergeOption.OverwriteChanges;

Resources