소변기 프로토콜


38

배경

남자 화장실에서 개별 소변기 선택 순서를 설명하는 소위 "소변 프로토콜"이 여러 곳에서 논의되었습니다. 이 xkcd 블로그 게시물 에는 하나의 버전이 제공됩니다 . 이 질문은 약간의 변형과 관련이 있습니다.

배열 : 한 줄에 소변기.
임상 시험 계획서 (Protocol) : 각각의 새로운 사람은 이미 사용중인 소변기와 가장 멀리 떨어진 소변기 중 하나를 선택합니다.

이것은 첫 번째 사람이 소변을 선택하는 데 아무런 제한 이 없습니다 .

업데이트 : 어떤 N 명에서 선택한 n 개의 소변기를 시작으로 수있는 다른 방법의 수의 순서 1, 2, 4, 8, 20 ... 참고이 없는 동일로 OEIS A095236 이보다 약간 엄격한 제한을 설명합니다, 질문.

태스크

0에서 10 사이의 정수 n이 주어지면, n 명이 n 소변기를 점유 할 수있는 모든 가능한 순서를 (순서대로) 출력하십시오. 각 주문은 최종 배열로 인쇄해야합니다. 맨 왼쪽 소변기에서 시작하여 사람을 나타내는 숫자 순서 (처음 9 명은 1-9, 10은 0)는 알파벳이 아닌 구분 기호 사이에 옵션이 있습니다. 또는 이후) 자릿수. 예를 들어 다음 출력이 모두 유효합니다.

>> 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

STDIN (또는 가장 가까운 대안), 명령 행 인수 또는 함수 인수를 통해 입력을받는 프로그램 또는 함수를 작성할 수 있습니다. 결과는 STDOUT (또는 가장 가까운 대안)으로 인쇄해야합니다.

채점

가장 짧은 코드가 승리합니다. 표준 이용 약관이 적용됩니다.


1
흠. 5 개의 소변 기용으로 이것을 얻 습니다 . 대신 16 행이어야합니다. 누구든지 그 솔루션 중 어떤 것이 잘못 되었습니까? 현재 시행 중입니다 : 다른 사람과의 거리가 가장 큰 소변기 중 하나를 선택하십시오.
knedlsepp

1
샌드 박스를위한 많은 것들 :-( 스펙은 시퀀스 정의가 아니라 작업에 설명되어 있습니다. 컴퓨터에 도착하자마자 업데이트하겠습니다
Uri Granta

1
@knedlsepp 3, 4, 17, 18 행이 잘못되었습니다. 여기에서 사람 # 3 span은 길이가 1 인 장소 span에 길이가 2 인 사람이 있습니다. 나는 갑자기 혼동을 일으켰다. OP가 의도적으로 링크에서 파생 된 것처럼 보이므로 링크를 따라야합니까?
BrainSteel

작업이 A095236과 동일 하지 않도록 사양이 업데이트되었습니다 .
Uri Granta

[1, 3, 2]로 형식을 출력 할 수 있습니까? 각 솔루션은 개행 문자로 구분됩니다. (따라서 ","의
구분자

답변:


11

피스, 53 51

MhSm^-dG2HjbmjdmehxkbQusmm+dkfqgTdeSmgbdQUQGUtQm]dQ

이것은 반복적 인 접근 방식입니다. 순서가 지정된 위치 세트에 부분적으로 채워진 가능한 경우 모든 최적의 추가 위치를 찾은 다음 해당 위치 목록을 생성하고 반복합니다.

결과는 형식으로 생성 된 [<first person's location>, <second person's location> ...]다음 원하는 형식으로 변환됩니다. MhSm^-dG2H주어진 스톨에서 점유 된 스톨 (제곱)까지의 최소 거리를 찾는 도우미 함수를 정의합니다. 재미있게도 구분 기호는 무료입니다.

실행 예.

설명:

먼저 헬퍼 함수 g는 G와 H의 값 사이의 최소 제곱 거리를 찾습니다.

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

다음으로, 우리는 그 소변과 점유 한 소변기 사이의 최소 제곱 거리의 소변 위치의 최대 위치를 찾습니다.

( Q입력입니다.)

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

d이 경우 점유 된 소변기 목록이 표시 b되고 소변기 위치는 반복됩니다.

다음으로, 가장 가까운 점유 소변기로부터 최소 제곱 거리가 위에서 찾은 최대 값과 동일한 모든 소변기 위치를 찾습니다.

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

다음으로 위에서 찾은 소변 위치를 추가하여 생성 한 소변 위치 목록을 생성합니다 d. 우리는 따라서 길이의 목록을 확장, 소변기 각각의 위치 이전 목록이 작업을 수행 할 것이다 NN+1. G주어진 길이의 점유 된 소변기 위치의 법적 목록입니다.

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

다음으로 위의 표현을 반복적으로 적용하여 점유 한 소변 위치 목록의 전체 목록을 생성합니다. ureduce 함수는 두 번째 인수에 요소가있는 횟수만큼 정확하게이를 수행합니다.

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]]. 

위의 표현 [<1st location>, <2nd location>, ... ]에서 원하는 출력 형식으로 변환하십시오 [<person in slot 1>, <person in slot 2>, ... ]. 그런 다음 출력 양식이 출력 문자열에 결합되어 인쇄됩니다. 인쇄는 암시 적입니다.

jbmjdmehxkbQ
jbm             '\n'.join(map(λ k:                                    ,<above>)
   jdm     Q                      ' '.join(map(λ b:                ,Q)
        xkb                                        b.index(k)
      eh                                                     +1 %10

젠장, Pyth에서 재귀 솔루션 작성을 중단해야합니다. 나는 항상 두들겨 : P
orlp

kajsdlkas^23asdjkla1lasdkj~JZasSSA-거의 절반 크기입니다.
Optimizer

@Optimizer 덜 바쁠 때 설명을 추가하겠습니다.
isaacg 2016 년

8

피스, 75 71 67

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

재귀 조합 솔루션.

이 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)))

어떻게 작동합니까? "재귀 조합 솔루션"보다 자세한 내용.
tbodt

@tbodt Pyth로 번역하기 전에 작성한 Python 코드를 추가했습니다.
orlp

5

C, 929 878 바이트

이건 괴물이야 죄송합니다.

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);}}

정의 3 개 기능, f(int*,int), P(int*,int,int,int,int),와 L(int). 를 호출 L(n)하면 STDOUT으로 출력됩니다.

에 대한 출력 n=5:

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

업데이트 : 구분 기호를 제거하고 코드를 수정했습니다. 이전 코드는 n = 7 +에 실패했을뿐만 아니라 n = 10 (아주!)에 대해서는 아무것도 출력하지 못했습니다. 나는이 무리를 더 철저히 테스트했습니다. 이제 최대 n = 13의 입력을 지원합니다 ( 16 진수로 인쇄되도록 "%d"변경해야 함 "%x"). 입력의 크기에 따라 다릅니다 sizeof(long)그리고 것으로 간주됩니다 8연습.

작동 방식에 대한 설명과 이러한 이상한 제한이 존재하는 이유는 다음과 같습니다.

이것들은 많이 사용되었으므로 몇 바이트를 저장하도록 정의했습니다.

typedef unsigned long U; typedef unsigned char C;

여기 있습니다 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;
}

f크기의 정수 배열 얻어 nn자체. 여기서 유일하게 영리한 것은 호출 함수에 의해 unsigned long로 변환되는를 반환한다는 것 char[8]입니다. 따라서 배열의 각 문자 0xFF는 다음 사람에게 유효한 소변기를 가리키는 색인으로 설정되거나 색인으로 설정됩니다 . 의 경우 n<10다음 사람이 사용할 수있는 모든 유효한 소변기를 보관하기 위해 5 바이트 이상이 필요하지 않습니다.

여기 있습니다 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);
    }
}

P어레이 소요 u사이즈의 n정확히 하나 개의 요소로 설정되는 것을 특징을 1, 나머지이다 0. 그런 다음 가능한 모든 순열을 재귀 적으로 찾아서 인쇄합니다.

여기 있습니다 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);
    }
}

LP n매번 다른 시작 위치로 시간을 호출하기 만하면 됩니다.

관심있는, 이것은 (이하 golfed) f의 시퀀스를 생성합니다 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;
}

시작시 "1 4 ..."는 사양에
맞지 않는

2
@anatolyg 아니요. 다음은 "1 4"가 발생하는 방법에 대한 단계별 설명입니다. gist.github.com/orlp/a5706ba664b70209b48a
orlp

구분 기호는 선택 사항입니다. % d :-) 뒤의 공백을 제거하여 1 바이트 (!)를 절약 할 수 있습니다.
Uri Granta

@UriZarfaty 감사합니다! 실제로, 여기에 저장 될 많은 바이트가 있습니다. 나는 현재 더 나은 해결책과 설명을 작성하고 있습니다.
BrainSteel

@yo '나는 당신이 출력을 약간 혼란스럽게 생각합니다. 14352수단 # 1 의 결과는 가장 왼쪽의 소변기를 선택했습니다. 사람 # 2는 가장 오른쪽을 선택한 다음 # 3을 가운데로 강제했습니다. 다음에 선택해야하는 소변기의 수가 아닙니다.
BrainSteel

4

파이썬 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)

재귀 적 접근.


4

자바 스크립트 (ES6) 153 160 169

Math.min을 사용하여 최대 거리 (물리적 코드 및 16 바이트 절약)를 찾아 편집하십시오 .

재귀 검색은 n> 10으로 작업 할 수 있으며 % 10을 제거하십시오 (콘솔이 모든 출력을 풀 때까지 기다릴 준비가 됨).

I 사용중인 슬롯 (양수) 또는 가까운 슬롯에서 현재 거리 저장 한 배열을 사용 (따라서 네거티브 번호 <>부호로 교체된다).

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+[]))()}

언 골프

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
}

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


2

매스 매 티카, 123 104

f[n_,s_:{}]:=If[Length@s<n,f[n,s~Join~{#}]&/@MaximalBy[Range@n,Min@Abs[#-s]&];,Print@@Ordering@s~Mod~10]

@ MartinBüttner n~f~s~Join~{#}가됩니다 Join[f[n,s],{#}].
alephalpha

아 맞다, 나는 그것이 올바른 연관성이라고 생각했다.
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

1

펄, 174

아주 짧지는 않지만 재미 있습니다. 나는 use feature 'say';바이트 총계를 계산하지 않습니다 .

$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

골퍼 해제 :

$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;
}

1

C, 248 바이트

이 코드는 재귀 알고리즘을 사용하여 원하는 결과를 생성합니다.

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);}

넓히는:

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);
}

1

강타, 744 674 바이트

이것은 여전히 ​​길다 :). 나는 문자열을 사용하여 소변기의 행과 범람 알고리즘을 사용하여 각 재귀 단계에서 가장 먼 소변기를 찾습니다. ungolfed 코드는 거의 자명하다. 소변기의 수는 키보드에서 읽습니다.

코드 (골프) :

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

사용하다:

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

그리고 골퍼하지 않습니다 :

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.