Merge Sort a Linked List

Question: I was recently brushing up on some fundamentals and found merge sorting a linked list to be a pretty good challenge. If you have a good implementation then show it off here.
Comment: https://stackoverflow.com/a/46319131/359538
Comment: Cross-posting a recursive implementation in the solution here - https://stackoverflow.com/questions/71443824/merge-sort-linkedlist-stackoverflow-error
Answer:
Wonder why it should be big challenge as it is stated here, here is a straightforward implementation in Java with out any "clever tricks".
//The main function
public static Node merge_sort(Node head)
{
    if(head == null || head.next == null)
        return head;

    Node middle = getMiddle(head);      //get the middle of the list
    Node left_head = head;
    Node right_head = middle.next;
    middle.next = null;             //split the list into two halfs

    return merge(merge_sort(left_head), merge_sort(right_head));  //recurse on that
}

//Merge subroutine to merge two sorted lists
public static Node merge(Node a, Node b)
{
    Node dummyHead = new Node();
    for(Node current  = dummyHead; a != null && b != null; current = current.next;)
    {
        if(a.data <= b.data)
        {
            current.next = a;
            a = a.next;
        }
        else
        {
            current.next = b;
            b = b.next;
        }

    }
    dummyHead.next = (a == null) ? b : a;
    return dummyHead.next;
}

//Finding the middle element of the list for splitting
public static Node getMiddle(Node head)
{
    if(head == null)
        return head;

    Node slow = head, fast = head;

    while(fast.next != null && fast.next.next != null)
    {
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow;
}

Comment: [non-web.archive explanation](https://blog.csdn.net/EckoTan/article/details/46219501) in stead of stale link removed in revision 4.
Answer:
A simpler/clearer implementation might be the recursive implementation, from which the NLog(N) execution time is more clear.
typedef struct _aList {
    struct _aList* next;
    struct _aList* prev; // Optional.
    // some data
} aList;

aList* merge_sort_list_recursive(aList *list,int (*compare)(aList *one,aList *two))
{
    // Trivial case.
    if (!list || !list->next)
        return list;

    aList *right = list,
          *temp  = list,
          *last  = list,
          *result = 0,
          *next   = 0,
          *tail   = 0;

    // Find halfway through the list (by running two pointers, one at twice the speed of the other).
    while (temp && temp->next)
    {
        last = right;
        right = right->next;
        temp = temp->next->next;
    }

    // Break the list in two. (prev pointers are broken here, but we fix later)
    last->next = 0;

    // Recurse on the two smaller lists:
    list = merge_sort_list_recursive(list, compare);
    right = merge_sort_list_recursive(right, compare);

    // Merge:
    while (list || right)
    {
        // Take from empty lists, or compare:
        if (!right) {
            next = list;
            list = list->next;
        } else if (!list) {
            next = right;
            right = right->next;
        } else if (compare(list, right) < 0) {
            next = list;
            list = list->next;
        } else {
            next = right;
            right = right->next;
        }
        if (!result) {
            result=next;
        } else {
            tail->next=next;
        }
        next->prev = tail;  // Optional.
        tail = next;
    }
    return result;
}

NB: This has a Log(N) storage requirement for the recursion. Performance should be roughly comparable with the other strategy I posted. There is a potential optimisation here by running the merge loop while (list && right), and simple appending the remaining list (since we don't really care about the end of the lists; knowing that they're merged suffices).
Answer:
Heavily based on the EXCELLENT code from: http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html
Trimmed slightly, and tidied:

typedef struct _aList {
    struct _aList* next;
    struct _aList* prev; // Optional.
       // some data
} aList;

aList *merge_sort_list(aList *list,int (*compare)(aList *one,aList *two))
{
    int listSize=1,numMerges,leftSize,rightSize;
    aList *tail,*left,*right,*next;
    if (!list || !list->next) return list;  // Trivial case

    do { // For each power of two<=list length
        numMerges=0,left=list;tail=list=0; // Start at the start

        while (left) { // Do this list_len/listSize times:
            numMerges++,right=left,leftSize=0,rightSize=listSize;
            // Cut list into two halves (but don't overrun)
            while (right && leftSize<listSize) leftSize++,right=right->next;
            // Run through the lists appending onto what we have so far.
            while (leftSize>0 || (rightSize>0 && right)) {
                // Left empty, take right OR Right empty, take left, OR compare.
                if (!leftSize)                  {next=right;right=right->next;rightSize--;}
                else if (!rightSize || !right)  {next=left;left=left->next;leftSize--;}
                else if (compare(left,right)<0) {next=left;left=left->next;leftSize--;}
                else                            {next=right;right=right->next;rightSize--;}
                // Update pointers to keep track of where we are:
                if (tail) tail->next=next;  else list=next;
                // Sort prev pointer
                next->prev=tail; // Optional.
                tail=next;
            }
            // Right is now AFTER the list we just sorted, so start the next sort there.
            left=right;
        }
        // Terminate the list, double the list-sort size.
        tail->next=0,listSize<<=1;
    } while (numMerges>1); // If we only did one merge, then we just sorted the whole list.
    return list;
}

NB: This is O(NLog(N)) guaranteed, and uses O(1) resources (no recursion, no stack, nothing).
Comment: No surprise. The recursive one uses extra storage to speed things up.
Comment: I thought I'd try this code on my own Linked List.  For some reason it runs slower than the recursive version over an int list of 10 million items.  It took around 6-7 seconds for the recursive version and around 10 for this one?
Answer: One interesting way is to maintain a stack, and only merge if the list on the stack has the same number of elements, and otherwise push the list, until you run out of elements in the incoming list, and then merge up the stack.
Answer: The simplest is from
Gonnet + Baeza Yates Handbook of Algorithms. You call it with the number of sorted elements you want, which recursively gets bisected until it reaches a request for a size one list which you then just peel off the front of the original list. These all get merged up into a full sized sorted list.
[Note that the cool stack-based one in the first post is called the Online Mergesort and it gets the tiniest mention in an exercise in Knuth Vol 3]
Answer: Here's an alternative recursive version.  This does not need to step along the list to split it: we supply a pointer to a head element (which is not part of the sort) and a length, and the recursive function returns a pointer to the end of the sorted list.
element* mergesort(element *head,long lengtho)
{
  long count1=(lengtho/2), count2=(lengtho-count1);
  element *next1,*next2,*tail1,*tail2,*tail;
  if (lengtho<=1) return head->next;  /* Trivial case. */

  tail1 = mergesort(head,count1);
  tail2 = mergesort(tail1,count2);
  tail=head;
  next1 = head->next;
  next2 = tail1->next;
  tail1->next = tail2->next; /* in case this ends up as the tail */
  while (1) {
    if(cmp(next1,next2)<=0) {
      tail->next=next1; tail=next1;
      if(--count1==0) { tail->next=next2; return tail2; }
      next1=next1->next;
    } else {
      tail->next=next2; tail=next2;
      if(--count2==0) { tail->next=next1; return tail1; }
      next2=next2->next;
    }
  }
}

Comment: I came up with essentially the same implementation, [except with pointers-to-pointers instead of dummy nodes](http://pastebin.com/kFbnWZqc), thinking clearly my innovative code must be a quantum leap in computer science. Nothing new under the sun I suppose. Any suggestions for a clean way of speeding up the mostly pre-sorted case?
Answer: I'd been obsessing over optimizing clutter for this algorithm and below is what I've finally arrived at. Lot of other code on Internet and StackOverflow is horribly bad. There are people trying to get middle point of the list, doing recursion, having multiple loops for left over nodes, maintaining counts of ton of things - ALL of which is unnecessary. MergeSort naturally fits to linked list and algorithm can be beautiful and compact but it's not trivial to get to that state.
Below code maintains minimum number of variables and has minimum number of logical steps needed for the algorithm (i.e. without making code unmaintainable/unreadable) as far as I know. However I haven't tried to minimize LOC and kept as much white space as necessary to keep things readable. I've tested this code through fairly rigorous unit tests.
Note that this answer combines few techniques from other answer https://stackoverflow.com/a/3032462/207661. While the code is in C#, it should be trivial to convert in to C++, Java, etc.
SingleListNode<T> SortLinkedList<T>(SingleListNode<T> head) where T : IComparable<T>
{
    int blockSize = 1, blockCount;
    do
    {
        //Maintain two lists pointing to two blocks, left and right
        SingleListNode<T> left = head, right = head, tail = null;
        head = null; //Start a new list
        blockCount = 0;

        //Walk through entire list in blocks of size blockCount
        while (left != null)
        {
            blockCount++;

            //Advance right to start of next block, measure size of left list while doing so
            int leftSize = 0, rightSize = blockSize;
            for (;leftSize < blockSize && right != null; ++leftSize)
                right = right.Next;

            //Merge two list until their individual ends
            bool leftEmpty = leftSize == 0, rightEmpty = rightSize == 0 || right == null;
            while (!leftEmpty || !rightEmpty)
            {
                SingleListNode<T> smaller;
                //Using <= instead of < gives us sort stability
                if (rightEmpty || (!leftEmpty && left.Value.CompareTo(right.Value) <= 0))
                {
                    smaller = left; left = left.Next; --leftSize;
                    leftEmpty = leftSize == 0;
                }
                else
                {
                    smaller = right; right = right.Next; --rightSize;
                    rightEmpty = rightSize == 0 || right == null;
                }

                //Update new list
                if (tail != null)
                    tail.Next = smaller;
                else
                    head = smaller;
                tail = smaller;
            }

            //right now points to next block for left
            left = right;
        }

        //terminate new list, take care of case when input list is null
        if (tail != null)
            tail.Next = null;

        //Lg n iterations
        blockSize <<= 1;

    } while (blockCount > 1);

    return head;
}

Points of interest

There is no special handling for cases like null list of list of 1 etc required. These cases "just works".
Lot of "standard" algorithms texts have two loops to go over leftover elements to handle the case when one list is shorter than other. Above code eliminates need for it.
We make sure sort is stable
The inner while loop which is a hot spot evaluates 3 expressions per iteration on average which I think is minimum one can do.

Update: @ideasman42 has translated above code to C/C++ along with suggestions for fixing comments and bit more improvement. Above code is now up to date with these.
Comment: This is absolutely brilliant ! I converted it to Delphi and it works very nice. Thank you, sir !
Comment: The comments look like they're not updated to match the code. They refer to variables which don't exist in the code `p q & k` which *(I think)* should be `left right & block_size` respectively.
Comment: Made an improved version of this answer: https://gist.github.com/ideasman42/5921b0edfc6aa41a9ce0 1) Use a pointer to the tail (remove 2x conditional checks, reduces code-size). 2) Avoid re-assigning empty values the size doesn't change. 3) Corrected comments.
Comment: Thanks @ideaman42. I've added one improvement in above code. For tail_p, there is no direct C# equivalent so it stays same :(.
Comment: While this is quite good, the version from Mono's eglib performs slightly faster in my tests (optimized C) ~10-20%, See: http://stackoverflow.com/a/18246901/432509
Answer: I decided to test the examples here, and also one more approach, originally written by Jonathan Cunningham in Pop-11. I coded all the approaches in C# and did a comparison with a range of different list sizes. I compared the Mono eglib approach by Raja R Harinath, the C# code by Shital Shah, the Java approach by Jayadev, the recursive and non-recursive versions by David Gamble, the first C code by Ed Wynn (this crashed with my sample dataset, I didn't debug), and Cunningham's version. Full code here: https://gist.github.com/314e572808f29adb0e41.git.
Mono eglib is based on a similar idea to Cunningham's and is of comparable speed, unless the list happens to be sorted already, in which case Cunningham's approach is much much faster (if its partially sorted, the eglib is slightly faster). The eglib code uses a fixed table to hold the merge sort recursion, whereas Cunningham's approach works by using increasing levels of recursion - so it starts out using no recursion, then 1-deep recursion, then 2-deep recursion and so on, according to how many steps are needed to do the sort. I find the Cunningham code a little easier to follow and there is no guessing involved in how big to make the recursion table, so it gets my vote. The other approaches I tried from this page were two or more times slower.
Here is the C# port of the Pop-11 sort:
///
/// Sort a linked list in place. Returns the sorted list.
/// Originally by Jonathan Cunningham in Pop-11, May 1981.
/// Ported to C# by Jon Meyer.
///
public class ListSorter<T> where T : IComparable<T> {
    SingleListNode<T> workNode = new SingleListNode<T>(default(T));
    SingleListNode<T> list;

    ///
    /// Sorts a linked list. Returns the sorted list.
    ///
    public SingleListNode<T> Sort(SingleListNode<T> head) {
        if (head == null) throw new NullReferenceException("head");
        list = head;

        var run = GetRun(); // get first run
        // As we progress, we increase the recursion depth.
        var n = 1;
        while (list != null) {
            var run2 = GetSequence(n);
            run = Merge(run, run2);
            n++;
        }
        return run;
    }

    // Get the longest run of ordered elements from list.
    // The run is returned, and list is updated to point to the
    // first out-of-order element.
    SingleListNode<T> GetRun() {
        var run = list; // the return result is the original list
        var prevNode = list;
        var prevItem = list.Value;

        list = list.Next; // advance to the next item
        while (list != null) {
            var comp = prevItem.CompareTo(list.Value);
            if (comp > 0) {
                // reached end of sequence
                prevNode.Next = null;
                break;
            }
            prevItem = list.Value;
            prevNode = list;
            list = list.Next;
        }
        return run;
    }

    // Generates a sequence of Merge and GetRun() operations.
    // If n is 1, returns GetRun()
    // If n is 2, returns Merge(GetRun(), GetRun())
    // If n is 3, returns Merge(Merge(GetRun(), GetRun()),
    //                          Merge(GetRun(), GetRun()))
    // and so on.
    SingleListNode<T> GetSequence(int n) {
        if (n < 2) {
            return GetRun();
        } else {
            n--;
            var run1 = GetSequence(n);
            if (list == null) return run1;
            var run2 = GetSequence(n);
            return Merge(run1, run2);
        }
    }

    // Given two ordered lists this returns a list that is the
    // result of merging the two lists in-place (modifying the pairs
    // in list1 and list2).
    SingleListNode<T> Merge(SingleListNode<T> list1, SingleListNode<T> list2) {
        // we reuse a single work node to hold the result.
        // Simplifies the number of test cases in the code below.
        var prevNode = workNode;
        while (true) {
            if (list1.Value.CompareTo(list2.Value) <= 0) {
                // list1 goes first
                prevNode.Next = list1;
                prevNode = list1;
                if ((list1 = list1.Next) == null) {
                    // reached end of list1 - join list2 to prevNode
                    prevNode.Next = list2;
                    break;
                }
            } else {        // same but for list2
                prevNode.Next = list2;
                prevNode = list2;
                if ((list2 = list2.Next) == null) {
                    prevNode.Next = list1;
                    break;
                }
            }
        }

        // the result is in the back of the workNode
        return workNode.Next;
    }
}

Comment: The mono eglib method is similar to what I posted in my answer and both are essentially the same as HP / Microsoft STL std::list::sort(). In the mono eglib example, the  "recursion" table is reversed, rank[i] points to a run of length 2 to the power i, except the last entry rank[MAX_RANKS-1] points to a list of unlimited size, and is added to by merging runs of length 2 to the power (MAX_RANK-2). A MAX_RANK of 26 to 32 is more than enough.
Comment: A similar strategy is used in a floating point summation function where an array of partial sums indexed by the exponent of a floating point number is used to hold the partial sums, so that only values with identical exponents are added, until it's time to return the full sum by adding up the values in the array from smallest to largest. I'm not sure which was invented first, the summation function or the linked list merge sort.
Answer:
Here is my implementation of Knuth's "List merge sort" (Algorithm 5.2.4L from Vol.3 of TAOCP, 2nd ed.).  I'll add some comments at the end, but here's a summary:
On random input, it runs a bit faster than Simon Tatham's code (see Dave Gamble's non-recursive answer, with a link) but a bit slower than Dave Gamble's recursive code.  It's harder to understand than either.  At least in my implementation, it requires each element to have TWO pointers to elements.  (An alternative would be one pointer and a boolean flag.)  So, it's probably not a useful approach.  However, one distinctive point is that it runs very fast if the input has long stretches that are already sorted.
element *knuthsort(element *list)
{ /* This is my attempt at implementing Knuth's Algorithm 5.2.4L "List merge sort"
     from Vol.3 of TAOCP, 2nd ed. */
  element *p, *pnext, *q, *qnext, head1, head2, *s, *t;
  if(!list) return NULL;

L1: /* This is the clever L1 from exercise 12, p.167, solution p.647. */
  head1.next=list;
  t=&head2;
  for(p=list, pnext=p->next; pnext; p=pnext, pnext=p->next) {
    if( cmp(p,pnext) > 0 ) { t->next=NULL; t->spare=pnext; t=p; }
  }
  t->next=NULL; t->spare=NULL; p->spare=NULL;
  head2.next=head2.spare;

L2: /* begin a new pass: */
  t=&head2;
  q=t->next;
  if(!q) return head1.next;
  s=&head1;
  p=s->next;

L3: /* compare: */
  if( cmp(p,q) > 0 ) goto L6;
L4: /* add p onto the current end, s: */
  if(s->next) s->next=p; else s->spare=p;
  s=p;
  if(p->next) { p=p->next; goto L3; }
  else p=p->spare;
L5: /* complete the sublist by adding q and all its successors: */
  s->next=q; s=t;
  for(qnext=q->next; qnext; q=qnext, qnext=q->next);
  t=q; q=q->spare;
  goto L8;
L6: /* add q onto the current end, s: */
  if(s->next) s->next=q; else s->spare=q;
  s=q;
  if(q->next) { q=q->next; goto L3; }
  else q=q->spare;
L7: /* complete the sublist by adding p and all its successors: */
  s->next=p;
  s=t;
  for(pnext=p->next; pnext; p=pnext, pnext=p->next);
  t=p; p=p->spare;
L8: /* is this end of the pass? */
  if(q) goto L3;
  if(s->next) s->next=p; else s->spare=p;
  t->next=NULL; t->spare=NULL;
  goto L2;
}

Comment: The overall strategy is that we hold two chains of sublists, extending from the two dummy elements head1 and head2.  A sublist is known to be sorted. We make several passes, merging the first sublist from head1 with the first from head2, then the second with the second, and so on. (It is essential that there are equal numbers of sublists, or one extra in head1's chain.)  The newly merged sublists are attached alternately to the first and second chain, in place, stably, and without recursion.
Comment: A significant quirk of this implementation is that it uses a second pointer, e->spare, with each element.  Before the end of a sublist, e->next gives the next element.  At the end, e->next is NULL.  The start of the next sublist (if any) is given by e->spare.  At the end of the sort, the entire list is linked via ->next. Knuth's pseudo-code used array indices instead of pointers, and a negative index announced the end of a sublist (and the absolute value gave the next sublist's start).
Comment: Step L1 arranges the input list into sublists.  A "vanilla" version starts with all sublists of length 1.  The "clever" version here keeps any ordered sequences in the input list. In particular, if the list is sorted on arrival, the sort terminates after (n-1) comparisons.  The clever version therefore gives a massive saving on sorted input, and a lesser saving on input that has some bias towards being sorted.  On random input, the clever version is usually very slightly faster (by a couple of percent) although it uses more comparisons.
Comment: As I said at the start, I'm not expecting anyone to like this as an algorithm (unless you often sort an almost-perfectly-sorted list).  I've added this (to a fairly old post) to save you the trouble and disappointment I've just gone through ;-)
Answer: There's a non-recursive linked-list mergesort in mono eglib.
The basic idea is that the control-loop for the various merges parallels the bitwise-increment of a binary integer.  There are O(n) merges to "insert" n nodes into the merge tree, and the rank of those merges corresponds to the binary digit that gets incremented.  Using this analogy, only O(log n) nodes of the merge-tree need to be materialized into a temporary holding array.
Comment: This is the best implementation I've found so far, made a portable implementation of it (which can be included directly, with addition of optiona `thunk` argument ~ like `qsort_r`). See https://gist.github.com/ideasman42/46d1c7b494baaea799d2#file-linked_list_sort_eglib-c
Answer: Another example of a non-recursive merge sort for linked lists, where the functions are not part of a class. This example code and HP / Microsoft std::list::sort both use the same basic algorithm. A bottom up, non-recursive, merge sort that uses a small (26 to 32) array of pointers to the first nodes of a list, where array[i] is either 0 or points to a list of size 2 to the power i. On my system, Intel 2600K 3.4ghz, it can sort 4 million nodes with 32 bit unsigned integers as data in about 1 second.
typedef struct NODE_{
    struct NODE_ * next;
    uint32_t data;
}NODE;

NODE * MergeLists(NODE *, NODE *); /* prototype */

/* sort a list using array of pointers to list       */
/* aList[i] == NULL or ptr to list with 2^i nodes    */

#define NUMLISTS 32             /* number of lists */
NODE * SortList(NODE *pList)
{
NODE * aList[NUMLISTS];         /* array of lists */
NODE * pNode;
NODE * pNext;
int i;
    if(pList == NULL)           /* check for empty list */
        return NULL;
    for(i = 0; i < NUMLISTS; i++)   /* init array */
        aList[i] = NULL;
    pNode = pList;              /* merge nodes into array */
    while(pNode != NULL){
        pNext = pNode->next;
        pNode->next = NULL;
        for(i = 0; (i < NUMLISTS) && (aList[i] != NULL); i++){
            pNode = MergeLists(aList[i], pNode);
            aList[i] = NULL;
        }
        if(i == NUMLISTS)   /* don't go beyond end of array */
            i--;
        aList[i] = pNode;
        pNode = pNext;
    }
    pNode = NULL;           /* merge array into one list */
    for(i = 0; i < NUMLISTS; i++)
        pNode = MergeLists(aList[i], pNode);
    return pNode;
}

/* merge two already sorted lists                    */
/* compare uses pSrc2 < pSrc1 to follow the STL rule */
/*   of only using < and not <=                      */
NODE * MergeLists(NODE *pSrc1, NODE *pSrc2)
{
NODE *pDst = NULL;          /* destination head ptr */
NODE **ppDst = &pDst;       /* ptr to head or prev->next */
    if(pSrc1 == NULL)
        return pSrc2;
    if(pSrc2 == NULL)
        return pSrc1;
    while(1){
        if(pSrc2->data < pSrc1->data){  /* if src2 < src1 */
            *ppDst = pSrc2;
            pSrc2 = *(ppDst = &(pSrc2->next));
            if(pSrc2 == NULL){
                *ppDst = pSrc1;
                break;
            }
        } else {                        /* src1 <= src2 */
            *ppDst = pSrc1;
            pSrc1 = *(ppDst = &(pSrc1->next));
            if(pSrc1 == NULL){
                *ppDst = pSrc2;
                break;
            }
        }
    }
    return pDst;
}

Visual Studio 2015 changed std::list::sort to be based on iterators instead of lists, and also changed to a top down merge sort, which requires the overhead of scanning. I initially assumed that the switch to top down was needed to work with the iterators, but when it was asked about again, I investigated this and determined that the switch to the slower top down method was not needed, and bottom up could be implemented using the same iterator based logic. The answer in this link explains this and provide a stand-alone example as well as a replacement for VS2019's std::list::sort() in the include file "list".
`std::list<>::sort()` - why the sudden switch to top-down strategy?
Answer: A tested, working C++ version of single linked list, based on the highest voted answer.
singlelinkedlist.h:
#pragma once
#include <stdexcept>
#include <iostream>
#include <initializer_list>
namespace ythlearn{
    template<typename T>
    class Linkedlist{
    public:
        class Node{
        public:
            Node* next;
            T elem;
        };
        Node head;
        int _size;
    public:
        Linkedlist(){
            head.next = nullptr;
            _size = 0;
        }

        Linkedlist(std::initializer_list<T> init_list){
            head.next = nullptr;
            _size = 0;
            for(auto s = init_list.begin(); s!=init_list.end(); s++){
                push_left(*s);
            }
        }

        int size(){
            return _size;
        }

        bool isEmpty(){
            return size() == 0;
        }

        bool isSorted(){
            Node* n_ptr = head.next;
            while(n_ptr->next != nullptr){
                if(n_ptr->elem > n_ptr->next->elem)
                    return false;
                n_ptr = n_ptr->next;
            }
            return true;
        }

        Linkedlist& push_left(T elem){
            Node* n = new Node;
            n->elem = elem;
            n->next = head.next;
            head.next = n;
            ++_size;
            return *this;
        }

        void print(){
                Node* loopPtr = head.next;
                while(loopPtr != nullptr){
                    std::cout << loopPtr->elem << " ";
                    loopPtr = loopPtr->next;
                }
                std::cout << std::endl;
        }

        void call_merge(){
            head.next = merge_sort(head.next);
        }

        Node* merge_sort(Node* n){
            if(n == nullptr || n->next == nullptr)
                return n;
            Node* middle = getMiddle(n);
            Node* left_head = n;
            Node* right_head = middle->next;
            middle->next = nullptr;
            return merge(merge_sort(left_head), merge_sort(right_head));
        }

        Node* getMiddle(Node* n){
            if(n == nullptr)
                return n;
            Node* slow, *fast;
            slow = fast = n;
            while(fast->next != nullptr && fast->next->next != nullptr){
                slow = slow->next;
                fast = fast->next->next;
            }
            return slow;
        }

        Node* merge(Node* a, Node* b){
            Node dummyHead;
            Node* current = &dummyHead;
            while(a != nullptr && b != nullptr){
                if(a->elem elem){
                    current->next = a;
                    a = a->next;
                }else{
                    current->next = b;
                    b = b->next;
                }
                current = current->next;
            }
            current->next = (a == nullptr) ? b : a;
            return dummyHead.next;
        }

        Linkedlist(const Linkedlist&) = delete;
        Linkedlist& operator=(const Linkedlist&) const = delete;
        ~Linkedlist(){
            Node* node_to_delete;
            Node* ptr = head.next;
            while(ptr != nullptr){
                node_to_delete = ptr;
                ptr = ptr->next;
                delete node_to_delete;
            }

        }

    };
}

main.cpp:
#include <iostream>
#include <cassert>
#include "singlelinkedlist.h"
using namespace std;
using namespace ythlearn;

int main(){
    Linkedlist<int> l = {3,6,-5,222,495,-129,0};
    l.print();
    l.call_merge();
    l.print();
    assert(l.isSorted());
    return 0;
}

Comment: Thanks for the modular code. I have one doubt regarding the condition for getting the middle element of the list .
I am using
while(slow ! = nullptr && fast->next != nullptr){
                slow = slow->next;
                fast = fast->next->next;
            }
It is not giving me the proper output. it is crashing. could you please explain the condition that you've use ie:
```while(fast->next != nullptr && fast->next->next != nullptr){
                slow = slow->next;
                fast = fast->next->next;
            }
```
Why are we checking for fast->next->next ? Thanks
Answer: Simplest Java Implementation:

Time Complexity: O(nLogn) n = number of nodes. Each iteration through the linked list doubles the size of the sorted smaller linked lists. For example, after the first iteration, the linked list will be sorted into two halves. After the second iteration, the linked list will be sorted into four halves. It will keep sorting up to the size of the linked list. This will take O(logn) doublings of the small linked lists' sizes to reach the original linked list size. The n in nlogn is there because each iteration of the linked list will take time proportional to the number of nodes in the originial linked list.

class Node {
    int data;
    Node next;
    Node(int d) {
        data = d;
    }
}

class LinkedList {
    Node head;
    public Node mergesort(Node head) {
          if(head == null || head.next == null) return head;
          Node middle = middle(head), middle_next = middle.next;
          middle.next = null;
          Node left = mergesort(head), right = mergesort(middle_next), node = merge(left, right);
          return node;
    }

    public Node merge(Node first, Node second) {
          Node node = null;
          if (first == null) return second;
          else if (second == null) return first;
          else if (first.data <= second.data) {
              node = first;
              node.next = merge(first.next, second);

          } else {
              node = second;
              node.next = merge(first, second.next);
          }
          return node;
    }

    public Node middle(Node head) {
          if (head == null) return head;
          Node second = head, first = head.next;
          while(first != null) {
              first = first.next;
              if (first != null) {
                 second = second.next;
                 first = first.next;
              }
          }
          return second;
    }

}

Comment: Nice explanation of the time complexity.
Answer: This is the entire Piece of code which shows how we can create linklist in java and sort it using Merge sort. I am creating node in MergeNode class and there is another class MergesortLinklist where there is divide and merge logic.
class MergeNode {
    Object value;
    MergeNode next;

    MergeNode(Object val) {
        value = val;
        next = null;

    }

    MergeNode() {
        value = null;
        next = null;

    }

    public Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public MergeNode getNext() {
        return next;
    }

    public void setNext(MergeNode next) {
        this.next = next;
    }

    @Override
    public String toString() {
        return "MergeNode [value=" + value + ", next=" + next + "]";
    }

}

public class MergesortLinkList {
    MergeNode head;
    static int totalnode;

    public MergeNode getHead() {
        return head;
    }

    public void setHead(MergeNode head) {
        this.head = head;
    }

    MergeNode add(int i) {
        // TODO Auto-generated method stub
        if (head == null) {
            head = new MergeNode(i);
            // System.out.println("head value is  "+head);
            return head;

        }
        MergeNode temp = head;

        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = new MergeNode(i);
        return head;

    }

    MergeNode mergesort(MergeNode nl1) {
        // TODO Auto-generated method stub

        if (nl1.next == null) {
            return nl1;
        }

        int counter = 0;

        MergeNode temp = nl1;

        while (temp != null) {
            counter++;
            temp = temp.next;

        }
        System.out.println("total nodes  " + counter);

        int middle = (counter - 1) / 2;

        temp = nl1;
        MergeNode left = nl1, right = nl1;
        int leftindex = 0, rightindex = 0;

        if (middle == leftindex) {
            right = left.next;
        }
        while (leftindex < middle) {

            leftindex++;
            left = left.next;
            right = left.next;
        }

        left.next = null;
        left = nl1;

        System.out.println(left.toString());
        System.out.println(right.toString());

        MergeNode p1 = mergesort(left);
        MergeNode p2 = mergesort(right);

        MergeNode node = merge(p1, p2);

        return node;

    }

    MergeNode merge(MergeNode p1, MergeNode p2) {
        // TODO Auto-generated method stub

        MergeNode L = p1;
        MergeNode R = p2;

        int Lcount = 0, Rcount = 0;

        MergeNode tempnode = null;

        while (L != null && R != null) {

            int val1 = (int) L.value;

            int val2 = (int) R.value;

            if (val1 > val2) {

                if (tempnode == null) {
                    tempnode = new MergeNode(val2);
                    R = R.next;
                } else {

                    MergeNode store = tempnode;

                    while (store.next != null) {
                        store = store.next;
                    }
                    store.next = new MergeNode(val2);

                    R = R.next;
                }

            } else {
                if (tempnode == null) {
                    tempnode = new MergeNode(val1);
                    L = L.next;
                } else {

                    MergeNode store = tempnode;

                    while (store.next != null) {
                        store = store.next;
                    }
                    store.next = new MergeNode(val1);

                    L = L.next;
                }

            }

        }

        MergeNode handle = tempnode;

        while (L != null) {

            while (handle.next != null) {

                handle = handle.next;

            }
            handle.next = L;

            L = null;

        }

        // Copy remaining elements of L[] if any
        while (R != null) {
            while (handle.next != null) {

                handle = handle.next;

            }
            handle.next = R;

            R = null;

        }

        System.out.println("----------------sorted value-----------");
        System.out.println(tempnode.toString());
        return tempnode;
    }

    public static void main(String[] args) {
        MergesortLinkList objsort = new MergesortLinkList();
        MergeNode n1 = objsort.add(9);
        MergeNode n2 = objsort.add(7);
        MergeNode n3 = objsort.add(6);
        MergeNode n4 = objsort.add(87);
        MergeNode n5 = objsort.add(16);
        MergeNode n6 = objsort.add(81);

        MergeNode n7 = objsort.add(21);
        MergeNode n8 = objsort.add(16);

        MergeNode n9 = objsort.add(99);
        MergeNode n10 = objsort.add(31);

        MergeNode val = objsort.mergesort(n1);

        System.out.println("===============sorted values=====================");
        while (val != null) {
            System.out.println(" value is  " + val.value);
            val = val.next;
        }
    }

}

Answer: I don't see any C++ solutions posted here. So, here it goes. Hope it helps someone.
class Solution {
public:
    ListNode *merge(ListNode *left, ListNode *right){
        ListNode *head = NULL, *temp = NULL;
        // Find which one is the head node for the merged list
        if(left->val <= right->val){
            head = left, temp = left;
            left = left->next;
        }
        else{
            head = right, temp = right;
            right = right->next;
        }
        while(left && right){
            if(left->val <= right->val){
                temp->next = left;
                temp = left;
                left = left->next;
            }
            else{
                temp->next = right;
                temp = right;
                right = right->next;
            }
        }
        // If some elements still left in the left or the right list
        if(left)
            temp->next = left;
        if(right)
            temp->next = right;
        return head;
    }

    ListNode* sortList(ListNode* head){
        if(!head || !head->next)
            return head;

        // Find the length of the list
        int length = 0;
        ListNode *temp = head;
        while(temp){
            length++;
            temp = temp->next;
        }
        // Reset temp
        temp = head;
        // Store half of it in left and the other half in right
        // Create two lists and sort them
        ListNode *left = temp, *prev = NULL;
        int i = 0, mid = length / 2;
        // Left list
        while(i < mid){
            prev = temp;
            temp = temp->next;
            i++;
        }
        // The end of the left list should point to NULL
        if(prev)
            prev->next = NULL;
        // Right list
        ListNode  *right = temp;
        // Sort left list
        ListNode *sortedLeft = sortList(left);
        // Sort right list
        ListNode *sortedRight = sortList(right);
        // Merge them
        ListNode *sortedList = merge(sortedLeft, sortedRight);
        return sortedList;
    }
};

Answer: Here is the Java Implementation of Merge Sort on Linked List:

Time Complexity: O(n.logn)
Space Complexity: O(1) - Merge sort implementation on Linked List avoids the O(n) auxiliary storage cost normally associated with the
  algorithm

class Solution
{
    public ListNode mergeSortList(ListNode head)
    {
        if(head == null || head.next == null)
            return head;

        ListNode mid = getMid(head), second_head = mid.next; mid.next = null;

        return merge(mergeSortList(head), mergeSortList(second_head));
    }

    private ListNode merge(ListNode head1, ListNode head2)
    {
        ListNode result = new ListNode(0), current = result;

        while(head1 != null && head2 != null)
        {
            if(head1.val < head2.val)
            {
                current.next = head1;
                head1 = head1.next;
            }
            else
            {
                current.next = head2;
                head2 = head2.next;
            }
            current = current.next;
        }

        if(head1 != null) current.next = head1;
        if(head2 != null) current.next = head2;

        return result.next;
    }

    private ListNode getMid(ListNode head)
    {
        ListNode slow = head, fast = head.next;

        while(fast != null && fast.next != null)
        {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
}

Comment: `while(fast != null && fast.next != null)`, doesn't it cause a infinite recursion for a list that only has 2 elements?
Comment: @Rick the first line of `mergeSortList` checks the same condition and breaks the recursion in that case.
Answer: Hey I know that this is a bit late an answer but got a fast simple one.
The code is in F# but will goes in any language. Since this is an uncommen language of the ML family, I'll give some point to enhance the readability.
F# are nesting done by tabulating. the last line of code in a function (nested part) are the return value. (x, y) is a tuple, x::xs is a list of the head x and tail xs (where xs can be empty), |> take the result of last line an pipe it as argument to the expression right of it (readability enhancing) and last (fun args -> some expression) are a lambda function.
// split the list into a singleton list
let split list = List.map (fun x -> [x]) lst

// takes to list and merge them into a sorted list
let sort lst1 lst2 =
   // nested function to hide accumulator
   let rec s acc pair =
       match pair with
       // empty list case, return the sorted list
       | [], [] -> List.rev acc
       | xs, [] | [], xs ->
          // one empty list case,
          // append the rest of xs onto acc and return the sorted list
          List.fold (fun ys y -> y :: ys) acc xs
          |> List.rev
       // general case
       | x::xs, y::ys ->
          match x < y with
          | true -> // cons x onto the accumulator
              s (x::acc) (xs,y::ys)
          | _ ->
              // cons y onto the accumulator
              s (y::acc) (x::xs,ys)

    s [] (lst1, lst2)

let msort lst =
  let rec merge acc lst =
      match lst with
      | [] ->
          match acc with
          | [] -> [] // empty list case
          | _ -> merge [] acc
      | x :: [] -> // single list case (x is a list)
         match acc with
         | [] -> x // since acc are empty there are only x left, hence x are the sorted list.
         | _ -> merge [] (x::acc) // still need merging.
       | x1 :: x2 :: xs ->
           // merge the lists x1 and x2 and add them to the acummulator. recursiv call
           merge (sort x1 x2 :: acc) xs

   // return part
   split list // expand to singleton list list
   |> merge [] // merge and sort recursively.

It is important to notice that this is fully tail recursive so no possibility of stack overflow, and by first expanding the list to a singleton list list in one go we, lower the constant factor on the worst cost. Since merge are working on list of list, we can recursively merge and sort the inner list until we get to the fix point where all inner list are sorted into one list and then we return that list, hence collapsing from a list list to a list again.
Answer: Here is the solution using Swift Programming Language.
//Main MergeSort Function
func mergeSort(head: Node?) -> Node? {
   guard let head = head else { return nil }
   guard let _ = head.next else { return head }

   let middle = getMiddle(head: head)
   let left = head
   let right = middle.next

   middle.next = nil

   return merge(left: mergeSort(head: left), right: mergeSort(head: right))
}

//Merge Function
func merge(left: Node?, right: Node?) -> Node? {

   guard let left = left, let right = right else { return nil}

   let dummyHead: Node = Node(value: 0)

   var current: Node? = dummyHead
   var currentLeft: Node? = left
   var currentRight: Node? = right

   while currentLeft != nil && currentRight != nil {
       if currentLeft!.value < currentRight!.value {
        current?.next = currentLeft
        currentLeft = currentLeft!.next
       } else {
        current?.next = currentRight
        currentRight = currentRight!.next
       }
       current = current?.next
   }

   if currentLeft != nil {
        current?.next = currentLeft
   }

   if currentRight != nil {
        current?.next = currentRight
   }

   return dummyHead.next!
}

And here are the Node Class & getMiddle Method
class Node {
    //Node Class which takes Integers as value
    var value: Int
    var next: Node?

    init(value: Int) {
        self.value = value
    }
}

func getMiddle(head: Node) -> Node {
    guard let nextNode = head.next else { return head }

    var slow: Node = head
    var fast: Node? = head

    while fast?.next?.next != nil {
        slow = slow.next!
        fast = fast!.next?.next
    }

    return slow
}

Answer: /**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0)
            return null;

        List<Integer> list = new ArrayList<>();

        for(int i = 0; i < lists.length; i++){
            ListNode listNode = lists[i];
            while(listNode != null){
                list.add(listNode.val);
                listNode = listNode.next;
            }
        }
        if(list.size() == 0)
            return null;

        Collections.sort(list);
        ListNode result = new ListNode(list.remove(0));
        list.forEach(v -> doAdd(v, result));
        return result;
    }

    private void doAdd(int val, ListNode node){
        if(node.next == null){
            node.next = new ListNode(val);
            return;
        }
        doAdd(val, node.next);
    }
}

Answer:
public int[] msort(int[] a) {
    if (a.Length > 1) {
        int min = a.Length / 2;
        int max = min;

        int[] b = new int[min];
        int[] c = new int[max]; // dividing main array into two half arrays
        for (int i = 0; i < min; i++) {
            b[i] = a[i];
        }

        for (int i = min; i < min + max; i++) {
            c[i - min] = a[i];
        }

        b = msort(b);
        c = msort(c);

        int x = 0;
        int y = 0;
        int z = 0;

        while (b.Length != y && c.Length != z) {
            if (b[y] < c[z]) {
                a[x] = b[y];
                //r--
                x++;
                y++;
            } else {
                a[x] = c[z];
                x++;
                z++;
            }
        }

        while (b.Length != y) {
            a[x] = b[y];
            x++;
            y++;
        }

        while (c.Length != z) {
            a[x] = c[z];
            x++;
            z++;
        }
    }

    return a;
}

Comment: First of all, your answer is nowhere matching with OP question. Second, not sure, what are your commenting ?

Merge Sort a Linked List


Is it appropriate for a manager to request a filled out background check to be submitted to him

Question: I recently received verbal confirmation of an offer of full-time employment from a company I have been doing contract work for. The first email that was sent to me included a .pdf document including: Employment history, basic personal information(email, phone, etc), Social Security Number, Education history to be filled out for a background check. My managers words where "Fill this out, scan it, and send it to me and the HR manager." My question is: "Why would I send this to my personal manager? is that normal procedure?" every job I have been at previously to this on just used the online background checks like ADP or Workday so this is very odd to me. To be honest I don't even know if I am comfortable enough to fill out the information and mail this form to the HR manager that is a few states away. Any thoughts on this would be appreciated because I don't understand the human resources side of this.
Comment: You're going to have to provide SSN to the company/HR anyway for compensation and taxes.  I understand your reluctance to share SSN with your boss, but if (s)he can't be trusted with your SSN, I feel you probably have much bigger problems headed your way.
Comment: What's on the form?  Name, address, previous employers?  Or something more invasive and personal than that?
Comment: Good point, added in the post
Comment: Which of "Employment history, basic personal information (email, phone, etc), Social Security Number, Education history" don't you want your manager to know? And why not? These are all things that any job applicant would include with their application (except maybe SSN I guess, but that's still a normal type of thing for an employer to know about an employee).
Comment: I don't want my manager to see SSN, I'm very selective about that information as are most people
Comment: If the manager asks for the SSN, then you _do_ have a problem.
Comment: @cdkMoose I think this issue is more about emailing that sort of information. Unless you can encrypt it, NEVER email documentation with PII in it since it is too easily stolen.
Comment: @rhoonah, I was answering the comment above mine in reference to OP not wanting the manager to even see the SSN, in any form
Comment: There is information that only payroll needs to know. Not even the CEO.
Answer: It would be perfectly reasonable to try to contact the HR Manager and explain that you aren't comfortable using email for personal information like your social security number - and ask if you could fax or mail (overnight/certified/etc) the form directly to them instead.
If your issue is that you don't want to fill out all the information requested, for whatever reason, you would also want to discuss that with them. If you don't want to fill out something such as full length of history or past education, etc, it's certainly your right to object - but they would generally be allowed (in the US) so consider this as a failure to comply with the background check and thus you would not be hired. So far the information you mentioned being requested is not exceptional and is typical for a background check, and is legally permissible in the US in every jurisdiction I'm aware of.
Note that many companies are moving to background check services, but so far this is not legally required, so companies are typically allowed to conduct their own or retain the information as they see fit (within broader laws of how they must handle that information). So it's not especially unusual they not use an online service.
If it's a legitimate company you've worked for and thus isn't a scam to steal your personal info, I'd suggest you clarify and restrict your concerns and talk with HR directly if there is some specific concern like using email (which is itself reasonable).
Comment: The only thing less secure than email is a fax. Unless you're certain that it'll be routed to the correct person, a fax is as secure as a letter addressed "to whom it may concern".
Answer: Personally, I never provide Personally Identifiable Information (PII) such as SSN, DOB, etc. to a prospective company until I have an offer in hand. There is no reason to provide that sort of information during an interview process prior to being offered the job. Once you are offered and accept the position, you will then be required to provide it for for payroll, citizenship verification, etc.
I used to be an engineering manager and told my new hires to simply bring the required documentation in on their first day where they filled it out and then we snail mailed (or faxed) it to corporate. If it went via fax, I made sure they were standing by to receive it.
Guard your information jealously to avoid identity theft.
With that being said, there is no reason that your manager needs access to data such as your DOB or SSN so I would not send that information to them but only to HR.
Comment: If you're going to downvote my comment which simply offers a suggestion on how to protect your PII then I'd appreciate an explanation why.


Uses of Ruby on Rails

Question: I am a somewhat experienced rubyist, but I am now starting to do rails development. I know rails is used to make "web applications" but what exactly does that mean? Do you build entire sites with rails or do you build a feature for a website in rails, and integrate it in to an existing website? (I know this question is kind of vague, but any answers to how ROR is used in the creation of websites would be much appreciated).
Answer: Generally speaking, you will build a full site with Rails, though you can integrate it into an existing website, as well. It is designed to provide a top-to-bottom solution for entire websites.
For standalone features or small scripts you just want to expose to the web, you might look at something like Sinatra or Camping.
Answer: What is Ruby on Rails?
Answer: I'm also build some rails applications in that I had entirely use rails to develop my web application. It's quite easy rather than using two or three languages. But when I developed I had to use Javascripts, CSS and Ajax to create more attractively
Answer: For me it's a great framework to build website and minimal knowledge is required although experience and knowledge of ruby gives you an upper hand.
I also feel that rails is good not only to build websites but to manage it.
Also the support community of rails is awesome and  is complemented by guys like Ryan bates with their screen casts.
Also when we build a website using ror, we have the flexibility to concentrate on different features at different times or by different person.
This gets a great modular structure.
So you can design the basic functionality today and tell your colleague to get the views attractive using JS and friends without affecting your functionality.
Also the external support for rails (like gems and plug ins) is awesome and makes life heaven!
I would suggest that it's a great framework and the best feature is that it is a very easy to begin and learn but it always surprises you with new things.
Thus it allows you to learn a lot!
Hope it helps.
Answer: The website/web application distinction is made because there are many Rails apps in existence with no front end or 'website' to speak of. Using Rails, one could serve JSON amongst a cluster of compute nodes for data aggregation, or text to unix sockets for display on terminals. The uses for Rails are only limited by ones imagination, and you could even use Rails for single host interprocess communication if you desired. This might prove effective for a highly skilled rails programmer rather than learn a new tool to achieve similar results.

Uses of Ruby on Rails


Why is it a problem if China starts "dumping" US Treasuries? What does it mean to be dumping?

Question: China has 1.2 trillion dollars worth of us treasuries. Why would it be a problem for them to get rid of all of them? Why would that destabilize the US economy?
Answer: It would increase the total supply of US treasuries available at any point in time, which would require a higher interest rate for the market to clear. Higher interest rates would increase the cost of capital in the US economy, which in most conditions will reduce investment.
However, higher supply would also decrease the exchange rate of the USD, which could be beneficial for exports (which needs to be considered in a context of higher cost of consumer imports and higher cost of production inputs).
"Dumping" would be fine as a descriptive word for many informal contexts, but "dumping" has specific meaning in an international legal context, such as in the WTO, and so regarding the specific question of what it would mean to unload large volumes of US treasuries at the same time, e.g. for the purpose of negatively impacting the US economy, "dumping" would not be the correct term.
It should also be mentioned that China would immediately lose significant financial assets if the 1.2 trillion in treasuries were to lose 100 billion or 200 billion dollars in equivalent value. Considering the relatively large volume of credit extended in the Chinese economy relative to financial assets, this implies a relatively major economic cost to China if it were to make such a move. On the matter of strategic reasons to hold large volumes of US treasuries, the face value argument of the Chinese government is legitimate, if not the complete story: What else should they be holding if not US treasuries?
Answer: If China starts dumping u.s. currencies it simply raises the yield of bonds. It's happened before and is simply part of bond yield fluctuation.
Normally when an institution owns a significant percent of a security and decides to try and reposition itself, it begins to sell the security preferably at some percentage of the daily volume or at a rate that the existing market makers can sustain a given price.
The way Treasuries work are that they are for 100 dollars each and they pay periodic coupons which are interest. So a bonds flat value is determined as 100 plus all the coupon payments it will pay yet.
If investments are typically earning a lot then under normal circumstances because you have to wait to collect the coupon payments, and to get the 100 back at maturity, (up to 30 years) the bond may sell for under 100 or at discount. So if you bought the bond for 90 dollars you get 10 plus all coupons as yield on it, giving the yield. Today's yields range from 2.7 to 3 percent roughly which is the same even though some bonds are discounted, some premium and have different coupons depending on issuance.
Binds are issued at auctions by fed, to primary banks. Bonds are then sold on secondary markets where they very in characteristics but sell and buy at a given yield.
If China floods market the bond yield will go up. This is because there aren't enough buyers to sustain given yield, so 100 dollar bond will have to sell for less or at a discount. This means if you buy the bond for under less you get more if you wait for it to mature, thus the yield goes up.
As far as I'm aware the sale and demand for bonds on the secondary markets are the primary factor in determining yield on bonds. If the yield is driven up on the secondary then when the fed issues new bonds they will bid higher coupons because they could otherwise buy more competitive bonds on secondary than at auction.
Now considering that as far as I'm aware of the bond coupon is the only net faucet of m0 or newly minted currency. It would take up to 30 years for the new credits to be realized however it would have a net result of adding m0 or clean money to the economy mitigating the reliance on m2 which is currency generated from m0 but by banks in the form of loans and tied to interest.
Now considering that banks can not know the deposited, loan terms of everyone else, there is nothing to insure that there is even enough free currency available to pay all outstanding loans and interest, thus defaults and bankruptcy could be simply necessary for it all to account. Additional m0 could lower default rate, and have positive benefits.
Now considering that China and Japan have large supply of m0 generating bonds while U.S. uses much more costly and difficult m2, it seems to me this would not be likely course of events that bonds are dumped. But this last half I admit is a bit speculative.
Answer: Speaking as someone who has dealt with SAFE (China's State Administration of Foreign Exchange) I can confirm that they are extremely market savvy when it comes to market execution. They employ strategies such as political dealer influence, and timed volume execution to maximise their investments.
A "dumping" of US treasuries, i.e. selling them excessively, would easily be recognised by dealers as being different to their modus operandi. The more dealers SAFE used, the higher the risk of the information leaking, and it is probably a reasonably high risk in any case, but more dealers provides access to more liquidity so this would be an optimisation consideration. Even greater excessive selling would create a panic and a completely destabilising environment since the amount of influence China could exert is significant.
Since US treasuries and the cash dollar effectively underpin the entire system of leverage and collateral in finance, when US treasuries are shunned due to declining values (higher yields) and client margins start going up every market would become much more irrational and incredibly more volatile since leveraged positions would have to be liquidated. As a feedback loop more volatility forces higher margins and more irrational stop-loss triggers. In non-linear dynamics this represents movement away from one equilibrium in a chaotic manner to some other equilibrium or worse no equilibrium - just complete destabilisation and financial collapse. It is also completely possible that such an action, which Chinese investment mangers are certainly capable of knowing the consequences of, would be considered a hostile act by the US government and further conflate the situation via worried investors.
I highly suspect, however that if China were ever to engage in such a policy it would not be on a whim. I can almost guarantee that the process would be carefully planned to last years. I would suggest that the optimum way of China reducing their exposure would be to use the process of holding bonds to maturity rather than direct selling in the secondary market, since there is no dealer required. To accelerate the process of bonds rolling to maturity SAFE would likely sell longer bonds and buy shorter dated ones. This is also helpful since it might disguise their true intent with dealers. China would not have to sell their entire holding to have significant impact, either, probably just a fraction. As an example China could slowly engineer their portfolio so that they amass many holding in a particular sector, eg 1-4 years and then over that period of time do not reinvest any of their maturities and sell their dollars as they came due.
As for the exchange rate if China holds a bond to maturity and is repaid in dollars it then has two options; buys more US bonds (!) as a store of asset value (SAFE cannot simply deposit cash US dollars in a bank like you and I) or sell the USD for another currency. This process creates a supply a dollars and so the dollar would weaken, again enhancing the destabilising feedback loop.
Answer: The power of a currency comes from its usage and popularity. The dollar is strong and powerful currency because countries like China hold their state reserves in dollars. By following my statement previously that the power comes from popularity and usage, the problems and downfalls for a currency also come from its abandoning or as you would say - dumping. Abandoning currencies especially from big states that have great economic and influential power like China means distrust in the strength of that currency. In terms of money - distrust means failure of a currency and failure means - currency loses power therefore value. So to put it simply.
Before China dumps the dollar, the exchange rate between the dollar and the euro is (hypotetically) 1 dollar = 1 euro.
After China dumps the dollar, the exchange rate between the dollar and the euro is (hypotetically) 20 dollars = 1 euro.
When you need more units of a currency to buy 1 unit of another one, means that the first one is weak.
I hope this explains something.


Best history of Maxwell and his equations

Question: I've done my B.S. in Electrical Engineering as well as mathematics but I'd like to get a proper, or complete history of Maxwell and the history of his derivation of the equations and the newness of the methods he employed. Freeman Dyson's description of how mathematics parted from physics in the 19th century has me looking into what details he was describing. As always your input is greatly valued.
Comment: A classical, if dated, reference is [Whittaker's History of the Theories of Aether and Electricity](https://archive.org/details/historyoftheorie00whitrich/page/268/mode/2up). Chapter VIII is devoted to Maxwell.
Answer: Just quickly adding some more references for you. The analytical theory of EM starts with Biot and Poisson at the turn of the 19th century. The works by Poisson were particularly influential to George Green, who in turn was influential to Maxwell. Faraday was also critical to Maxwell's conceptions of the electromagnetic field, particularly his first few researches on electricity and magnetism, and the last few (if I recall correctly). They're good reads, and readily available.
I wrote a translation of Poisson's first memoir on electricity, posted on my website here, and Biot's paper is there too. Green's works are available in English online. You could also look into Ampere's writing and contemporary reviews of it. That'll set you up for reading Maxwell, and understanding the views he expresses.
The most direct resource that I personally have experience with would be Simpson's Maxwell on the Electromagnetic Field, which is an annotated walk-through of three of Maxwell's most important papers. It's written for a non-technical audience, but it doesn't shy away from details; it's filled with notes and context and I like it quite a bit.
Then after reading Maxwell's first few papers, you can read his Treatise, which is the master work. You'll learn things about electromagnetism there that they stopped teaching a long time ago, but it's still very valuable. Good luck!
References

Biot, J-B. Sur un problem physique, relatif a l'electricite (1801). Link.

Poisson, S-D. Memoire sur la distribution de l'electricite a la surfaces des corps conducteurs (1812-13). Link.

Green, George. An Essay on the Application of Mathematical Analysis to the Theories of Electricity and Magnetism (1828). Link.

Faraday, Michael. Experimental Researches in Electricity (1831-54). Series I, II, III, IX, XI, XIV, XIX, XXVIII, XXIX.

Assis & Chaib. Ampere's Electrodynamics: Analysis of the Meaning and Evolution of Ampere's Force between Current Elements (2015).

Simpson, Thomas K. Maxwell on the Electromagnetic Field (1997).

Maxwell, J. C. On Faraday's Lines of Force (1855). Transactions of the Cambridge Philosophical Society, Vol X. part I.

Maxwell, J. C. On Physical Lines of Force (1861). Philosophical Magazine, Vol XXI.

Maxwell, J. C. A Dynamical Theory of the Electromagnetic Field (1864). Royal Society Transactions, Vol. CLV.

Maxwell, J. C. A Treatise on Electricity and Magnetism (1873).
Comment: I second the works of Faraday on electromagnetism, they are amazing, and really well-written.
Answer: On my opinion, the best source is Maxwell's book itself, Treatise on electricity and magnetism. But there is also a comprehensive history:

E. Whittaker, A History of the Theories of Aether and Electricity.
Comment: Is it correct that Maxwell originally specified his equations as a collection of 20 differential equations that were later recast in vector form (by Heaviside?) to 4 equations? See: https://ddcolrs.wordpress.com/2018/01/17/maxwells-equations-from-20-to-4/ . So reading Maxwell's original work (although probably fascinating for the development of the theory and equations) would not give the whole history of the equations?
Comment: @Clive Long: Maxwell indeed writes 3 equations for one vector equation, but this makes little difference.
Answer:
Pierre Duhem, The Electric Theories of J. Clerk Maxwell, trans. of 1902 Les théories électriques de J. Clerk Maxwell (2015 re-typset ed.), vol. 314, Boston Studies in the Philosophy and History of Science (Cham: Springer International Publishing, 2015).
Sarkar, Tapan. 2006. History of Wireless. Hoboken, N.J.: Wiley-Interscience.
Comment: Dear Geremia, since you are an administrator on the website https://isidore.co/, you should disclose this affiliation when linking to the webiste in any of your posts (or avoid linking to it if it is not necessary).


Allow registered users of a Wordpress site to create favorites lists

Question: I've been building a Wodrdpress site lately. It's going to have free registration. I want it to have one and only certain feature for registered users. They should be able to create favorites lists. I mean is that they could favorite certain posts with something like a "like button" and view and edit all their favorites on a certain place like a listview. They shouldn't be able to comment, edit, upload or have any other interaction with the posts. I understand that this can by arranged by giving different permissions to the users. Although I have two questions.
1) Can you suggest some practices/plugins to feature a free registration for the users?
2) Can you suggest some practices/plugins so that registered users can create favorites lists as I explained above?
In case you need further info feel free to ask.
Thank you.
Answer: For point 2:
Check out this plugin:
https://favoriteposts.com/
Users are able to add posts and even pages to favorites list.


Comparing type of fields of different layers in Qgis

Question: Is it possible to have two property layer dialogs open at the same time? I would like to see the properties of two layer's fields at the same time.
I need this because when I want to join two layers by a common field I like to check they are of the same type. I am using 2.18.11.
Answer: No, the property dialog is modal (i.e. you can have just one open and you can't do anything else while it is open).
However, when setting the join, you have access to important information about the datatype. 123 for integers, 1.2 for floats, abc for string etc. I don't know whether they agreagate multiple types or not (ex: integer and long)
Comment: It's a pitty and to me, unconfortable, not being able to do anything else till the dialog is closed. But thanks a lot for the straight unswer.
Comment: @Pescariz Agreed... Regardless of the software, I sometimes just take a screenshot of such window and use it later to make comparisons.


Can quadcopters save energy by flying in formation?

Question: If two or more quadcopters are aligned, would the effect of drag due to the lead quadcopter's slipstream lead to measurable energy savings? And if so, how would one determine the optimal distance between the quadcopters?
Comment: `how would one determine the optimal distance` ... experimentally
Answer: My intuition would be no, as the rotor wake will be choppy and downward flowing.
Unlike slipstreaming in ground vehicles which reduces body drag, bird and some aircraft formations rely on the effect of wing-tip vortices to gain lift, hence reducing lift induced drag. Not having wings†, 'copters lack wing-tip vortices, so would not experience this effect, but instead the flow from the rotors will probably cause a following 'copter to lose lift.
†there probably will be vortices shed from the rotors if not ducted, but they will process with the rotor tips so not be in a stable relative position that can be flown through.


ORM Entity Xml Serialization

Question: I am looking for an ORM to use with .net, I need to be able to do full graph serialization to Xml on the entitys the ORM generates. My own research leads me towards using the WCF and the Entity Framework to achieve this, Is this the best option or is there a simpler way ?
Answer: Most O/R mappers have change tracking inside the context/session objects you use to fetch the entities. This gives problems when you pass the entity object over a wire as xml to a client, change it there and send it back: the session/context which fetched the object is long gone by then.
LLBLGen Pro has change tracking in the entities and therefore makes using entities over a wire a breeze. It comes with XML serialization/deserialization of graphs for WCF and also its own binary serialization for remoting (much faster than the default binary formatter, and also much more compact).
Disclaimer: I'm the lead developer of LLBLGen Pro.
Comment: And at least one of the upvotes comes from one of the support team !
Answer: Well, most ORM tools can emit standard POCO .NET classes, and most standard POCO classes lend themselves to serialization quite well. For example, LINQ-to-SQL has support for DataContractSerializer (not XmlSerializer) by setting Serialization Mode to Unidirectional. Entity Framework does the same (I don't think you need to change any settings for EF, though).
For "simpler" - well, what is the complexity? Setting up an Entity Framework (or LINQ-to-SQL) model isn't usually very tricky. Anything specific being problematic?
Note that xml serializers, by default, are tree serializers, not graph serializers. DataContractSerializer can support proper graphs, but you need to enable it (it isn't enabled by default in xml mode, since it produces very odd-looking xml).
You mention WCF; that is a communications technology; you don't mention comms in the question, so it isn't clear what you mean here. Note that "ADO.NET Data Services" is another option here, if you want REST-based data-access, but most ORMs should work OK with WCF. There are alternatives, of course.
Answer: DataSets must be the easiest way to serialize data to XML on the client side (see Using XML in a DataSet). But then it's obviously not an ORM library...
As far as I know, ORM libraries (like NHibernate) usually rely on the use of custom XmlSerializer (or customized WCF serialization), which may be too much work for you (or not...).
And then, full graph serialization to XML is set as a future goal for Salamanca, an open source software factory that includes an ORM library. We're still on early development stages, but any hand is welcome...

ORM Entity Xml Serialization


doubt between Past Continuous and Past Simple

Question: In the book English Grammar In Use by Raymond Murphy they gave the example for Past Continuous - ´Today Helen is wearing a skirt. Yesterday she was wearing trousers´. Please explain to me why it isn´t Past Simple because the action is complete, it had finished.
Comment: Very simple: was wearing is the past of is wearing.
Answer: Very simple: was wearing is the past of is wearing. Also, it means over a period of time in the past.
Of course, you can say: She wore trousers yesterday.
I am studying today.
Yesterday, I was not studying. In fact, I didn't study at all yesterday. I simply haven't studied at all recently.
Continuous forms are for what a person wants to say as an ongoing action. The speaker chooses what tense to use in these cases.
Answer: The action today isn't finished yet and is expected to continue for the rest of the day.
Yesterday she was wearing trousers for the whole day, not just part of it.
Compare:
Today Helen wears a skirt for the photoshoot. Yesterday she wore trousers.
This is for a limited period of time (during the photoshoot) not all day.
However, I would be quite happy to say "Today Helen is wearing a skirt. Yesterday she wore trousers." idiomatically.
Sometimes you have to learn rules first, and then you will learn later that rules are broken.
Comment: Today, Helen *is wearing* a skirt, not wears, usually.


Difference between a Virtual issue and a special issue?

Question: Can someone explain me the significance of Virtual issues, the difference between Virtual and Special issues? Also, under what conditions does a journal propose for a Virtual issue, does it have any impact on the Impact factor of the journal?
Answer: Virtual issues, which are also referred to as "collections" or by other names, are a set of papers that were already published in various issues of a journal and are centered around a single topic. This is usually done to highlight a certain topic or simply to help readers find papers on a topic. This is done on the editorial/website level and that is why it is "virtual" - usually no special content is created for this.
Special issues are issues in which the journal decides in advance about a certain topic, and invites submissions of papers on this topic. Often there is also an invited guest editor for the issue, who is an expert in the field. The final result could actually look similar to a virtual issue (a collection of papers on a single topic), but in a special issue these would be new papers submitted specifically for this issue. Sometimes there will also be some overview piece written by the editor.
Special issues might indeed affect the impact factor of the journal. For example, the journal Bioinformatics sometimes has a special issue in which the papers published are papers that were accepted to ISMB, a major bioinformatics conference. These papers probably get cited on average more than other papers in the journal, so it would increase the impact factor.
Answer: I suspect you might have this closed for being too broad, as each journal will have it's own specific meanings for these things. But, in my experience:
Virtual Issue: An issue of the journal that is, well, virtual. Meaning it's not going to be in the print edition. As Bitwise notes, this is often a collection of papers from other issues, and essentially a curated collection surrounding a topic, rather than new, standalone papers. See: http://www.journalofecology.org/view/0/virtualIssues.html
Special Issue: A special issue is also just that...special in some way. Usually it's organized around a particular theme, may or may not be printed, but is out of step with the regular focus of the journal. Note there are some journals where every issue is a "Special Issue on...". But for many, it's a rare, focused piece that took either targeted submissions or invited papers to cover a specific topic. I'd suggest, in contrast to virtual issues, that special issues are rarely collections of previously published articles.

Also, under what conditions does a journal propose for a Virtual
  issue, does it have any impact on the Impact factor of the journal?

Because someone at the editorial board wanted to do one? As for whether or not it has an impact on the IF of the journal, it will depend on the issue in question. A special issue made up of cutting edge expert reviews, or guidelines from a society, may have an extremely high citation rate, which would help the journal's IF.
Comment: I think virtual issues are actually just a collection of previously published papers - at least I know this is the case in some fields. For example: "Virtual Issues bundle together some of our previously published articles" (from here http://www.methodsinecologyandevolution.org/view/0/virtualIssues.html).
Comment: @Bitwise I've seen it used in other contexts, though in Ecology, it does seem to be focused on collections. And it appears more widely - editing my answer, as it appears the context I've heard it in is actually the rarer of the two.
Comment: Bitwise and Formite, that makes my doubt clear about the Virtual issues however, since these are done on the editorial/website level do you think these papers still account for more citations as they are centered around a particular theme? So by having Virtual issues in a journal a year or two (If these are collection of papers from highly cited authors and published in the last 2 years, as I believe IF is calculated on print publication dates) can increase the citations and thereby increase the IF?
Comment: @Divya Organization around a theme and being included in "The Best Papers on X this Year..." type collections likely improves readership dramatically, and thus citations. Reviews can be cited quickly - I had a review cited 4 times in the year it was published, and 13 times the next year.
Comment: Wow, 13 times cited the next year, thats a good count!!! Yes, I agree with you Formite, reviews can be cited quickly as they are short. Indded, journals that publish only review articles or that publish a special issue of review articles tend to have very high citation rates (and thus higher impact factors) than do journals that publish only feature articles.


Duplicate Meta Descriptions for Paginated Content

Question: How is it in 2019 with duplicate meta-description in case of large overview pages with a lot of pages (pagination).
I researched and found inconsitent guidance to that topic.
Comment: How is what? I'm not sure I understand the question. Could you clarify what kind of information you are looking for?
Answer: You have 2 options:

Write a different title + meta description for each page.
Don't paginate at all, Google loves long pages.

PS: Some might say "noindex, follow" the paginated pages but i think that's a bad idea since 1. You want them to rank and 2. Google said they will start nofollowing pages with noindex.
Comment: I aggree with "don't paginate".    Or if you do, put 100 items on the first page and `noindex` subsequent pages.   Pagination does nothing for SEO (except maybe hurt it) and 98% of users never use it.


Is there a repository of UX Discovery Questions?

Question: I was wondering if there is a site or repository of standard UX questions used in the Discovery phase of Website/Portal/Collaboration site.
Comment: Please add some more detail to your question to get good answers. Are these questions you want to ask clients, stakeholders, business owners, users and/or the engineering team? Also please give more detail about the nature and scope of your project.
Comment: Are you asking for heuristic surveys?
Answer: I can only assume that you are referring to heuristic evaluation questions. Here is a great guide to conducting an evaluation: http://www.uxforthemasses.com/usability-reviews/
Answer: Here's a great list of Heuristic Evaluation Questions from the Society for Technical Communication's Usability and User Experience special interest group. They have some questions that help you evaluate discoverability as well as general usability concerns. None are explicit "is this item discoverable?" questions, but they cover the low-level concerns that make up a discoverable interface such as

Is only (and all) information essential to decision making displayed on the screen?

For more high-level thought about the issue of discoverability consider Scott Berkun's The Myth of Discoverability article, which covers why you can't make everything equally discoverable and how to decide what should be most discoverable.
Answer: Following up on the above this is the ultimate UX repository checklist


How should use of a preprint server be incorporated into the publishing workflow?

Question: I am a biologist and very recently there has been a movement to increase the use of preprints in publishing biological research.  This has generated a lot of discussion about preprints and their merits and has spawned a few servers (e.g., bioRxiv) but I have not gotten a good sense of how I should incorporate the preprint server into my normal publishing workflow.
Comment: What specifically is not clear to you?  What options have you considered?  What considerations are/aren't important to you?  *Why* do you want to use a preprint server?  What are your goals, specifically?  This question is subjective, unclear, open-ended, and does not show much evidence of effort to articulate a well-posed question, so it might not be an ideal fit for this site.
Comment: Why close votes? There are so many question on Academia.SE which are very specific (page-long description of one's situation), very broad or in general "give me a life advice" that don't get down votes. This one is short, clear, important and re-usable.
Answer: Workflow may be different, but the one I am familiar with is:

put preprint on arXiv along with sending it to a journal
after the final version is confirmed, update the arXiv with the newest version of text (with your formatting)
(in case there are serious mistakes or omissions, update arXiv at anytime)

Sometimes version on arXiv is put before the submission to a journal, for example:

there is some work that need to be done before the submission, but we want to have it before a conference we are attending, or a talk at another department (so we can point the preprint to the reader),
we haven't decided yet where or if we want to send it.

And in some cases, arXiv is used instead of a journal, especially if:

the work is not suitable for publication in a journal (e.g. a PhD Thesis, textbook), but we want to disseminate it, preserve it and make it easily citable,
the author prefers it that way (e.g. it is a short note, or the topic is unconventional and the author prefers to avoid struggling with editors).
Answer: The role that pre-prints have in the collective workflow of people in a field depends half on each person's preferences and half on how it gets established as a means of communications. There are no 'right' or 'wrong' workflows for using a pre-print server (though there are wrong ways to use one), and you should use the one that fits you best personally and lets you communicate best with your colleagues.
There is a broad spectrum of reasons you might want to upload a preprint, which are explained in detail in this question. To give a brief summary, you might upload a preprint or postprint

to provide free access to your content to researchers and students in institutions without subscription to the journals you publish in, which is also a way
to help increase the use of your papers by the community, and hence the number of citations;
to establish priority of a result, and particularly as a way to get more widespread credit for having introduced an idea at an early stage;
to open a manuscript up for public comment from your colleagues after you feel it's mostly ready but before you're prepared to set it in (published) stone;
to make it visible to people who browse it often as a way to see new results;
to cite as-yet-unpublished work in some other paper, in a way that referees of the second one can see it;
to fulfil open-access conditions on a grant;

or for many other reasons. Whether these (or others) apply to you will determine how you use the repository. Some of these are personal choices, and may come down to how much you feel you stand to gain from non-institutional readers having access to your work. Some of these are field-dependent, and hinge on there being a significant fraction of the workers in your field that regularly check the repository.
The appropriate time to upload will typically vary on a case-by-case basis. You might upload at an almost-finished stage, at the time of submission to a journal, at time of acceptance, at the time the paper is published, or even six to twelve months after that. Each of these corresponds to some or other of the motivations above.
One thing that's important to keep in mind is that you must have a good idea of prospective journals you'd like to publish in, and of what their preprint policies are, before you upload, as it can rule out certain publication venues if you're not careful. This is again field-dependent; many physics journals take that as standard but biology ones might not.
Answer: I'm compelled to add an answer to this question from the biologist's point of view. arXiv and bioRxiv are extremely important in the field (both wet-lab biology and dry-lab bioinformatics/computational biology) for 3 reasons:

Getting your work out there ASAP (since peer-review can, and often will, take over a year).  As such, if another paper gets published that's very similar to yours in study design, methods, and research, then you have the benefit of the timestamp of arXiv/bioRxiv submission and can claim precedence.  Which brings me to the next point:
From personal experience, I've been in situations where my work was in the middle of peer-review but someone publishes a related paper (in the same subspecialty as me) in an Advanced Access issue of a peer-reviewed journal (e.g., Bioinformatics, Nucleic Acids Research, etc).  Their paper did not include a citation to my bioRxiv work, so I emailed the editor of the respective journal drawing attention to my preprint and timestamp.  The editor sent my query to the authors and all agreed to cite my bioRxiv work in the next edition of the paper (which came out the next month).  If I had not posted my preprint to bioRxiv 6 months beforehand, the situation would have been very different.  Once my paper got accepted, the bioRxiv citation transferred automatically to the journal article.  Hence, I did not lose a citation needlessly.
arXiv/bioRxiv is indispensable if you feel that giving away your work to peer-review might open you up to the "non-public domain", which is slang in our community meaning "opening yourself up to getting scooped."  This is important if you're publishing in a very hot, fast-moving field and/or there is academic funding/grants at stake (think study section at major organizations).  There are many reasons (not all of them noble) for why people volunteer their time to journal editorial boards and/or grant review panels.  I'll leave it at that.


What is the BER for multilevel modulated signal

Question: Assume I want to transmit a low or high symbol which can be BPSK modulated. For ordinary BPSK, bit 0 can be mapped to 1+i0 and bit 1 mapped to -1+i0. In my question, each two bits are BPSK modulated and a level dependent so bit 01 is mapped to 2+0i and bits 00 is mapped to 1+0i. Also bits 10 is mapped to -1+0i and bits 11 is mapped to -2+0i. This is BPSK (not QPSK) signal since there are BPSK demodulator and level detector at the receiver in which each of them output one bit at symbol period.I want to know what demodulation scheme to use in order to detect the symbol level and hence calculating the BER.
Answer: This is not BPSK! BPSK is binary phase shift keying with binary meaning 2 levels. What the OP is describing is Pulse Amplitude Modulation where multiple bits are mapped to multiple levels. In this case there are 4 levels so it would be 4-PAM. (As Dilip points out in the comments that the levels in 4-PAM would typically be equally spaced while here the inner levels are spaced further than the outer levels, complicating the BER computation slightly as detailed below but still PAM regardless).
The demodulation scheme would similar to BPSK demodulation in that you would multiply the received signal with the recovered carrier and low pass filter. Decision would be made on the output by setting decision thresholds half way between each of the levels (assuming equiprobable data) and then the derivation for BER follows similar to BPSK (solving for the tail probabilities under Gaussian distributions if the noise is assumed to be AWGN as is typically assumed, noting the different tail contributions involved since the levels aren't equally distributed as Dilip has pointed out - that said the thresholds at ±1.5 will likely dominate setting the error rate with significantly smaller error contribution from the threshold at 0).

With equiprobable distribution of symbols and AWGN with standard deviation $\sigma$ this would result in the following Symbol Error Rate:
$$\text{SER} = \text{erfc}(0.5/(\sqrt{2}\sigma) + \frac{1}{2}\text{erfc}(1/(\sqrt{2}\sigma) $$
For smaller $\sigma$ values the second term would likely be insignificant. For larger $\sigma$ there would be additional tail contributions from the next adjacent threshold levels which would also significantly complicate the BER computation as detailed below. Thankfully under all practical applications these tails would certainly be insignificant and can be safely ignored.
To go from Symbol Error Rate to Bit Error Rate, consider how many bit errors occur when a symbol error occurs. Because the mapping done by the OP was properly Gray-coded (only one bit change between adjacent symbols), only one bit error would occur with each symbol error.
Comment: @Riva11 If there are 4 amplitude levels in the signal, this is not a BPSK modulated signal.  That said, a BPSK demodulator that multiplies the recieved signal with the carrier and low pass filters will still put out 4 levels, and to demodulate you would set the thresholds as I have indicated. Am I missing something else?
Comment: It is still called PAM not BPSK. PAM need not have equally spaced levels, but under AWGN would have the best BER if done as such. Here is an example of PAM with unequal levels to make up for non-linearity in the modulator. If the modulation is done by changing the amplitude of each pulse only, this is called PAM.
Comment: Thanks Dan, but as i have written they are two separate blocks, one is Bpsk demodulator and one is level detector.
Comment: What OP @Riva11 describes is  _not_ 4-PAM in the usual sense of the word. Standard 4-PAM would use _equally-spaced_ levels $-3, -1, +1, +3$ instead of the $-2, -1, +1, +2$ used in the OP's system. Well, at least the dibits are assigned to the levels in Gray code order. Nonetheless, the first and second bits have _different_ probabilities of error and so the BER calculation is messy too.
Comment: @DilipSarwate Ah yes, good point!
Comment: Yes @DilipSarwate that is what I meant .
Answer: As Dan Boschen has already pointed out, the question has very little to do with BPSK which acronym stands for Binary Phase-Shift Keying; this is a 4-ary system not a binary one, and as stated has very little to do with phase-shift keying either.
This is a baseband 4-ary communication system that uses pulse modulation. At the output of the demodulator, we observe one of $4$ signal levels ($+2, +1, -1,-2$) corrupted by noise which we will assume to be Gaussian with mean $0$ and variance $\sigma^2$. If $b_0b_1$ denotes the two bits being transmitted, then the conditional distribution of $X$, the demodulator output is given by
\begin{align}
X \sim N(+2, \sigma^2) &~~\text{if}~~ b_0b_1 = 01,\\
X \sim N(+1, \sigma^2) &~~\text{if}~~ b_0b_1 = 00,\\
X \sim N(-1, \sigma^2) &~~\text{if}~~ b_0b_1 = 10,\\
X \sim N(-2, \sigma^2) &~~\text{if}~~ b_0b_1 = 11.
\end{align}
The demodulator output is mapped to the nearest signal level and the decoded bits $\hat{b}_0\hat{b}_1$ are those corresponding to this signal level. That is,
\begin{align}\text{If}~ X\in (1.5,\infty), &~\hat{b}_0\hat{b}_1 = 01,\\
\text{If}~ X\in (0, 1.5], &~\hat{b}_0\hat{b}_1 = 00,\\
\text{If}~ X\in (-1.5,0], &~\hat{b}_0\hat{b}_1 = 10,\\
\text{If}~ X\in (-\infty, -1.5], &~\hat{b}_0\hat{b}_1 = 11,\end{align}
With $P_e$ meaning probability of bit error, we have that
$$P_e(\hat{b}_0\neq b_0\mid b_0b_1 = 01) = P(N(+2, \sigma^2) < 0) = Q\left(\frac 2\sigma\right),\\
P_e(\hat{b}_0\neq b_0\mid b_0b_1 = 00) = P(N(+1, \sigma^2) < 0) = Q\left(\frac 1\sigma\right),\\
P_e(\hat{b}_0\neq b_0\mid b_0b_1 = 10) = P(N(-1, \sigma^2) > 0) = Q\left(\frac 1\sigma\right),\\
P_e(\hat{b}_0\neq b_0\mid b_0b_1 = 11) = P(N(-2, \sigma^2) > 0) = Q\left(\frac 2\sigma\right).$$
The average bit error probability for $b_0$ is thus
$$P_e(\hat{b}_0\neq b_0) = \left.\left. \frac 12 \right[\displaystyle Q\left(\frac 1\sigma\right) + Q\left(\frac 2\sigma\right)\right].\tag{1}$$
On the other hand, the calculations for $P_e(\hat{b_1}\neq b_1)$ are a lot messier. We have that
\begin{align}P_e(\hat{b}_1\neq b_1\mid b_0b_1 = 01) &= P(-1.5 < N(+2, \sigma^2) < 1.5)\\
&= Q\left(\frac{0.5}{\sigma}\right) - Q\left(\frac{3.5}{\sigma}\right),\\
P_e(\hat{b}_1\neq b_1\mid b_0b_1 = 00) &= P(N(+1, \sigma^2) < -1.5) + P(N(+1, \sigma^2) > 1.5)\\
&= Q\left(\frac{0.5}{\sigma}\right) + Q\left(\frac{2.5}{\sigma}\right),\\
P_e(\hat{b}_1\neq b_1\mid b_0b_1 = 10) &= P(N(-1, \sigma^2) < -1.5) + P(N(-1, \sigma^2) > 1.5)\\
&= Q\left(\frac{0.5}{\sigma}\right) + Q\left(\frac{2.5}{\sigma}\right),\\
P_e(\hat{b}_1\neq b_1\mid b_0b_1 = 11) &= P(-1.5 < N(-2, \sigma^2) < 1.5)\\
&= Q\left(\frac{0.5}{\sigma}\right) - Q\left(\frac{3.5}{\sigma}\right).\end{align}
The average bit error probability for $b_1$ is thus
$$P_e(\hat{b}_1\neq b_1) = Q\left(\frac{0.5}{\sigma}\right) + \left.\left. \frac 12 \right[\displaystyle Q\left(\frac{2.5}{\sigma}\right) - Q\left(\frac{3.5}{\sigma}\right)\right].\tag{2}$$
Thus the two bits being transmitted have significantly different average bit error probabilities with $P_e(\hat{b}_1\neq b_1) >> P_e(\hat{b}_0\neq b_0)$ for typical values of $\sigma$. $Q(x)$ is a very rapidly decreasing function of its argument and the dominant terms $\displaystyle Q\left(\frac{0.5}{\sigma}\right)$ and $\displaystyle \frac 12 Q\left(\frac 1\sigma\right)$ in $(2)$
 and $(1)$ respectively can differ by an order of magnitude or more.


How can a user be informed of the reason for a revert if there is no event log available?

Question: I presume a typical case of smart contract use is purchasing tokens from a smart contract using Metamask. If the contract is at all complex (such as a tiered pricing sale with various caps) and a request to purchase tokens fails - for instance due to exceeding some cap - the user only knows that it has failed, and otherwise has no clue about what caused the failure. If they call the support staff of the company that owns the contract the support staff will likely be similarly in the dark. I totally disagree with the sentiment "fail early and hard -- without any logged event". I wholly support "fail early and hard, but leave tracks." Is this simply beyond the capability of the EVM? There is a failed transaction record present after a failure. Why can't it contain a log from the operation that failed? I must be missing some key point about the way logging "works" (or doesn't)...
Answer: There have been a few EIP attempts to add return data/revert reason to the receipt generated from a transaction, but there has been no consensus on how to fairly and safely charge for the data returned, so of course it hasn't been added in a fork. Since reversion reverts everything, you of course can't fetch return data.
An approach that could be used (I don't know if anyone has used it thus far) is to have a top level "error handling contract", essentially it's a proxy that catches all errors and logs an event of the reversion with the revert reason. Of course you lose the original record of msg.sender since the error handler is called.
Comment: Thanks. I hadn't thought of the gas implications, and how revert error logging could be subverted as a communication tool. A general approach would be to charge for all logging, based on number of bytes logged - regardless of whether the request reverted. But if event output is disposed as part of the reverted state (which still seems wrong to me) there is no simple solution - except check for all possible legitimate failures in a front end dApp.