El protocolo urinario

38

Fondo

El llamado "Protocolo Urinario", que describe el orden en que se recogen los urinarios individuales en el baño de hombres, se ha discutido en varios lugares. Se da una versión en esta publicación de blog xkcd . Esta pregunta se refiere a una ligera variación:

Disposición : n urinarios en línea.
Protocolo : cada nueva persona selecciona uno de los urinarios más distantes de los que ya están en uso.

Tenga en cuenta que esto no impone restricciones sobre qué urinario es elegido por la primera persona.

Actualización : La secuencia de la cantidad de formas diferentes en que n personas pueden seleccionar n urinarios comienza con 1, 2, 4, 8, 20 ... Tenga en cuenta que esto no es lo mismo que OEIS A095236 , que describe restricciones ligeramente más estrictas que en este pregunta.

Tarea

Dado un número entero n entre 0 y 10, genera (en cualquier orden) todos los ordenamientos posibles en los que n personas pueden ocupar n urinarios. Cada pedido debe imprimirse como disposición final: una secuencia de dígitos que representa a las personas (1-9 para las primeras 9 personas, 0 para la décima), comenzando desde el orinal más a la izquierda, con separadores opcionales no alfanuméricos entre (pero no antes o después) los dígitos. Por ejemplo, las siguientes salidas son válidas:

>> 3
132
213
312
231

>> 4
1|3|4|2
1|4|3|2
3|1|4|2
4|1|3|2
2|3|1|4
2|4|1|3
2|3|4|1
2|4|3|1

Puede escribir un programa o función, tomando datos a través de STDIN (o la alternativa más cercana), argumento de línea de comandos o argumento de función. Los resultados deben imprimirse en STDOUT (o la alternativa más cercana).

Tanteo

El código más corto gana. Aplican términos y condiciones estándar.

Uri Granta
fuente
1
Hm. Por 5 urinarios obtengo esto . Debería ser 16 filas en su lugar. ¿Podría alguien explicar cuál de esas soluciones está mal? Esto se está implementando actualmente: elija cualquiera de los urinarios con la distancia máxima a cualquier otra persona.
knedlsepp
1
Tanto para el sandboxing :-( La especificación es como se describe en la tarea, no la definición de secuencia. Actualizaré tan pronto como llegue a una computadora.
Uri Granta
1
@knedlsepp Las filas 3, 4, 17, 18 son incorrectas. En estos, coloca a la persona # 3 en una spande longitud 1, donde hay una spande longitud 2 disponible. De repente me las arreglé para confundirme. Parece que el OP se deriva intencionalmente del enlace y, por lo tanto, ¿se debe seguir el enlace?
BrainSteel
Se actualizó la especificación para tener en cuenta que la tarea no es la misma que A095236.
Uri Granta
¿Está permitido generar el formato en [1, 3, 2], donde cada una de estas soluciones está separada por líneas nuevas? (por lo tanto, no solo un separador de ",", sino también un comienzo de "[" y el final de "]")
orlp

Respuestas:

11

Pyth, 53 51

MhSm^-dG2HjbmjdmehxkbQusmm+dkfqgTdeSmgbdQUQGUtQm]dQ

Este es un enfoque iterativo. Dado un posible conjunto parcialmente ordenado de ubicaciones ordenadas, encontramos todas las ubicaciones óptimas adicionales, luego generamos la lista de ubicaciones correspondiente y repetimos.

Los resultados se generan en la forma [<first person's location>, <second person's location> ...], luego esto se transforma en el formato deseado. MhSm^-dG2Hdefine una función auxiliar que encuentra las distancias mínimas desde un puesto dado a un puesto ocupado (al cuadrado). Divertidamente, el separador es gratis.

Ejemplo de ejecución.

Explicación:

Primero, la función auxiliar g, que encuentra la distancia al cuadrado mínima entre G y cualquier valor en H.

MhSm^-dG2H
M             def g(G,H): return
 hS           min(                         )
   m     H        map(lambda d:        , H) 
    ^-dG2                      (d-G)**2

A continuación, encontramos las ubicaciones máximas sobre urinarios de la distancia mínima al cuadrado entre ese urinario y cualquier urinario ocupado:

( Qes la entrada)

eSmgbdQ
eS          max(                                   )
  m   Q         map(lambda b:      , range(len(Q)))
   gbd                       g(b,d)

den este caso es la lista de urinarios ocupados, mientras que bitera sobre las ubicaciones de los urinarios.

A continuación, encontramos todas las ubicaciones de urinarios cuya distancia al cuadrado mínima desde el orinal ocupado más cercano es igual al valor máximo que se encuentra arriba.

fqgTdeSmgbdQUQ
f           UQ    filter(lambda T:                             , range(len(Q)))
 qgTd                             g(T,d) ==
     eSmgbdQ                                <value found above>

A continuación, generaremos las listas de ubicación de urinarios creadas agregando las ubicaciones de urinarios que se encuentran arriba d. Haremos esto para cada lista anterior de ubicaciones de urinarios, extendiendo así las listas de longitud Na N+1. Ges la lista de listas legales de ubicaciones de urinarios ocupadas de una longitud determinada.

smm+dkfqgTdeSmgbdQUQG
sm                  G    sum(map(lambda d:                               ,G)
  m+dk                                   map(lambda k:d+[k],            )
      fqgTdeSmgbdQUQ                                        <above list>

A continuación, aplicaremos la expresión anterior repetidamente para generar la lista completa de listas de ubicaciones de urinarios ocupadas. u, la función reducir, hace exactamente esto, tantas veces como haya elementos en su segundo argumento.

usmm+dkfqgTdeSmgbdQUQGUtQm]dQ
usmm+dkfqgTdeSmgbdQUQG           reduce(lambda G,H: <the above expression)
                      UtQ        repeat Q-1 times
                         m]dQ    starting with [[0], [1], ... [Q-1]]. 

Convertir de la representación anterior, que va [<1st location>, <2nd location>, ... ], a la forma de salida deseada, [<person in slot 1>, <person in slot 2>, ... ]. Luego, el formulario de salida se une a la cadena de salida y se imprime. La impresión es implícita.

jbmjdmehxkbQ
jbm             '\n'.join(map(λ k:                                    ,<above>)
   jdm     Q                      ' '.join(map(λ b:                ,Q)
        xkb                                        b.index(k)
      eh                                                     +1 %10
isaacg
fuente
Maldición, debería dejar de escribir soluciones recursivas en Pyth. Siempre me dan una paliza: P
orlp
kajsdlkas^23asdjkla1lasdkj~JZasSSA- Casi la mitad del tamaño.
Optimizador
@Optimizer Agregaré una explicación cuando esté menos ocupado.
isaacg
8

Pyth, 75 71 67

DcGHFk_UQJf!s:GeS,0-TkhS,h+TklGUQIJRsmcX>G0dhHhHJ)R]Gjbmjdmebkcm0Q0

Solución combinatoria recursiva.

Es una traducción bastante directa de esta solución de Python:

N = int(input())

def gen(l, p):
    for d in reversed(range(N)):
        s = []
        for i in range(N):
            if not sum(l[max(0,i-d):min(i+d+1, len(l))]):
                s.append(i)

        if s:
            r = []
            for possib in s:
                j = l[:]
                j[possib] = p+1
                r += gen(j, p+1)

            return r

    return [l]

print("\n".join(" ".join(str(x % 10) for x in sol) for sol in gen([0] * N, 0)))
orlp
fuente
¿Cómo funciona? En más detalle que "solución combinatoria recursiva".
tbodt
@tbodt Agregué el código de Python que escribí antes de traducirlo a Pyth.
orlp
5

C, 929 878 bytes

Este es un monstruo, muchachos. Lo siento.

typedef unsigned long U;typedef unsigned char C;U f(int*u,n){C c[8],a[8];*(U*)(&c)=-1;int i,b=0,l=-9,s=-2,f=0,d;for (i=0; i<n; i++) {if (!u[i]&&s<0)s=i,l=0;if(!u[i])l++;if(u[i]&&s>=0){if(!s)l=2*l-1;d=(l-1)/2;if(b<d)*(U*)(a)=0,*(U*)(c)=-1,*c=s,*a=l,f=1,b=d;else if(b==d)c[f]=s,a[f++]=l;s=-1;}}if(s>=0&&l){l=2*l-1;d=(l-1)/2;if(b<d)*(U*)(c)=-1,*c=s,*a=l,f=1,b=d;else if(b==d)c[f]=s,a[f++]=l;}d=f;for(i=0;i<d;i++){if((c[i]+1)&&c[i]){if(c[i]+a[i]==n)c[i]=n-1;else{if(!(a[i]%2))c[f++]=b+c[i]+1;c[i]+=b;}}}return*(U*)c;}void P(int*u,n,i,c,m){for(i=0;i<n;i++){if(!u[i])c++;if(u[i]>m)m=u[i];}if(!c){for(i=0;i<n;i++)printf("%d",u[i]==10?0:u[i]);printf("\n");}else{int s[8][n];for(i=0;i<8;i++)for(c=0;c<n;c++)s[i][c]=u[c];U t=f(u,n);C*H=&t;for(i=0;i<8;i++)if((C)(H[i]+1))s[i][H[i]]=m+1,P(s[i],n,0,0,0);}}void L(n){int u[n],i,j;for(i=0;i<n;i++){for(j=0;j<n;j++)u[j]=j==i?1:0;P(u,n,0,0,0);}}

Define 3 funciones, f(int*,int), P(int*,int,int,int,int), y L(int). Llama L(n)y sale a STDOUT.

Salida para n=5:

14352
15342
31452
31542
41352
51342
41532
51432
24153
25143
34152
35142
23415
23514
24513
25413
24315
25314
24351
25341

Actualización: eliminé los separadores y arreglé el código. El código anterior no solo falló para n = 7 +, sino que no pudo generar nada para n = 10 (¡Uy!). He probado más a fondo este grupo. Ahora admite entradas de hasta n = 13 (aunque "%d"debería cambiarse para "%x"que se imprima en hexadecimal). El tamaño de la entrada depende sizeof(long)y se supone que está 8en la práctica.

Aquí hay una explicación de cómo funciona y por qué existe una restricción tan extraña:

Estos se usaron mucho, por lo que los definimos para guardar un par de bytes:

typedef unsigned long U; typedef unsigned char C;

Aqui esta f:

U f(int*u,n){
    C c[8],a[8];
    *(U*)(&c)=-1;
    int i,b=0,l=-9,s=-2,f=0,d;
    for (i=0; i<n; i++) {
        if (!u[i]&&s<0)
            s=i,l=0;
        if(!u[i])
            l++;
        if(u[i]&&s>=0){
            if(!s)
                l=2*l-1;
            d=(l-1)/2;
            if(b<d)
                *(U*)(a)=0,
                *(U*)(c)=-1,
                *c=s,
                *a=l,
                f=1,
                b=d;
            else if(b==d)
                c[f]=s,a[f++]=l;
            s=-1;
        }
    }
    if(s>=0&&l){
        l=2*l-1;
        d=(l-1)/2;
        if(b<d)
            *(U*)(c)=-1,
            *c=s,
            *a=l,
            f=1,
            b=d;
        else if(b==d)
            c[f]=s,a[f++]=l;
    }
    d=f;
    for(i=0;i<d;i++){
        if((c[i]+1)&&c[i]){
            if(c[i]+a[i]==n)
                c[i]=n-1;
            else{
                if(!(a[i]%2))
                    c[f++]=b+c[i]+1;
                c[i]+=b;
            }
        }
    }
    return*(U*)c;
}

ftoma una matriz de enteros de tamaño n, y en nsí mismo. El único bit inteligente aquí es que devuelve un unsigned long, que se convierte en a char[8]por la función de llamada. Por lo tanto, cada carácter de la matriz se establece 0xFFen un índice o apunta a un urinario válido para la siguiente persona. Para n<10, nunca necesitamos más de 5 bytes para contener cada urinario válido que la siguiente persona pueda usar.

Aqui esta P:

void P(int*u,n,i,c,m){
    for(i=0;i<n;i++){
        if(!u[i])c++;
        if(u[i]>m)m=u[i];
    }
    if(!c){
        for(i=0;i<n;i++)
            printf("%d",u[i]==10?0:u[i]);
        printf("\n");
    }
    else{
        int s[8][n];
        for(i=0;i<8;i++)
            for(c=0;c<n;c++)
                s[i][c]=u[c];
        U t=f(u,n);
        C*H=&t;
        for(i=0;i<8;i++)
            if((C)(H[i]+1))
                s[i][H[i]]=m+1,P(s[i],n,0,0,0);
    }
}

Ptoma una matriz ude tamaño nen el que exactamente se establece un elemento 1, y el resto lo son 0. Luego encuentra e imprime cada permutación posible de forma recursiva.

Aqui esta L:

void L(n){
    int u[n],i,j;
    for(i=0;i<n;i++){
        for(j=0;j<n;j++)
            u[j]=j==i?1:0;
        P(u,n,0,0,0);
    }
}

Lsimplemente llama P ntiempos con diferentes posiciones de inicio cada vez.

Para los interesados, esto (menos golfizado) fgenerará la secuencia en A095236 .

U f(int*u,n) {
    C c[8];
    *(U*)(&c) = -1;
    int i,b=0,l=-10,s=-2,f=0,d;
    for (i=0; i<n; i++) {
        if (!u[i]&&s<0) {
            s=i,l=0;
        }
        if(!u[i]){
            l++;
        }
        if (u[i]&&s>=0) {
            if (!s) {
                l=2*l-1;
            }
            if (b<l) {
                *(U*)(&c)=-1;
                c[0]=s;
                f=1;
                b=l;
            }
            else if (b==l)
                c[f++]=s;
            s=-1;
        }
    }
    if (s>=0&&l) {
        l=2*l-1;
        if (b<l) {
            *(U*)(&c)=-1;
            c[0]=s;
            f=1;
            b=l;
        }
        else if (b==l)
            c[f++]=s;
    }
    d=f;
    for (i=0; i<d; i++) {
        if ((c[i]+1)&&c[i]) {
            if (c[i]+b==n) {
                c[i]=n-1;
            }
            else{
                if (!(b%2)) {
                    c[f++]=(b-1)/2+c[i]+1;
                }
                c[i]+=(b-1)/2;
            }
        }
    }
    return *(U*)c;
}
BrainSteel
fuente
"1 4 ..." al principio parece estar en contra de la especificación: si el primer número es 1, el siguiente debería ser 5.
anatolyg
2
@anatolyg No. Aquí hay una explicación paso a paso de cómo puede ocurrir "1 4": gist.github.com/orlp/a5706ba664b70209b48a
orlp
Recuerde, los separadores son opcionales. Puede ahorrar 1 byte (!) Eliminando el espacio después de% d :-)
Uri Granta
@UriZarfaty ¡Gracias! En realidad, hay una tonelada de bytes para guardar aquí. Actualmente estoy escribiendo una mejor solución y una explicación.
BrainSteel
@yo 'Creo que estás confundiendo un poco la salida. Una salida de 14352significa que la persona # 1 eligió el orinal más a la izquierda. La persona n. ° 2 eligió la más a la derecha, que luego forzó a la n. ° 3 al centro. No es el número del urinario elegido a continuación lo que debe salir.
BrainSteel
4

Pitón 2, 208

n=input()
r=range(n)
l=[0]*n
def f(a,d=-1):
 if a>n:print''.join(l);return
 for i in r:
  t=min([n]+[abs(i-j)for j in r if l[j]])
  if t==d:p+=[i]
  if t>d:p=[i];d=t
 for i in p:l[i]=`a%10`;f(a+1);l[i]=0
f(1)

Enfoque recursivo.

Jakube
fuente
4

JavaScript (ES6) 153 160 169

Edite usando Math.min para encontrar (por supuesto) la distancia máxima: código simplificado y 16 bytes guardados.

Búsqueda recursiva, puede funcionar con n> 10, simplemente elimine% 10 (y prepárese para esperar mientras la consola desenrolla toda su salida).

Utilizo una sola matriz para almacenar la ranura en uso (números positivos) o la distancia actual desde la ranura más cercana (los números negativos así <y >se intercambian en el código).

F=n=>{(R=(m,d,t,x=Math.min(...d=m?
  d.map((v,i)=>(c=i<t?i-t:t-i)?v<c?c:v:m%10)
  :Array(n).fill(-n)))=>
x<0?d.map((v,i)=>v>x||R(-~m,d,i)):console.log(d+[]))()}

Sin golf

F=n=>{
  var R=(m, // current 'man', undefined at first step
   d, // slot array
   t // current position to fill
  ) =>
  {
    if (m) // if not at first step
    {
      d[t] = m % 10; // mark slot in use, (10 stored as 0 )
      d = d.map((v,i) => { // update distances in d[] 
        var c = i<t ? i-t : t-i; // distance from the current position (negated)
        return v < c ? c : v; // change if less than current distance
      });
    }
    else
    {
      d = Array(n).fill(-n) // fill distance array with max at first step
      // negative means slot free, value is the distance from nearest used slot
      // >= 0 means slot in use by man number 1..n 
    }
    var x = Math.min(...d);
    if ( x < 0 ) // if there is still any free slot
    {
      d.forEach((v,i) => { // check distance for each slot 
        if (v <= x) // if slot is at max distance, call recursive search
          R(-~m, [...d], i) // ~- is like '+1', but works on undefined too
      });
    }
    else
    {
      console.log(d+[]); // no free slot, output current solution
    }
  }

  R() // first step call
}

Prueba en la consola Firefox / FireBug

F(5)

1,4,3,5,2
1,5,3,4,2
3,1,4,5,2
3,1,5,4,2
4,1,3,5,2
5,1,3 , 4,2
4,1,5,3,2
5,1,4,3,2
2,4,1,5,3
2,5,1,4,3
3,4,1,5,2
3 5,1,4,2
2,3,4,1,5
2,3,5,1,4
2,4,3,1,5
2,5,3,1,4
2,4,5 1,3
2,5,4,1,3
2,4,3,5,1
2,5,3,4,1

edc65
fuente
2

Mathematica, 123 104

f[n_,s_:{}]:=If[Length@s<n,f[n,s~Join~{#}]&/@MaximalBy[Range@n,Min@Abs[#-s]&];,Print@@Ordering@s~Mod~10]
alephalpha
fuente
@ MartinBüttner n~f~s~Join~{#}se convertirá Join[f[n,s],{#}].
alephalpha
Oh cierto, pensé que era correcto asociativo.
Martin Ender
1

MATLAB, 164

function o=t(n),o=mod(r(zeros(1,n)),10);function o=r(s),o=[];d=bwdist(s);m=max(d);J=find(d==m);if~d,o=s;J=[];end,n=max(s)+1;for j=J,o=[o;r(s+n*(1:numel(s)==j))];end
knedlsepp
fuente
1

Perl, 174

No muy corto, pero divertido. No cuento use feature 'say';para el total de bytes.

$n=pop;@u="_"x$n." "x$n."_"x$n;for$p(1..$n){@u=map{my@r;for$x(reverse 0..$n){
s/(?<=\D{$x}) (?=\D{$x})/push@r,$_;substr $r[-1],pos,1,$p%10/eg and last;
}@r}@u}y/_//d&&say for@u

De-golf:

$n = pop; # Get number of urinals from commandline
@state = ( "_" x $n . " " x $n . "_" x $n );

for my $person (1 .. $n) {
  # Replace each state with its list of possible next states.
  @state = map {
    my @results;
    for my $distance (reverse 0 .. $n) {
      # If there are any spots with at least $distance empty on
      # both sides, then add an entry to @results with the current
      # $person number in that spot, for each spot. Note that this
      # is only used for its side-effect on @results; the modified $_
      # is never used.
      s{
        (?<=\D{$distance})
        [ ]
        (?=\D{$distance})
      }{
        push @results, $_;
        substr $results[-1], pos(), 1, $person % 10;
      }xeg
      # If we found any spots, move on, otherwise try
      # with $distance one lower.
      and last;
    }
    # New state is the array we built up.
    @results;
  } @state;
}

# After adding all the people, remove underscores and print the results
for my $result (@state) {
  $result =~ tr/_//d;
  say $result;
}
hobbs
fuente
1

C, 248 bytes

Este código utiliza un algoritmo recursivo para generar el resultado deseado.

void q(char*f,int l,int d,char*o){char*c=f;while(f<c+l){if(!*f){sprintf(o+4*d,"%03i,",f-c);*f=1;q(c,l,d+1,o);*f=0;}f++;}if(d+1==l){o[4*d+3]=0;printf("%s\n",o);}}int main(int i,char**v){int k=atoi(v[1]);char*c=calloc(k,5),*o=c+k;q(c,k,0,o);free(c);}

Expandido:

void printperms(char* memory,int length,int offset,char*output)
{
    char*temp_char=memory;
    while(memory<temp_char+length)
    {
        if(!*memory)
        {
            sprintf(output+4*offset,"%03i,",memory-temp_char);
            *memory=1;
            printperms(temp_char,length,offset+1,output);
            *memory=0;
        }
        memory++;
    }
    if(offset+1==length)
    {
        output[4*offset+3]=0;
        printf("%s\n",output);
    }
}

int main(int i,char**v)
{
    int argument=atoi(v[1]);
    char*t=calloc(argument,5),*output=t+argument;
    printperms(t,argument,0,output);
    free(t);
}
Gerwin
fuente
1

Bash, 744 674 bytes

Esto todavía es demasiado largo :). Utilizo una cadena para representar la fila de urinarios y un algoritmo de inundación para encontrar los urinarios más distantes en cada fase de recursión. El código sin golf es casi autoexplicativo. El número de urinarios se lee desde el teclado.

Código (golfizado):

read l;u=----------;u=-${u::$l}-
s(){ u=${u:0:$1}$2${u:$((1+$1))};}
m(){ local u=$1;a=();while :;do [ 0 -ne `expr index - ${u:1:$l}` ]||break;t=$u;y=$u;for i in `seq $l`;do [ ${y:$i:1} = - ]||{ s $(($i-1)) X;s $(($i+1)) X;};done;done;while :;do k=`expr index $t -`;[ 0 != $k ]||break;t=${t:0:$(($k-1))}X${t:$k};if [ 1 -ne $k ]&&[ $(($l+2)) -ne $k ];then a+=($(($k-1)));fi;done;}
e(){ local u f b v;u=$1;f=$2;if [ 1 -eq $l ];then echo 1;return;fi;if [ 1 = $f ];then for i in `seq $l`;do v=$u;s $i 1;e $u 2;u=$v;done;else m $u;b=(${a[@]});if [ 0 -eq ${#b} ];then echo ${u:1:$l};else for i in ${b[@]};do v=$u;s $i $(($f%10));e $u $(($f+1));u=$v;a=(${b[@]});done;fi;fi;}
e $u 1

Utilizar:

$ source ./script.sh
input number of urinals from keyboard

Y sin golf va:

read l  # read number of urinals
u=----------
u=-${u:0:$l}- #row is two positions longer (it will be helpful when finding the most distant urinals)

# So, for the end, with 6 men, u might look like this:
# -143652-

# subu no fellow_no => set urinal [number] occupied by [fellow_no]
# this is just convenience for resetting a character inside a string
subu(){ u=${u:0:$1}$2${u:$((1+$1))};}


# this will be iterated in longest to find the remotest places:
# -1---3---2- => spreadstep => X1X-X3X-X2X => spreadstep => X1XXX3XXX2X
# see longest() to get more explanation.
spreadstep()
{
    y=$u
    for i in `seq 1 $l`
    do
    if [ "${y:$i:1}" != "-" ]
    then
        subu $(($i-1)) X
        subu $(($i+1)) X
    fi
    done
}

# Find the urinals with the longest distance. It uses spreadstep() - see above.
# -1---3---2- => spreadstep => X1X-X3X-X2X => spreadstep => X1XXX3XXX2X
# ---> last state with free ones was X1X-X3X-X2X ,
#                                     123456789
# free urinals are no. 3 and no. 7 => save them to arr
longest()
{
    local u=$1
    arr=()
    while true
    do
        if [ 0 -eq `expr index - ${u:1:$l}` ]
        then
            break
        fi
        save=$u
        spreadstep
    done

    while true
    do
        index=`expr index $save -`
        if [ 0 == $index ]
        then
            break
        fi

        save=${save:0:$(($index-1))}X${save:$index}
        if [ 1 -ne $index ] && [ $(($l+2)) -ne $index ]
        then
            arr+=($(($index-1)))
        fi
    done
}

# main function, recursively called
# the first fellow may take any of the urinals.
# the next fellows - only those with the longest distance.
placements_with_start()
{
    local u=$1
    local fellow=$2
    if [ 1 -eq $l ] # special case - there is no 2nd fellow, so below code would work incorrect 
    then
        echo "1"
        return
    fi
    if [ 1 == $fellow ]       # may take any of urinals
    then
        for i in `seq 1 $l`
        do
            local _u=$u
            subu $i 1                     # take the urinal
            placements_with_start $u 2    # let the 2nd fellow choose :)
            u=$_u
        done
    else
        longest $u   # find the ones he can take
        local _arr=(${arr[@]})
        if [ 0 -eq ${#_arr} ]
        then
            echo ${u:1:$l}    # no more free urinals - everyone took one - print the result
        else
            for i in ${_arr[@]}
            do
                local _u=$u
                subu $i $(($fellow % 10))                # take urinal
                placements_with_start $u $(($fellow+1))  # find locations for for next fellow
                u=$_u
                arr=(${_arr[@]})
            done
        fi
    fi
}

placements_with_start $u 1
pawel.boczarski
fuente