N Doors, K Monkeys


14

มีประตู N และลิง K ในขั้นต้นทุกประตูถูกปิด

รอบที่ 1:ลิงตัวที่ 1 เข้าชมทุกประตูและสลับประตู (ถ้าประตูปิดมันจะเปิดออกถ้ามันเปิดอยู่ก็จะปิด)

รอบ 2 : ลิงตัวที่ 1 เข้าชมทุกประตูและสลับประตู จากนั้นลิงตัวที่สองจะไปที่ประตูทุกบานและสลับประตู

. . .

. . .

รอบ k: ลิงตัวที่ 1 เข้าชมทุกประตูและสลับประตู . . . . . . . . . ลิง kth เข้าเยี่ยมชมทุก ๆ ประตู kth และสลับประตู

อินพุต: NK (คั่นด้วยช่องว่างเดียว)

เอาท์พุท: หมายเลขประตูที่เปิดอยู่โดยคั่นด้วยช่องว่างเดียว

ตัวอย่าง :

อินพุต: 3 3

ผลลัพธ์: 1 2

ข้อ จำกัด :

0 <N <101

0 <= K <= N

หมายเหตุ :

  • สมมติว่าประตู N มีหมายเลขจาก 1 ถึง N และ K ลิงนั้นมีหมายเลขตั้งแต่ 1 ถึง K

  • รหัสที่สั้นที่สุดจะชนะ แสดงเอาต์พุตสำหรับ N = 23, K = 21



ฉันเพิ่งมีคำถามถ้า N = K ทุกหมายเลขเฉพาะประตูเปิดใช่ไหม
Fabinout

@ Fabinout ไม่n=k=3ออกจะ1 2ผิดดังนั้นคุณ ... และ 5 เอาท์พุท1 2 4มีรูปแบบ แต่มันชัดเจนมากน้อยกว่านั้น
เครื่องทำความเย็นคณิตศาสตร์

@Fabinout มันเป็นไปตามชุดเลขฟีโบนักชีที่แปลกมากมันเป็นคณิตศาสตร์นามธรรมขั้นสูงมาก
เครื่องทำความเย็นคณิตศาสตร์

@triedToGetProgrammingStraight คุณถูกต้องความทรงจำของฉันบอกฉันว่าคำตอบคือรายการหมายเลขเฉพาะเมื่อมันเป็นรายการของหมายเลขสแควร์
Fabinout

คำตอบ:


14

APL, 32 28 26

{(2|+/(⍳⍺)∘.{+/0=⍺|⍨⍳⍵}⍳⍵)/⍳⍺}/⎕

⎕:
      23 21
 1 2 4 8 9 16 18 23 

ชี้แจง

  • {+/0=⍺|⍨⍳⍵}เป็นฟังก์ชั่นที่คืนค่าจำนวนครั้งของประตู(อาร์กิวเมนต์ซ้าย) ถูกสลับในรอบ(อาร์กิวเมนต์ขวา) ซึ่งเท่ากับจำนวนของปัจจัยที่มีค่า≤ :

    • ⍳⍵ สร้างอาร์เรย์ตัวเลขตั้งแต่ 1 ถึง

    • ⍺|⍨คำนวณโมดูลัสแต่ละรายการของอาร์เรย์นั้น

    • 0= เปลี่ยนเป็น 1 ที่มี 0 และ 0 สำหรับทุกสิ่งอื่น

    • +/ รวมอาเรย์ที่เกิดขึ้น

  • ฟังก์ชั่นด้านนอก:

    • (⍳⍺), ⍳⍵สร้างอาร์เรย์จาก 1 ถึง n และ 1 K

    • ∘.{...}สำหรับองค์ประกอบทุกคู่ของทั้งสองอาร์เรย์ให้ใช้ฟังก์ชัน สิ่งนี้ให้เมทริกซ์จำนวนครั้งที่สลับแต่ละแถวแสดงถึงประตูและแต่ละคอลัมน์แสดงถึงรอบ

    • +/รวมคอลัมน์ สิ่งนี้จะช่วยให้จำนวนครั้งที่ประตูแต่ละบานถูกสลับในทุกรอบ

    • 2|โมดูลัส 2 ดังนั้นหากเปิดประตูมันจะเป็น 1 ถ้ามันปิดมันเป็น 0

    • (...)/⍳⍺ ในที่สุดสร้างอาร์เรย์จาก 1 ถึง N และเลือกเฉพาะที่มี 1 ในอาร์เรย์ในขั้นตอนก่อนหน้า

  • /⎕ สุดท้ายแทรกฟังก์ชั่นระหว่างตัวเลขจากการป้อนข้อมูล


แก้ไข

{(2|+⌿0=(,↑⍳¨⍳⍵)∘.|⍳⍺)/⍳⍺}/⎕
  • ,↑⍳¨⍳⍵สร้าง "monkeys" ทั้งหมด (ถ้า K = 4 นี่คือ1 0 0 0 1 2 0 0 1 2 3 0 1 2 3 4)

    • ⍳⍵อาร์เรย์จาก 1 ถึง(K)

    • ⍳¨ สำหรับแต่ละรายการให้สร้างอาร์เรย์จาก 1 ถึงหมายเลขนั้น

    • ,↑แปลงอาเรย์ที่ซ้อนกันเป็นเมทริกซ์ ( ) แล้วคลี่คลายเป็นอาเรย์แบบง่าย ๆ ( ,)

  • (,↑⍳¨⍳⍵)∘.|⍳⍺สำหรับแต่ละหมายเลขจาก 1 ถึง(N) ให้ดัดแปลงกับลิงแต่ละตัว

  • 0=เปลี่ยนเป็น 1 ที่มี 0 และ 0 สำหรับทุกสิ่งอื่น สิ่งนี้ให้เมทริกซ์ของการสลับ: แถวคือลิงแต่ละตัวในแต่ละรอบคอลัมน์คือประตู 1 หมายถึงการสลับ 0 หมายถึงไม่มีการสลับ

  • +⌿ รวมจำนวนแถวเพื่อรับจำนวนครั้งในการเปิดประตูแต่ละบาน

ส่วนอื่น ๆ จะไม่เปลี่ยนแปลง


แก้ไข

{(≠⌿0=(,↑⍳¨⍳⍵)∘.|⍳⍺)/⍳⍺}/⎕

ใช้ XOR ลด ( ≠⌿) แทนผลรวมและ mod 2 ( 2|+⌿)


APL ถูกออกแบบมาสำหรับสคริปต์กอล์ฟหรือไม่? ;-)
celtschk

@celtschk ใช่แล้วส่วนหนึ่ง มันถูกออกแบบมาเพื่อแสดงอัลกอริทึมอย่างรัดกุม
luser droog

เหตุใดคุณจึงใช้การลด dfn {}/แทนที่จะใช้ N และ K เป็นอาร์กิวเมนต์ของ dfn
Adám

@ Adámเพราะ 1) สิ่งนี้ผ่านพ้นไปแล้ว 2) คำถามนี้มีมาก่อน "โปรแกรมหรือฟังก์ชั่น" และมาตรฐาน I / O; 3) OP กล่าวว่า "คั่นด้วยช่องว่างเดียว" โดยเฉพาะ
TwiNight

ยุติธรรมเพียงพอ แต่อย่างน้อยคุณก็สามารถบันทึกไบต์ด้วยi←⍳⍺
Adám

4

GolfScript, 33 ตัวอักษร

~:k;),1>{0\{1$)%!k@-&^}+k,/}," "*

ถ้าประตูถูกกำหนดหมายเลขเริ่มต้นด้วยศูนย์มันจะประหยัดได้ 3 ตัวอักษร

ตัวอย่าง ( ออนไลน์ ):

> 3 3
1 2

> 23 21
1 2 4 8 9 16 18 23

3

Mathematica 104 ตัวอักษร

{n,k}=FromDigits/@StringSplit@InputString[];Select[Range@n,OddQ@DivisorSum[#,If[#>k,0,k+1-#]&]&]~Row~" "

ตัวอย่าง:

ใน [1]: = {n, k} = FromDigits / @ StringSplit @ InputString []; เลือก [Range @ n, OddQ @ DivisorSum [#, ถ้า [#> k, 0, k + 1 - #] &] & ] ~ แถว ~ ""

? 23 21

ออก [1] = 1 2 4 8 9 16 18 23


1
คุณสามารถเคาะอีก 15 {n,k}=%~Read~{Number,Number}ตัวอักษรปิดแยกการป้อนข้อมูลด้วยการสมมติว่ากระแสการป้อนข้อมูลเช่น:
Marcks Thomas

3

ทับทิม, 88

ตามคำตอบของ @ manatwork

gets;~/ /
$><<(1..$`.to_i).select{|d|(1..k=$'.to_i).count{|m|d%m<1&&(k-m+1)%2>0}%2>0}*$&

Globals หลบซึ่งมักจะทำลายการเน้นไวยากรณ์!


ขออภัยดูเหมือนว่า 90 ตัวอักษร ( ฉบับแก้ไข 2 ) และตัวอักษร 86 ตัว ( ฉบับที่ 3 ) ดูเหมือนว่าจะเป็นบั๊กกี้: หมายเลขใหม่, 22, ปรากฏในผลลัพธ์ของพวกเขา
จัดการ

@ การจัดการที่ดีโทรฉันคิดว่าฉันได้รับการแก้ไขตอนนี้ที่ค่าใช้จ่ายของตัวละครทั้งสอง ฉันรู้สึกเหมือนว่าcountบิตนั้นจะได้รับการปรับปรุงให้ดีขึ้นต่อไปฉันหวังว่าทับทิมจะมี#sumวิธีการในตัวสำหรับสิ่งต่าง ๆ เช่น:>
Paul Prestidge

ว้าว! ประทับใจจริงๆ
จัดการ

3

Python 3 97 84

หากลิงปรากฏในจำนวนรอบเท่ากันนั่นจะไม่มีการเปลี่ยนแปลงเลย หากลิงปรากฏในจำนวนครั้งที่เท่ากันนั่นก็เหมือนกับในหนึ่งรอบ

ดังนั้นลิงบางตัวสามารถถูกปล่อยออกไปและคนอื่น ๆ ก็ต้องเปลี่ยนประตูทันที

N,K=map(int,input().split())
r=set()
while K>0:r^=set(range(K,N+1,K));K-=2
print(*r)

เอาท์พุทสำหรับ23 21:

1 2 4 8 9 16 18 23

การใช้ชุดปฏิบัติการที่ชาญฉลาด! ฉันคิดว่าคุณสามารถร่นไปrange(2-K%2,K+1,2) range(K,0,-2)
xnor

หรือดีกว่าให้แทนที่forด้วยการwhileวนซ้ำ:while K>0:r^=set(range(K,N+1,K));K-=2
xnor

@xnor: ขอบคุณที่ดีมาก!
Reinstate Monica

2

R - 74

x=scan(n=2);cat(which(colSums((!sapply(1:x[1],`%%`,1:x[2]))*x[2]:1)%%2>0))

จำลอง:

> x=scan(n=2);cat(which(colSums((!sapply(1:x[1],`%%`,1:x[2]))*x[2]:1)%%2>0))
1: 23 21
Read 2 items
1 2 4 8 9 16 18 23

2

javascript 148 127

function e(n,k){b=array(n);d=[];function a(c){for(i=0;i<n;i+=c)b[i]=!b[i];c<k&&a(c+1)}a(1);for(i in b)b[i]&&d.push(i);return d}

นี่คือรุ่นที่อ่านได้ (นิดหน่อย):

function e(n, k) {     //define N and K
     b = array(n); //declare all doors as closed
     d = [];     //create array later used to print results

     function a(c) {   //(recursive) function that does all the work
         for (i = 0; i < n; i += c)  //increment by c until you reach N and...
              b[i] = !b[i];  //toggle said doors
         c < k && a(c + 1)  //until you reach k, repeat with a new C (next monkey)
     }
     a(1); //start up A

     for (i in b) b[i] && d.push(i); //convert doors to a list of numbers
     return d //NO, i refuse to explain this....
}   //closes function to avoid annoying errors

เดโมซอ

ฉันควรทราบว่ามันเริ่มนับจาก 0 (ข้อผิดพลาดแบบ off-by-one)


คุณสามารถลบบรรทัดที่ 3 ของคุณถ้าคุณเปลี่ยนบรรทัดที่ 2 เป็นb=Array(n);นี้จะเริ่มต้นอาร์เรย์ของคุณเป็นความยาว n ที่เต็มไปด้วยไม่ได้กำหนด ไม่ได้กำหนดเป็นจริงดังนั้นการผ่านลิงครั้งแรกจะเปลี่ยนเป็นความจริงทั้งหมด
path411

@ path411 ขอบคุณมาก! ฉันประหลาดใจที่ฉันลืมวิธีการประกาศอาเรย์ "เหมาะสม"! คุณสามารถรู้สึกฟรี+1
Math chiller

น่าสนใจ ดูเหมือนว่าคุณเป็นคนเดียวที่ฉันได้เห็นจนถึงตอนนี้ซึ่งดูเหมือนจะได้คำตอบที่คล้ายกันกับฉันสำหรับ N = 23, K = 21 ข้อแตกต่างเพียงอย่างเดียวคือปัญหาแบบแยกออกซึ่งมี 0 และไม่รวม 23 รายการ
Iszi

คิดออกว่ามีอะไรผิดปกติกับฉันและอันนี้มีปัญหาเดียวกัน ในแต่ละรอบคุณจะส่งลิงหนึ่งตัวผ่านทุกประตู อย่างไรก็ตามตามข้อกำหนดของการท้าทายจะต้องมี $ i monkeys ที่วิ่งผ่านแต่ละรอบ - โดยที่ $ i คือจำนวนรอบที่คุณอยู่
Iszi

2

จาวาสคริปต์, 153

(function(g){o=[],f=g[0];for(;i<g[1];i++)for(n=0;n<=i;n++)for(_=n;_<f;_+=n+1)o[_]=!o[_];for(;f--;)o[f]&&(l=f+1+s+l);alert(l)})(prompt().split(i=l=s=' '))

เอาต์พุตสำหรับ N = 23, K = 21:

1 2 4 8 9 16 18 23  

ผ่านการทดสอบใน Chrome แต่ไม่ได้ใช้ฟีเจอร์ ECMAScript ที่แปลกใหม่ดังนั้นควรทำงานกับเบราว์เซอร์ใด ๆ !

ฉันรู้ว่าฉันจะไม่ชนะรายการอื่น ๆ และ @tryingToGetProgrammingStrainght ได้ส่งรายการใน JavaScript แล้ว แต่ฉันไม่ได้รับผลลัพธ์เดียวกันสำหรับ N = 23, K = 21 เนื่องจากทุกคนเข้าร่วมด้วยดังนั้นฉันคิดว่าฉัน ต้องไปที่รุ่นของฉันเอง

แก้ไข : แหล่งที่มาหมายเหตุประกอบ (ในการดูสิ่งนี้อีกครั้งฉันเห็นสถานที่เพื่อบันทึกอีก 3 ตัวอักษรดังนั้นมันอาจจะยังคงได้รับการปรับปรุง ... )

(function(g) {
    // initialise variables, set f to N
    o = [], f = g[0];

    // round counter
    // since ++' ' == 1 we can use the same variable set in args
    for (; i < g[1]; i++)
        // monkey counter, needs to be reset each round
        for (n = 0 ; n <= i; n++)
            // iterate to N and flip each Kth door
            for (_ = n; _ < f; _ += n + 1)
                // flip the bits (as undef is falsy, we don't need to initialise)
                // o[_] = !~~o[_]|0; // flips undef to 1
                o[_] = !o[_]; // but booleans are fine
    // decrement f to 0, so we don't need an additional counter
    for (;f--;)
        // build string in reverse order
        o[f] && (l = f + 1 + s + l); // l = (f + 1) + ' ' + l
    alert(l)
    // return l // use with test
// get input from user and store ' ' in variable for use later
})(prompt().split(i = l = s = ' '))
// })('23 21'.split(i = l = s = ' ')) // lazy...

// == '1 2 4 8 9 16 18 23  '; // test

การทำงานที่ดี! หากคุณจะให้รุ่นที่อ่านและแสดงความคิดเห็นฉันจะคง+1
Math chiller

อัปเดตคำตอบ! เนื่องจากฉันไม่สามารถแสดงความคิดเห็นในคำตอบของคุณเพื่อเพิ่มความคิดเห็นของ @ path411 คุณสามารถตั้งค่า b = [] และดัชนีว่างเปล่ายังไม่ได้กำหนดและนั่นจะช่วยให้คุณประหยัดอีก 6 ตัวอักษร!
Dom Hastings

ฉันทำอย่างนั้นแล้ว ....
เครื่องทำความเย็นคณิตศาสตร์

1

Ruby - 65 ตัวอักษร

(1..n).each{|d|
t=0
(1..k).each{|m|t+=n-m+1 if d%m==0}
p d if t%2>0}

n = 23, k = 21 # => 1 2 4 8 9 16 18 23 

นี่คือการคำนวณในรหัสหลอก:

  • ให้ s (d) เป็นจำนวนครั้งที่ประตู d ถูกจับหลังจากรอบ k
  • s (d) = ผลรวม (m = 1..m = k) (d% m == 0? (n-m + 1): 0)
  • door d เปิดหลังจาก k รอบถ้า s (d)% 2 = 1 (หรือ> 0)

หากคุณไม่มั่นใจว่าการแสดงออกของ s (d) นั้นถูกต้องให้ดูด้วยวิธีนี้:

  • ให้ s (d, r) เป็นจำนวนครั้งที่ประตู d ถูกสัมผัสหลังจากรอบ r
  • s (d, k) - s (d, k-1) = ผลรวม (m = 1, .. , m = k) (d% m == 0? 1: 0)
  • s (d, k-1) - s (d, k-2) = ผลรวม (m = 1, .. , m = (k-1)) (d% m == 0? 1: 0)
  • ...
  • s (d, 2) - s (d, 1) = d% 2 == 0? 1: 0
  • s (d, 1) = 1
  • หาผลรวมทั้งสองข้างเพื่อให้ได้นิพจน์ข้างต้นสำหรับ s (d) ซึ่งเท่ากับ s (d, k)

รัดกุมมาก! ทำอะไรnและkมาจากไหน และเอาท์พุทที่ดูเหมือนจะถูกคั่นด้วยการขึ้นบรรทัดใหม่มากกว่าช่องว่าง
Paul Prestidge

1

PowerShell: 132

รหัส Golfed:

$n,$k=(read-host)-split' ';0|sv($d=1..$n);1..$k|%{1..$_|%{$m=$_;$d|?{!($_%$m)}|%{sv $_ (!(gv $_ -Va))}}};($d|?{(gv $_ -Va)})-join' '

ยกเลิกการตีกอล์ฟ, แสดงความคิดเห็นรหัส:

# Get number of doors and monkeys from user as space-delimited string.
# Store number of doors as $n, number of monkeys as $k.
$n,$k=(read-host)-split' ';

# Store a list of doors in $d.
# Create each door as a variable set to zero.
0|sv($d=1..$n);

# Begin a loop for each round.
1..$k|%{

    # Begin a loop for each monkey in the current round.
    1..$_|%{

        # Store the current monkey's ID in $m.
        $m=$_;

        # Select only the doors which are evenly divisible by $m.
        # Pass the doors to a loop.
        $d|?{!($_%$m)}|%{

            # Toggle the selected doors.
            sv $_ (!(gv $_ -Va))
        }
    }
};

# Select the currently open doors.
# Output them as a space-delimited string.
($d|?{(gv $_ -Va)})-join' '

# Variables cleanup - don't include in golfed code.
$d|%{rv $_};rv n;rv d;rv k;rv m;

# NOTE TO SELF - Output for N=23 K=21 should be:
# 1 2 4 8 9 16 18 23

โอ้ฉันเห็นว่าปัญหาของฉันคืออะไร ฉันเข้าใจผิดคำถาม - นี่ไม่ใช่ปัญหา 100 ล็อกเกอร์ มันคือสิ่งที่เกิดขึ้น! นี้จะต้องมีการทำงานมากขึ้นอีกนิด ...
Iszi

1
หวาน! แก้ไขให้ตรงกับความต้องการของการท้าทายอย่างถูกต้องเท่านั้นที่จะได้รับ 6 ตัวอักษรในที่สุด
Iszi

0

Powershell, 66 ไบต์

ขึ้นอยู่กับแครี Swoveland ของคำตอบ

param($n,$k)1..$n|?{$d=$_
(1..$k|?{($n-$_+1)*!($d%$_)%2}).Count%2}

สคริปต์ทดสอบ:

$f = {

param($n,$k)1..$n|?{$d=$_
(1..$k|?{($n-$_+1)*!($d%$_)%2}).Count%2}

}

@(
    ,(3, 3   , 1,2)
    ,(23, 21 , 1, 2, 4, 8, 9, 16, 18, 23)
) | % {
    $n,$k,$expected = $_
    $result = &$f $n $k
    "$("$result"-eq"$expected"): $result"
}

เอาท์พุท:

True: 1 2
True: 1 2 4 8 9 16 18 23
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.