N Türen, K Affen


13

Es gibt N Türen und K Affen. Zunächst sind alle Türen geschlossen.

Runde 1: Der 1. Affe besucht jede Tür und schaltet die Tür um (wenn die Tür geschlossen ist, wird sie geöffnet; wenn sie offen ist, wird sie geschlossen).

Runde 2 : Der 1. Affe besucht jede Tür und schaltet die Tür um. Dann besucht der 2. Affe jede 2. Tür und schaltet die Tür um.

. . .

. . .

Runde k: Der 1. Affe besucht jede Tür und schaltet die Tür um. . . . . . . . . . Der k-te Affe besucht jede k-te Tür und schaltet die Tür um.

Eingabe: NK (durch ein Leerzeichen getrennt)

Ausgang: Offene Türnummern, jeweils durch ein Leerzeichen getrennt.

Beispiel :

Eingabe: 3 3

Ausgabe: 1 2

Einschränkungen :

0 <N <101

0 <= K <= N

Hinweis :

  • Angenommen, N Türen sind von 1 bis N nummeriert, und K Affen sind von 1 bis K nummeriert

  • Der mit dem kürzesten Code gewinnt. Auch Ausgabe für N = 23, K = 21 anzeigen


inspiriert von diesem Puzzle ?
Math Chiller

Ich habe nur eine Frage, wenn N = K, ist jede Primzahl Tür offen, oder?
Fabinout

@Fabinout no n=k=3würde 1 2so ur falsch ausgeben ... und 5 Ausgänge 1 2 4gibt es ein Muster, aber es ist viel weniger offensichtlich als das.
Math Chiller

@Fabinout es folgt einer sehr seltsamen Art von Fibonacci-Zahlensatz, seine sehr fortgeschrittene abstrakte Mathematik.
Math Chiller

@tryingToGetProgrammingStraight du hast recht, meine Erinnerungen sagten mir, dass die Antwort die Liste der Primzahlen war, als es die Liste der quadratischen Zahlen war.
Fabinout

Antworten:


14

APL, 32 28 26

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

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

Erklärung

  • {+/0=⍺|⍨⍳⍵}ist eine Funktion, die zurückgibt, wie oft door (linkes Argument) auf round (rechtes Argument) umgeschaltet wird , was der Anzahl der Faktoren von ≤ entspricht :

    • ⍳⍵ Generieren Sie ein numerisches Array von 1 bis

    • ⍺|⍨Berechnen Sie den Modul für jedes Element dieses Arrays

    • 0= Ändern Sie in eine 1, wo es eine 0 gab, und eine 0 für alles andere

    • +/ Summiere das resultierende Array

  • Die äußere Funktion:

    • (⍳⍺), ⍳⍵Generiere Arrays von 1 bis N und 1 bis K

    • ∘.{...}Wenden Sie für jedes Elementpaar der beiden Arrays die Funktion an. Dies ergibt eine Matrix, die angibt, wie oft umgeschaltet wurde, wobei jede Reihe eine Tür und jede Spalte eine Runde darstellt.

    • +/Summiere die Spalten. Dies gibt eine Reihe der Häufigkeit an, mit der jede Tür über alle Runden hinweg umgeschaltet wird.

    • 2|Modul 2, also wenn eine Tür offen ist, ist es eine 1; Wenn es geschlossen ist, ist es eine 0.

    • (...)/⍳⍺ Generieren Sie abschließend ein Array von 1 bis N und wählen Sie nur diejenigen aus, bei denen das Array im vorherigen Schritt eine 1 enthält.

  • /⎕ Fügen Sie abschließend die Funktion zwischen die eingegebenen Zahlen ein.


BEARBEITEN

{(2|+⌿0=(,↑⍳¨⍳⍵)∘.|⍳⍺)/⍳⍺}/⎕
  • ,↑⍳¨⍳⍵Generiere alle "Affen" (Wenn K = 4, dann ist dies 1 0 0 0 1 2 0 0 1 2 3 0 1 2 3 4)

    • ⍳⍵Array von 1 bis (K)

    • ⍳¨ Generieren Sie für jede davon ein Array von 1 bis zu dieser Zahl

    • ,↑Konvertiere das verschachtelte Array in eine Matrix ( ) und entwirre es dann in ein einfaches Array ( ,)

  • (,↑⍳¨⍳⍵)∘.|⍳⍺Modifiziere sie für jede Zahl von 1 bis (N) mit jedem Affen.

  • 0=Ändern Sie in eine 1, wo es eine 0 gab, und eine 0 für alles andere. Dies ergibt eine Matrix von Umschaltern: Reihen sind jeder Affe in jeder Runde, Spalten sind Türen; 1 bedeutet ein Umschalten, 0 bedeutet kein Umschalten.

  • +⌿ Summieren Sie die Zeilen, um zu ermitteln, wie oft jede Tür umgeschaltet wird

Andere Teile werden nicht verändert


BEARBEITEN

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

Verwende XOR reduce ( ≠⌿) anstelle von sum und mod 2 ( 2|+⌿)


Wurde APL für Golfskripte entwickelt? ;-)
Celtschk

@celtschk Ja, teilweise in gewisser Weise. Es wurde entwickelt, um Algorithmen präzise auszudrücken.
Luser Droog

Warum verwenden Sie eine DFN-Reduzierung, {}/anstatt nur N und K als Argumente für die DFN zu verwenden?
Adám

@Adam Weil 1) das an mir vorbei ist; 2) Diese Frage geht den "Programm- oder Funktions-" und E / A-Standardisierungen voraus. 3) Das OP sagte ausdrücklich "durch ein Leerzeichen getrennt"
TwiNight

Fair genug, aber zumindest können Sie ein Byte mit speicherni←⍳⍺
Adám

4

GolfScript, 33 Zeichen

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

Wenn Türen beginnend mit Null nummeriert würden, würden 3 Zeichen gespeichert.

Beispiele ( online ):

> 3 3
1 2

> 23 21
1 2 4 8 9 16 18 23

3

Mathematica, 104 Zeichen

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

Beispiel:

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

? 23 21

Out [1] = 1 2 4 8 9 16 18 23


1
Sie können das Parsen der Eingabe um weitere 15 Zeichen unterbinden, indem Sie einen Eingabestream annehmen, z {n,k}=%~Read~{Number,Number}.
Marcks Thomas

3

Rubin, 88

Basierend auf der Antwort von @ manatwork.

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

Diese zwielichtigen Globals brechen immer die Syntaxhervorhebung!


Tut mir leid, aber die 90 Zeichen ( Revision 2 ) und 86 Zeichen ( Revision 3 ) scheinen fehlerhaft zu sein: Eine neue Zahl, 22, erschien in ihren Ergebnissen.
Manatwork

@manatwork Guter Anruf, ich denke, ich habe es jetzt auf Kosten von zwei Zeichen behoben. Ich habe das Gefühl, dass das countetwas weiter verbessert werden könnte. Ich wünschte Ruby hätte eine eingebaute #sumMethode für
solche

Beeindruckend! Wirklich beeindruckt.
Manatwork

3

Python 3, 97 84

Wenn ein Affe in einer geraden Anzahl von Runden auftaucht, ändert sich nichts daran. Wenn ein Affe mehrmals auftaucht, ist das dasselbe wie in genau einer Runde.

So können einige Affen weggelassen werden und die anderen müssen nur einmal die Türen wechseln.

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

Ausgabe für 23 21:

1 2 4 8 9 16 18 23

Clevere Verwendung von Set-Operationen! Ich denke , man kann verkürzen range(2-K%2,K+1,2)zu range(K,0,-2).
21.

Oder noch besser, ersetzen Sie die forSchleife durch eine whileSchleife:while K>0:r^=set(range(K,N+1,K));K-=2
xnor

@xnor: danke, das ist toll!
Setzen Sie Monica am

2

R - 74

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

Simulation:

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

Hier ist eine (winzig kleine) lesbare Version:

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

DEMO Geige

Ich sollte beachten, dass es beginnt von 0 zu zählen (technisch ein Fehler von eins zu eins)


Sie können Ihre 3. Zeile entfernen, wenn Sie die 2. Zeile in ändern. b=Array(n);Dies initialisiert Ihr Array als n Länge, die mit undefined gefüllt ist. ! undefined ist wahr, so dass der erste Affenpass alles in Wahrheiten verwandelt.
Path411

@ Path411 Vielen Dank! Ich bin überrascht, ich habe vergessen, wie "richtige" Array-Deklaration funktioniert! Sie können sich frei fühlen+1
Math Chiller

Interessant. Es scheint so, als ob Sie die einzige sind, die ich bisher gesehen habe, die eine ähnliche Antwort wie ich für N = 23, K = 21 zu erhalten scheint. Der einzige Unterschied ist das Off-by-One-Problem, das 0 enthält und 23 ausschließt.
Iszi

Ich habe herausgefunden, was mit mir los ist, und dieser hat das gleiche Problem. Für jede Runde schickst du nur einen Affen durch alle Türen. Gemäß den Herausforderungsspezifikationen müssen jedoch in jeder Runde $ i-Affen laufen - wobei $ i die Nummer der Runde ist, in der Sie sich befinden.
Iszi

2

JavaScript, 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=' '))

Ausgabe für N = 23, K = 21:

1 2 4 8 9 16 18 23  

Getestet in Chrome, verwendet aber keine ausgefallenen neuen ECMAScript-Funktionen und sollte daher in jedem Browser funktionieren!

Ich weiß, dass ich niemals gegen die anderen Einträge gewinnen werde und dass @tryingToGetProgrammingStrainght bereits einen Eintrag in JavaScript eingereicht hat, aber ich habe nicht die gleichen Ergebnisse für N = 23, K = 21 erhalten, wie alle anderen, also dachte ich, ich würde mal meine eigene version ausprobieren.

Edit : Quelle mit Anmerkungen (beim erneuten Hinsehen habe ich Orte gefunden, an denen 3 weitere Zeichen gespeichert werden können, sodass es wahrscheinlich noch verbessert werden kann ...)

(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

gute Arbeit! Wenn Sie auch eine lesbare und kommentierte Version zur Verfügung stellen würden, würde ich wahrscheinlich+1
Math Chiller

Antwort aktualisiert! Da ich Ihre Antwort nicht kommentieren kann, können Sie zum Kommentar von @ path411 b = [] setzen, und die leeren Indizes sind immer noch undefiniert. Dadurch sparen Sie weitere 6 Zeichen!
Dom Hastings

das habe ich schon gemacht ....
Math chiller

1

Ruby - 65 Zeichen

(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 

Hier ist die Berechnung in Pseudocode:

  • Sei s (d) die Häufigkeit, mit der Tür d nach k Runden berührt wird.
  • s (d) = Summe (m = 1. m = k) (d% m == 0 & le; (n-m + 1): 0)
  • Tür d ist nach k Runden offen, wenn s (d)% 2 = 1 (oder> 0)

Wenn Sie nicht davon überzeugt sind, dass der Ausdruck für s (d) korrekt ist, sehen Sie ihn folgendermaßen an:

  • Sei s (d, r) die Häufigkeit, mit der Tür d nach r Runden berührt wird.
  • s (d, k) - s (d, k - 1) = Summe (m = 1, .., m = k) (d% m == 0? 1: 0)
  • s (d, k - 1) - s (d, k - 2) = Summe (m = 1, ..., m = (k - 1)) (d% m == 0 & le; 1: 0)
  • ...
  • s (d, 2) - s (d, 1) = d% 2 == 0 & le; 1: 0
  • s (d, 1) = 1
  • Summiere beide Seiten, um den obigen Ausdruck für s (d) zu erhalten, der gleich s (d, k) ist

Sehr prägnant! Woher nund woher k? Und die Ausgabe scheint eher durch Zeilenumbrüche als durch Leerzeichen getrennt zu sein.
Paul Prestidge

1

PowerShell: 132

Golf Code:

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

Nicht Golf spielender, kommentierter Code:

# 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

Oh, ich sehe, was mein Problem ist. Ich habe die Frage falsch verstanden - das ist nicht das 100-Schließfach-Problem. Es ist das, eine Kerbe aufgenommen! Dies erfordert ein bisschen mehr Arbeit ...
Iszi

1
Süss! Das Problem zu beheben, um die Herausforderungsanforderungen ordnungsgemäß zu erfüllen, brachte am Ende nur einen Gewinn von 6 Zeichen.
Iszi

0

Powershell, 66 Bytes

Basierend auf der Antwort von Cary Swoveland .

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

Testskript:

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

Ausgabe:

True: 1 2
True: 1 2 4 8 9 16 18 23
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.