text:
Correlation Coefficient of Words
This is going to be relatively quick...
Challenge
Given a lower-case word as input, calculate the Pearson's Correlation Coefficient between the letter position of the word (nth letter within the word, x), and the letter position within the alphabet (nth letter of the alphabet, y).
Background
Pearson's Correlation Coefficient is worked out for data sets x and y, as:

where x and y are the respective data sets as explained above (and further below), and n is the length of the string.
Examples
  Input: forty
  Output: 0.964406804

Explanation:
  Letters: f o r t y
  Alphabet Number (y): 6 15 18 20 25
  Letter Position (x): 1 2 3 4 5
  Length of word (n): 5

Correlation coefficient is worked out from the above formula.
  Input: bells
  Output: 0.971793199

Explanation:
  Letters: b e l l s
  Alphabet Number (y): 2 5 12 12 19
  Letter Position (x): 1 2 3 4 5
  Length of word (n): 5

Correlation coefficient is once again worked out from the above formula.
Rules

Input must provide the word as a lower-case alphabetic string with no spaces (assumed input). The delivery of this string is entirely up to you (file, STDIN, function, array, carrier pigeon, etc.)
Output is in the form of a numeric that will, by the formula, provide r, such that -1 <= r <= 1. Delivery of the output, once again, is entirely up to you.
No silly loop holes
This is not code-golf, as I'm sure there will be many languages that may have native statistical functions. Instead, this will be a popularity contest, so most votes wins here, so make your entry count... I'll be throwing in a bounty for the most creative answer that attracts my attention a little later down the line...

Any questions/comments?

Relevant Wikipedia article

I wish you had made this a pop con in the sandbox, so I could have said it over there. If you want to avoid built-ins in code golf challenges, just ban functions that compute the PCC. This type of popularity contest has fallen out of scope. The tag wiki explicitly says Questions like "do (this) the most creative way" should be avoided. Creativity should be the tool, not the goal.

I wasn't aware of this when I posted my previous comment, but this has already be done as a code golf challenge.

R, 63 bytes
s=strsplit(scan(,""),"")[[1]];cor(match(s,letters),1:length(s))

Ungolfed :
#Takes the input and splits it, letters by letters
s=strsplit(
           scan(,""),
           "")[[1]];

#Finds the positions of each letters in the lowercase alphabet, and correlates them with
#their position in the word
cor(
    match(s,letters),
    1:length(s)
    )

Nice! I came up with a similar solution, but yours is much neater (especially the use of match). You can save one byte by making it a one-liner, and another byte by getting the nchar of the input string rather than the length of the split vector. Like so: cor(match(strsplit(i<-scan(,""),"")[[1]],letters),1:nchar(i))

... it's not [tag:code-golf] though

@rturnbull : your solution doesn't work on my computer. I wonder if the fact that strsplit(scan) is inside the cor isn't problematic
@JonathanAllan : True enough, but it's always funnier !

Ah, I think the problem was the placement of the assignment operator to i. (I don't actually fully understand R's behavior with this.) Try it now: cor(match(strsplit(i,"")[[1]],letters),1:nchar(i<-scan(,""))).

Python
That's a lot of traversals, let's do all we need to do in one pass for efficiency.
Since y will be [1,2,...,len(x)] we can calculate it's sum and sum of squares using the formulas for triangle and square pyramid numbers respectively.
...and there's really no need for two square roots since the two are multiplied we can just square the product.
def p(l):
    y = sx = sxy = sx2 = 0
    for c in l:
        y += 1
        x = ord(c) - 96
        sx += x
        sxy += x * y
        sx2 += x * x
    sy = y * (y + 1) / 2
    sy2 = sy * (2 * y + 1) / 3
    return (n * sxy - sx * sy ) / ((n * sx2 - sx * sx) * (n * sy2 - sy * sy)) ** .5

Python 3
Simply uses the formula in the challenge. Doesn't use any libraries like numpy and friends.
from math import sqrt

def correlation_coefficient(word):
  alphabet = 'abcdefghijklmnopqrstuvwxyz'

  x = list(range(len(word)))
  y = list(map(alphabet.index, word))
  n = len(word)

  top = n * sum(a*b for a, b in zip(x, y)) - sum(x) * sum(y)
  bottom = (sqrt(n * sum(a ** 2 for a in x) - sum(x) ** 2)
          * sqrt(n * sum(a ** 2 for a in y) - sum(y) ** 2))

  r = top / bottom
  return r

Ideone it!


text:
Visualize sorting
Say I have a list such as [3, 0, 4, 2, 1], and I use selection sort to sort it, I could visualize it like this:
3,0,4,2,1
|-|
0,3,4,2,1
  |-----|
0,1,4,2,3
    |-|
0,1,2,4,3
      |-|
0,1,2,3,4

This challenge is about visualizing sorting like this.
Input
Your input will be a list of positive integers, in any format you like.
Task
Your submission should sort the input list by only swapping two elements at a time, and at each swap, the submission should display the list, and a character under each of the elements being swapped. If a number that was swapped has more than one digit, the character can be anywhere underneath it. At the end, the submission should display the sorted list.
Other rules

The sorting must use fewer swaps than n4, where n is the length of the list.
The sorting doesn't have to be deterministic.
The characters under the swapped can be any char except space.

Could I assume that the integers are unique?

n^4? You're being a bit generous here.

@JörgHülsermann No

If anyone is interested in sorting https://www.toptal.com/developers/sorting-algorithms/

As you count only swaps and not compares, one could implement a radix-like sort with just n-1 swaps

You say the input is positive integers but your example has a 0 (please fix only the example so as not to invalidate answers that can't handle 0)

https://www.youtube.com/watch?v=Ns4TPTC8whw

Perl, 62 bytes
Includes +3 for -p
Give input as a single line of numbers on STDIN:
perl -M5.010 visisort.pl <<< "3 0 4 2 1"

Repeatedly swaps the first inversion. Swap complexity is O(n^2), time complexity is O(n^3). Uses the numbers being swapped as mark:
3 0 4 2 1
3 0
0 3 4 2 1
    4 2
0 3 2 4 1
  3 2
0 2 3 4 1
      4 1
0 2 3 1 4
    3 1
0 2 1 3 4
  2 1
0 1 2 3 4

visisort.pl:
#!/usr/bin/perl -p
$&>$'&&say$_.$"x"@-".!s/(\S+) \G(\S+)/$2 $1/.$&while/\S+ /g

The program also supports negative values and floating point numbers
If you insist on a connecting character the code becomes 66 bytes:
#!/usr/bin/perl -p
$&>$'&&say$_.$"x"@-".!s/(\S+) \G(\S+)/$2 $1/.$1.-$2while/\S+ /g

But now it doesn't support negative numbers and 0 anymore (but the program only has to support positive integers anyways. The 0 in the example is a mistake)

Given that The characters under the swapped can be any char except space.  you should not have spaces between number in the mark line

@edc65 The character(s) under the elements being swapped is not a space. Nothing is said about the characters between them

Not entirely convinced, but ok. I was too fast downvoting (but I got your attention). If you make an (empty) edit to your answer I'll change my vote

@edc65 Well, your comment made me reread the challenge very carefully. Notice that he also talks about the case of multidigit numbers clearly meaning you can e.g. just put a _ under the first digit which means that all characters inbetween would in fact be spaces). So I stand by my interpretation (unless the OP disagrees of course). Buit just to make you happy I added a version without space too :-)

PHP, 248 Bytes
Bubblesort boring wins
<?for($c=count($a=$_GET[a]);$c--;){for($s=$i=0;$i<$c;){$l=strlen($j=join(",",$a));if($a[$i]>$a[$i+1]){$t=$a[$i];$a[$i]=$a[$i+1];$a[$i+1]=$t;$m=" ";$m[$s]=I;$m[$s+strlen($a[$i].$a[$i+1])]=X;echo"$j\n$m\n";}$s+=strlen($a[$i++])+1;}}echo join(",",$a);

PHP, 266 Bytes a way with array_slice and min
modified output I  X instead of *~~*
<?for($c=count($a=$_GET[a]);$i<$c;){$j=join(",",$s=($d=array_slice)($a,$i));$x=array_search($m=min($s),$s);echo($o=join(",",$a));$a[$x+$i]=$a[$i];$a[$i]=$m;if($i++!=$c-1){$t=" ";$t[$z=($f=strlen)($o)-($l=$f($j))]=I;$t[$l+$z-$f(join(",",$d($s,$x)))]=X;echo"\n$t\n";}}

282 Bytes
<?for($c=count($a=$_GET[a]);$i<$c;){$j=join(",",$s=($d=array_slice)($a,$i));$x=array_search($m=min($s),$s);echo($o=join(",",$a));$a[$x+$i]=$a[$i];$a[$i]=$m;if($i++!=$c-1)echo"\n".str_repeat(" ",($f=strlen)($o)-($l=$f($j))).($x?str_pad("*",$l-$f(join(",",$d($s,$x))),"~"):"")."*\n";}

How it works
Looks for the minimum in an array and take this on first position
Look for the minimum without first position .... and so on
If a value is double the first value will be swap
Output Example
31,7,0,5,5,5,753,5,99,4,333,5,2,1001,35,1,67
*~~~~*
0,7,31,5,5,5,753,5,99,4,333,5,2,1001,35,1,67
  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*
0,1,31,5,5,5,753,5,99,4,333,5,2,1001,35,7,67
    *~~~~~~~~~~~~~~~~~~~~~~~~~*
0,1,2,5,5,5,753,5,99,4,333,5,31,1001,35,7,67
      *~~~~~~~~~~~~~~*
0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67
        *
0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67
          *
0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67
            *~~~*
0,1,2,4,5,5,5,753,99,5,333,5,31,1001,35,7,67
              *~~~~~~*
0,1,2,4,5,5,5,5,99,753,333,5,31,1001,35,7,67
                *~~~~~~~~~~*
0,1,2,4,5,5,5,5,5,753,333,99,31,1001,35,7,67
                  *~~~~~~~~~~~~~~~~~~~~~*
0,1,2,4,5,5,5,5,5,7,333,99,31,1001,35,753,67
                    *~~~~~~*
0,1,2,4,5,5,5,5,5,7,31,99,333,1001,35,753,67
                       *~~~~~~~~~~~*
0,1,2,4,5,5,5,5,5,7,31,35,333,1001,99,753,67
                          *~~~~~~~~~~~~~~~*
0,1,2,4,5,5,5,5,5,7,31,35,67,1001,99,753,333
                             *~~~~*
0,1,2,4,5,5,5,5,5,7,31,35,67,99,1001,753,333
                                *~~~~~~~~*
0,1,2,4,5,5,5,5,5,7,31,35,67,99,333,753,1001
                                    *
0,1,2,4,5,5,5,5,5,7,31,35,67,99,333,753,1001

Instead of echo$t."\n";, you can use echo"$t\n"; and save a byte.

@IsmaelMiguel Feel free to edit my posts if you find something to improve

Code edits on posts are usually frowned upon, which I totally agree with.

JavaScript (ES6), 158 bytes
a=>{for(;;){console.log(``+a);i=a.findIndex((e,i)=>e<a[i-1]);if(i<0)break;console.log(` `.repeat(`${a.slice(0,i)}`.length-1)+`|-|`);t=a[i];a[i]=a[--i];a[i]=t}}

Bubble sort. Sample output:
3,0,4,2,1
|-|
0,3,4,2,1
    |-|
0,3,2,4,1
  |-|
0,2,3,4,1
      |-|
0,2,3,1,4
    |-|
0,2,1,3,4
  |-|
0,1,2,3,4

@nimi Since I'm always swapping adjacent elements, I can always put the - under the , and then the two |s will always be under the adjacent numbers.

aah, clever! Thanks!

Bubble sort is a really judicious choice indeed to simplify the highlighting of the swapped numbers. Well done!

Haskell, 165 164 162 bytes
s%c=drop 2$show s>>c
p#x|(h,t:s)<-span(/=minimum x)x=id=<<[show$p++x,"\n ",[' '|p>[]],p%" ","|",h%"-",['|'|h>[]],"\n",(p++[t])#(drop 1h++take 1h++s)]|1<2=""
([]#)

This visualizes selection sort. Usage example:
*Main> putStr $ ([]#) [31,7,0,5,5,5,753,5,99,4,333,5,2,1001,35,1,67]
[31,7,0,5,5,5,753,5,99,4,333,5,2,1001,35,1,67]
 |----|
[0,7,31,5,5,5,753,5,99,4,333,5,2,1001,35,1,67]
   |-------------------------------------|
[0,1,31,5,5,5,753,5,99,4,333,5,2,1001,35,7,67]
     |-------------------------|
[0,1,2,5,5,5,753,5,99,4,333,5,31,1001,35,7,67]
       |--------------|
[0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67]
         |
[0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67]
           |
[0,1,2,4,5,5,753,5,99,5,333,5,31,1001,35,7,67]
             |---|
[0,1,2,4,5,5,5,753,99,5,333,5,31,1001,35,7,67]
               |------|
[0,1,2,4,5,5,5,5,99,753,333,5,31,1001,35,7,67]
                 |----------|
[0,1,2,4,5,5,5,5,5,753,333,99,31,1001,35,7,67]
                   |---------------------|
[0,1,2,4,5,5,5,5,5,7,333,99,31,1001,35,753,67]
                     |------|
[0,1,2,4,5,5,5,5,5,7,31,99,333,1001,35,753,67]
                        |-----------|
[0,1,2,4,5,5,5,5,5,7,31,35,333,1001,99,753,67]
                           |---------------|
[0,1,2,4,5,5,5,5,5,7,31,35,67,1001,99,753,333]
                              |----|
[0,1,2,4,5,5,5,5,5,7,31,35,67,99,1001,753,333]
                                 |--------|
[0,1,2,4,5,5,5,5,5,7,31,35,67,99,333,753,1001]
                                     |
[0,1,2,4,5,5,5,5,5,7,31,35,67,99,333,753,1001]
                                         |

How it works:
s % c is a helper function that makes length (show s) - 2 copies of character c. It's used for spacing before both |, one time with c == ' ' and one time with c == '-'.
The main function # takes a list p which is the sorted part of the list and x which is the yet to sort part. The pattern match (h,t:s)<-span(/=minimum x)x splits the list x at its minimum element and binds h to the part before the minimum, t to the minimum itself and s to the part after the minimum. The rest is formatting two lines: 1) the list at its current state (p++x) and 2) the |----| part followed by a recursive call of # with t appended to p and the head of h inserted between the tail of h and s.
PS: works also with negativ and/or floating point numbers:
*Main> putStr $ ([]#) [-3,-1,4e33,-7.3]
[-3.0,-1.0,4.0e33,-7.3]
 |----------------|
[-7.3,-1.0,4.0e33,-3.0]
      |-----------|
[-7.3,-3.0,4.0e33,-1.0]
           |------|
[-7.3,-3.0,-1.0,4.0e33]
                |

Edit: @BlackCap saved 2 bytes. Thanks!

id=<<[show$p++x,"\n ",[' '|p>[]],p%" ","|",h%"-",['|'|h>[]],"\n",(p++[t])#(drop 1h++take 1h++s)]

Python 2, 267 bytes
It works with decimals and negative numbers as well.
p=1
while p!=len(a):
 q=p-1;k=a[p:];m=min(k);n=k.index(m)+p;b=map(str,a)
 if a[q]>m:print','.join(b)+'\n'+''.join(' '*len(i)for i in b[:q])+' '*q+'*'+'-'*(len(b[n])+n-q-2)+''.join('-'*len(i)for i in b[q:n])+'*';a[q],a[n]=[a[n],a[q]]
 p+=1
print','.join(map(str,a))

Example:
7,2,64,-106,52.7,-542.25,54,209,0,-1,200.005,200,3,6,1,0,335,-500,3.1,-0.002
*----------------------*
-542.25,2,64,-106,52.7,7,54,209,0,-1,200.005,200,3,6,1,0,335,-500,3.1,-0.002
        *-------------------------------------------------------*
-542.25,-500,64,-106,52.7,7,54,209,0,-1,200.005,200,3,6,1,0,335,2,3.1,-0.002
             *-----*
-542.25,-500,-106,64,52.7,7,54,209,0,-1,200.005,200,3,6,1,0,335,2,3.1,-0.002
                  *-------------------*
-542.25,-500,-106,-1,52.7,7,54,209,0,64,200.005,200,3,6,1,0,335,2,3.1,-0.002
                     *-----------------------------------------------------*
-542.25,-500,-106,-1,-0.002,7,54,209,0,64,200.005,200,3,6,1,0,335,2,3.1,52.7
                            *--------*
-542.25,-500,-106,-1,-0.002,0,54,209,7,64,200.005,200,3,6,1,0,335,2,3.1,52.7
                              *-----------------------------*
-542.25,-500,-106,-1,-0.002,0,0,209,7,64,200.005,200,3,6,1,54,335,2,3.1,52.7
                                *------------------------*
-542.25,-500,-106,-1,-0.002,0,0,1,7,64,200.005,200,3,6,209,54,335,2,3.1,52.7
                                  *-------------------------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,64,200.005,200,3,6,209,54,335,7,3.1,52.7
                                    *--------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,200.005,200,64,6,209,54,335,7,3.1,52.7
                                      *-------------------------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,200,64,6,209,54,335,7,200.005,52.7
                                          *------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,64,200,209,54,335,7,200.005,52.7
                                            *-----------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,200,209,54,335,64,200.005,52.7
                                              *----------------------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,52.7,209,54,335,64,200.005,200
                                                   *----*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,52.7,54,209,335,64,200.005,200
                                                      *--------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,52.7,54,64,335,209,200.005,200
                                                         *-----------------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,52.7,54,64,200,209,200.005,335
                                                             *---------*
-542.25,-500,-106,-1,-0.002,0,0,1,2,3,3.1,6,7,52.7,54,64,200,200.005,209,335

JavaScript (ES6), 147 155
Using n*n compares, but (I believe) the minimum number of swaps. And the swap positions are more variable compared to the boring bubble sort.
l=>l.reduce((z,v,i)=>l.map((n,j)=>s+=`${j>i?n<l[i]?l[p=j,t=s,i]=n:0:u=s,n},`.length,s=p=0)|p?z+`
${l[p]=v,' '.repeat(u)}^${Array(t-u)}^
`+l:z,''+l)

Less golfed and hopefully more understandable
l=>
  l.reduce( (z,v,i) => // update z for each list element v at position i
    ( // begin outer loop body
      // loop to find the least value that is to be placed at pos i
      l.map( (n,j) => // for each list element n at position j
        ( // begin inner loop body
          j > i ? // check if at position after i
            n < l[i] && // check if lower value
            (
              p = j, // remember position in p
              l[i] = n, // store value in l[i] (could change later)
              t = s // in t, string length of list elements up element preciding j
            )
          : // else, position up to i
            u = s, // in u, string length of list elements up element preciding i
          s += `${n},`.length, // string length of list elements up to this point (value length + comma)
        ) // end inner loop body
        , s = p = 0 // init s and p at start of inner loop
      ),
      p ? (// if found a lower value, complete the swap and update output
          l[p] = v, // complete swap, l[i] was assigned before
          z + '\n' + ' '.repeat(u) + // spaces to align
               '^' + // left marker
               Array(t-u) + // swap highlight, using sequence of commas
               '^\n' + // right marker, newline
               l + // list values after the swap, newline
      )
      : z // else output is unchanged
    ) // end outer loop body
    , ''+l // init string output at start of outer loop
  ) // output is the result of reduce

Test

f=
l=>l.reduce((z,v,i)=>l.map((n,j)=>s+=`${j>i?n<l[i]?l[p=j,t=s,i]=n:0:u=s,n},`.length,s=p=0)|p?z+`
${l[p]=v,' '.repeat(u)}^${Array(t-u)}^
`+l:z,''+l)

function sort()
{
  var list=I.value.match(/-?[\d.]+/g).map(x=>+x)
  O.textContent = f(list)
}

sort()
#I { width:80% }
<input id=I value='3, 0, 4, 2, 1'>
<button onclick='sort()'>Sort</button>

Jelly, 36 bytes
I;0CMḢ;L‘ṬCœṗ¹UF©µÐĿ,n+32Ọ$¥¥2\;/®ṭG

Try it online!
Explanation
I;0CMḢ;L‘ṬCœṗ¹UF©µÐĿ,n+32Ọ$¥¥2\;/®ṭG
                 µÐĿ                 Repeat until we see a previously seen value:
I;0                                    Take differences of adjacent inputs, and 0
   CM                                  Find the indices (M) of the smallest (C)
           œṗ                          Split {the input} into pieces
        ‘Ṭ                               that end
      ;L  C                              everywhere except
     Ḣ                                 the first of the chosen deltas
             ¹                         Resolve parser ambiguity
              U                        Reverse each piece
               F                       Concatenate the pieces back into a list
                ©                      Store the value in a register
                                     Then, on the accumulated list of results:
                             2\        Look at each consecutive pair of results
                    ,       ¥  ;/      and return the first element, followed by
                      +32Ọ$            the character with code 32 plus
                     n     ¥           1 (if unequal), 0 (if equal)
                                 ®ṭ  Append the value of the register
                                   G Output in grid form

The example shown in the TIO link is a particularly hard one for this program; the ;0 near the start is necessary to ensure that the loop ends just at the point where the input becomes sorted. This normally isn't necessary (because it will end after one more iteration), but if the last swap is of the first two elements (as seen here), the one-more-iteration won't happen and makes it impossible to finish the list consistently. As such, we need to ensure we don't swap anything on the last loop iteration.

Java 7, 256 241 282 Bytes
Thanks to @Geobits and @Axelh for saving 15 bytes
 void f(int[]a){int m,i,j,l=a.length;for(i=0;i<l;j=a[i],a[i]=a[m],a[m]=j,i++){for(int k:a)System.out.print(k+" ");System.out.println();for(j=i+1,m=i;j<l;m=a[j]<a[m]?j:m,j++);for(j=0;j<=m&i!=l-1;j++)System.out.print(j==i|j==m?a[j]+" ":"  ");System.out.println();}}

Ungolfed
 void f(int[]a){
    int m,i,j,l=a.length;
for(i=0;i<l;j=a[i],a[i]=a[m],a[m]=j,i++){
    for(int k:a)
        System.out.print(k+" ");
    System.out.println();
     for(j=i+1,m=i;j<l;m=a[j]<a[m]?j:m,j++);
      for(j=0;j<=m&i!=l-1;j++)
      System.out.print(j==i|j==m?a[j]+" ":"  ");
      System.out.println();

}
}

output
3 0 1 4 2
3 0
0 3 1 4 2
  3 1
0 1 3 4 2
    3   2
0 1 2 4 3
      4 3
0 1 2 3 4

This is still missing the declaration of out, you need to put something like PrintStream out=System.out; somewhere in your code.

After fixing the import/declaration of out, you should use a ternary instead of if/else if you're going to be printing on both branches. Something like out.print(a>b?a:b); instead of if(a>b)out.print(a);else out.print(b);

You can reduce the if else liek this : if(j==i|j==m)out.print(a[j]);out.print(" "); or even better with a ternary out.print((j==i|j==m?a[j]:" ")+" "); and then you can remove {} of the loop PS : I use a import static for the out instance, if that's ok ;)

Hmm, apart from the golfing tips from the others, the output is incorrect.. Here is an ideone with your code copy-pasted (and added System. in front of the outs), and it's missing the 2 and 3 on the two last swap-lines.

@KevinCruijssen I corrected it.Actually I mix up i variable with j variable(should be i)in this linefor(j=0;j<=m&i!=l-1;j++)

The characters under the swapped can be any char except space. choose some other char

J, 66 65 bytes
[:(>@,@(2({.;'^ '{~=/)\])@,{:)@":]C.~a:,[:<"1\@;({.,.}.)&.>@C.@/:

Try it online!

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Simulate keystrokes
Your job is to simulate a couple of keystrokes that a user types in.
Input
A string array or string with a delimiter of your choice (outside the range 32-126) containing at least one 'keystroke'.
This array will only contain two types of string: passive keystrokes (single chars) and commands (chars within brackets [ ]).

Passive keystrokes

ASCII character codes [32-126]

Commands:

[B] : backspace (remove last character added if there is one)
[C] : copy all of what has already been written
[D] : delete all of what has been written
[P] : paste what has been copied

Output
The string produced by the keystrokes.
Examples
['H', 'e', 'l', 'l', 'o'] -> 'Hello'
['H', 'e', 'l', 'l', 'o', ' ', '[C]', '[P]'] -> 'Hello Hello '
['[D]', 'D', '[B]'] -> ''
['H', '[C]', 'i', '[P]', '[C]', '[P]'] -> 'HiHHiH'
['e', '[C]', '[B]', 'I', ' ', 'l', 'i', 'k', '[P]', ' ', 'b', '[P]', '[P]', 's', '!'] -> I like bees!
['N', '[P]'] -> 'N'
['#', '5', '0', 'K', '0', '0', '1', '[D]', '#', 'n', 'o', 't'] -> '#not'
['H', 'o', 'w', ' ', '[D]', 'H', 'e', 'y'] -> 'Hey'
['s', 'u', 'd', '[B]', 'p', '[C]', '[D]', 'I', ' ' , 'h', 'a', 'v', 'e', ' ', '[P]', 'p', 'e', 'r', '!'] -> 'I have supper!'

This is code-golf, so shortest code in bytes wins!

FYI I found a bug in my code, may I suggest a test case with a capital B for bees :)

There should also be an example with [D] where it's not the only one used, so the code won't just be split('[D]')[1] or something.

@mbomb007, I added test cases (#8, #9)

And I think mbomb007 was asking for a test case with multiple deletions.

@MartinEnder, oh I thought he wanted one where there are commands other than [D]

05AB1E, 34 33 31 27 bytes
Uses CP-1252 encoding.
õUvygiyJë"XJ¨DU\"4äyáÇ5%è.V

Try it online!
Explanation
õU                                  # initialize X as the empty string
v                                   # for each y in input
 ygiyJ                              # if len(y) == 1 join y with stack
      ë                             # else
       "XJ¨DU\"                     # push this string
               4ä                   # split into 4 parts (of size [2,1,2,1])
                 yá                 # push only letters of y
                   Ç5%              # mod its ascii code by 5
                      è             # index into the string above with this
                       .V           # evaluate as 05AB1E code

The pairs of functions evaluated in the code above are:
DU    # [C] -> duplicate and store in X
XJ    # [P] -> push X and join with stack
¨     # [B] -> remove last char of string
\     # [D] -> remove top of stack

Saved 4 bytes using the mod 5 trick from Lynn's CJam answer

Vim, 76, 64, 62, 58 keystrokes
Thanks to Loovjo for saving 7 keystrokes

Did someone say simulate keystrokes? Well then, it's a good thing my favorite language to golf in is all about simulating keystrokes!
:no s :%s/\M[
sB]/<C-v><C-h>
sC]/<C-v><esc>0y$A
sD]/<C-v><esc>"_S
sP]/<C-v><C-r>"
s<bs>\n
S<C-r>"

Input comes in this format:
h
e
l
l
o

[C]
[P]

This is a pretty straightforward answer. It just translates each "command" to the vim keystroke equivalent of that command. Let's take it line by line.
:no s :%s/\M[

This saves a ton of bytes. Vim has a builtin "command line" where you can create mappings, change settings, save files, etc. Here we are creating a mapping. :no is short for :nnoremap which means "When we are in normal mode, substitute this left hand side for this right hand side." Since we are calling :%s/ five different times, this saves a lot. The \M is a nice trick. It means that the following search will be "Very No Magic", which means that the regex [B] will match the literal text [B] rather than a range containing just a B in it. Since the majority of the substitute commands have a brackets in them, we fill in the first one.
Then, we call five substitute commands. It's worth noting why I called <C-v> so many times. Characters like <esc>, <C-v>, <C-r>, etc. are unprintable characters, and must be typed into the command line with a <C-v>.

[B]: backspace. This one is pretty easy. Simply substitute each [B] with Ctrl-h, which is equivalent to backspace in vim.
[C]: copy all of what has already been written. This is translated to <esc>0y$A. This means:
<esc>      " Escape to normal mode
     0     " Move to the beginning of this line
      y$   " Yank to the end of the line
        A  " Re enter insert mode at the end of this line.

We could almost simply do Y in place of 0y$ which means "yank the whole line", but this also grabs a newline that we don't want.
[D]: delete all of what has been written. This is <esc>"_S. As before, <esc> exits insert mode so we can run commands. There are some things that are more convenient here. So we do
  S         " Delete this whole line and enter insert mode again
"_          " Send it to 'the black hole register'. This is just so that we don't overwrite the main register.

[P]: paste what has been copied. This one is also very straightforward. It is just <C-r>" which means Insert the contents of register '"'. " happens to be the main register that 'y' yanks to.

Now that we have translated all of the commands, we must join all the lines together by removing all of the newline characters. Thanks to our mapping, this is just
s<bs>\n

The <bs> is a backspace, (ASCII 0x08) and we need it because of the [ we filled in.
By now, we have translated the input into vim code, and we just need to run it. So we:
S           " Delete this whole line and enter insert mode
 <C-r>"     " Insert the keystrokes of register '"' as if they were typed by the user

Where's the Insert mode effect of <C-r> documented?

@Neil In general, you can find a key for a specific mode at :h mode_keystroke. In this case, it would be :h i_ctrl-r

@Loovjo Oh sorry, I forgot to mention. Input is expected to be on multiple lines so that I don't have to worry about commas, or the /g flag. I'll add those details in.

Also, what does 0ii<esc>D@" do?

@Loovjo I've added a more thorough explanation. Also, thanks for the previous tip! As I thought it over, I realized that actually would work. I ended up taking a whopping 12 bytes off!

Mappings, eh? :) thanks for the detailed explanation, I always learn something new!

CJam, 33 bytes
q~{_[`';"];""L~""]:L~"]\1>3b=}%s~

Try it online!
Explanation
q~                                  Read an evaluate input list.
  {                          }%     Map over each string in it:
   _                                 Duplicate the string, say S.
    [`';"];""L~""]:L~"]              Replace it the following list:
                                      [repr(S) '; "];" "L~" "]:L~"]
                       \             Bring S on top of the stack.
                        1>           Chop off the first char.
                          3b         Base-3 conversion.
                            =        Modular index into the list.
                               s~   Concatenate and run as CJam code.

The “hash function” 1>3b maps

single-character strings to 0 (= 0 mod 5),
[B] to 291 (= 1 mod 5),
[D] to 297 (= 2 mod 5),
[P] to 333 (= 3 mod 5),
[C] to 294 (= 4 mod 5).

This value (mod 5) is used as an index into a list of CJam code snippets:

For single-character strings, say h, the snippet "h" is returned, which pushes a single-character string to the stack.
For [B], the snippet ; is returned, which pops an element.
For [D], the snippet ]; is returned, which clears the stack.
For [P], the snippet L~ is returned, which appends variable L onto the stack.
For [C], the snippet ]:L~ is returned, which stores the current stack in the variable L.

These snippets are concatenated and executed; the final stack is printed implicitly by CJam. L is initially the empty list, so the copy buffer is initially “empty”.

JavaScript (ES6), 84 80 77 76 bytes
Saved 3 bytes thanks to @Neil, 1 more thanks to @edc65
x=>x.reduce((s,[c,z])=>z<'C'?s.slice(0,-1):z<'D'?t=s:z<'P'?"":s+=z?t:c,t="")

.map is two bytes longer:
x=>x.map(([c,z])=>s=z<'C'?s.slice(0,-1):z<'D'?t=s:z<'P'?"":s+=z?t:c,s=t="")&&s

Test snippet

f=x=>x.reduce((s,[c,z])=>z<'C'?s.slice(0,-1):z<'D'?t=s:z<'P'?"":s+=z?t:c,t="")

console.log(f(['e', '[C]', '[B]', 'I', ' ', 'l', 'i', 'k', '[P]', ' ', 'b', '[P]', '[P]', 's', '!']))
<button onclick="console.log(f(I.value.split('\n')))">Run</button>

<textarea id=I rows=10>H
e
l
l
o

[C]
[P]</textarea>

The difference is that you can save 3 bytes on the reduce version by using (s,[c,z]).

@Neil Nice! That saves a byte on the .map version too.

x=>x.reduce((s,[c,z])=>z<'C'?s.slice(0,-1):z<'D'?t=s:z<'P'?'':s+=z?t:c,t='') 1 byte less. Curiously undefined < any char is false

x=>x.reduce((s,[c,z])=>z<'C'?s.slice(0,-1):z<'D'?t=s:z<'P'?"":z?t:s+c,t="") saves one more character.  If z is truthy, paste, else add char to output.

@Grax when pasting you have to add to the current output, so z?s+t:s+c that is 1 byte more than s+=z?t:c

Aha.  That makes sense

Python 2, 96 95 93 bytes
r=c=""
for o in input():c=[c,r][x=="[C]"];r=[r+c,r[:-1],r,"",r+o][ord(o[1:2]or"E")%5]
print r

Can you move the or"E" to the definition of x to save a space?

@xnor I believe so.

Actually, it looks like defining x isn't worth it. The x=="C" can just be o=="[C]".

Jelly, 50 51 48 bytes
Ṿ”;;µṭ“Ṗ“ø©“ḣ0“;®”
L>1a2ị$i@“BCDP0”ịÇ
Ç€“⁶Ṗ©”;FV

TryItOnline
Or all test cases
How?
Ṿ”;;µṭ“Ṗ“ø©“ḣ0“;®” - Link 1, CreateCodeLookupValueList: keystroke
      “Ṗ“ø©“ḣ0“;®” - list of strings, ["Ṗ","ø©","ḣ0"";®"] - these are Jelly code for:
                         Ṗ  : pop (i.e. delete last entry)
                         ø© : niladic separation and copy to register (i.e. copy)
                         ḣ0 : head to 0 (i.e. delete all entries)
                         ;® : concatenate with value of register (i.e. paste)
    µ              - monadic chain separation
Ṿ                  - uneval - make a Jelly code version of the keystroke
                                               e.g. "I" -> "“I”"
 ”;                - string literal ";"                      |
   ;               - concatenate e.g. ";I"                   v
     ṭ             - tack, to make the list ["Ṗ","ø©",";®","“I”"]
                             a keystroke - a command will evaluate to a string like
                             "“[C]”" but wont be accessed)

L>1a2ị$i@“BCDP0”ịÇ - Link 2, ConvertAKeystokeToJellyCodeString: keystroke
L>1                - length greater than 1? (i.e. isCommand?)
      $            - last two links as a monad
   a               - and
    2ị             - index 2 of the keystroke (0 due to and for a passive keystroke)
         “BCDP0”   - Literal string "BCP0"
       i@          - find first matching index of, with reversed arguments
                ị  - index into
                 Ç - call last link (1) as a monad (get code to replace this keystroke)

Ç€“⁶Ṗ©”;FV - Main link: list of keystrokes
Ç€         - call last link (2) as a monad (convert to Jelly code)
  “⁶Ṗ©”    - literal string "⁶Ṗ©" - setup the register with an empty string:
                 ⁶ :literal " ";
                 Ṗ : pop the space to give an empty string;
                 © : places it into the register
       ;   - concatenate (put that at the front)
        F  - flatten list (lists and strings are equivalent in Jelly)
         V - evaluate the string

For example
The input:
    ['e', '[C]', '[B]', 'I', ' ', 'l', 'i', 'k', '[P]', ' ', 'B', '[P]', '[P]', 's', '!']
Becomes the Jelly code:
    "⁶Ṗ©;“e”ø©Ṗ;“I”;“ ”;“l”;“i”;“k”;®;“ ”;“B”;®;®;“s”;“!”"
Which then evaluates to
    "I like Bees!"

- with a capital 'B' as a test case, since before I fixed a bug it would have returned "I likeees!"

I'm not sure it's a valid test case, but I tried with an overly complex string and this appears to fail: ['e', 'e', 'e', '[B]', '[C]', '[B]', '[D]', 'I', ' ', 'l', 'i', 'k', '[P]', '[B]', ' ', 'b', '[P]', 's', '!'].

Ah - yes I missed this edge case, there is a copy before deleting the entire string and the code I wrote ignores it. I will look at it a little later, thanks for notifying me.

OK I fixed that up and it actually saves bytes too!

Perl, 53 50 bytes
Includes +1 for -p
Give input on STDIN terminated by newlines (the last newline may be left out, so it counts as a string separated by newlines):
keystrokes.pl
H
e
[C]
[D]
a
b
[B]
[P]
z
^D

gives
aHez

keystrokes.pl:
#!/usr/bin/perl -p
$\.=/^.$/?$&:/P/?$a:(/C/?$a=$\:chop($\x=/B/))x0}{

Almost caught the Jelly answer but the fiend escaped to 48 bytes...

Python 120 119 116 bytes
f=lambda s,r='',c='':f(s[1:],*{'B':(r[:-1],c),'C':(r,r),'D':('',c),'P':(r+c,c),'':(r+s[0],c)}[s[0][1:2]])if s else r

Ideone
A recursive function with input, s, a list of the key-strokes.
Each recursive call updates the return text, r and, in the case of a [C], the clipboard, c until s is empty.
The new values of r and c are found by indexing into a dictionary, {...}, and passed with unpacking, *. For the passive keystrokes s[0][1:2]will return an empty string and the key '' will be used instead.

Might I ask why you define the lambda as lambda s,r='',c='' instead of lambda s,r,c=''?

The specification is that  we take an input array of characters (here s) so the function needs to work with no other input.

My apologies, reading comprehension failure.

Haskell, 136 133 130 127 bytes
k c b(('[':m:_):i)|m<'C'=k c[q|b>"",q<-init b]i|m<'D'=k b b i|m<'P'=k c""i|1<3=k c(b++c)i
k c b(s:i)=k c(b++s)i
k c b[]=b
k""""

Try it on Ideone.
Explanation: k performs a tail recursion over a list of commands. b is the buffer in which the string is constructed, c saves the copied part.
k c b ("[B]":i) = k c (take(length b - 1)b) i -- remove last element of buffer
k c b ("[C]":i) = k b b i                     -- set copy to buffer
k c b ("[D]":i) = k c "" i                    -- clear the buffer
k c b ("[P]":i) = k c (b++c) i                -- append content of copy to the buffer
k c b (s:i)     = k c (b++s) i                -- append char to the buffer
k c b []        = b                           -- command list is empty, return buffer
f = k "" ""                                   -- initialise copy and buffer with empty strings

Edit: To save some bytes the commands[B][C][D][P]are no longer matched exactly but compared: less than 'C'? -> B and so on.
Thanks to @nimi for saving 3 bytes.

@nimi init b throws an exception if b is the empty list.

@nimi That's clever, thanks! As for the anonymous function I somehow had in mind that anonymous functions are only acceptable when they are the only statement and there are no other helper functions. However searching Meta turned up nothing like that, so I guess it's ok.

Here it is. It's allowed to declare helper functions for expressions that evaluate to functions.

Mathematica, 100 bytes
""<>Fold[Switch[#2,"[B]",Most@#~Check~{},"[C]",a=#,"[D]",{},"[P]",#~Join~a,_,Append@##]&,a={};{},#]&

Anonymous function. Takes a list of strings as input and returns a string as output. Ignore any messages generated.

PHP, 131 Bytes
17 Bytes save by @IsmaelMiguel ternary operator
<?$c=[];foreach($_GET[a]as$v)($t=$v[1])!=P?$t!=C?$t!=B?$t!=D?$o[]=$v:$o=[]:array_pop($o):$c=$o:$o=array_merge($o,$c);echo join($o);

147 bytes: <?$c=[];foreach($_GET[a]as$k=>$v)$v=="[P]"?$o=array_merge($o,$c):($v=="[C]"?$c=$o:($v=="[B]"?array_pop($o):$v=="[D]"?$o=[]:$o[]=$v));echo join($o);. (replaced your whole if() chain with a chain of trenary operations).

@IsmaelMiguel Thank You. I had no desire to use the operator

I can see why. It looks so ugly and ... it really is something that hurts the eye.

Java 7, 207 203 bytes
String c(String[]a){String r="",c=r;for(String s:a){int k=s.length(),l=r.length(),z;if(k>1){z=s.charAt(1);r=z<67?l>0?r.substring(0,l-1):"":z<68?r:z<69?"":z<81?r+c:r+s;c=z==67?r:c;}r+=k<2?s:"";}return r;}

This can most definitely be golfed some more, but this is my initial answer. Will edit after I found something to remove those equals-checks.. replaced with charAt, but can probably still be golfed..
Ungolfed & test code:
Try it here.
class M{
  static String c(final String[] a) {
    String r = "",
           c = r;
    for(String s : a){
      int k = s.length(),
          l = r.length(),
          z;
      if(k > 1){
        z = s.charAt(1);
        r = z < 67
             ? l > 0
                ? r.substring(0, l-1)
                : ""
             : z < 68
                ? r
                : z < 69
                   ? ""
                   : z < 81
                      ? r + c
                      : r + s;
        c = z == 67
             ? r
             : c;
      }
      r += k < 2
            ? s
            : "";
    }
    return r;
  }

  public static void main(String[] a){
    System.out.println(c(new String[]{ "H", "e", "l", "l", "o" }));
    System.out.println(c(new String[]{ "H", "e", "l", "l", "o", " ", "[C]", "[P]" }));
    System.out.println(c(new String[]{ "[D]", "D", "[B]" }));
    System.out.println(c(new String[]{ "H", "[C]", "i", "[P]", "[C]", "[P]" }));
    System.out.println(c(new String[]{ "e", "[C]", "[B]", "I", " ", "l", "i", "k", "[P]", " ", "b", "[P]", "[P]", "s", "!" }));
    System.out.println(c(new String[]{ "N", "[P]" }));
    System.out.println(c(new String[]{ "#", "5", "0", "K", "0", "0", "1", "[D]", "#", "n", "o", "t" }));
    System.out.println(c(new String[]{ "H", "o", "w", " ", "[D]", "H", "e", "y" }));
    System.out.println(c(new String[]{ "s", "u", "d", "[B]", "p", "[C]", "[D]", "I", " ", "h", "a", "v", "e", " ", "[P]", "p", "e", "r", "!" }));
  }
}

Output:
Hello
Hello Hello

HiHHiH
I like bees!
N
#not
Hey
I have supper!

PHP, 108 bytes
for(;null!==$s=$argv[++$i];)($g=$s[1])!=B?$g!=C?$g!=D?$o.=$g!=P?$s:$c:$o='':$c=$o:$o=substr($o,0,-1);echo$o;

Uses a string based approach rather than an array based one.
Use like:
php -r "for(;null!==$s=$argv[++$i];)($g=$s[1])!=B?$g!=C?$g!=D?$o.=$g!=P?$s:$c:$o='':$c=$o:$o=substr($o,0,-1);echo$o;" a b "[C]" "[B]" "[P]" "[C]" "[D]" j "[P]"

edit: saved 8 bytes by fiddling the order of the ?:s and making them negative to avoid having to use so many brackets;

$s=$argv[++$i] instead of null!==$s=$argv[++$i] if you use PHP >7 you could write $s=$argv[++$i]??0 to skip the notice

It's not there to skip the notice but to allow you to enter '0' seeing as how '0' is false. There are so many other notices that skipping that one in particular seems like a waste of time.

SpecBAS - 216 bytes
1 s$,t$="": INPUT a$: DIM b$(SPLIT a$,NOT ",")
2 FOR EACH l$ IN b$()
3 CASE l$
4 WHEN "[B]": s$=s$( TO LEN s$-1)
5 WHEN "[C]": t$=s$
6 WHEN "[D]": s$=""
7 WHEN "[P]": s$=s$+t$
8 OTHERWISE : s$=s$+l$
9 END CASE
10 NEXT l$: ?s$

Input is given as a string with commas, which is then turned into array.

PHP 7.1, 95 92 bytes
Note: requires PHP 7.1 for negative string offsets.
for(;n|$i=$argv[++$x];)($l=$i[1])?$l^r?$l^s?$l^t?$o.=$c:$o="":$c=$o:$o[-1]="":$o.=$i;echo$o;

Without negative string offsets (101 bytes):
php -r 'for(;n|$i=$argv[++$x];)($l=$i[1])?$l^r?$l^s?$l^t?$o.=$c:$o="":$c=$o:$o=substr($o,0,-1):$o.=$i;echo$o;' e [C] [B] I ' ' l i k [P] ' ' b [P] [P] s ! 2>/dev/null;echo

Run like this:
php -nr 'for(;n|$i=$argv[++$x];)($l=$i[1])?$l^r?$l^s?$l^t?$o.=$c:$o="":$c=$o:$o[-1]="":$o.=$i;echo$o;' e [C] [B] I ' ' l i k [P] ' ' b [P] [P] s !;echo
> I like bees!

Explanation
for(
  ;
  n|$i=$argv[++$x];   # Iterates over the input until null.
)
  ($l=$i[1])?         # Check if this item is a command, if so set to $l
    $l^r?             # If the command is not B
      $l^s?           # If the command is not C
        $l^t?         # If the command is not D
          $o.=$c      # Then it's P, so paste the clipboard ($c)
        :$o=""        #      It's D, so delete output
      :$c=$o          #      It's C, so copy output to clipboard
    :$o[-1]=""        #      It's B, so remove the last output char
  :$o.=$i;            # No command, add the current item to the output.

echo$o;               # Print the output.

Tweaks

Saved 3 bytes by combining the output handling with the command handling

Nice to see a PHP entry explained in detail :)

V, 49 bytes
íÛBÝ/
íÛCÝ/0y$A
íÛDÝ/"_S
íÛPÝ/"
íî
0éiD@"

Try it online!
Since this contains unprintable characters, here is a hexdump:
0000000: eddb 42dd 2f16 080a eddb 43dd 2f16 1b30  ..B./.....C./..0
0000010: 7924 410a eddb 44dd 2f16 1b22 5f53 0aed  y$A...D./.."_S..
0000020: db50 dd2f 1612 220a edee 0a30 e969 4440  .P./.."....0.iD@
0000030: 22

This is just a direct translation of my vim answer so that I could compete with Jelly. Unfortunately, I'm still one byte over, but I'm still working on the last one. :)
I'm more proud of that answer anyway, so if you want a very detailed explanation, read that one instead.

Actually, 56 bytes
''j"'[B]"'XaÆ"'[C]""k;╗i"aÆ"'[P]""╜i"aÆ"'[D]"'éaÆ''+ƒkΣR

Try it online!
Explanation:
''j"'[B]"'XaÆ"'[C]""k;╗i"aÆ"'[P]""╜i"aÆ"'[D]"'éaÆ''+ƒkΣR
''j                                                       insert an apostrophe between every pair of commands
   "'[B]"'XaÆ"'[C]""k;╗i"aÆ"'[P]""╜i"aÆ"'[D]"'éaÆ         replace:
   "'[B]"'XaÆ                                               "'[B]" with "X"
             "'[C]""k;╗i"aÆ                                 "'[C]" with "k;╗i"
                           "'[P]""╜i"aÆ                     "'[P]" with "╜i"
                                       "'[D]"'éaÆ           "'[D]" with "é"
                                                 ''+      prepend an apostrophe
                                                          now the input has been converted to the equivalent Actually program ("'<character>" pushes the character, "X" removes the last character, "k;╗i" saves the current stack state to a register, and "╜i" pushes the saved stack state)
                                                    ƒ     execute the code
                                                     kΣ   concatenate the characters
                                                       R  reverse the string

Java, 181
String v(String[]a){String r="",c=r;for(String s:a){try{int p=s.charAt(1)%5;r=p<1?r+c:p>2?"":p==1?r.length()<2?"":r.split(".$")[0]:r;c=p==2?r:c;}catch(Exception e){r+=s;}}return r;}

More readable version:
String v(String[]a){
    String r="",c=r;
    for(String s:a){
        try{
            int p=s.charAt(1)%5;
            r= p<1
                 ? r+c
                 : p>2
                    ? ""
                    :p==1
                        ? r.length()<2
                                     ?""
                                     :r.split(".$")[0]
                        :r;
            c=p==2?r:c;
        }catch(Exception e){
            r+=s;
        }
    }return r;
}

You can save some byte (1 or 2) by changing your try catch into a if(s.length()>1){...}else

and change the p==1 into p<2

MATL, 46 bytes
vXKx"@gtnq?2)XJ66=?3L)}J67=?XK}J68=?vx}K]]]]&h

Try it online! Or verify all test cases.
Explanation
v                % Push empty array
XK               % Copy to clipboard K. This initiallizes it as empty
x                % Delete
"                % Implicitly input cell array. For each
  @g             % Push current cell's contents
  t              % Duplicate elements
  n              % Number of elements
  q?             % If more then 1
    2)           % Get second char. Copy to clipboard J
    66=?         % If it ss 'B'
      3L)        % Remove last element from string built up to now
    }            % Else
      J67=?      % If it was a 'C'
        XK       % Copy string built up to now into clipboard K
      }          % Else
        J68=?    % If was a 'D'
          vx     % Delete stack. This deletes string built up to now, if any
        }        % Else: it was a 'P'
          K      % Paste from clipboard K
        ]        % End if
      ]          % End if
    ]            % End if
  ]              % End if
  &h             % Horizontally concatenate stack
                 % Implicitly end for
                 % Implicitly display

TCL, 186 bytes
proc t w {foreach "B C P N D r Q" [list {[string range $r 0 end-1]} {[set Q $r]} {$r$Q} {$r$g}] break;foreach g $w {eval "set c \$[string index ${g}N 1]";eval "set r \"$c\""};return $r}

Nicely formatted:
proc t w {
    foreach "B C P N D r Q" [list {[string range $r 0 end-1]} {[set Q $r]} {$r$Q} {$r$g}] break;
    foreach g $w {
        eval "set c \$[string index ${g}N 1]"
        eval "set r \"$c\""
    }
    return $r
}

I just wanted to prove I could do this in TCL

You can save bytes: replace foreach by lmap; returnby set x. This is what I can say on a quick glance.

Scala, 158 bytes
(i:Seq[String])=>(("","")/:i){case((a,c),k)=>if(k.size<2)(a+k,c)else
if(k=="[B]")(a dropRight 1,c)else
if(k=="[C]")(a,a)else
if(k=="[D]")("",c)else(a+c,c)}._1

Ungolfed:
(i:Seq[String]) => i.foldLeft(("", "")){
  case ((res,clipboard),key) =>
    if (k.size == 1) (res+key,clipboard)
    else if (k=="[B]") (res dropRight 1, clipboard)
    else if (k=="[C]") (res, res)
    else if (k=="[D]") ("", clipboard)else(acc+clipboard,clipboard)
}._1

Solves this problem as a fold with the result and the clipboard as accumulator. Sadly, scala doesn't have a ternary conditional operator, but instead uses if else as an expression.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Draw a Fibonacci series of squares!
Introduction
To draw a Fibonacci series of square, you start by drawing a one-unit square:
 _
|_|

Then another one to the left:
 _ _
|_|_|

Then a two-unit one on top:
 _ _
|   |
|_ _|
|_|_|

Then a three-unit one on the right:
 _ _ _ _ _
|   |     |
|_ _|     |
|_|_|_ _ _|

Then a five-unit one on the bottom:
 _ _ _ _ _
|   |     |
|_ _|     |
|_|_|_ _ _|
|         |
|         |
|         |
|         |
|_ _ _ _ _|

etc.
Your task
Given N squares to print (0 <= N <= 20), print the figure that contains N squares. For example, if N was 4, it should print:
 _ _ _ _ _
|   |     |
|_ _|     |
|_|_|_ _ _|

Note that it does not have to exactly follow this format, just something that represents the same figure.
Since it has four squares in it:
     3
    _v_ _ _ _
   |   |     |
   |_ _|     |< 4
2 >|_|_|_ _ _|
      ^
      1

Remember, this is code-golf, so the code with the smallest number of bytes wins.

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1697 1087"><title>Fibonacci Folge</title><desc>16 Zahlen der Fibonacci Folge</desc><defs><view id="fibo14" viewBox="50 50 610 377" /><view id="fibo12" viewBox="427 283 233 144" /><view id="fibo10" viewBox="427 283 89 55" /><view id="fibo8" viewBox="482 317 34 21" /><view id="fibo6" viewBox="482 317 13 8" /><view id="fibo4" viewBox="490 322 5 3" /></defs><rect x="491" y="322" width="1" height="1" fill="#dddd88" /><rect x="490" y="322" width="1" height="1" fill="#dddddd" /><rect x="490" y="323" width="2" height="2" fill="#eeee99" /><rect x="492" y="322" width="3" height="3" fill="#eeeeee" /><rect x="490" y="317" width="5" height="5" fill="#cccc77" /><rect x="482" y="317" width="8" height="8" fill="#cccccc" /><rect x="482" y="325" width="13" height="13" fill="#dddd88" /><rect x="495" y="317" width="21" height="21" fill="#dddddd" /><rect x="482" y="283" width="34" height="34" fill="#eeee99" /><rect x="427" y="283" width="55" height="55" fill="#eeeeee" /><rect x="427" y="338" width="89" height="89" fill="#cccc77" /><rect x="516" y="283" width="144" height="144" fill="#cccccc" /><rect x="427" y="50" width="233" height="233" fill="#dddd88" /><rect x="50" y="50" width="377" height="377" fill="#dddddd" /><rect x="50" y="427" width="610" height="610" fill="#eeee99" /><rect x="660" y="50" width="987" height="987" fill="#eeeeee" /><g font-family="Arial" text-anchor="middle"><text x="505" y="327" dominant-baseline="middle" font-size="0.7rem">21</text><text x="499" y="300" dominant-baseline="middle" font-size="0.9rem">34</text><text x="455" y="310" dominant-baseline="middle" font-size="1.2rem">55</text><g font-size="2.0rem"><text x="471" y="382" dominant-baseline="middle">89</text><text x="588" y="355" dominant-baseline="middle">144</text><text x="543" y="166" dominant-baseline="middle">233</text><text x="239" y="239" dominant-baseline="middle">377</text><text x="355" y="732" dominant-baseline="middle">610</text><text x="1153" y="543" dominant-baseline="middle">987</text></g></g><path d="M1647 50 a987,987 0 0,1 -987,987 a610,610 0 0,1 -610,-610 a377,377 0 0,1 377,-377 a233,233 0 0,1 233,233 a144,144 0 0,1 -144,144 a89,89 0 0,1 -89,-89 a55,55 0 0,1 55,-55 a34,34 0 0,1 34,34 a21,21 0 0,1 -21,21 a13,13 0 0,1 -13,-13 a8,8 0 0,1 8,-8 a5,5 0 0,1 5,5 a3,3 0 0,1 -3,3 a2,2 0 0,1 -2,-2 a1,1 0 0,1 1,-1 a1,1 0 0,1 1,1" stroke="black" stroke-width="0.25" fill="none" /></svg>

Oliver I have added a SVG as snippet to visualize your post. If it is not helpful please delete it

Up to F(50), really? That would be ~12.5 billion character wide.

@Arnauld You're right. I have updated it to up to 20.

Does the output have to follow the cumbersome I/O formats (i.e. is this an ASCII art challenge?), or could it use built-in graphics?

@JHM I have updated the question.

"highly discouraged" doesn't mean anything - builtins are either allowed or not. You also don't state which builtins you mean - just Fibonacci square drawing builtins? Fibonacci builtins in general? And it does not have to exactly follow this format, just something that represents the same figure isn't really descriptive. You need to be more precise about exactly what is valid and what isn't. Once again, the Sandbox could've helped you work out problems before posting this to main. 5 hours is not nearly enough time in the Sandbox to get feedback.

related

Please exclude the N=0 case since it almost certainly has to be handled as an (uninteresting) exception

Would OOOOOO\nO  OOO\nO  O O\nOOOOOO\n (replace \n by real newlines) be a valid result for the n=4 case ? Different orientation, no attempt to use nice box characters. (It can be converted to the example format by replaceing each O by _| and replacing spurious characters, but that takes quite a bit of code)

Even N=20 is quite high. It gives a solution of about 150 million characters with the suggested output format. Possibly  lower the limit even more.

Is it OK for the spiral as a whole to turn left instead of right ?