[Question]
  [
# Rolling a 1x1x2 block
This challenge is inspired by the game Bloxorz. Like that game, there is a 1x1x2 block, which may be moved on a square grid in any of the four cardinal directions. It moves by rotating 90 degrees about one of its edges which is touching the ground. Initially, the block is standing upright on a single square in a square grid. After some sequence of moves, determine whether it is:
* Standing upright on the starting square,
* Laying half-on, half-off the starting square, or
* Not on the starting square at all.
## Input
Input is given as a string consisting of the characters `F`, `B`, `L`, and `R`, which represent moving forward, backward, left, and right.
## Output
Output can be 1, 0.5, or 0, representing the fraction of the block resting on the starting square. Your program may use some other set of three distinct outputs, as long as they consistently represent the three possibilities.
## Test cases
```
"FFFBBB" -> 1
"" -> 1
"FRRRBLL" -> 1
"FRBL" -> 0.5
"FRBBL" -> 0
```
  
[Answer]
# [JavaScript (Node.js)](https://nodejs.org), 111 bytes
*-3 thanks to [@Steffan](https://codegolf.stackexchange.com/users/92689/steffan), and -2 from there*
Expects an array of ASCII codes. Returns \$0,1,2\$ instead of \$0,1/2,1\$.
```
a=>a.map(d=>o=(p[d<76|0]+="011343011334"[o+=d%7%4*3]-2,2-o%9&7)%3,p=[o=0,0])|o?3>>p[o-1]+1&!p[2-o]:(p=='0,0')*2
```
[Try it online!](https://tio.run/##RZDLboMwEEX3fIWLRGICOAbToD6GqlRlxYqt5YVlQtIqzVgQdZV/pyYP9S5Go3PPZuZb/@rRDF/2lByx2049TBpKzX60pR2UCNTK7rXYnLmKwOdpKnIxT5H7EiPogiLIV0IlWZwlGDwtijAQsQWJwGOuwjO@ibK0EpNUReniwUqnqWdqAZZOWIarbHqRHiF@XddVVfkxIes1SWcy79fcSd22bdU0rvgnVXP1HOHs8cYcvDNPeazH4VObPR0JlMTgccTDlh1wR3sqGWOjupxrLi0zez18uFe8n2g4Z/oD "JavaScript (Node.js) – Try It Online")
### How?
We keep track of the orientation \$o\in[0,1,2]\$ of the rolling block and the position \$p=(x,y)\$ of its top-left cube as described in this diagram:
[![orientations](https://i.stack.imgur.com/ViD88.png)](https://i.stack.imgur.com/ViD88.png)
Given the ASCII code \$d\$ of a direction character, we can turn it into a value in \$[0,1,2,3]\$ by reducing it modulo \$7\$ and then modulo \$4\$. To determine whether it's a vertical or horizontal move, we can simply test \$d<76\$.
| Character | d = ASCII code | d mod 7 | (d mod 7) mod 4 | d < 76 |
| --- | --- | --- | --- | --- |
| "B" | 66 | 3 | 3 | true |
| "F" | 70 | 0 | 0 | true |
| "L" | 76 | 6 | 2 | false |
| "R" | 82 | 5 | 1 | false |
We use a lookup string of digits in \$[0\dots4]\$ to get either \$dx+2\$ or \$dy+2\$:
```
p[d < 76 | 0] += "011343011334"[o += d % 7 % 4 * 3] - 2
```
The new orientation is given by the following magic formula (found by Steffan):
```
o = (2 - o % 9 & 7) % 3
```
Once all iterations have been processed, the test to be applied depends on the final value of \$o\$.
```
o ?
  3 >> p[o - 1] + 1 & !p[2 - o]
:
  (p == '0,0') * 2
```
* \$o=0\$ : return \$2\$ if \$x=0\$ and \$y=0\$, or \$0\$ otherwise
* \$o=1\$ : return \$1\$ if \$y=0\$ and \$x\in[-1,0]\$, or \$0\$ otherwise
* \$o=2\$ : return \$1\$ if \$x=0\$ and \$y\in[-1,0]\$, or \$0\$ otherwise
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), ~~78~~ 43 bytes
```
≔ＵＶ1jθ≔Ｅ²θηＦＥＳＸθ⌕FRBιＵＭη⁺κ×ι⊕№⁺⁻ηι…ηλκＩ⊘№ηθ
```
[Try it online!](https://tio.run/##PY7BqsIwEEX3fsXQ1RTi4r3tW2mwKCiU6g@EGk00ndQk7cOvjxMRZzGLcw@X2xsVeq9czqsY7ZWwfSbjaTMrN6mksfq5VbWAR/23@AgHNeJvIQIM04sP8GY7Gqd0TMHSFTlr/b8O@BDQWDpj1XTrSoCt@YBt6YdBMTcsuiniXcDJDjqiFbCjPuhBU9JnlH6ihG/lYIm/KSUC5LN3Who/FuBqJvdSzXtaHpBQqphwq9z87TBlcjFybrquW@/3eTm7Fw "Charcoal – Try It Online") Link is to verbose version of code. Explanation:
```
≔ＵＶ1jθ
```
Get `i` (square root of `-1`) into a variable.
```
≔Ｅ²θη
```
Start off with both cubes of the block on the starting square, which I've chosen to be `i` as it's golfier that way.
```
ＦＥＳＸθ⌕FRBι
```
Convert the movements into powers of `i` (`F = 1, R = i, B = -1, L = -i`) and loop over them.
```
ＵＭη⁺κ×ι⊕№⁺⁻ηι…ηλκ
```
Calculate which cube (if any) needs to move two squares (if both cubes were on the same square then I move the second cube two squares otherwise if one cube would have moved onto the square the other cube vacated then that cube moves two squares so that both cubes end up on the same square) and move the cubes appropriately.
```
Ｉ⊘№ηθ
```
Output half of the number of cubes that have returned to the starting square.
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 39 bytes
Maybe there is a clever string replacement or complex number algorithm that'll crush this score?
```
NÑN
=ḞḢH‘ɓ+0¦
ṚÇṚ
Ṛ1ĿṚ
⁹Ŀ
O:5%6çƒØ0AṀ«1
```
A full program which accepts the string and prints \$0\$ (standing at the origin), \$\frac{1}{2}\$ (covering the origin, but laying down), or \$1\$ (neither).
**[Try it online!](https://tio.run/##y0rNyan8/9/v8EQ/LtuHO@Y93LHI41HDjJOTtQ0OLeN6uHPW4XYgAWIYHtkPYj1q3HlkP5e/lamq2eHlxyYdnmHg@HBnw6HVhs7///9XCnJz83ELAkInHycQCnLycVMCAA "Jelly – Try It Online")**
### How?
Starts at \$[0,0]\$ and executes the string as instructions tracking coordinates of the centre of the block (i.e. executing `F` would lead to \$[0,1.5]\$) then inspects the resulting position.
Note, right and left are actually mirrored to make the code slightly shorter, so executing `R` would lead to \$[-1.5, 0]\$.
```
NÑN            - Link 1 (B): [x, y]
N              - negate
 Ñ             - call the next Link (Link 2) as a monad
  N            - negate
=ḞḢH‘ɓ+0¦      - Link 2 (F): [x, y]
 Ḟ             - floor -> [floor(x), floor(y)]
=              - ([x, y]) equals? (that) (vectorises)
  Ḣ            - head -> x eqauls floor(x)?
   H           - halve
    ‘          - increment -> 1 if rolling or 1.5 if toppling or erecting
     ɓ         - start a new chain with swapped arguments
       0¦      - apply to index 0 (the y of [x, y])
      +        -   add
ṚÇṚ            - Link 3 (L): [x, y]
Ṛ              - reverse
 Ç             - call the last Link (Link 2) as a monad
  Ṛ            - reverse
Ṛ1ĿṚ           - Link 4 (R): [x, y]
Ṛ              - reverse
  Ŀ            - monadic call to Link:
 1             -  1
   Ṛ           - reverse
⁹Ŀ             - Link 5 (call correct function): location [x, y]; instruction N
 Ŀ             - monadic call to Link:
⁹              -   chain's right argument = N
               - ...i.e. call Link N with argument [x, y]
O:5%6çƒØ0AṀ«1 - Main Link: list of characters, S
O             - ordinals (S) e.g. "BFLR" ->[66,70,76,82]
 :5           - integer divide by five   ->[13,14,15,16]
   %6         - mod six                  ->[ 1, 2, 3, 4]
      ƒØ0     - starting with [x,y]=[0,0] reduce that using:
     ç        -   call the last Link (Link 5) as a dyad
         A    - absolute values (that)
          Ṁ   - maximum
           «1 - minimum of that and one
```
[Answer]
# [Python 3.8+](https://docs.python.org/3.8/), 173 bytes
```
f=lambda s,c=[0,0]:f(s[1:],[v*n for v in(lambda x,y:[x,y+1.5-x%1])(*[w*n for w in c[::r]])[::r]])if s and[n:=2*(s[0]in"BL")-1,r:=2*(s[0]in"RL")-1]else min(1,max(map(abs,c)))
```
A recursive function that accepts a string ,`s`, and returns \$0\$ (standing at the origin), \$\frac{1}{2}\$ (covering the origin, but laying down), or \$1\$ (neither).
**[Try it online!](https://tio.run/##bVJNb6MwEL3zK2ZZdbFToNAPaYXEHjjklFOOS1DlJqbxigyR7XxUVX97dgxOy0o7B8DvPc@8eWL/Zrc9Pvzc68ulLTuxe9kIMPG6rLM4a4qWmTovmrg@zhDaXsMRFDIvO8dvRU2P2zx9Ss43ecPZrD554YmEsK6LQjcN9y/VggGBmxqL8n5GrbNGYVgtQp7ksZ5iywFrZGck7GhiHu/Eme3EnokXcsc5v1hprIESWABU4Xw@r6oqjOn7e/IL8hEdzmNN0PlyuawWC0f@g1YLr3dolj594ldiwAMeuAXdfLfj4KMYpHut0LI2Ct8d@BECyd9b5g78I@JBMAqiFSZJssIV/pa6N8CEhV6rV4XcpQNb0R0lwSMGP0Bs/oi1RMvTNF2ha7SRLc22z7Z/VmisPqyt6tEw5KMTLV00UTQcTlvVScCRcYWQlH7rq/i2pEUrir3Gm8dmory7K@HR97QHjU4dDAGg214LfJUsz1z52VNDZOL/Nq8uD50lTcum9EjSz@L5b2T2y/xXyNM7PuzxBmV9@Qs "Python 3.8 (pre-release) – Try It Online")**
[Answer]
# [J](http://jsoftware.com/), 54 bytes
```
1#.0=&><@0 0(2$]-.~]+(*1,1+=/))&.>/@,~0j1<@^'RFLB'i.|.
```
[Try it online!](https://tio.run/##Vc7BCoJAEAbg@zzFZNG6qetuUKCoyAZ7kg57Nw9hZYc8KOEhfHUzy6yBYf5vTv@182a@SLcz3yMEDEZOGPpI0EaOfr8Ow51OVCfmjIfLKIg5cnO9SB3Wppa5ErawQpfSJYvc2G75VQTxgWiVSFKwB@so5MdLiSckSikpJfl6SkprLZPk9yH/9SL0fTjsyzqvwLyjhXlTVHVxO9NXxxEAGWb4mT7CcCYCNIANGO82BjoRCjDG@2kyUb4zZ5tBI4F2Tw "J – Try It Online")
Output:
* 2 = fully on origin
* 1 = half on origin
* 0 = not on origin
## idea
We imagine the moving block as two separate squares which move around together, sometimes sliding on top of one another (flat to upright), sometimes spreading out (upright to flat), sometimes moving in parallel (flat rolling). For example, Consider `FFRR`:
```
0   0   <- start, both blocks on origin
0j1 0j2 <- F, blocks slide apart
0j3 0j3 <- F, blocks slide together
1j3 2j3 <- R, blocks slide apart again
1j2 2j2 <- B, blocks move in parallel
```
At a high level, it works like this:
1. `0j1<@^'RFLB'i.|.` Map `RFLB` to the complex numbers `1 0j1 _1 0j_1`, reverse them, and append `0 0` (the starting point of our two sliding blocks), setting ourselves up for a single reduction.
2. `2$]-.~]+(*1,1+=/)` The reduction logic. Multiply the current "step direction" by either `1 1` or `1 2`. Multiply by `1 1` if our sliding blocks are currently separate, and by `1 2` (to separate them) if they are currently overlapping.
3. `]+` Add that adjusted "step direction" elementwise to the current position to create two new positions...
4. `]-.` And set minus the current positions from the new ones.
5. `2$` Ensure the new position is extended to two elements -- in the case that we go to standing long ways, the previous step will only return a single result -- the new position -- and so we have to duplicate that.
[Answer]
# Python3, 356 bytes:
```
m={'F':[0,1],'B':[0,-1],'L':[1,-1],'R':[1,1]}
def M(x,c,o):p,v=m[x[0]];J=c[[0,-1][v!=1]][0];K=c[[0,-1][v!=1]][1];return[[([(J+2*v,K),(J+v,K)],1),([(J+v,K)],0),([(x+v,y)for x,y in c],o)][o],[([(J,K+2*v),(J,K+v)],2),([(x,y+v)for x,y in c],o),([(J,K+v)],0)][o]][p]
f=lambda x,c=[(0,0)],o=0:1*((0,0)in c)/len(c)if''==x else f(x[1:],*M(x,sorted(c,reverse=1),o))
```
[Try it online!](https://tio.run/##ZZBBT4MwGIbv@xV1Hmjnp9IZE8PSSw8ctnnh@uU7TChxyUZJhwRi/O3Ygs64nXjep7wvoXXfvNvq6aV2w3BUn1EaJRiDJIj0SPcBtx7lhNmIkr5mhSnZK@8gByuSGlp1xA5jotVa5Tg1sb1Rksjb1eZKSlo503y4CpEjX98tFy1sBHgKTwLpGc8pHlPnUy9K61gHPdtXLCf/dUJLMI7AJsyEEU@try2nGvQ@Xdbgp9GO82GEsKZZqQ6741ux8@/mCnkczsCqOJELPqbQF48HU/Fc7MsoUqpj5nAyrOQdyoRgEa7lZF1jCp6DM61xJ6P8/1ghhtrtq4aXfJ6mqdZ6LgS7lbOzvcxplmV6u73WenLxw/M/@6v/pE6n8vAN)
[Answer]
# [C++ (gcc)](https://gcc.gnu.org/), 145 bytes
A little late to the party, but here is my two cents (or 145, rather).
Outputs:
* 2 = Standing upright on origin
* 1 = Half-on, half-off the origin
* 0 = Not on the origin
```
int f(char*s){int d=0,p=0;for(s--;*++s;){int n=*s>71?*s>79?3:-3:*s>69?2:-2;p+=d&&d!=n?n:n*2;if(d==-n||d==n)d=0;else if(!d)d=-n;}return!p+!(p+d);}
```
[Try it online!](https://tio.run/##fY@xboMwEIbn8hQmlSIb121KpFbBOEgMTJl4A2qbxFI4LNtMCc9OjTplSJe7@/5POt1Ja9lZymUxEFCP5aVzmSe3lZTYvVmx4/3osGeMZ5R6/qdAZP74/Vmt9VDtC7Yv4vh1qPKC5dxSobZblQqooIAs56bHSggG93tsQOJirq9eo5inKiIDPjsdJgeppSm2VBE@L69msKML5Y8J/sMHJSl9vxyTyRs4I@gG7W0nNYqGJ@tRQ2cAE3RLXuQ4BVSW8Z9N0zR1XW/IihrUlT/YZ3nTtm19Oj3X9X/uUc7LLw "C++ (gcc) – Try It Online")
## Explanation
We store the direction the block is facing in variable `d` and the position of one side of the block in variable `p`. We then use numbers 2 and 3 to represent the directions (with ±2 being forward/backward and ±3 being right/left), since 2 and 3 are linearly independent so we can represent any position that way with a single variable.
We then check if `p` equals 0 and if `p+d` equals 0, and add those values. If both `p == 0` and `p+d == 0`, then we are standing upright on the origin. If one of `p == 0` and `p+d == 0` is true, then we are sideways on the origin (since p is always tracking the same end of the block). If neither is true, then we are not on the origin.
### Ungolfed
```
int f(char*s) {
    int d = 0;  // Direction of the block (-2 = back, +2 = front, -3 = left, +3 = right)
    int p = 0;  // Position of the block
    
    // Loop through the string with pointer arithmetic. When we reach \0, we break out.
    for (s--;*++s;) {
        // The current movement of the block. 
        int n = *s > 71 ? (*s > 79 ? 3 : -3) : (*s > 69 ? 2 : -2);
        
        p += (d && d != n) ? n : n*2;  // If (d == 0 || d == n) (if d is upright or d and n are in the same direction), add 2n. Otherwise, add n. (we flipped the conditional to save a byte)
        if (d == -n || d == n) d = 0;  // If (d == -n || d == n) (in other words, if d is aligned with n), set d to be 0 (upright).
        else if (d == 0) d = -n;       // If no direction (block is upright), set d to be -n.
                                       // Otherwise, don't touch d since we are rolling "sideways", so the direction does not have to change.
    }
    return !p+!(p+d);                  // If p+d == 0, then the block is either straight or sideways on the origin. If additionally, p == 0, then the block is straight and on the origin.
}
```
[Answer]
# [JavaScript (Node.js)](https://nodejs.org), 78 bytes
```
a=>a.map(d=>p[k=d<76|0]+=~-(d/2&2)*(p[1-k]&1^3),p=[0,0])|'21'[p[0]**2+p[1]**2]
```
[Try it online!](https://tio.run/##Tcy7DoIwFAbgnadoGKDcC0YdtAxNZGJibWrSAPUC0gbUifjqSING/@WcfOfPufInH8r@ou5BJ6t6EnjiOOXhjStY4VTRBlf77WZEzMOvAFZRYiWOCxWNg4ZZ8XHl@ApT5CPmjHYS21RRxFw38eaGnmzaUQMAM8syQojpAxBFINai9yVfyYqiIHk@H35C8qU3CwrXH/ugNi25@fcJGcwIhewPvDzDAeAUlLIbZFuHrTxBAclDiLqHgzNnegM "JavaScript (Node.js) – Try It Online")
Only even positions are tile. Position [1,0] mean half on [0,0] and half on [2,0]. Position [1,1] unused
| Character | d = ASCII code | d in binary | d / 2 & 2 | d < 76 |
| --- | --- | --- | --- | --- |
| "B" | 66 | 1000010 | 0 | true |
| "F" | 70 | 1000110 | 2 | true |
| "L" | 76 | 1001100 | 2 | false |
| "R" | 82 | 1010010 | 0 | false |
```
a=>                   // Take Buffer input instead to save a byte
a.map(d=>             // For each instruction
  p[k=d=='B'|d=='F']  // Dimension
  +=((d/2&2)-1)       // Direction
  *(p[1-k]%2?2:3)     // If lay on another direction, move 1
  ,                   // Else move 1.5
  p=[0,0]
)|(                   // Result
  p[0]**2+p[1]**2==0?2:p[0]**2+p[1]**2==1?1:0
)
```
]