text:
Create a list of snaking numbers under 50,000
Snaking Number Challenge
I wonder how many snaking numbers there are between 1 and 50,000?

Snaking Numbers, in this game, are numbers which can be typed out on a traditional numberpad (format below) by moving one key up, down, left, or right.
7 8 9
4 5 6
1 2 3
 0

For example, if you start with the number 5, you could select 4, 6, 8, or 2 as your next valid move - however 7, 3, 9, and 1 are off-limits as they are positioned diagonally to the current key.
So, if you have 5, then 2, your next viable key choices are 0, 1, 3, or 5 again.
In this Code Golf exercise, you are to output a list of all the positive snaking numbers between 1 and 50k, along with a final count of all the numbers that meet the criterion.
Rules

Numbers cannot start with a Zero.
Numbers must be whole positive integers.
Each consecutive number, read from left to right, must "snake" around the numberpad.
The snake cannot travel diagonally across keys
The number 0 can be accessed from both numbers 1 and 2
Numbers cannot be paired (eg: 22)

Examples of valid Snaking Numbers:
12369
45201
1254
10102
1
12
987

Examples of invalid numbers
1238 - 8 is not connected
0001 - multiple leading 0s
0101 - leading 0
159  - snake cannot travel diagonally
4556 - duplicate 5

As per normal Code Golfs, the aim is fewest bytes!
According to my maths and rules, you should have 670 valid snaking numbers in your list, plus 670 itself printed as the last number.

Should the output be sorted? Or is it allowed in any order?

Seeing as you're asking us to output a fixed and finite set of integers, I'd suggest including the full list in the spec.

Related

This is a subset of A215009.

Would it be alright to print 670 first?

K (ngn/k), 60 57 60 bytes
(x;#x:({*/1=3!5&+/x*x:+1_-':(+0 1,'2*!3 3)@10\x}')#1+!50000)

Try it online!
!50000 list of 0 .. 49999
1+ add 1 to all
({ }')# filter with the function in { }
10\x decimal digits of the argument
( )@ use as indices in ...

!3 3 a pair of lists: (0 0 0 1 1 1 2 2 2;0 1 2 0 1 2 0 1 2)

2* multiply all by 2

0 1,' prepend 0 to the first list and 1 to the second

+ transpose (pair of lists -> list of pairs). this gives us the approx button coords.

-': subtract from each pair the previous pair. use 0 0 as an imaginary element before the first.
1_ drop the first
+ transpose
x*x: square (assign to x and multiply by x). here x is a pair of lists - ∆x-s and ∆y-s
+/ sum the two lists (element by element)
5& min with 5
3! mod 3
1= boolean list of where it's equal to 1
*/ product (boolean "and")
(x;#x: ) make a pair of the result and the length (#) of the result

Jelly,  24  23 bytes
5ȷ4µDo1.’d3ZIASĊ’ẸµÐḟṄL

A full program which prints a list of all the results and then the number of results.
Try it online!
How?
5ȷ4µDo1.’d3ZIASĊ’ẸµÐḟṄL - Main Link: no arguments
5ȷ4                     - 5*10^4 = 50000
   µ              µÐḟ   - filter discard those for which this is truthy:
                        -                  e.g.: 8520        ... or           4559
    D                   -   decimal digits       [8,5,2,0]                    [4,5,5,9]
      1.                -   literal 1.5
     o                  -   logical OR           [8,5,2,1.5]                  [4,5,5,9]
        ’               -   decrement            [7,4,1,0.5]                  [3,4,4,8]
         d3             -   div-mod by 3         [[2,1],[1,1],[0,1],[0,0.5]]  [[1,0],[1,1],[1,1],[2,2]]
           Z            -   transpose            [[2,1,0,0],[1,1,1,0.5]]      [[1,1,1,2],[0,1,1,2]]
            I           -   deltas               [[-1,-1,0],[0,0,-0.5]]       [[0,0,1],[1,0,1]]
             A          -   absolute value       [[1,1,0],[0,0,0.5]]          [[0,0,1],[1,0,1]]
              S         -   sum (vectorises)     [1,1,0.5]                    [1,0,2]
               Ċ        -   ceiling              [1,1,1]                      [1,0,2]
                ’       -   decrement            [0,0,0]                      [0,-1,1]
                 Ẹ      -   any?                 0 (i.e. keep)                1 (i.e. discard)
                     Ṅ  - print and yield
                      L - length
                        - implicit print

I'd love to know how this one works. Any chance you could give a breakdown?

@MightBeAlon will do later...

I am curious, how does 1.evaluate to 1.5?

@EmbodimentofIgnorance during literal parsing a missing digit after a period is treated as being a five. See the final else clause of parse_literal in interpreter.py

Python 3, 140 bytes
f=lambda s:''==s[1:]or s[1]in'10021234562216565878 43 749 9   5  8'[int(s[0])::10]and f(s[1:])
print(*filter(f,map(str,range(1,50000))),670)

Try it online!
I'm positive someone will be able to do this with an expression instead of a lookup string.

Python 2, 101 bytes
print[n for n in range(1,50000)if all(`n`[i:i+2]in`0x20b33ec8bc49a10589e76b15`for i in range(4))],670

Try it online!
The hex number is decimal 10120214525632365878969854741, which encodes every ordered pair of digits that can appear adjacent to one another.

JavaScript (V8),  112 106  104 bytes
Saved 2 bytes thanks to @NahuelFouilleul
A full program.
for(n=0;++n<5e4;)[...n+''].every(x=>'6589632145201478'.match(x+p+'|'+p+(p=x)),p='')&&print(n)
print(670)

Try it online!
Or 96 bytes if we can output the numbers in reverse order:
for(n=5e4;n--;)[...n+''].every(x=>'6589632145201478'.match(x+p+'|'+p+(p=x)),p='')&&print(n||670)

Try it online!

works also removing the last 3 maybe because 36 is already in string

@NahuelFouilleul Good catch. Thanks!

also 6589632145201478 is one byte shorter

Stax, 37 35 bytes
ü╞╡~▄ⁿ♪eµïê◙ü╔ï▼ΔJr¥æ≤PH╟♀I♣Δz8─¶Γ╞Ç▓

Run and debug it at staxlang.xyz!
It was so nice and short, until it wasn't.
Unpacked (42 bytes) and explanation
49999{E2B{{om"#qYY>!(AFI"%A|E2B{{om-C_Qf%p
49999{                                 f      Filter range [1..49999]:
      E2B                                       All adjacent pairs of digits
         {{om                                   Each sorted
             "#qYY>!(AFI"%A|                    Literal 2012365478963258741
                            E2B{{om             Pairs of digits, each sorted
                                   -            Set difference
                                    C           Cancel block execution if any remain
                                     _Q         Print current value
                                        %p    Print length

2012365478963258741 encodes the keypad. Look at pairs of adjacent digits. Perhaps if I could get a decently short alternative that goes in both directions for each pair, I could cut the eight bytes of {{om.
Without that trailing 670, a simple filter would suffice: f..! instead of {..C_Qf%p. There might be a better way to go about handling this irregularity. In either case, this filter-range behavior is undocumented.

Sorry about the documentation gaps.  FWIW, that one will be in the next release, 1.1.7.  You can see a preview at http://stax.tomtheisen.com/ , but it's a secret so don't tell anyone. ;)

Perl 5 (-M5.01), 96, 92 bytes
-4 bytes thanks to @Xcali
$r=join"|",map$t++."[^$_]",12,240,1350,26,157,2648,359,48,579,68;map/$r/||say,1..5e4;say 670

TIO

92

thanks indeed, over-complicated because first answer was positive match

PHP, 145 bytes
for(;$i++<5e4;$f&&print$i._)for($f=1,$l=b;''<$d=("$i")[$$i++];$l=$d)$f&=$l>a||strstr([12,240,1053,26,157,2468,359,48,579,68][$l],$d)>'';echo 670;

Try it online!
For every number from 1 to 50,000, checks every digit of that number from left to right. If all digits are in the list of valid digits of the previous digit, that number is printed. At the end prints a hard coded 670 since it takes less bytes than actually counting it.

05AB1E, 23 bytes
ŽÅKLʒSÌYX;:3‰üαï€OP}=g=

Try it online!
Port of Jonathan Allan's Jelly answer.

Ah, smart of just compressing the 50000 in 3 bytes. I was using ₄50* or 4°5* when I was making an attempt earlier. And at first I was confused why you had €OP instead of just OP, but then I realized the single digit numbers (being an empty list after the üα) would then be [] → 0 → 0 instead of [] → [] → 1. :)

@KevinCruijssen Why 4°5* when you can 5°;? I like ZAK better though. And yeah, that edge-case for single-digit numbers is a pain.

JavaScript (SpiderMonkey), 179 173 151 129 bytes
[12,240,1350,26,157,2468,359,48,579,68].map((_,i,l)=>i&&(f=(v,t)=>print(v)|v<5e3&&[...l[t]+''].map(k=>f(v+k,k)))(i,i)),print(670)

Try it online!
-22 bytes thank to Arnauld
-22 bytes thank to dana
explanation:
[12,240,1350,26,157,2468,359,48,579,68]
// an array where keys are current position and values, the possible destinations
.map((_,i,l)=>                    // loop over it
    i&&(                          // if key is not 0
        f=(v,t)=>                 // create a function
                 print(v)|        // which print the value
                          v<5e3&& // and if the limit is not attained
                                 [...l[t]+''].map(k=>f(v+k,k))
                    // recurcively call itself with for each destinations
                                                              )(i,i)),
                    // make the first call with each digit
print(670) // finally print 670

@dana also gave a 123 bytes solution if we can print 670 first
[21,420,5310,62,751,8642,953,84,975,86].map((_,i,a)=>(f=(v,t)=>print(i?v:640)|i&v<5e3&&[...a[t]+''].map(k=>f(v+k,k)))(i,i))

@Arnauld thank I forgot this rule

Some optimizations

129?

123 if 640 can be printed first.

Ruby, 99 bytes
1.upto(5e4){|n|w,*x=n.digits;x.all?{|d|[6,21,43,68,162,340,552,272,672,320][w][w=d]>0}&&p(n)}
p 670

Try it online!

Stax, 28 26 bytes
Δh┤♣É╦&·é╝n$K»à¶▲v═NÆ;↨m≥8

Run and debug it
Unpacked, ungolfed, and commented, it looks like this.
G               Call to unbalanced trailing '}', then resume here
670P            Print 670
}               Call target
219J            219 squared (47961)
f               Filter 1-based range by the rest of the program; implicitly output
  $2B           Convert to string and get adjacent pairs; e.g. 213 -> ["21", "13"]
  O             Push 1 under list of pairs
  F             Iterate over pairs, using the rest of the program
    o           Order each pair; e.g. "21" -> "12"
    "{<f:[/T8Z" string literal with code points [123 60 102 58 91 47 84 56 90]
    $           concate as string i.e. "12360102589147845690"
    s#          How many times does the current pair appear in the constant string?
    *           Multiply this by running total.  Any zero will cause the result to be zero.

Run this one
The secret sauce is in the string literal "{<f:[/T8Z".  After jamming all the codepoints together, you get 12360102589147845690.  The ascending pairs in this string are the valid snake moves.

15JJ instead of 219J would work as well, but I don't think you can golf any byte from there unless there's a 1-byte constant for 15.

Haskell, 118 bytes
(filter(and.(zipWith elem.tail<*>map f).show)[1..50000],670)
f c=words"12 024 0135 26 157 2468 359 48 579 68"!!read[c]

Try it online!
A first pass; I'm not good at compression.
The s= doesn't count, since we don't actually need to bind the result.
Ungolfed code.

Japt, 34 bytes
5e4õs f_ä@"-Pì[/Z8"mc øZñÃe
pUl

Try it

Perl 6, 64 bytes
{670,grep {[+&](:36<12HGX91H8VCL3MG0FDVQ>X+>m:ov/../)%2},1..5e4}

Try it online!
Explanation
{670,grep {...},1..5e4}  # Meet questionable output requirements

# Actual decision problem

     :36<12HGX91H8VCL3MG0FDVQ>  # Bit field of allowed transitions
                                # encoded in base 36
                                 m:ov/../  # All 2-digit substrings
                              X+>  # Right shift by each substring
                                   # (implicitly converted to an integer)
[+&](                                    )  # Binary and
                                          %2  # Modulo 2

It's a pity ~> isn't implemented yet, otherwise you might be able to do this with just string operators, with the bit field being a string

Pyth, 68 65 45 bytes
l
f.Am}dCtB+J`65874589632012541_PJCtB`TS50000

Try it online!
Inspiration for the revised lookup process came from Khuldraeseth na'Barya's Stax answer, go give them an upvote!

Edit 2: Rewrote to save a bunch of bytes, previous version:
l
f.Am}ed@c"12 024 0135 26 157 2468 359 48 579 68";shdCtB`TS50000

Edit: Golfed 3 bytes by using string lookups, previous version:
l
f.Am}ed@sMMc"12 024 0135 26 157 2468 359 48 579 68";hdCtBjT;S50000

Charcoal, 42 bytes
≔ΦＩ…·¹×⁵⁰φ⬤ι№”)¶∧XRτ_ΠＧêＲ⁵m⎇λ”✂ιμ⁺²μ¹θθＩＬθ

Try it online! Link is to verbose version of code. Explanation:
≔ΦＩ…·¹×⁵⁰φ

Process the inclusive range from 1 to 50,000 cast to string.
⬤ι№”)¶∧XRτ_ΠＧêＲ⁵m⎇λ”✂ιμ⁺²μ¹θ

Filter out those that have pairs of digits not contained in the compressed string 01478963202125458565236987410.
θＩＬθ

Output the remaining array and its length.


text:
Write a "hello world" program that can be compiled/interpreted as two different languages simultaneously
Rules:

Your program must print "hello world" when executed
Your program must be interpretable or compilable into 2 or more languages
Your program must require no input or arguments
Languages with identical syntax are too easy, and will be shunned. We all know you can write echo hello world in Bash and Batch, so let's make it more interesting.

I'll add my example as an answer.

Really close and not a dupe. (This does a subset of that challenge.)

Welcome to Programming Puzzles and Code Golf! I marked your challenge as duplicate of this challenge, which is almost identical with just a different scoring algorithm. Additionally, "identical syntax" is not an observable or objective requirement, and needs to be more clearly defined or removed to make this challenge valid by the rules of this site. In the future, I recommend using the Sandbox to get some reviews

before posting the challenge to the main site. Please ping me here or in chat if you edit this question such that it is not a duplicate and has no unobservable requirements so I can revert the duplicate mark (if I hammer more than once); alternatively, if the challenge is significantly different enough to not be a duplicate, consider rewriting it into Sandbox.

@HyperNeutrino Thanks for the feedback. I will copy this over to the sandbox and see where it goes.

I have posted a modified version of my question here: https://codegolf.meta.stackexchange.com/a/18038/88942

Python 2.7 and Bash, 45 bytes
x="hello world"
''''echo $x;exit #'''
print x

Adding 1 byte can make it Python 3 compatible as well -- print(x)
Explanation by line:

Variable assignment valid in both languages
Python comment ''' with an extra ' will be interpreted as 0-length string concatenation in bash, followed by echo and exit. The #''' closes the python comment block, but is preceded by a bash comment, so it will be ignored
Python print (bash will exit before getting here, so it won't complain)

Ruby and Foo, 17 bytes
puts"hello world"

Foo prints everything in the quotes, and Ruby uses a built-in function to output to stdout.

source: Stack Exchange

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

sort: votes


text:
Plane Blowup
The Blow-up is a powerful tool in algebraic geometry. It allows the removal of singularities from algebraic sets while preserving the rest of their structure.
If you're not familiar with any of that don't worry, the actual computation is not difficult to understand (see below).
In the following we are considering the blow-up of the point \$(0,0)\$ of an algebraic curve in 2D. An algebraic curve in 2D is given by the zero-locus of a polynomial in two variables (e.g. \$p(x,y) = x^2 + y^2 - 1\$ for the unit circle, or \$p(x,y) = y-x^2\$ for a parabola). The blowup of that curve (in \$(0,0)\$) is given by two polynomials \$r,s\$ as defined below. Both \$r\$ and \$s\$ do describe \$p\$ with the (possible) singularity at \$(0,0)\$ removed.
Challenge
Given some polynomial \$p\$, find \$r\$ and \$s\$ as defined below.
Definition
First of all note that everything I say here is simplified, and does not completely correspond to the actual definitions.
Given a polynomial \$p\$ in two variables \$x,y\$ the blowup is given by two polynomials \$r,s\$ again each in two variables.
To get \$r\$ we first define \$R(x,v) := p(x,vx)\$. Then \$R(x,v)\$ is probably a multiple of \$x\$, i.e. \$R(x,v) = x^n \cdot r(x,v)\$ for some \$n\$ where \$x\$ does not divide \$r(x,v)\$. Then \$r(x,v)\$ is basically what remains after the division.
The other polynomial is defined exactly the same, but we switch the variables: First write \$S(u,y) := p(uy,y)\$. Then \$s\$ is defined such that \$S(u,y) = y^m \cdot s(u,y)\$ for some \$m\$ where \$y\$ does not divide \$s(u,y)\$.
In order to make it clearer consider following
Example
Consider the curve given by the zero locus of \$p(x,y) = y^2 - (1+x)  x^2\$. (It has a singularity at \$(0,0)\$ because there is no well defined tangent at that point. )

Then we find
$$R(x,v) = p(x,vx) = v^2x^2-(1+x)x^2 = x^2  (v^2-1-x)$$
Then \$r(x,v) = v^2 -1 -x\$ is the first polynomial.
Similarly
$$S(u,y) = p(uy,y) = y^2 - (1+ uy)  u^2  y^2 = y^2  (1 - (1 + uy)u^2)$$
Then \$s(u,y) = 1 - (1 + uy)u^2 = 1 - u^2 + u^3y\$.

Input/Output Format
(Same as here.) The polynomials are represented given as(m+1) x (n+1) matrices/lists of lists of integer coefficients, in the example below the terms of the coefficients are given in their position:
[   1 * 1,   1 * x,   1 * x^2,   1 * x^3,  ... , 1 * x^n ]
[   y * 1,   y * x,   y * x^2,   y * x^4,  ... , y * x^n ]
[   ...  ,   ...   ,   ...   ,    ...   ,  ... ,   ...   ]
[ y^m * 1, y^m * x, y^m * x^2, y^m * x^3 , ..., y^m * x^n]

So an ellipse 0 = x^2 + 2y^2 -1 would be represented as
[[-1, 0, 1],
 [ 0, 0, 0],
 [ 2, 0, 0]]

If you prefer you can also swap x and y. In each direction you are allowed to have trailing zeros (i.e. coefficients of higher degrees that are just zero). If it is more convenient you can also have staggered arrays (instead of a rectangular one) such that all sub sub-arrays contain no trailing zeros.

The output format is the same as the input format.

Examples
More to be added (source for more)
Trifolium
p(x,y) = (x^2 + y^2)^2 - (x^3 - 3xy^2)
r(x,v) = v^4  x + 2  v^2  x + x + 3  v^2 - 1
s(u,y) = u^4  y + 2  u^2  y + y - u^3 + 3  u

Descartes Folium
p(x,y) = y^3 - 3xy + x^3
r(x,v) = v^3  x + x - 3v
s(u,y) = u^3  y + y - 3u

Examples w/o pictures
Trifolium:
p:
[[0,0,0,-1,1],
 [0,0,0, 0,0],
 [0,3,2, 0,0],
 [0,0,0, 0,0],
 [1,0,0, 0,0]]
r: (using the "down" dimension for v instead of y)
[[-1,1],
 [ 0,0],
 [ 3,2],
 [ 0,0],
 [ 0,1]]
s: (using the "right" dimension for u instead of x)
[[0,3,0,-1,0],
 [1,0,2, 0,1]]

Descartes Folium:
p:
[[0, 0,0,1],
 [0,-3,0,0],
 [0, 0,0,0],
 [1, 0,0,0]]
r:
[[ 0,1],
 [-3,0],
 [ 0,0],
 [ 0,1]]
s:
[[0,-3,0,0],
 [1, 0,0,1]]

Lemniscate:
p:
[[0,0,-1,0,1],
 [0,0, 0,0,0],
 [1,0, 0,0,0]]
r:
[[-1,0,1],
 [ 0,0,0],
 [ 1,0,0]]
s:
[[1,0,-1,0,0],
 [0,0, 0,0,0],
 [0,0, 0,0,1]]

Powers:
p:
[[0,1,1,1,1]]

r:
[[1,1,1,1]]

s:
[[0,1,0,0,0],
 [0,0,1,0,0],
 [0,0,0,1,0],
 [0,0,0,0,1]]

This title definitely isn't what I thought it was...

Suggested testcase: 0+x+x^2+x^3+x^4

@Cowsquack Added it!

Python 3 + numpy, 165 134 bytes
lambda p:(r(p),r(p.T).T)
from numpy import*
def r(p):w,l=where(p);s=w+l;n=min(s);o=zeros((len(p),max(s)-n+1));o[w,s-n]=p[w,l];return o

Try it online!
The function takes one numpy 2D array p as input and returns a tuple of (r,s) of two numpy 2D arrays.
The breakdown of the solution is as follows. In order to compute the polynomial \$r\$, we rewrite each term \$x^jy^i\$ of \$p\$ into \$x^{j+i}(\frac{y}{x})^i\$, and it becomes \$x^{j+i}u^i\$ in \$p(x,ux)\$. So we can rearrange the input \$(m+1)\times (n+1)\$ matrix \$P\$ into a \$(m+1)\times (m+n-1)\$ matrix \$D\$ corresponding to \$p(x,ux)\$ by setting \$D[i,j+i]=P[i,j]\$. Then we eliminate all-zero columns at the beginning and end of \$D\$ to perform a reduction and get the output matrix \$R\$ for \$r\$.
To compute \$s\$, we simply swap \$x\$ and \$y\$, repeat the same process, and then swap them back. This corresponds to computing \$R\$ for \$P^T\$ and then transposes the outcome.
The following ungolfed code shows the above computation process.
Ungolfed (Basic)
import numpy as np

def r(p):
    num_rows, num_cols = p.shape
    deg_mat = np.zeros((num_rows, num_rows + num_cols - 1))
    for i, row in enumerate(p):
        deg_mat[i, i:i+num_cols] = row
    non_zero_col_idx, = np.where(deg_mat.any(axis=0))
    return deg_mat[:,non_zero_col_idx.min():non_zero_col_idx.max()+1]

def rs(p):
    return r(p), r(p.T).T

Try it online!
A further improvement of the solution computes the matrix \$R\$ in one single pass based on \$R[i,j+i-c]=P[i,j]\$, where \$c=\min_{P[i,j]\neq 0}i+j\$.
Ungolfed (Improved)
import numpy as np

def r(p):
    y_deg, x_deg = np.where(p)  # Retrieve degrees of y and x for non-zero elements in p
    total_deg = y_deg + x_deg
    min_total_deg = total_deg.min()
    max_total_deg = total_deg.max()
    out = np.zeros((p.shape[0], max_total_deg - min_total_deg + 1))
    out[y_deg, y_deg + x_deg - min_total_deg] = p[y_deg, x_deg]
    return out

def rs(p):
    return r(p), r(p.T).T

Try it online!

APL (Dyalog Unicode), 38 37 bytes
1 byte saved thanks to ngn by using +/∘⍴ in place of the dummy literal 0
⊢∘⍉\+/∘⍴{q↓⍨⊃⍸×∨/q←(-⍳≢⍉⍵)⊖⍺↑⍵}¨⊂,⊂∘⍉

Try it online!
(a train with ⎕io (index origin) set as 0)
⊂ enclosed right argument
, concatenated with

⊂∘ enclosed
⍉ transposed right argument

\$s\$ is computed from the former, \$r\$ from the latter
¨ on each
+/∘⍴{ ... } perform the following function with left argument

+/ sum

⍴ the shape of the right argument, i.e. get rows+columns

and the right argument will be each of the enclosed matrices.
⍺↑⍵ and take left argument ⍺ many rows from the right argument ⍵, if ⍵ is deficient in rows (which it will be because rows+columns > rows), it is padded with enough 0s
The computation of substituting \$vx\$ or \$uy\$ in place of \$y\$ or \$x\$ is done by rotating the columns of ⍵ by their index, and since ⍵ is padded with 0s, columns of ⍵ are effectively prepended by the desired amount of 0s.
⊖ rotate columns by

⍉⍵ transposed ⍵
≢ count rows, all together, ≢⍉⍵ gets the number of columns in ⍵
⍳ range 0 .. count-1
- negated, to rotate in the other direction and the default for ⊖, to ultimately yield 0 ¯1 ¯2 ... -(count-1), this automatically vectorises across each column such that the 0-th column is rotated by 0, the 1-st by 1, ...

q← assign this to variable q
Now to divide the polynomial by the largest power of \$x\$ or \$y\$, the leading all-0 rows have to be removed.
∨/ reduce by LCM across each row, if the row is all-0s, this yields 0, otherwise it gives a positive number
× get its sign, 0 → 0 and positive number → 1
⍸ indices of truthies, i.e. indices of 1s
⊃ pick the first element, ⊃⍸ simply gets the index of the first 1
q↓⍨ drops that many rows from q, again ⎕io←0 helps in ⍸ returning the correct value for dropping the leading all-0 rows
(exit function)
\$s\$ is already achieved, to get \$r\$ the second value has to be transposed via ⊢∘⍉\

Other approaches are listed below.
⍝(⊢∘⍉\+/∘⍴{q↓⍨⊃⍸×∨/q←(-⍳≢⍉⍵)⊖⍺↑⍵}¨⊂,⊂∘⍉)¨a
⍝(⊢∘⍉\∘⌽⍴{q↓⍨⊃⍸×∨/q←(-⍳⍺)⊖⍵↑⍨+/⍴⍵}¨⊂∘⍉,⊂)¨a
⍝(⊢∘⍉\⌽∘⍴{q↓⍨⊃⍸×∨/q←(-⍳⍺)⊖⍵↑⍨+/⍴⍵}¨⊂,⊂∘⍉)¨a
⍝(⊢∘⍉\0{q↓⍨⊃⍸×∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵}¨⊂,⊂∘⍉)¨a
⍝(⊢∘⍉\+/∘⍴({⍵↓⍨⊃⍸×∨/⍵}(-∘⍳1⊃⊢∘⍴)⊖↑)¨⊂,⊂∘⍉)¨a
⍝(⊂∘⍉∘⊃@0⍴{q↓⍨⊃⍸×∨/q←(-⍳⍺)⊖⍵↑⍨+/⍴⍵}¨⊂∘⍉,⊂)¨a
⍝{⊢∘⍉\{q↓⍨⊃⍸×∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵}¨⍵(⍉⍵)}¨a
⍝(⊢∘⍉\(({⍵↓⍨⊃⍸×∨/⍵}(-∘⍳1⊃⍴)⊖⊢↑⍨1⊥⍴)¨⊂,⊂∘⍉))¨a
⍝(0 1{⍉⍣⍺⊢q↓⍨⊃⍸×∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵}¨⊂,⊂∘⍉)¨a
⍝{⊢∘⍉\{q[;⍸×∨\∨⌿q←↑(,\0⍴⍨≢⍵),¨↓⍵]}¨⍵(⍉⍵)}¨a
⍝{⊢∘⍉\{q↓⍨1⍳⍨×∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵}¨⍵(⍉⍵)}¨a
⍝(⊢∘⍉\(((⊢↓⍨1⍳⍨0≠∨/)(-∘⍳1⊃⍴)⊖⊢↑⍨1⊥⍴)¨⊂,⊂∘⍉))¨a
⍝{⊢∘⍉\{q[⍸×∨\∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵;]}¨⍵(⍉⍵)}¨a
⍝{⊢∘⍉\{q↓⍨+/0=∨\∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵}¨⍵(⍉⍵)}¨a
⍝{⊢∘⍉\{q↓⍨⌊/+⌿∧⍀0=q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵}¨⍵(⍉⍵)}¨a
⍝(⌽∘⍉¨1↓({⊖⍉q[⍸×∨\∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵;]}\3/⊂))¨a
⍝{⊢∘⍉\{↑(↓q)/⍨∨\×∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵}¨⍵(⍉⍵)}¨a
⍝f←⊢∘⍉\⋄{f{q[⍸×∨\∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵;]}¨f⍵⍵}¨a
⍝{1↓⌽∘⍉¨{⊖⍉q[⍸×∨\∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵;]}\3/⊂⍵}¨a
⍝{f←{q[⍸×∨\∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵;]}⋄(f⍵)(⍉f⍉⍵)}¨a
⍝{⊢∘⍉\{↑(↓q)/⍨∨\0≠∨/q←(-⍳≢⍉⍵)⊖⍵↑⍨+/⍴⍵}¨⍵(⍉⍵)}¨a
⍝{⊢∘⍉\{(0~⍨∊⍵)@(↓⍉(⊢-⌊/)@1+⍀⍉↑⍸0≠⍵)⊢0⍴⍨,⍨⌈/⍴⍵}¨⍵(⍉⍵)}¨a

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


text:
Compress my Malbolge!
Background
Malbolge is truly intriguing language. But programs written in it are also extraordinairly huge (and in some cases, unpostable on PPCG).
Your challenge (shall you accept it) is, to compress and decompress given normalized Malbolge program. Devise your own lossless algorithm. You may compress your data further using an existing algorithm afterwards, but you must cite the algorithm used. You may use dictionaries.
Input
On the input, there will be given (in most cases very long) string, containing only following characters: i</*jpov. Example data:
iooooooooooooooooooooovoooioooipooooo<ooooooooooivojo<<<<<oio*ioooooooooooooooopiooooooooooooooooooo/jpooooooooooo

Example bigger chunk of data, 86 kilobytes big.
Output
Well, not very much to say about it, output depends on the algorithm.
Rules:

Input taken by your program, compressed, and then decompressed, shall be identical.
Submissions are scored by the following formula: \$ \frac{Compressed}{Original} \times 100\% \$, applied to the example 86 kilobytes big chunk.
If a submission abuses the fact that only one example chunk is provided (eg. by hardcoding it), I reserve right to add more example chunks.
Standard loopholes are forbidden, I/O rules apply.

Note: 7zip with PPMd algorithm manages to compress the code with 2,95% score.

Is our submission supposed to include both a compressor and decompressor code?

@AdmBorkBork yes. You may submit this as two programs, functions, whatever.

This could be a great challenge, but it's currently very flawed. The scoring method strongly encourages hardcoding, and "I reserve the right to retroactively make existing solutions invalid" isn't a good solution at all. Compression challenges typically solve this by counting the size of (compressed data + decompressor).

@Grimy Well, you may be right. But I'd like to check what are the most efficient compressors community can make. I made myself one that has 1,1% score. If there was golfing need, the submissions would balance code size and the ratio, and I don't want THAT.

You think you don't want that, but without that, the score can be driven arbitrarily low by using larger and larger dictionaries, which is honestly quite boring. Or straight up 0% by hardcoding (you say you may add more test cases, but nothing prevents one from hardcoding those too).

@Grimy you're not right. People who put effort into their answers will downvote boring solutions (because well, they may better, but technically not, AND because they put a lot of time into their solution, and somebody has JUST came up to the party with simple and boring solution), punishing fun destroyers and effectively making them remove crappy answers.

Related

CGCC is not a popularity contest. Most answerers are not trying to gather upvotes, but to optimize for the question’s objective winning criterion. If that criterion makes it so that only boring solutions can win, that’s an issue with the question.

@Grimy why the popularity-contest tag tho? Who cares about being boring, I'm reaching half a hundred answers, every single one made in either Brainfuck or Malbolge

Challenges on CGCC should be self-contained. You should add a description of what exactly each command does, and how normalised Malbolge interprets a program

@JoKing umm, what? Why should I. Does the information alter the way the code can be compressed?

oh nvm, i was thinking this was a [tag:meta-golf] challenge, where the output had to still be runnable. Isn't this just a straight compression challenge that has nothing to do with Malbolge then?

@JoKing sure! You're right, partially.

Score with test 1: 38.6%, Score with test 2: 4.9%
Compressor
Jelly, 97 bytes
ṡ2ṢŒɠżQƊ1ị>ɗƇ3NÞḣ8Ṫ€,‘ɼ$€Ẏœṣ;@W}ɗjƭƒ
7©ṛ⁸“i</*jpov”iⱮ’Ç31¡
“i</*jpov”iⱮḅ8b256,ÇĖF€LÞḢL;L};÷/$ʋ,ḷɗ

Try it online!
Decompressor
Jelly, 44 bytes
ḅ256ḃ8
ḣ3s2ṚṣḢ}©¥jƭƒṫ5µṛ®n8Ɗ¿‘
ḢĿị“i</*jpov”

Try it online!
Explanation
Uses two different methods and picks the one with the shortest output.
Method 1: Convert the input from base 8 to base 256
Method 2: Repeatedly finds the 8 most common sublists of length 2 and replaces them with an integer between 8 and 255. The dictionary is stored at the beginning of the output.
The first byte of the output indicates the method used.
Input to compressor is a string of Malbolge. Output is a list of integers between 0 and 255. This could easily be encoded in Jelly’s code page if preferred. Input and output to/from decompressor mirror the compressor.

Retina, 47.25%
I know this is currently uninteresting, but this is still a WIP.
Cheap algorithm to compress Malbolge programs.
ooooooooo
a
oooooooo
b
ooooooo
c
oooooo
d
ooooo
e
oooo
f
ooo
g
j\*
h
jah
k

Decompressor:
a
ooooooooo
b
oooooooo
c
ooooooo
d
oooooo
e
ooooo
f
oooo
g
ooo
h
j\*
k
jah

Explanation
This simply shortens the source by replacing the o's, after noticing that there are too many o's in the Malbolge program. Try compressor online!

I think you can possibly do better by replacing first oo with a, then aa with b, then bb with c and so on (or, possibly but very unlikely, the same but for runs of three)

For some reason I actually got the compression ratio really high.

This code using standard Python libraries serves as a baseline for other advanced approaches.
Here is the outcomes for common compression algorithms.
Test case 0
Library   Score
gzip      50.000%
bz2       64.912%
lzma      87.719%

Test case 1
Library   Score
gzip      3.908%
bz2       2.968%
lzma      3.826%

PPMd      3.161%

NOTE: The PPMd algorithm score is obtained manually using 7zip to compress Test Case 1 into a zip file using a dictionary size of 16M and word size of 16 on Windows.

You can try PPMd aswell, as it's really close to 1%.

///, 0.00116%
Compressor (large test case)
Decompressor (large test case)
Compressor (small test case)
Decompressor (small test case)
Explanation: simple dictionary-based approach. The decompressor performs the same substitions as the compressor, but in reverse order. Note that both these programs take input by concatenating it into the source, as is usual for ///.


text:
Calculate Landau's function
Landau's function \$g(n)\$ (OEIS A000793) gives the maximum order of an element of the symmetric group \$S_n\$.  Here, the order of a permutation \$\pi\$ is the smallest positive integer \$k\$ such that \$\pi^k\$ is the identity - which is equal to the least common multiple of the lengths of the cycles in the permutation's cycle decomposition.  For example, \$g(14) = 84\$ which is achieved for example by (1,2,3)(4,5,6,7)(8,9,10,11,12,13,14).
Therefore, \$g(n)\$ is also equal to the maximum value of \$\operatorname{lcm}(a_1, \ldots, a_k)\$ where \$a_1 + \cdots + a_k = n\$ with \$a_1, \ldots, a_k\$ positive integers.
Problem
Write a function or program that calculates Landau's function.
Input
A positive integer \$n\$.
Output
\$g(n)\$, the maximum order of an element of the symmetric group \$S_n\$.
Examples
n    g(n)
1    1
2    2
3    3
4    4
5    6
6    6
7    12
8    15
9    20
10   30
11   30
12   60
13   60
14   84
15   105
16   140
17   210
18   210
19   420
20   420

Score
This is code-golf: Shortest program in bytes wins.  (Nevertheless, shortest implementations in multiple languages are welcome.)
Note that there are no requirements imposed on run-time; therefore, your implementation does not necessarily need to be able to generate all the above example results in any reasonable time.
Standard loopholes are forbidden.

05AB1E, 6 bytes
Åœ€.¿Z

Try it online!
    Åœ       # integer partitions of the input
      €.¿    # lcm of each
         Z   # maximum

Wolfram Language (Mathematica), 44 bytes
Max[PermutationOrder/@Permutations@Range@#]&

Try it online!
Wolfram Language (Mathematica), 31 bytes
@DanielSchepler has a better solution:
Max[LCM@@@IntegerPartitions@#]&

Try it online!

Not that familiar with the language - but Max[Apply@LCM/@IntegerPartitions@#]& seems to work for me and would give 36 bytes if it's correct.

@DanielSchepler yes, super! Why don't you propose it as a separate solution? You can even do Max[LCM@@@IntegerPartitions@#]& for 31 bytes, because @@@ does Apply at level 1.

Haskell, 44 bytes
(%1)
n%t=maximum$t:[(n-d)%lcm t d|d<-[1..n]]

Try it online!

Python, 87 bytes
f=lambda n,d=1:max([f(m,min(range(d,d<<n,d),key=(n-m).__rmod__))for m in range(n)]+[d])

Try it online!
A recursive function that tracks the remaining n to partition and the running LCM d. Note that this means we don't need to track the actual numbers in the partition or how many of them we've used. We try each possible next part, n-m, replacing n with what's left m, and d with lcm(d,n-m). We take the maximum of those recursive results and d itself. When nothing remains n=0, the result ist just d.
The tricky thing is that Python doesn't have any built-ins for LCM, GCD, or prime factorization. To do lcm(d,m-n), we generate a list of multiples of d, and take the value attaining the minimum modulo n-m, that is with key=(n-m).__rmod__. Since min will give the earlier value in case of a tie, this is always the first nonzero multiple of d that's divisible by n-m, so their LCM. We only multiples of d up to d*(n-m) to be guaranteed to hit the LCM, but it's shorter to write d<<n (which is d*2**n) which suffices with Python's upper bounds being exclusive.
Python 3's math library has gcd (but not lcm) after 3.5, which is a few bytes shorter. Thanks to @Joel for shortening the import.
Python 3.5+, 84 bytes
import math
f=lambda n,d=1:max([f(m,d*(n-m)//math.gcd(n-m,d))for m in range(n)]+[d])

Try it online!
Using numpy's lcm is yet shorter.
Python with numpy, 77 bytes
from numpy import*
f=lambda n,d=1:max([f(m,lcm(d,n-m))for m in range(n)]+[d])

Try it online!

Using from math import* is 85 bytes and using import math + math.gcd(...) is 84 bytes. The same applies to numpy.

@Joel Thanks, I forgot about that.

@Joel Thanks, I had forgotten to update the byte count, they're both 77. numpy's length of 5 is the break-even point for import*.

Right. In that case I prefer to use import numpy because numpy.max would override Python's built-in max (same for min) if from numpy import* is used. It does not cause problems here but we all know that import* is not a good programming practice in general.

@Joel While import* is no doubt bad practice, I don't think it actually overwrites Python's min and max, so the confusion would be someone expecting numpy's function and getting the base one.

Oh, you are right. I saw a warning about that in an earlier version of numpy. Maybe in the newer versions the behavior has changed.

Jelly, 7 bytes
Œṗæl/€Ṁ

Try it online!
A monadic link taking an integer as its argument and returning an integer.
Explanation
Œṗ      | Integer partitions
  æl/€  | Reduce each using LCM
      Ṁ | Maximum

JavaScript (ES6), 92 bytes
Computes the maximum value of \$\operatorname{lcm}(a_1,\ldots,a_k)\$ where \$a_1+\ldots+a_k\$ is a partition of \$n\$.
f=(n,i=1,l=m=0)=>n?i>n?m:f(n-i,i,l*i/(G=(a,b)=>b?G(b,a%b):a)(l,i)||i)&f(n,i+1,l)|m:m=l>m?l:m

Try it online!

JavaScript (ES6), 95 bytes
f=(n,i=1,m)=>i>>n?m:f(n,i+1,i<m|(g=(n,k=2,p=0)=>k>n?p:n%k?p+g(n,k+1):g(n/k,k,p*k||k))(i)>n?m:i)

Try it online!
How?
We define:
$$\cases{
g(1)=0\\
g(n)=\sum_{j=1}^{N}{p_j}^{k_j}\quad\text{for}\enspace n>1\enspace\text{and}\enspace n=\prod_{j=1}^{N}{p_j}^{k_j}
}$$
(this is A008475)
Then we use the formula (from A000793):
$$f(n)=\max_{g(k)\le n}k$$

Perl 6, 50 bytes
{max .map:{+(.[$_],{.[@^a]}...$_,)}}o&permutations

Try it online!
Checks all permutations directly, like @histocrat's Ruby solution.
Explanation
                                     &permutations  # Permutations of [0;n)
{                                  }o  # Feed into block
     .map:{                       }  # Map permutations
                           ...  # Construct sequence
             .[$_]  # Start with permutation applied to itself [1]
                  ,{.[@^a]}  # Generate next item by applying permutation again
                              $_,  # Until it matches original permutation [2]
           +(                    )  # Length of sequence
 max  # Find maximum

1 We can use any sequence of n distinct items for the check, so we simply take the permutation itself.
2 If the endpoint is a container, the ... sequence operator smartmatches against the first item. So we have to pass a single-element list.

Gaia, 25 23 22 bytes
,:Π¤d¦&⊢⌉/
1w&ḍΣ¦¦⇈⊢¦⌉

Try it online!
Not having LCM or integer partitions makes this approach rather long.
,:Π¤d¦&⊢⌉/		;* helper function: LCM of 2 inputs

1w&ḍΣ¦¦			;* push integer partitions
         ¦		;* for each
       ⇈⊢		;* Reduce by helper function
	  ⌉		;* and take the max

Ruby, 77 bytes
f=->n{a=*0...n;a.permutation.map{|p|(1..).find{a.map!{|i|p[i]}==a.sort}}.max}

Try it online!
(1..) infinite range syntax is too new for TIO, so the link sets an arbitrary upper bound.
This uses the direct definition--enumerate all possible permutations, then test each one by mutating a until it gets back to its original position (which also conveniently means I can just mutate the original array in each loop).

Haskell, 70 67 bytes
f n=maximum[foldl1 lcm a|k<-[1..n],a<-mapM id$[1..n]<$[1..k],sum a==n]

Try it online!
Edit: -3 bytes thanks to @xnor.

I think it should work to do mapM(:[1..n]), since the extra element is harmless.

Python 3 + numpy, 115 102 99 bytes
-13 bytes thanks to @Daniel Shepler
-3 more bytes from @Daniel Shepler
import numpy
c=lambda n:[n]+[numpy.lcm(i,j)for i in range(1,n)for j in c(n-i)]
l=lambda n:max(c(n))

Try it online!
Brute force method: find all possible sequences a,b,c,... where a+b+c+...=n, then pick the one with the highest lcm.

Incidentally, I have a Python 3 + numpy solution running 87 bytes.

I don't know enough about numpy to figure out how to do that, so I suggest you just post your solution separately.

Well, I was planning to wait for a while to post it.

I just realized you posted this challenge. Sorry, I'll do my best.

Since it came up, you should not try to run this solution for any input higher than 26, even with caching. After nearly freezing my computer for about two and a half hours, the process was killed without giving out an answer. This is not surprising, since it had to calculate the maximum of summing each of about 2^26 lists, which are not memory efficient.

If you change c to return a set and memoize it doesn't do badly at all (though admittedly it does ungolf a bit): https://tio.run/##RY1BCsIwEEX3PUWWM1CLoiuhV/AKEsfUTkkmIU3AWnr2Ggvq7vM@//0wpd7LcV3ZBR@TkuzCVFFrtbvdtZLzLEuThb3AvHWNJQdcD9j5qFixqKjlYeBQy4aGDyKQHeOClf2LnH5C4Yjfqy4LJe/tWO5@ubExX0lTb6AMRn6Z9uLFIBBWIbIksHDaF8kb

Pyth, 24 15  bytes
eSm.U/*bZibZd./

Try it online!
             ./Q  # List of partitions of the input
  m               # map that over lambda d:
   .U       d     # reduce d (with starting value first element of the list) on lambda b,Z:
     /*bZgbZ      # (b * Z) / GCD(b, Z)
 S                # this gives the list of lcms of all partitions. Sort this
e                 # and take the last element (maximum)

-9 bytes: paid attention and noticed that Pyth actually has a GCD builtin (i).


text:
Heavy Box Stacking
You have a bunch of heavy boxes and you want to stack them in the fewest number of stacks possible. The issue is that you can't stack more boxes on a box than it can support, so heavier boxes must go on the bottom of a stack.
The Challenge
Input: A list of weights of boxes, in whole kg.
Output: A list of lists describing the stacks of boxes. This must use the fewest number of stacks possible for the input. To be a valid stack, the weight of each box in the stack must be greater than or equal to the sum of the weight of all boxes above it.
Examples of Valid stacks
(In bottom to top order)

[3]
[1, 1]
[3, 2, 1]
[4, 2, 1, 1]
[27, 17, 6, 3, 1]
[33, 32, 1]
[999, 888, 99, 11, 1]

Examples of Invalid stacks
(In order from bottom to top)

[1, 2]
[3, 3, 3]
[5, 5, 1]
[999, 888, 777]
[4, 3, 2]
[4321, 3000, 1234, 321]

Example Test Cases
1
IN: [1, 2, 3, 4, 5, 6, 9, 12]
OUT: [[12, 6, 3, 2, 1], [9, 5, 4]]

2
IN: [87, 432, 9999, 1234, 3030]
OUT: [[9999, 3030, 1234, 432, 87]]

3
IN: [1, 5, 3, 1, 4, 2, 1, 6, 1, 7, 2, 3]
OUT: [[6, 3, 2, 1], [7, 4, 2, 1], [5, 3, 1, 1]]

4
IN: [8, 5, 8, 8, 1, 2]
OUT: [[8, 8], [8, 5, 2, 1]]

Rules and Assumptions

Standard I/O rules and banned loopholes apply
Use any convenient format for I/O

Stacks may be described top to bottom or bottom to top, as long as you are consistent.
The order of stacks (rather than boxes within those stacks) does not matter.
You may also take input boxes as a presorted list. Order is not particularly important for the input, so long as the general problem isn't being solved by the sorting itself.

If there is more than one optimal configuration of stacks, you may output any one of them
You may assume that there is at least one box and that all boxes weigh at least 1 kg
You must support weights up to 9,999 kg, at minimum.
You must support up to 9,999 total boxes, at minimum.
Boxes with the same weight are indistinguishable, so there is no need to annotate which box was used where.

Happy golfing! Good luck!

May we take the weights in sorted order? (either ascending or descending)

"You must support up to 9,999 total boxes, at minimum." How is "support" interpreted here? Does it merely mean the program should be able to take such size of input, or does it mean that the program should actually provide the answer in a reasonable amount of time? If it is the latter, there should be much larger test cases provided.

Suggested test case: [8, 8, 8, 5, 1] -> [[8, 8], [8, 5, 1]]

Or even better: [8, 5, 8, 8, 1, 2] -> [[8, 8], [8, 5, 2, 1]]

"You must support weights up to 9,999 kg, at minimum" So is this intended to be not just code golf, but code golf using an efficient algorithm?

@Arnauld, since otherwise that would add uninteresting sorting code to an answer, I'm going to say yes, you can take in the inputs in sorted order.

@Jonah the purpose of that is actually to require a minimum integer precision.

@Joel, It means you need to be able to handle inputs of up to 9,999 boxes, at minimum. Your solution can blow up once you add the 10,000th box; it only has to work for inputs of that size and smaller. (maybe someone wants to make a regex to solve the problem or something equally insane)

@Hiatsu added, though I'm curious as to what makes this a good test case

@Beefster So it means that the solution should be able to provide a correct answer for the input range given an infinite amount of time and memory. Is that right?

@Joel yes, correct. (Though to be pedantic, I would say 'sufficient' rather than 'infinite' there, since a correct solution solves the general problem in finite time and space since the problem is decidable.)

@Beefster, woops, I quote the wrong thing.  I meant to say: "You must support up to 9,999 total boxes, at minimum."  -- So is this intended to be not just code golf, but code golf using an efficient algorithm?  Eg, the submitted solutions do not meet this requirement afaict.

@Beefster That test case has strongly unbalanced stacks, unlike all the other test cases.

@Jonah efficiency doesn't matter as long as the program terminates eventually. All that matters is that the solution produces an optimal number of stacks. This problem is $O(n!)$ at worst. The purpose of the 9,999 box requirement is to specify a soft minimum on space requirements.

Jelly, 19 bytes
Œ!ŒṖ€ẎṖÄ>ḊƲ€¬ȦƊƇLÞḢ

Try it online!
Obvious -3 thanks to Nick Kennedy...
Top to bottom.
Explanation:
Œ!ŒṖ€ẎṖÄ>ḊƲ€¬ȦƊƇLÞḢ  Arguments: S (e.g. [1, 2, 3, 4, 5])
Œ!                   Permutations (e.g. [..., [4, 1, 5, 2, 3], ...])
    €                Map link over left argument (e.g. [..., [..., [[4, 1], [5], [2, 3]], ...], ...])
  ŒṖ                  Partitions (e.g. [..., [[4, 1], [5], [2, 3]], ...])
     Ẏ               Concatenate elements (e.g. [..., ..., [[4, 1], [5], [2, 3]], ..., ...])
               Ƈ     Filter by link (e.g. [..., [[1, 3], [2], [4], [5]], ...])
              Ɗ       Create >=3-link monadic chain (e.g. [[1], [], [0]])
           €           Map link over left argument (e.g. [[1], [], [0]])
          Ʋ             Create >=4-link monadic chain (e.g. [1])
      Ṗ                  Remove last element (e.g. [4])
       Ä                 Cumulative sum (e.g. [4])
         Ḋ               [Get original argument] Remove first element (e.g. [1])
        >                Greater than (vectorizes) (e.g. [1])
            ¬          Logical NOT (vectorizes) (e.g. [[0], [], [1]])
             Ȧ         Check if non-empty and not containing zeroes after flattening (e.g. 0)
                 Þ   Sort by link (e.g. [[[1, 2, 3], [4, 5]], ..., [[5], [4], [3], [2], [1]]])
                L     Length (e.g. 4)
                  Ḣ  Pop first element (e.g. [[1, 2, 3], [4, 5]])

Any chance at a less compact version with explanation? I learn a ton from those.

@JohnKeates Added one.

JavaScript (Node.js),  139 122  116 bytes
Expects the input sorted in ascending order.
f=(A,s=[],[n,...a]=A,r)=>n?s.some((b,i,[...c])=>n<eval(b.join`+`)?0:f(A,c,a,c[i]=[n,...b]))?S:r?0:f(A,[...s,[]]):S=s

Try it online!
Commented
f = (                        // f is a recursive function taking:
  A,                         //   A[] = input array
  s = [],                    //   s[] = list of stacks, initially empty
  [n,                        //   n   = next weight to process
      ...a] = A,             //   a[] = array of remaining weights
  r                          //   r   = recursion flag
) =>                         //
  n ?                        // if n is defined:
    s.some((b, i,            //   for each stack b[] at position i in s[],
                  [...c]) => //   using c[] as a copy of s[]:
      n < eval(b.join`+`) ?  //     if n is not heavy enough to support all values in b[]:
        0                    //       abort
      :                      //     else:
        f(                   //       do a recursive call:
          A, c, a,           //         using A[], c[] and a[]
          c[i] = [n, ...b]   //         with n prepended to c[i]
        )                    //       end of recursive call
    ) ?                      //   end of some(); if successful:
      S                      //     return S[]
    :                        //   else:
      r ?                    //     if this is a recursive call:
        0                    //       do nothing
      :                      //     else:
        f(A, [...s, []])     //       try again with an additional stack
  :                          // else:
    S = s                    //   success: save the solution in S[]

Python 3.8 (pre-release), 178 bytes
f=lambda b,s=[[]]:(a for i in range(len(s))if b[0]>=sum(s[i])for a in f(b[1:],s[:i]+[[b[0]]+s[i]]+s[i+1:]+[[]]))if b else[s]
g=lambda a:(c:=sorted(f(a),key=len)[0])[:c.index([])]

Try it online!
Now works on all possible inputs. (It times out on TIO with more than ten or so boxes, but it calculates a correct answer)

list(reversed(sorted(a))) can be written as sorted(a)[::-1] for golfing purpose.

You would think I would know that by now, especially since I do so much other indexing. Thanks.

Just as a side remark, if not for golfing it would be better write sorted(a, reverse=True) instead.


text:
Divide Numbers by 0
We've all been told at some point in our lives that dividing by 0 is impossible. And for the most part, that statement is true. But what if there was a way to perform the forbidden operation? Welcome to  my newest creation: b-numbers.
b-numbers are a little bit like imaginary numbers: the main pronumeral involved represents an expression that isn't mathematically impossible (i represents \$\sqrt{-1}\$).
In this case \$b\$ will be said to represent the expression \$\frac{1}{0}\$. From here, it is easy to determine what \$\frac{x}{0}\$ would equal:
$$
\frac{x}{0} = \frac{x}{1} \cdot \frac{1}{0} = xb
$$
The Task
Given an expression  involving a division by 0, output the simplified value in terms of \$b\$. Note that input will be in the form of n/0 where n is any rational number or any b-number in decimal form. Leading 0s and trailing 0s wont be included.
Example Input
4/0
1/0
0/0
80/0
-8/0
1.5/0
2.03/0
-1/0
-3.14/0
b/0
3b/0
-b/0
121/0

Example Output
4b
b
0
80b
-8b
1.5b
2.03b
-b
-3.14b
b
3b
-b
121b

Score
This is code golf, so fewest bytes wins. Standard loopholes are forbidden.
Leaderboards
Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.
To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:
# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:
# Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:
# Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the leaderboard snippet:
# [><>](http://esolangs.org/wiki/Fish), 121 bytes

var QUESTION_ID=191101;
var OVERRIDE_USER=8478;
var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;function answersUrl(d){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+d+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(d,e){return"https://api.stackexchange.com/2.2/answers/"+e.join(";")+"/comments?page="+d+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(d){answers.push.apply(answers,d.items),answers_hash=[],answer_ids=[],d.items.forEach(function(e){e.comments=[];var f=+e.share_link.match(/\d+/);answer_ids.push(f),answers_hash[f]=e}),d.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(d){d.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),d.has_more?getComments():more_answers?getAnswers():process()}})}getAnswers();var SCORE_REG=function(){var d=String.raw`h\d`,e=String.raw`\-?\d+\.?\d*`,f=String.raw`[^\n<>]*`,g=String.raw`<s>${f}</s>|<strike>${f}</strike>|<del>${f}</del>`,h=String.raw`[^\n\d<>]*`,j=String.raw`<[^\n<>]+>`;return new RegExp(String.raw`<${d}>`+String.raw`\s*([^\n,]*[^\s,]),.*?`+String.raw`(${e})`+String.raw`(?=`+String.raw`${h}`+String.raw`(?:(?:${g}|${j})${h})*`+String.raw`</${d}>`+String.raw`)`)}(),OVERRIDE_REG=/^Override\s*header:\s*/i;function getAuthorName(d){return d.owner.display_name}function process(){var d=[];answers.forEach(function(n){var o=n.body;n.comments.forEach(function(q){OVERRIDE_REG.test(q.body)&&(o="
"+q.body.replace(OVERRIDE_REG,"")+"
")});var p=o.match(SCORE_REG);p&&d.push({user:getAuthorName(n),size:+p[2],language:p[1],link:n.share_link})}),d.sort(function(n,o){var p=n.size,q=o.size;return p-q});var e={},f=1,g=null,h=1;d.forEach(function(n){n.size!=g&&(h=f),g=n.size,++f;var o=jQuery("#answer-template").html();o=o.replace("{{PLACE}}",h+".").replace("{{NAME}}",n.user).replace("{{LANGUAGE}}",n.language).replace("{{SIZE}}",n.size).replace("{{LINK}}",n.link),o=jQuery(o),jQuery("#answers").append(o);var p=n.language;p=jQuery(""+n.language+"").text().toLowerCase(),e[p]=e[p]||{lang:n.language,user:n.user,size:n.size,link:n.link,uniq:p}});var j=[];for(var k in e)e.hasOwnProperty(k)&&j.push(e[k]);j.sort(function(n,o){return n.uniq>o.uniq?1:n.uniq<o.uniq?-1:0});for(var l=0;l<j.length;++l){var m=jQuery("#language-template").html(),k=j[l];m=m.replace("{{LANGUAGE}}",k.lang).replace("{{NAME}}",k.user).replace("{{SIZE}}",k.size).replace("{{LINK}}",k.link),m=jQuery(m),jQuery("#languages").append(m)}}
body{text-align:left!important}#answer-list{padding:10px;float:left}#language-list{padding:10px;float:left}table thead{font-weight:700}table td{padding:5px}
  <link rel="stylesheet" type="text/css" href="https://cdn.sstatic.net/Sites/codegolf/primary.css?v=f52df912b654">

Winners by Language

Language	User	Score

Leaderboard

	Author	Language	Size

{{PLACE}}	{{NAME}}	{{LANGUAGE}}	{{SIZE}}

{{LANGUAGE}}	{{NAME}}	{{SIZE}}

1/0 (b) ÷ 0/1 (0) = 0/0

1/0 (b) ÷ 0/1 = 1/0 × 1 = 1/0 (b)

Suggested test case -3.14b/0 - I had some short code that'd work for all other test cases :(

I suspect that I'm doing something wrong, but if b/0 = b then if I divide both parts by b then 1/0 = 1. Do I need c-numbers to divide like this?

@someone $\frac x b=\frac x{\frac10}=\frac{\frac x1}{\frac10}=\frac{x\cdot0}{1\cdot1}=\frac01=0$. That is, dividing by $b$ results in $0$, so dividing both parts by $b$ leads to $0=0$, not $b=1$.

@Erik that way, b/b = 0 when it's normally (and I'm pretty sure it's easily proven from all the various axioms) expected to be 1 (otherwise, b's multiplicative inverse seems to be not its multiplicative inverse). I'm pretty sure you just can't loophole against division by zero by adding b=1/0 or anything similar.

@someone TBF, the normal axioms don't exactly hold when you define division by zero anyway, so you still can't just "divide $b$ from both sides", or at least expect that $\frac b b=1$... :P My equation uses undefined stuff in it, based on how I would define them. ;)

There's a reason division by zero is undefined... $b=1\cdot b=\frac11\cdot b=\frac33\cdot b=\frac{3\cdot1}{3\cdot0}=\frac30=3\cdot\frac10=3b$. So you should be able to simplify all the examples (excepting the third of 0) to just $b$

Shouldn't the 3rd example have output 0b rather than 0? If the two expressions were equivalent then the question would have no premise

@trichoplax Indeed, if $0b=0$ (which example 3 suggests), then $b/0 = (0b)/0 = b \cdot (0/0) = b\cdot 0 = 0$. Then, to maintain consistency with the example $b/0 = b$, we must have $b=0$, and so $x\cdot b = x\cdot 0 = 0 = 0b$ for any $x$ in our original ring as well (assuming standard ring axioms), which renders the challenge moot. Btw, it is possible to make division by zero well defined (e.g. wheel theory), but you have to redefine 'division' to make it not quite the same as a multiplicative inverse.

Maybe it is also possible to make it well defined by restricting some distributive properties of division and multiplication? E.g, the false derivation $i = \sqrt{-1} = \sqrt{1/(-1)} = \sqrt{1}/\sqrt{-1} = 1/i = -i$ is 'possible' since distributing square roots over division no longer works if we 'allow' square roots of negative numbers. So maybe removing the rule $(ab)/c = a(b/c)$ and replacing it by something more restrictive can make this system non-trivial (i.e. ensure that not everything is equal)

Suggested test case: 3.1b/0

The "standard" way to make division by zero sensible is the projectively extended real line, which adds a single value ∞ (no separate +∞ and -∞!). Then x÷0 for any x≠0 is ∞, and things work out fine—as long as you're okay with weirdnesses like ∞÷2=∞. You'll find if you play around a bit that, if you want addition and multiplication to keep as many of their standard properties as possible, then your b must have properties more consistent with infinity than with anything else (b+1=b, b×2=b, b÷2=b, and so on).

Since $x/0=xb$ why not $b/0=bb=b^2$?

$\frac{1}{0}=b\implies 0\times b = 1$ we have $ 1=0\times b=0\times \frac{1}{0}=0\times\frac{1\times 1}{0\times 0}=0\times\frac{1}{0}\times\frac{1}{0}=0\times b\times b=1\times b=b $, then $ 1=b\times 0=1\times 0=0$

Hm... Your type of imaginary number has interesting property: $$\frac{b^{b}}{b}=1$$

Can we use a different symbol for division instead of /?

Is 1b and 0b simplified enough for testcases (2) & (3)? Or should it be exactly like the example output?

Malbolge Unshackled (20-trit rotation variant), 3,62e6 bytes
Size of this answer exceeds maximum postable program size (eh), so the code is located in my GitHub repository (note: Don't copy the code using CTRL+A and CTRL+C, just rightclick and click "Save destination element as...").
How to run this?
This might be a tricky part, because naive Haskell interpreter will take ages upon ages to run this. TIO has decent Malbogle Unshackled interpreter, but sadly I won't be able to use it (limitations).
The best one I could find is the fixed 20-trit rotation width variant, that performs very well, calculating (pretty much) instantly.
To make the interpreter a bit faster, I've removed all the checks from Matthias Lutter's Malbolge Unshackled interpreter.
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* translation = "5z]&gqtyfr$(we4{WP)H-Zn,[%\\3dL+Q;>U!pJS72Fh"
        "OA1CB6v^=I_0/8|jsb9m<.TVac`uY*MK'X~xDl}REokN:#?G\"i@";

typedef struct Word {
    unsigned int area;
    unsigned int high;
    unsigned int low;
} Word;

void word2string(Word w, char* s, int min_length) {
    if (!s) return;
    if (min_length < 1) min_length = 1;
    if (min_length > 20) min_length = 20;
    s[0] = (w.area%3) + '0';
    s[1] = 't';
    char tmp[20];
    int i;
    for (i=0;i<10;i++) {
        tmp[19-i] = (w.low % 3) + '0';
        w.low /= 3;
    }
    for (i=0;i<10;i++) {
        tmp[9-i] = (w.high % 3) + '0';
        w.high /= 3;
    }
    i = 0;
    while (tmp[i] == s[0] && i < 20 - min_length) i++;
    int j = 2;
    while (i < 20) {
        s[j] = tmp[i];
        i++;
        j++;
    }
    s[j] = 0;
}

unsigned int crazy_low(unsigned int a, unsigned int d){
    unsigned int crz[] = {1,0,0,1,0,2,2,2,1};
    int position = 0;
    unsigned int output = 0;
    while (position < 10){
        unsigned int i = a%3;
        unsigned int j = d%3;
        unsigned int out = crz[i+3*j];
        unsigned int multiple = 1;
        int k;
        for (k=0;k<position;k++)
            multiple *= 3;
        output += multiple*out;
        a /= 3;
        d /= 3;
        position++;
    }
    return output;
}

Word zero() {
    Word result = {0, 0, 0};
    return result;
}

Word increment(Word d) {
    d.low++;
    if (d.low >= 59049) {
        d.low = 0;
        d.high++;
        if (d.high >= 59049) {
            fprintf(stderr,"error: overflow\n");
            exit(1);
        }
    }
    return d;
}

Word decrement(Word d) {
    if (d.low == 0) {
        d.low = 59048;
        d.high--;
    }else{
        d.low--;
    }
    return d;
}

Word crazy(Word a, Word d){
    Word output;
    unsigned int crz[] = {1,0,0,1,0,2,2,2,1};
    output.area = crz[a.area+3*d.area];
    output.high = crazy_low(a.high, d.high);
    output.low = crazy_low(a.low, d.low);
    return output;
}

Word rotate_r(Word d){
    unsigned int carry_h = d.high%3;
    unsigned int carry_l = d.low%3;
    d.high = 19683 * carry_l + d.high / 3;
    d.low = 19683 * carry_h + d.low / 3;
    return d;
}

// last_initialized: if set, use to fill newly generated memory with preinitial values...
Word* ptr_to(Word** mem[], Word d, unsigned int last_initialized) {
    if ((mem[d.area])[d.high]) {
        return &(((mem[d.area])[d.high])[d.low]);
    }
    (mem[d.area])[d.high] = (Word*)malloc(59049 * sizeof(Word));
    if (!(mem[d.area])[d.high]) {
        fprintf(stderr,"error: out of memory.\n");
        exit(1);
    }
    if (last_initialized) {
        Word repitition[6];
        repitition[(last_initialized-1) % 6] =
                ((mem[0])[(last_initialized-1) / 59049])
                    [(last_initialized-1) % 59049];
        repitition[(last_initialized) % 6] =
                ((mem[0])[last_initialized / 59049])
                    [last_initialized % 59049];
        unsigned int i;
        for (i=0;i<6;i++) {
            repitition[(last_initialized+1+i) % 6] =
                    crazy(repitition[(last_initialized+i) % 6],
                        repitition[(last_initialized-1+i) % 6]);
        }
        unsigned int offset = (59049*d.high) % 6;
        i = 0;
        while (1){
            ((mem[d.area])[d.high])[i] = repitition[(i+offset)%6];
            if (i == 59048) {
                break;
            }
            i++;
        }
    }
    return &(((mem[d.area])[d.high])[d.low]);
}

unsigned int get_instruction(Word** mem[], Word c,
        unsigned int last_initialized,
        int ignore_invalid) {
    Word* instr = ptr_to(mem, c, last_initialized);
    unsigned int instruction = instr->low;
    instruction = (instruction+c.low + 59049 * c.high
            + (c.area==1?52:(c.area==2?10:0)))%94;
    return instruction;
}

int main(int argc, char* argv[]) {
    Word** memory[3];
    int i,j;
    for (i=0; i<3; i++) {
        memory[i] = (Word**)malloc(59049 * sizeof(Word*));
        if (!memory) {
            fprintf(stderr,"not enough memory.\n");
            return 1;
        }
        for (j=0; j<59049; j++) {
            (memory[i])[j] = 0;
        }
    }
    Word a, c, d;
    unsigned int result;
    FILE* file;
    if (argc < 2) {
        // read program code from STDIN
        file = stdin;
    }else{
        file = fopen(argv[1],"rb");
    }
    if (file == NULL) {
        fprintf(stderr, "File not found: %s\n",argv[1]);
        return 1;
    }
    a = zero();
    c = zero();
    d = zero();
    result = 0;
    while (!feof(file)){
        unsigned int instr;
        Word* cell = ptr_to(memory, d, 0);
        (*cell) = zero();
        result = fread(&cell->low,1,1,file);
        if (result > 1)
            return 1;
        if (result == 0 || cell->low == 0x1a || cell->low == 0x04)
            break;
        instr = (cell->low + d.low + 59049*d.high)%94;
        if (cell->low == ' ' || cell->low == '\t' || cell->low == '\r'
                || cell->low == '\n');
        else if (cell->low >= 33 && cell->low < 127 &&
                (instr == 4 || instr == 5 || instr == 23 || instr == 39
                    || instr == 40 || instr == 62 || instr == 68
                    || instr == 81)) {
            d = increment(d);
        }
    }
    if (file != stdin) {
        fclose(file);
    }
    unsigned int last_initialized = 0;
    while (1){
        *ptr_to(memory, d, 0) = crazy(*ptr_to(memory, decrement(d), 0),
                *ptr_to(memory, decrement(decrement(d)), 0));
        last_initialized = d.low + 59049*d.high;
        if (d.low == 59048) {
            break;
        }
        d = increment(d);
    }
    d = zero();

    unsigned int step = 0;
    while (1) {
        unsigned int instruction = get_instruction(memory, c,
                last_initialized, 0);
        step++;
        switch (instruction){
            case 4:
                c = *ptr_to(memory,d,last_initialized);
                break;
            case 5:
                if (!a.area) {
                    printf("%c",(char)(a.low + 59049*a.high));
                }else if (a.area == 2 && a.low == 59047
                        && a.high == 59048) {
                    printf("\n");
                }
                break;
            case 23:
                a = zero();
                a.low = getchar();
                if (a.low == EOF) {
                    a.low = 59048;
                    a.high = 59048;
                    a.area = 2;
                }else if (a.low == '\n'){
                    a.low = 59047;
                    a.high = 59048;
                    a.area = 2;
                }
                break;
            case 39:
                a = (*ptr_to(memory,d,last_initialized)
                        = rotate_r(*ptr_to(memory,d,last_initialized)));
                break;
            case 40:
                d = *ptr_to(memory,d,last_initialized);
                break;
            case 62:
                a = (*ptr_to(memory,d,last_initialized)
                        = crazy(a, *ptr_to(memory,d,last_initialized)));
                break;
            case 81:
                return 0;
            case 68:
            default:
                break;
        }

        Word* mem_c = ptr_to(memory, c, last_initialized);
        mem_c->low = translation[mem_c->low - 33];

        c = increment(c);
        d = increment(d);
    }
    return 0;
}

It's working!

I hope you didn't type all that.

When I opened your program, Chrome attempted to translate it from Polish

How to generate this program?

PHP, 65 64 61 58 bytes
-1 byte by using a b instead of '' (empty string). Since "b"s are trimmed, it will be same as an empty string in this specific case.
-3 bytes by using substr instead of explode to get first part of input.
-3 bytes by using better methods to detect 1 and -1.
<?=($n=substr($argn,0,-2))?trim($n+1?$n-1?$n:b:'-',b).b:0;

Try it online!
Tests: Try it online!
If first part of input before "/" (we call it $n) is 0, prints 0.
Else prints $n itself with any "b" at the end trimmed from it and special cases of -1 and 1 handled, so the "1" digit is not printed. And at the end appends a single "b". The trimming part is to make sure we don't get a double "b" at the end like "3bb".

very nicely done!

Replacing $n==-1 with $n>0 (-2 bytes) seems to work. You could try that.

@IsmaelMiguel, that is not working, if you meant $n<0, that won't work too, since we have inputs like -8/0.

@IsmaelMiguel, but you gave me an idea, replaced $n==-1?'-':$n with $n+1?$n:'-' to save 2 bytes!

:/ When I tested, it seemed to work. but well, good thing that you found another way.

Perl 6, 32 bytes
{~m/^0/||S/[(\-|^)1|b]?\/0/$0b/}

Try it online!
A couple of regexes, one to check if the input is 0/0, and the other to replace the trailing /0 with just b (and to remove the old b, 1, and/or -1)
Explanation (old)
{                          }  # Anonymous codeblock
 ~m/^0/     # Return 0 if the input starts with 0
       ||   # Otherwise
         S/             / /  # Substitute
                     \/0       # The /0
          (        )?          # Optionally starting with
           <wb>1               # 1 or -1
                |b             # Or b
                         b   # With just b

Won't this fail on input 0.5/0? Although, I guess that kind of decimal isn't included in the spec

Jelly, 18 bytes
I ended up stealing Erik's ṾṖ$İƑ¡ for this one (otherwise I'd also have 19)...
ṖṖv0ḢṾṖ$İƑ¡,Ạ¡”boḢ

A full program which prints the result.
Try it online! Or see the test-suite.
How?
ṖṖv0ḢṾṖ$İƑ¡,Ạ¡”boḢ - Main Link: list of characters S
Ṗ                  - discard right-most (of S)
 Ṗ                 - discard right-most
   0               - literal zero
  v                - evaluate as Jelly code with right argument (0)
                   - ... b is covert-to-base, so "nb0" gives [n]
    Ḣ              - head ([n]->n or n->n)
          ¡        - repeat...
         Ƒ         - ...# of times: is invariant under:
        İ          -   reciprocation (n->1/n)
       $           - ...action: last two links as a monad:
     Ṿ             -   un-evaluate (-1->"-1" or 1->"1")
      Ṗ            -   discard right-most ("-1"->"-" or "1"->"")
             ¡     - repeat...
            Ạ      - ...# of times: all?
           ,  ”b   - ...action: pair with a 'b' character
                o  - logical OR with:
                 Ḣ -   head (S)  (i.e. if we end with 0 use the 1st character of the input)
                   - implicit print

Ahhh, and I was thinking of ways I could abuse v... :D

Retina, 28 24 bytes
b?/0
b
^0b
0
(^|-)1b
$1b

Try it online!
First try at using Retina, so there's probably considerable room for golfing.

18 bytes: Try it online!

After hunting for what \b does (I'm that inexperienced with regex), I was a bit disappointed to find that it can't be shortened to the unprintable backspace character. Anyhow, thanks

@UnrelatedString of course it can't be shortened to backspace, after all, \b is merely an ASCII representation of the backspace character in normal strings :P

Jelly, 19 bytes
ṖṖḟ”bȯ1VṾṖ$İƑ¡,Ạ¡”b

Try it online!
Full program.

convey, 47 bytes
['b'}
 >>~^]] '-'[
 91+>##"@]
{?~""@@<}
 ]11-^}

Try it online!
I would like to put off the space betwen the number and 'b' in the output but i dont know how to do it :(
How it works (-3/0):

How it works (1/0):

Oh, the output was a bit jagged, you couldn't have done it properly. Fixed it in the interpreter, so it's now 3b as one would expect it. :-)

Python 3.8 (pre-release), 69 66 bytes / 73 70 bytes
Python already had a solution here but it didn't work properly on -1/0. That solution also uses regex while this one is vanilla python.
Lambda version (66 bytes)
lambda x:{"0":0,"1":"b","-1":"-b"}.get(a:=x[:-2].strip("b"),a+"b")

Try it online!
Print version (70 bytes)
print({"0":0,"1":"b","-1":"-b"}.get(a:=input()[:-2].strip("b"),a+"b"))

Try it online!
How it works :
starting from a string x:

x[:-2] remove the /0 part
.strip("b") remove any eventual b present in the string
a:= store our new string into a

Then we check if our new sring is equal to any "0", "1" or "-1":

if True, {...}.get() will replace it by the appropriate string
else, we will print it inchanged adding "b" at the end of the string

Thanks to ovs for reminding me that str.strip existed saving 3 bytes on each program

.strip("b") is 3 bytes shorter than .split("b")[0].

@ovs my bad I totally forgot about that ^^'

Keg, 18B
All credit is to Jono 2906.
__:b=;[b]^:\1=[_]^

Explanation
__                 # Take implicit input and remove the "trash" (/0).
  :b=              # Is the last character equal to b?
     ;             # Negate(decrement) this value.
      [b]          # If the last character is not b, append b.
         ^         # Reverse the stack.
          :\1=     # Is the first character equal to 1?
              [_]  # If so, reduce the value.
                 ^ # Reverse the stack back and implicit output.

TIO!

Python 3, 68 bytes
import re
print(re.sub('^0b$','0',re.sub(r'(^1)?b?/0','b',input())))

Try it online!

Nice solution! But import re rises the bytecount to 64.

@movatica good point, new here so didn't realize import statement was included (although of course it is). Edited.

Welcome! :) You still can keep the shorter lambda version though! It does not need to be a full program. And the import statement can be placed after the lambda definition, so 64 bytes are possible!

@movatica ah, nice! I didn't find a way to make it work with import and lambda. Thank you

In the given exmple, -1/0 should return -b and not -1b. You could achieve that bay changing '(^1)?b?/0','b' by '(^(-)?1)?b?/0','\\2b' at the cost of 7 bytes :/  Also you don't need the $ in your first regex, neither you need the r in front of your string

JavaScript (ES6), 45 bytes
s=>+(n=s.split`/`[0])?[n*n-1?n:'-'[~n]]+'b':n

Try it online!
Commented
s =>                  // s = input: "numerator/0"
  +(                  //
    n = s.split`/`[0] // n = numerator, as a string
  ) ?                 // if n coerced to a Number is neither equal to 0 nor NaN:
    [ n * n - 1 ?     //   if abs(n) is not equal to 1:
        n             //     append the numerator
      :               //   else:
        '-'[~n]       //     append '-' if n = -1, or an empty string otherwise
    ] + 'b'           //   append 'b'
  :                   // else:
    n                 //   just output the numerator because it's either "0" or
                      //   an expression that already contains 'b'

C (clang), 298 263 217 179 bytes
i;f(char*s){for(i=0;s[i]-47&&(*s-49|s[1]-98||!printf("b"));)write(1,s+i,s[i++]!=98);}main(){char*s;gets(s);printf(*s-98&&*s-49|s[1]-47?*s-48?*s-45|s[1]-49?f(s),"b":"-b":"0":"b");}

Try it online!
After a while, I actually managed to make this function the way you want. It's pretty big, I will say, I had to debug a lot.
Thanks to ceilingcat for golfing 35 bytes, another 46 bytes, and another 38 bytes.

Very well done! I'm proud of you!

@lyxal Thanks for the compliment. It took a long time to make this.

171 bytes

Wolfram Language (Mathematica), 37 bytes
ToExpression[""<>#~Drop~-2]b/.b^_->b&

Try it online!
Takes a list of characters as input.

C, 209 203 137 bytes
-66 bytes thanks to ceilingcat
char a[9];main(f){gets(a);f=strlen(a)-3;a[f+1]=0;printf((*a==55&a[1]==49&f==1?a[1]=98:*a==49&!f?*a=98:a[f]==98|*a==48&!f)?"%s":"%sb",a);}

TIO

Putting in -0/0 gives -0b, but it was never in the example input or test cases, so it's correct.

135 bytes

naz, 64 bytes
6a8m1s2x1v2m4a2x2v1x1f1r3x1v2e3x2v3e1o1f0x1x2f2m4a1o0x1x3f1o0x1f

Explanation (with 0x commands removed)
6a8m1s2x1v             # Set variable 1 equal to 47 ("/")
2m4a2x2v               # Set variable 2 equal to 98 ("b")
1x1f                   # Function 1
    1r                 # Read a byte of input
      3x1v2e           # Jump to function 2 if it equals variable 1
            3x2v3e     # Jump to function 3 if it equals variable 2
                  1o1f # Otherwise, output it and jump back to the start of the function
1x2f2m4a1o             # Function 2
                       # Set the register equal to 98 and output once
1x3f1o                 # Function 3
                       # Output once
1f                     # Call function 1

Ruby -p, 37 bytes
sub /(^1|-\K1)?b?\/0/,?b
sub /^0b/,?0

Try it online!

C++ (gcc), 96 bytes
#import<ios>
int f(int r,int i){i-=~r;i||printf("-");i--*~-i&&printf("%d",i?:r);i&&printf("b");}

Takes as input an integer r denoting a real number and the coefficient of a multiple of \$b\$ i.
Then "divides" by zero and does some hacking to avoid printing deviating results.
Try it online!

87 bytes

C (gcc), 71 bytes
f(r,i){i-=~r;i||printf("-");i--*~-i&&printf("%d",i?:r);i&&printf("b");}

Same as my C++ solution but with less boilerplate.
Try it online!

@ceilingcat Thanks.

65 bytes

05AB1E, 15 bytes
¨¨ÐĀiáм'b«Dþi1K

Try it online or verify all test cases.
Explanation:
¨¨               # Remove the last two characters of the (implicit) input
  Ð              # Then triplicate the string
   Āi            # Pop one, and if it's NOT 0 (using Python-style truthify):
     á           #  Pop again and only leave the letters (in case it contains a "b")
      м          #  And remove those letters
       'b«      '#  Then append a trailing "b"
          D      #  Duplicate it
           þ     #  Pop and only leave the digits
            i    #  If this is exactly 1:
             1K  #   Remove the 1
                 # (after which the top of the stack is output implicitly as result)

Brainfuck, 25 bytes
>,[>,]<[-<+>]<+++[<]>[.>]

Explanation
>,[>,]        read from stdin
<[-<+>]<+++   add last two cells and add three ( ascii('/') + ascii('0') + 3 = ascii('b')
[<]>          move pointer to first char to output
[.>]          output until cell w/ value 0

b/0 expected b, got bb; 0/0 expected 0, got 0b; -1/0 expected -b, got -1b.

Yeah, basically this only substitutes the /0 for b and doesn't take into account any of the cases for 0b, 1b, -1b or any inputs that already contain a b

Symja, 85 bytes
d(x_):=If((e=StringReplace(x,"/0"->""))!="0",If(StringContainsQ(e,"b"),e,e<>"b"),"0")

Try it Online!
I finally answered my own question!


text:
Concatenate the Cats
There is a sentence with many cats:
there is a cat house where many cats live. in the cat house, there is a cat called alice and a cat called bob. in this house where all cats live, a cat can be concatenated into a string of cats. The cat called alice likes to purr and the cat called bob likes to drink milk.

The Task
Concatenate (_) all pairs of neighbouring words in the sentence and place each in between the any such pair if that pair occurs more than once in the sentence. Note that overlapping counts, so blah blah occurs twice in blah blah blah.
For example, if the cat occurs more then once, add the concatenated words in between them like this: the the_cat cat
Example Output
there there_is is is_a a a_cat cat cat_house house where many cats live. in the the_cat cat cat_house house,
there there_is is is_a a a_cat cat cat_called called called_alice alice and a a_cat cat cat_called called called_bob bob.
the the_cat cat cat_called called called_alice alice likes likes_to to purr and the the_cat cat cat_called called called_bob bob likes likes_to to drink milk.

Some more examples:
milk milk milk       milk milk_milk milk milk_milk milk
a bun and a bunny    a bun and a bunny
milk milk milk.      milk milk milk.
bun bun bun bun.     bun bun_bun bun bun_bun bun bun.

Notes

All utf-8 characters are allowed. Meaning that punctuations are part of the input.
Punctuation becomes part of the word (e.g., with in the house, is a cat the word house, includes the comma)

Why not house house_where where, since house where appears twice? (Actually, I think the example output does not match the example input.)

well spotted, not on purpose

What types of characters can the input have? Do we need to worry about punctuation for what counts as a word?

Good question @xnor, updated the question above

@BobvanLuijt So that clarifies what characters are allowed, but I'm still not clear how punctuation or other characters affect what's considered a separate word.

So basically a word is a sequence of non-whitespace characters?

Is the count overlapping or not? i.e does milk milk occur twice or once in milk milk milk? (I'd guess twice so "yes" but I don't know)

Yes, correct. Suggestions on how to add this to the game rules are welcome :)

RE: xnor & Arnald's comments: does milk milk still occur twice in milk milk milk. or not? (Note the trailing period).

@JonathanAllan so should the output of milk milk milk be milk milk_milk milk milk_milk milk?

@JonathanAllan I think the second note means that milk milk milk. would be left alone, and milk milk milk milk. would become milk milk_milk milk milk_milk milk milk.

@Nick agreed. I've added milk milk milk. and bun bun bun bun. as test cases and nominated for re-opening.

Thanks @JonathanAllan. Did you remove your answer btw?

An example like this should produce this_should -> this should produce this_should is probably worth adding (since a filtering approach might yield this this_should should produce this_should by mistake).

Is cat cat_house house, a mistake, since the second word includes the comma?

Python 2, 99 107 103 102 bytes
def f(s):S=s.split();T=zip(S,S[1:]+[s]);return' '.join(x+(' '+x+'_'+y)*(T.count((x,y))>1)for x,y in T)

Try it online!
Fixed the milk milk milk style edge cases.

...but milk milk milk - count is non-overlapping; is that OK?

@Jonathan Allan: Hmm... OP has yet to weigh in, but I don't like that milk milk milk doesn't work with this code... thinking...

Also be incorrect with compound words, like a bun and a bunny though.

Okay, fixed now at a cost of 8 bytes...

Jelly,  23 22 21  18 bytes
Ḳµżj”_$ƝḢKċ@Ị¥?€`K

A full program which prints the output.
Try it online! Or see a test-suite.
How?
Ḳµżj”_$ƝḢKċ@Ị¥?€`K - Main Link: list of characters T
Ḳ                  - split (T) at spaces (call this W)
 µ                 - start a new monadic chain (i.e. f(W))
       Ɲ           - for neighbouring pairs:
      $            -   last two links as a monad:
   j               -     join with...
    ”_             -     ...underscore character
  ż                - zip (with W) (making pairs of ["left", "left_right"]
                   -               plus a trailing ["rightmost"])
                `  - use this as both left and right arguments of:
               €   -   for each:
              ?    -     if...
             ¥     -     ...condition: last two links as a dyad:
           @       -       with swapped arguments:
          ċ        -         count occurrences of right in left
            Ị      -       is insignificant? (abs(x) <= 1)
        Ḣ          -     ...then: head (   ["left", "left_right"] -> "left"
                   -                    or ["rightmost"] -> "rightmost")
         K         -     ...else: join with space (["same", "same_same"] -> "same same_same")
                 K - join with space characters
                   - implicit print

Zsh, 103 bytes
t=($=1)
for b a (${${t:1}:^t})s+=(${a}_$b)
for w ($s)((++i,${#s:#$w}-$#s+1))||s[i]=
echo ${t:^s} $t[-1]

Try it online!
The key constructs used here are:

${=1}: splits the first parameter into words (because there are no other flags, the {braces} are optional)
${a:^b}: substitutes array $a zipped with array $b
${a:#b}: substitutes array $a with all instances of b removed.
${#   }: the length of the contained expansion.
echo: <<< leaves extra spaces

If the input is already split into words, 99 bytes.

Jelly, 32 27 bytes
;⁶Ḳṡ2W€jj”_W$Ɗ€ĠL’$ƇẎƊ¦Ṗ€ẎK

Try it online!
Shorter and more correct! Thanks to @JonathanAllan for highlighting an issue with "milk milk milk"!
A monadic link that takes a Jelly string as its argument and returns a processed Jelly string.
Explanation
;⁶                          | Append a space
  Ḳ                         | Split at spaces
   ṡ2                       | Sliced of length 2
                     Ɗ¦     | At the indices indicated by the following:
               Ġ            | - Group indices of equal values
                   Ƈ        | - Keep only those where the following is non-zero:
                L           |   - Length
                 ’          |   - Decrease by 1
                    Ẏ       | - Tighten (join outermost lists together)
             Ɗ€             | Do the following as a monad:
     W€                     | - Wrap each word in a list
       j    $               | - Join with the following:
        j”_                 |   - The two words joined with "_"
           W                |   - Wrapped in a list
                       Ṗ€   | Remove last member of each list
                         Ẏ  | Tighten (join outermost lists)
                          K | Join with spaces

JavaScript (ES6), 94 bytes
s=>s.split` `.map((w,i,a)=>a.some((W,j)=>j!=i&W==w&a[j+1]==(p=a[i+1]))?w+` ${w}_`+p:w).join` `

Try it online!

Thanks @Arnauld, would you mind explaining a bit more in-depth about how it works?

...also milk milk milk... I've asked under the question for clarification.

@JonathanAllan Thanks for pointing this out. Now fixed.

J, 69 bytes
;:inv@(a:-.~],@,.a:,~(2(,'_'&,)&.>/\])#&.>~1<1#.[:=/~2<\])' '<;._1@,]

Try it online!
J, 56 bytes (but breaks on commas)
(a:-.~],@,.a:,~(2(,'_'&,)&.>/\])#&.>~1<1#.[:=/~2<\])&.;:

Try it online!
explanation for both
A bit verbose but the underlying idea is nice, so I'll explain that with pictures:
Let's start with this input:
low in xx xx low in bun bun bun bun.

First we turn it into words:
┌───┬──┬──┬──┬───┬──┬───┬───┬───┬────┐
│low│in│xx│xx│low│in│bun│bun│bun│bun.│
└───┴──┴──┴──┴───┴──┴───┴───┴───┴────┘

And then create the underscore concatenation of every pair, plus a blank item at the end:
┌──────┬─────┬─────┬──────┬──────┬──────┬───────┬───────┬────────┬┐
│low_in│in_xx│xx_xx│xx_low│low_in│in_bun│bun_bun│bun_bun│bun_bun.││
└──────┴─────┴─────┴──────┴──────┴──────┴───────┴───────┴────────┴┘

Let's zip these together and see where we're at:
┌────┬────────┐
│low │low_in  │
├────┼────────┤
│in  │in_xx   │
├────┼────────┤
│xx  │xx_xx   │
├────┼────────┤
│xx  │xx_low  │
├────┼────────┤
│low │low_in  │
├────┼────────┤
│in  │in_bun  │
├────┼────────┤
│bun │bun_bun │
├────┼────────┤
│bun │bun_bun │
├────┼────────┤
│bun │bun_bun.│
├────┼────────┤
│bun.│        │
└────┴────────┘

We notice that if we could keep just the items we want in the right column, we could flatten the whole thing, unbox, and we'd be done.
So we want a filter for the right column.  Let's start by treating the consecutive pairs of input words as single units (again, with a blank at the end):
┌────────┬───────┬───────┬────────┬────────┬────────┬─────────┬─────────┬──────────┬┐
│┌───┬──┐│┌──┬──┐│┌──┬──┐│┌──┬───┐│┌───┬──┐│┌──┬───┐│┌───┬───┐│┌───┬───┐│┌───┬────┐││
││low│in│││in│xx│││xx│xx│││xx│low│││low│in│││in│bun│││bun│bun│││bun│bun│││bun│bun.│││
│└───┴──┘│└──┴──┘│└──┴──┘│└──┴───┘│└───┴──┘│└──┴───┘│└───┴───┘│└───┴───┘│└───┴────┘││
└────────┴───────┴───────┴────────┴────────┴────────┴─────────┴─────────┴──────────┴┘

The filter we seek is simply any element that occurs more than once.   To find this we'll create a function table of equality:
1 0 0 0 1 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
1 0 0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 1 1 0 0
0 0 0 0 0 0 1 1 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 1

And sum it rowise or colwise (the direction doesn't matter, since it's symmetric):
2 1 1 1 2 1 2 2 1 1

And find all entries greater than 1:
1 0 0 0 1 0 1 1 0 0

This filter is all we need to carry out our plan from above and arrive at the answer.


text:
Count rook moves 1D
Given a position with a row of rooks and/or empty spaces, output how many different rook moves are possible. A rook can move left or right to an empty space, but not to one that requires passing over another rook. When a rook moves, the other rooks remain in place.
For example, from this position, 6 moves are possible:
.R..RRR.

The first (leftmost) rook can move 1 space left, or 1 or 2 spaces right (3 moves)
The next rook can only move 1 or 2 spaces left (2 moves)
The third rook cannot move at all because it's squeezed between two other rooks (0 moves)
The last rook can only move 1 space right (1 move)

Note that a position might have no rooks at all, or no empty spaces at all.
Input: A non-empty list (string, array, etc..) of rooks and empty spaces. You can represent them as True/False, 1/0, 'R'/'.', or any two consistent distinct single-byte characters or one-digit numbers of your choice. It's up to you which one means rook and which means empty space.
Output: A non-negative integer. Whole-number floats are also fine.
Test cases
The output is the number on the left.
6 .R..RRR.
0 .
0 R
4 R..RR
3 ...R
8 ..R..R..
0 ......

For more test cases, here are all inputs up to length 5.
0 .
0 R
0 ..
1 .R
1 R.
0 RR
0 ...
2 ..R
2 .R.
1 .RR
2 R..
2 R.R
1 RR.
0 RRR
0 ....
3 ...R
3 ..R.
2 ..RR
3 .R..
3 .R.R
2 .RR.
1 .RRR
3 R...
4 R..R
3 R.R.
2 R.RR
2 RR..
2 RR.R
1 RRR.
0 RRRR
0 .....
4 ....R
4 ...R.
3 ...RR
4 ..R..
4 ..R.R
3 ..RR.
2 ..RRR
4 .R...
5 .R..R
4 .R.R.
3 .R.RR
3 .RR..
3 .RR.R
2 .RRR.
1 .RRRR
4 R....
6 R...R
5 R..R.
4 R..RR
4 R.R..
4 R.R.R
3 R.RR.
2 R.RRR
3 RR...
4 RR..R
3 RR.R.
2 RR.RR
2 RRR..
2 RRR.R
1 RRRR.
0 RRRRR

Retina, 14 9 bytes
w`_+R|R_+

Try it online! Link includes test cases. Uses _ for empty space as it's the most pleasant non-regex character. Works by counting the number of substrings that correspond to a valid Rook move. A substring is a valid Rook move if it contains at least one _ plus a single R at either the beginning or the end.

Oh, you basically figured out how to do what I mentioned in my answer. Idk why I didn't think of that.

Python 3, 30 29 bytes
lambda s:sum((s+s).strip())/9

Try it online!
-1 byte thanks to @JoKing
The function takes a Python byte string as input. Each empty space is encoded as a tab and each rook is encoded as a byte b'\x00' having value 0.
The computation is equivalent to lambda s:(s+s).strip().count(b'\t') while having a lower byte count.

JavaScript (ES6),  38  33 bytes
Saved 5 bytes thanks to @JoKing
Takes input as a string. Expects a space for an empty square and any other character for a rook.
s=>(s+s).trim().split` `.length-1

Try it online!
Commented
s =>          // s = input, e.g. " R  RRR "
  (s + s)     // double -> " R  RRR  R  RRR "
  .trim()     // remove leading and trailing spaces -> "R  RRR  R  RRR"
  .split` `   // split on spaces -> [ 'R', '', 'RRR', '', 'R', '', 'RRR' ]
  .length - 1 // return the length - 1 -> 6

Python 2,  40  33 bytes
Saved 7 bytes thanks to @Grimy
lambda s:(s+s).strip().count(' ')

Try it online!

The Python version should use count instead of split (TIO)

@Grimy Thank you. :)

Japt, 5 bytes
²x èS

Try it
²x èS        Implicit input string of U
²            U + U
 x           Remove trailing and leading whitespace
   èS        Number of spaces

Perl 6, 16 bytes
{+m:ex/s+R|Rs+/}

Try it online!
A regex that matches all exhaustive instances of rooks followed by spaces, or spaces followed by a rook and returns the number of matches.

05AB1E, 5 bytes
«ðÚð¢

Try it online!
«       # concatenate the input with itself
 ðÚ     # remove leading and trailing spaces
   ð¢   # count spaces

Retina, 23 15 bytes
Double the number of spaces between rooks, grep lines with at least one rook, then count the number of spaces.
R.+R
$0$0
G`R

Try it online!
Though the program uses spaces instead of periods, I added prefix code so that the test cases provided may be easily pasted in and used.
I was hoping I could use overlapping matches with (?<=R.*) | (?=.*R), but overlaps aren't quite that aggressive. It would need to count all possible ways a match could be obtained in order to return the correct result with that method.

Seems to give the wrong result for .R.R.R. although changing the first line to R.+R might help?

@Neil Fixed. Thanks.

Jelly, 5 bytes
ḲẈ+ƝS

Try it online!
-1 thanks to Jonathan Allan.
0 represent a rook, 1 represents an empty space.

If you use a space character for a Rook and another character for a space you can use Ẉ to get the five: ḲẈ+ƝS

@JonathanAllan LOL didn't think of that. And before that was me experimenting with Ẉ but using ṣ0 instead...

Wolfram Language (Mathematica), 43 38 bytes
Count[Subsequences@#,{0,1..}|{1..,0}]&

Try it online!
Port of Neil's Retina solution. Uses 1 for spaces and 0 for rooks.

Jelly, 6 bytes
t1;ḟẠS

Try it online!
A monadic link taking a list of 0 for rook and 1 for space and returning an integer with the number of moves. The TIO link takes the pasted list of possible boards given in the question, converts to the right format and then outputs the calculated and correct answers.
Explanation
t1     | Trim 1s from end
  ;    | Concatenate to input
   ḟẠ  | Filter out 1s if all input were 1s, otherwise filter out 0s
     S | Sum

Japt, 6 bytes
Spaces for spaces, any other character for rooks.
²x ¸ÊÉ

Try it

Beat ya by 10 minutes :P

Goddamnit, @Oliver! :p

Snails, 7 bytes
At least it beats Retina :)
o
\.+\R

Try it online!

Stax, 7 6 5 bytes
àσQ█ε

Run and debug it
Use tab for empty square and any other character for rook.

Haskell, 36 bytes
f s=sum$snd.span(>0)=<<[s,reverse s]

Try it online!
Uses 1 for empty space, 0 for rook. Counts the number of 1's not in an initial block of ones, and adds that to the result for the reversed string.

Haskell, 33 bytes
sum.(t.reverse<>t)
t=snd.span(>0)

Try it online!
Anonymous function that takes input as a list of 1s (spaces) and 0s (rooks). This trims spaces from the start and the end of the list, then concatenates the two versions of the list and sums them.
This uses GHC 8.4.1 or later to have access to the <> operator without importing it.

C (clang), 57 bytes
i,r,o;g(*n,z){for(o=r=i=0;z--;i=-~i*!*n++)o+=*n?r=1,i:r;}

Try it online!

Saved 1 thanks to @ceilingcat

I realized it didn't worked for empty lists..
Now it works! Plus saved some bytes!
1=rook.   0=space.
for(..   i+=n++?-i:1)// counts spaces or reset extra moves =>  i=-~i!*n++ ( @ceilingcat )
o+=*n?r=1,i:r; // adds to output -i-(extra moves) when a rook is met plus sets -r-(rook met), -i- will be cleared in for increment sentence.
adds -r- for every space(rook met guaranteed )

Rocks? Do your rocks move?

@Mast lol sorry ! Edited

Python 2, 59 bytes
def f(r):S=map(len,r.split('R'));return sum(S)*2-S[0]-S[-1]

Try it online!

Japt, 6 bytes
²x ¸ÊÉ

Try it online

Stax, 7 6 bytes
-1 byte thanks to recursive
╣ë|óêπ

Run and debug it

Nice work.  By the way, subtrating 1 can be done with v, which will save you a byte.

C# (Visual C# Interactive Compiler), 27 bytes
x=>(x+x).Trim().Sum(d=>d)/9

Saved a byte thanks to @someone
Try it online!

Afaik you can use tabs to save a byte (shorter charcode), but I'm on a phone.

Haskell, 68 58 54 bytes
(n#y)(a:x)|a<1=n+(0#1)x|m<-n+1=y+(m#y)x
(_#_)x=0
f=0#0

Try it online!

C, 183 156 151 137 96 91 bytes
Thanks to ceilingcat for 91 bytes.
c,e;char*z,b[9];main(d){for(gets(z=b);e=*z>81?c-=e*~!d,d=0:e+1,*++z;);printf("%i",d?:c+e);}

R is a rook, everything else is a space.
TIO

A few things - a function (instead of a full program) is allowed, you can rely on undefined behavior (e.g. automatically zeroing) as long as your program works correctly on at least one compiler, it's shorter to use 82 instead or 'R', it's shorter to use e+e*d than e*(1+d), e=0,d=1;else e++; can be changed to e=-1,d=1;e++;, and b[a]andb[++a]can be replaced withband++b`

Perl 5 -MList::Util=sum -pF/R/, 40 bytes
$\=2*sum map$_=y///c,@F}{$\-="@F"+$F[-1]

Try it online!

Red, 46 bytes
func[s][length? next split trim append s s sp]

Try it online!
Just a Red port of Arnauld's JavaScript/Python solutions. Takes a space as an empty square.

Java 11, 35 32 bytes
s->(s+s).strip().chars().sum()/9

Port of @Joel's Python 3 answer.
-3 bytes thanks to @Joel as well.
Uses NULL-bytes (\0) for Rooks and tabs (\t) for spaces.
Try it online.
I tried using s->(s+s).trim().chars().sum()/9 at first as 31-byter, but this doesn't work because the String#trim builtin not only removes leading and trailing spaces/tabs/newlines, but also all other bytes that are smaller than or equal to U+0020 (unicode 32; a space), so it'll remove the NULL-bytes as well..
Thanks to Joel for recommending me the new Java 11+ String#strip builtin (which I forgot they added) as alternative. This one also removes trailing/leading portions, but in this case only whitespaces, so the NULL-bytes are retained.
Explanation:
s->                              // Method with String as parameter & integer return-type
  (s+s)                          //  Concatenate the input to itself
       .strip()                  //  Then trim all leading and trailing tabs
               .chars().sum()    //  Sum the unicode values of the remaining characters
                             /9  //  And divide it by 9 to get the amount of remaining tabs

Java 11+ allows using String.strip() to remove only whitespaces: 32 bytes

@Joel Ah, completely forgot about that one! Thanks. :)

Befunge-98 (PyFunge), 73 bytes
#;ep10fp#;>#v~:'.-#v_$1+0k
v0+ge0*gf0$_v#!-R':<
>ep20fp   v >0fg1-*0eg+.@

Try it online!

Pyth, 7 bytes
/r6*2Qd

Try it online!
Takes a string of R for rooks,  (space) for empty spaces
/     d  # Count spaces in
 r6      #  Strip spaces from
   *2Q   #   2 * input() (= concatenation)

x86-64 - 26 Bytes
Input is an array of up to 32 bits and an integer representing number of squares, 1 representing rook, 0 representing empty.
C4 E2 69 F7 C1       shlx        eax,ecx,edx
0B C1                or          eax,ecx
F3 0F BC C8          tzcnt       ecx,eax
D3 E8                shr         eax,cl
F3 0F BD C8          lzcnt       ecx,eax
F7 D0                not         eax
F3 0F B8 C0          popcnt      eax,eax
2B C1                sub         eax,ecx
C3                   ret

Copies the bits so that it is added to the left of it  and removes the trailing zero bits. Then gets number of leading zero bits and subtracts it from the total number of zero bits.
x86-64 Machine Code - 22 Bytes - regular length chess ranks only.
Input is a 32-bit integer with the least significant byte made of 8 bits representing the rooks. 1 is a rook, 0 is empty.
8A E9                mov         ch,cl
91                   xchg        eax,ecx
F3 0F BC C8          tzcnt       ecx,eax
D3 E8                shr         eax,cl
F3 0F BD C8          lzcnt       ecx,eax
F7 D0                not         eax
F3 0F B8 C0          popcnt      eax,eax
2B C1                sub         eax,ecx
C3                   ret

Copies the bits into the next significant byte and removes the trailing zero bits. Then gets number of leading zero bits and subtracts it from the total number of zero bits.

So this only works for rows of exactly length 8? If yes, that seems a bit too specific for the challenge.

Accidentally assumed they were regular rook ranks, fixed now.