พิธีสารทางปัสสาวะ


38

พื้นหลัง

ที่เรียกว่า "พิธีสารทางปัสสาวะ" ซึ่งอธิบายถึงลำดับของการเลือกโถฉี่แต่ละคนในห้องน้ำของผู้ชายได้มีการพูดคุยกันในหลายสถานที่ มีหนึ่งเวอร์ชันในโพสต์บล็อก xkcdนี้ คำถามนี้เกี่ยวข้องกับการเปลี่ยนแปลงเล็กน้อย:

การจัดเรียง : n โถฉี่ในบรรทัด
โปรโตคอล : แต่ละคนใหม่เลือกหนึ่งในโถฉี่ที่ห่างไกลที่สุดจากที่ใช้งานอยู่แล้ว

โปรดทราบว่าสถานที่นี้ไม่มีข้อ จำกัด ในการเลือกปัสสาวะจากคนแรก

อัปเดต : ลำดับของจำนวนวิธีต่างๆที่ n คนสามารถเลือก n urinals เริ่มต้นด้วย 1, 2, 4, 8, 20 ... โปรดทราบว่าสิ่งนี้ไม่เหมือนกับOEIS A095236ซึ่งอธิบายข้อ จำกัด ที่เข้มงวดกว่านี้เล็กน้อย คำถาม.

งาน

กำหนดจำนวนเต็ม n ระหว่าง 0 ถึง 10 เอาต์พุต (ในลำดับใดก็ได้) ลำดับที่เป็นไปได้ทั้งหมดซึ่ง n คนสามารถครอบครอง n urinals การสั่งซื้อแต่ละครั้งควรพิมพ์เป็นการจัดเรียงขั้นสุดท้าย: ลำดับของตัวเลขที่แสดงถึงผู้คน (1-9 สำหรับ 9 คนแรก, 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
มากสำหรับ sandboxing :-( Spec เป็นไปตามที่อธิบายไว้ในภารกิจไม่ใช่คำจำกัดความของลำดับฉันจะอัปเดตทันทีที่ฉันไปถึงคอมพิวเตอร์
Uri Granta

1
@knedlsepp แถว 3, 4, 17, 18 ไม่ถูกต้อง ในที่นี้คุณวางคนที่ 3 ในspanความยาว 1 ซึ่งมีspanความยาว 2 ทันใดนั้นฉันก็สับสนตัวเอง มันจะปรากฏขึ้น OP ได้มาจากการเชื่อมโยงโดยเจตนาและดังนั้นจึงควรมีการติดตามการเชื่อมโยง?
BrainSteel

อัปเดตข้อมูลจำเพาะเพื่อให้ทราบว่างานไม่เหมือนกับ A095236
Uri Granta

อนุญาตให้ส่งออกรูปแบบใน [1, 3, 2] ซึ่งแต่ละโซลูชันดังกล่าวคั่นด้วยการขึ้นบรรทัดใหม่หรือไม่ (ดังนั้นไม่เพียง แต่เป็นตัวคั่นของ "," แต่ยังเป็นจุดเริ่มต้นของ "[" และจุดสิ้นสุดของ "]")
orlp

คำตอบ:


11

Pyth, 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ต่อไปเราจะสร้างรายการที่ตั้งของปัสสาวะที่สร้างขึ้นโดยการเพิ่มสถานที่ปัสสาวะพบข้างต้น เราจะทำเช่นนี้สำหรับรายการก่อนหน้านี้แต่ละสถานที่ปัสสาวะดังนั้นการขยายรายการจากระยะเวลาในการN คือรายการของรายการทางกฎหมายของสถานที่ปัสสาวะที่ถูกครอบครองซึ่งมีความยาวตามที่กำหนดN+1G

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

ต่อไปเราจะใช้การแสดงออกข้างต้นซ้ำ ๆ เพื่อสร้างรายการที่สมบูรณ์ของรายชื่อสถานที่ปัสสาวะที่ถูกครอบครอง uฟังก์ชั่นลดทำเช่นนี้หลายครั้งเท่าที่มีองค์ประกอบในการโต้แย้งที่สอง

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

Damnit ฉันควรหยุดเขียนโซลูชันแบบเรียกซ้ำใน Pyth ฉันมักจะเอาชนะ: P
orlp

kajsdlkas^23asdjkla1lasdkj~JZasSSA- เกือบครึ่งหนึ่งขนาด
เครื่องมือเพิ่มประสิทธิภาพ

@Optimizer ฉันจะเพิ่มคำอธิบายเมื่อฉันไม่ว่าง
isaacg

8

Pyth, 75 71 67

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

โซลูชัน combinatorial แบบเรียกซ้ำ

เป็นการแปลโดยตรงจากโซลูชัน 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)))

มันทำงานอย่างไร ในรายละเอียดมากกว่า "โซลูชัน combinatorial แบบเรียกซ้ำ"
58

@tbodt เพิ่มรหัส Python ที่ฉันเขียนก่อนแปลเป็น Pyth
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 (แม้ว่า"%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ใช้อาร์เรย์ของจำนวนเต็มขนาดnและnตัวมันเอง บิตที่ฉลาดเพียงอย่างเดียวที่นี่คือมันคืนค่าunsigned longซึ่งถูกแปลงเป็น a 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);
    }
}

Lเพียงแค่เรียกP nเวลาด้วยตำแหน่งเริ่มต้นที่แตกต่างกันในแต่ละครั้ง

สำหรับความสนใจนี้ (แข็งแรงเล่นกอล์ฟน้อยกว่า) 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 ..." ที่เริ่มต้นน่าจะเป็นกับสเปค: ถ้าตัวเลขแรกคือ 1, หนึ่งต่อไปควรจะเป็น 5
anatolyg

2
@anatolyg ไม่นี่คือคำอธิบายทีละขั้นตอนเกี่ยวกับวิธีการ "1 4" สามารถเกิดขึ้นได้: gist.github.com/orlp/a5706ba664b70209b48a
orlp

จำไว้ว่าตัวคั่นเป็นตัวเลือก คุณสามารถประหยัดได้ 1 ไบต์ (!) โดยการลบช่องว่างหลังจาก% d :-)
Uri Granta

@UriZarfaty ขอบคุณ! ที่จริงแล้วมีจำนวนไบต์ที่ต้องบันทึกที่นี่ ฉันกำลังเขียนทางออกที่ดีขึ้นและคำอธิบาย
BrainSteel

@yo 'ฉันคิดว่าคุณสับสนเอาท์พุทเล็กน้อย ผลลัพธ์ของ14352วิธีการที่บุคคล # 1 เลือกปัสสาวะซ้ายสุด บุคคล # 2 เลือกหนึ่งที่เหมาะสมที่สุดซึ่งจากนั้นบังคับให้ # 3 ลงในกลาง ไม่ใช่จำนวนปัสสาวะที่เลือกถัดไปที่ควรส่งออก
BrainSteel

4

Python 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

JavaScript (ES6) 153 160 169

แก้ไขการใช้ Math.min เพื่อค้นหาระยะทางสูงสุด (แน่นอน): รหัสคล่องตัวและบันทึก 16 ไบต์

การค้นหาแบบเรียกซ้ำสามารถทำงานกับ n> 10 เพียงลบ% 10 (และพร้อมที่จะรอในขณะที่คอนโซลเปิดใช้งานเอาต์พุตทั้งหมด)

ฉันใช้อาเรย์เดี่ยวเพื่อเก็บสล็อตที่ใช้งานอยู่ (ตัวเลขบวก) หรือระยะทางปัจจุบันจากสล็อตที่ใกล้ที่สุด (ตัวเลขติดลบดังนั้น<และ>ถูกสลับเป็นรหัส)

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

Ungolfed

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

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]

@ 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

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

De-แข็งแรงเล่นกอล์ฟ:

$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 ไบต์

รหัสนี้ใช้ algoritm แบบเรียกซ้ำเพื่อสร้างผลลัพธ์ที่ต้องการ

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

Bash, 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.