Giao thức tiết niệu


38

Lý lịch

Cái gọi là "Giao thức tiết niệu", mô tả thứ tự các bồn tiểu được chọn trong phòng tắm nam, đã được thảo luận ở nhiều nơi. Một phiên bản được đưa ra trong bài đăng blog xkcd này . Câu hỏi này liên quan đến một biến thể nhỏ:

Sắp xếp : n niệu trong một dòng.
Giao thức : mỗi người mới chọn một trong những bồn tiểu xa nhất so với những người đã sử dụng.

Lưu ý rằng nơi này không có hạn chế về việc người đầu tiên được chọn nước tiểu.

Cập nhật : Trình tự số lượng các cách khác nhau trong đó n người có thể chọn n niệu bắt đầu bằng 1, 2, 4, 8, 20 ... Lưu ý rằng điều này không giống với OEIS A095236 , mô tả các hạn chế hơi nghiêm ngặt hơn so với điều này câu hỏi

Bài tập

Cho một số nguyên n trong khoảng từ 0 đến 10, đầu ra (theo bất kỳ thứ tự nào) tất cả các thứ tự có thể có trong đó n người có thể chiếm n niệu. Mỗi đơn hàng phải được in dưới dạng sắp xếp cuối cùng: một chuỗi các chữ số đại diện cho mọi người (1-9 cho 9 người đầu tiên, 0 cho người thứ mười), bắt đầu từ bồn tiểu ngoài cùng bên trái, với các dấu tách không chữ và số tùy chọn giữa (nhưng không phải trước hoặc sau) các chữ số. Ví dụ: các đầu ra sau đây đều hợp lệ:

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

Bạn có thể viết chương trình hoặc hàm, lấy đầu vào qua STDIN (hoặc thay thế gần nhất), đối số dòng lệnh hoặc đối số hàm. Kết quả phải được in thành STDOUT (hoặc thay thế gần nhất).

Chấm điểm

Mã ngắn nhất sẽ thắng. Điều khoản và điều kiện tiêu chuẩn được áp dụng.


1
Hừm. Trong 5 lần tiểu tôi nhận được điều này . Nó sẽ là 16 hàng thay thế. Bất cứ ai có thể giải thích những giải pháp nào là sai? Điều này hiện đang được thực hiện: Chọn bất kỳ một trong những bồn tiểu có khoảng cách tối đa với bất kỳ ai khác.
knedlsepp 18/03/2015

1
Quá nhiều cho việc tạo hộp cát :-( Spec được mô tả trong tác vụ, không phải định nghĩa trình tự. Tôi sẽ cập nhật ngay khi tôi nhận được vào máy tính.
Uri Granta

1
@knedlsepp Hàng 3, 4, 17, 18 không chính xác. Trong đó, bạn đặt người số 3 ở spanđộ dài 1, trong đó có spanđộ dài 2 có sẵn. Tôi đột nhiên xoay sở để nhầm lẫn bản thân mình. Nó sẽ xuất hiện OP được cố ý xuất phát từ liên kết, và do đó liên kết nên được theo sau?
BrainSteel 18/03/2015

Thông số kỹ thuật được cập nhật để lưu ý rằng tác vụ không giống với A095236.
Uri Granta

Được phép xuất định dạng trong [1, 3, 2], trong đó mỗi giải pháp như vậy được phân tách bằng các dòng mới? (vì vậy không chỉ là một seperator của "", mà còn là một sự khởi đầu của '[' và kết thúc của ']')
orlp

Câu trả lời:


11

Bình thường, 53 51

MhSm^-dG2HjbmjdmehxkbQusmm+dkfqgTdeSmgbdQUQGUtQm]dQ

Đây là một cách tiếp cận lặp đi lặp lại. Với một phần có thể được điền vào các nhóm vị trí được đặt hàng, chúng tôi tìm thấy tất cả các vị trí tối ưu hơn nữa, sau đó tạo danh sách vị trí tương ứng và lặp lại.

Kết quả được tạo ra trong biểu mẫu [<first person's location>, <second person's location> ...], sau đó điều này được chuyển thành định dạng mong muốn. MhSm^-dG2Hđịnh nghĩa một hàm trợ giúp tìm khoảng cách tối thiểu từ một gian hàng nhất định đến một gian hàng bị chiếm dụng (bình phương). Thật thú vị, dải phân cách là miễn phí.

Ví dụ chạy.

Giải trình:

Đầu tiên, hàm trợ giúp g, tìm khoảng cách bình phương tối thiểu giữa G và bất kỳ giá trị nào trong H.

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

Tiếp theo, chúng tôi tìm thấy tối đa trên các vị trí tiểu của khoảng cách bình phương tối thiểu giữa bồn tiểu đó và bất kỳ bồn tiểu bị chiếm dụng nào:

( Qlà đầu vào.)

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

dtrong trường hợp này là danh sách các bồn tiểu bị chiếm đóng, trong khi blặp đi lặp lại trên các vị trí nước tiểu.

Tiếp theo, chúng tôi tìm thấy tất cả các vị trí bồn tiểu có khoảng cách bình phương tối thiểu từ bồn tiểu chiếm gần nhất bằng với giá trị tối đa được tìm thấy ở trên.

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

Tiếp theo, chúng tôi sẽ tạo danh sách vị trí nước tiểu được tạo bằng cách thêm các vị trí tiểu tiện được tìm thấy ở trên d. Chúng tôi sẽ làm điều này cho từng danh sách các vị trí bồn tiểu trước đó, do đó mở rộng danh sách từ chiều dài Nsang N+1. Glà danh sách các danh sách pháp lý của các vị trí tiểu tiện chiếm một chiều dài nhất định.

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

Tiếp theo, chúng tôi sẽ áp dụng biểu thức trên nhiều lần, để tạo danh sách đầy đủ các danh sách các vị trí bồn tiểu bị chiếm đóng. u, hàm giảm, thực hiện chính xác điều này, nhiều lần như có các phần tử trong đối số thứ hai của nó.

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

Chuyển đổi từ biểu diễn trên, đi [<1st location>, <2nd location>, ... ], sang dạng đầu ra mong muốn , [<person in slot 1>, <person in slot 2>, ... ]. Sau đó, mẫu đầu ra được nối vào chuỗi đầu ra và được in. In ấn là ngầm.

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

Chết tiệt, tôi nên dừng viết các giải pháp đệ quy trong Pyth. Tôi luôn bị đánh bại: P
orlp 18/03/2015

kajsdlkas^23asdjkla1lasdkj~JZasSSA- gần một nửa kích thước.
Tối ưu hóa

@Optimizer Tôi sẽ thêm một lời giải thích khi tôi ít bận rộn hơn.
isaacg

8

Bình thường, 75 71 67

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

Giải pháp tổ hợp đệ quy.

Đây là một bản dịch khá trực tiếp từ giải pháp Python này:

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

Làm thế nào mà làm việc? Chi tiết hơn "giải pháp tổ hợp đệ quy".
tbodt 18/03/2015

@tbodt Đã thêm mã Python mà tôi đã viết trước khi dịch sang Pyth.
orlp 18/03/2015

5

C, 929 878 byte

Đây là một con quái vật, các bạn. Lấy làm tiếc.

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

Định nghĩa 3 chức năng, f(int*,int), P(int*,int,int,int,int), và L(int). Gọi L(n)và nó xuất ra STDOUT.

Đầu ra cho n=5:

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

Cập nhật: Tôi đã xóa các dấu phân cách và sửa mã. Mã cũ không chỉ thất bại cho n = 7 +, mà còn không thể xuất bất cứ thứ gì cho n = 10 (rất tiếc!). Tôi đã kiểm tra kỹ hơn bó này. Bây giờ nó hỗ trợ đầu vào lên tới n = 13 (mặc dù "%d"nên thay đổi thành để "%x"in theo hệ thập lục phân). Kích thước của đầu vào phụ thuộc vào sizeof(long)và nó được giả định là 8trong thực tế.

Dưới đây là một số giải thích về cách thức hoạt động của nó và tại sao lại tồn tại một hạn chế kỳ lạ như vậy:

Chúng được sử dụng rất nhiều, vì vậy chúng tôi xác định chúng để lưu một vài byte:

typedef unsigned long U; typedef unsigned char C;

Đây là 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;
}

fmất một mảng các số nguyên kích thước n, và nchính nó. Thông minh duy nhất ở đây là nó trả về một unsigned long, được chuyển đổi thànhchar[8] bởi chức năng gọi. Do đó, mỗi ký tự trong mảng được đặt thành 0xFFhoặc chỉ mục trỏ đến một bồn tiểu hợp lệ cho người tiếp theo. Đối với n<10, chúng tôi không bao giờ cần nhiều hơn 5 byte để giữ mỗi bồn tiểu hợp lệ mà người tiếp theo có thể sử dụng.

Đây là 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);
    }
}

Pmất một mảng ukích thướcn trong đó chính xác một phần tử được đặt thành 1và phần còn lại là 0. Sau đó, nó tìm và in mọi hoán vị có thể đệ quy.

Đây là 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);
    }
}

L gọi đơn giản P n thời gian với các vị trí bắt đầu khác nhau mỗi lần.

Đối với người quan tâm, điều này (ít chơi gôn) fsẽ tạo ra chuỗi trong 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 ..." khi bắt đầu dường như chống lại thông số kỹ thuật: nếu số đầu tiên là 1, số tiếp theo sẽ là 5.
anatolyg 18/03/2015

2
@anatolyg Không. Đây là giải thích từng bước về cách "1 4" có thể xảy ra: gist.github.com/orlp/a5706ba664b70209b48a
orlp 18/03/2015

Hãy nhớ rằng, các phân cách là tùy chọn. Bạn có thể lưu 1 byte (!) Bằng cách xóa khoảng trắng sau% d :-)
Uri Granta

@UriZarfaty Cảm ơn! Trên thực tế, có rất nhiều byte được lưu ở đây. Tôi hiện đang viết một giải pháp tốt hơn và giải thích.
BrainSteel 18/03/2015

@yo 'Tôi nghĩ bạn đang nhầm lẫn đầu ra một chút. Một đầu ra của 14352phương tiện số 1 đã chọn nước tiểu bên trái nhất. Người số 2 đã chọn người đúng nhất, sau đó buộc số 3 vào giữa. Đây không phải là số lượng nước tiểu được chọn tiếp theo nên là đầu ra.
BrainSteel

4

Con tră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)

Phương pháp đệ quy.


4

JavaScript (ES6) 153 160 169

Chỉnh sửa Sử dụng Math.min để tìm (tất nhiên) khoảng cách tối đa: mã được sắp xếp hợp lý và 16 byte được lưu.

Tìm kiếm đệ quy, có thể hoạt động với n> 10, chỉ cần xóa% 10 (và sẵn sàng chờ trong khi bảng điều khiển hủy tất cả đầu ra của nó).

Tôi sử dụng một mảng duy nhất để lưu trữ vị trí đang sử dụng (số dương) hoặc khoảng cách hiện tại từ vị trí gần nhất (số âm vì vậy <>được hoán đổi trong mã).

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

Bị đánh cắp

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
}

Kiểm tra trong bảng điều khiển 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

Toán học, 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~{#}sẽ trở thành Join[f[n,s],{#}].
alephalpha

Oh đúng, tôi nghĩ đó là kết hợp đúng.
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

Perl, 174

Không ngắn lắm, nhưng vui. Tôi không tính use feature 'say';vào tổng số byte.

$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

Bỏ chơi gôn:

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

Mã này sử dụng một algoritm đệ quy để tạo ra kết quả mong muốn.

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

Mở rộng:

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

Bash, 744 674 byte

Đây vẫn là cách quá dài :). Tôi sử dụng một chuỗi để biểu diễn các hàng của bồn tiểu và thuật toán chống ngập để tìm các bồn tiểu xa nhất trong mỗi giai đoạn đệ quy. Các mã không rõ ràng là gần như tự giải thích. Số lượng bồn tiểu được đọc từ bàn phím.

Mã (đánh gôn):

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

Sử dụng:

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

Và vô dụng nó đi:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.