N Doors, K Monkeys

14

Jest N drzwi i K małp. Początkowo wszystkie drzwi są zamknięte.

Runda 1: 1. małpa odwiedza każde drzwi i zamyka je (jeśli drzwi są zamknięte, zostają otwarte; jeśli są otwarte, zostają zamknięte).

Runda 2 : 1. małpa odwiedza każde drzwi i zamyka je. Następnie 2. małpa odwiedza każde drugie drzwi i zamyka je.

. . .

. . .

Runda k: 1. małpa odwiedza każde drzwi i zamyka je. . . . . . . . . . K-ta małpa odwiedza każde k-te drzwi i zamyka je.

Dane wejściowe: NK (oddzielone pojedynczym odstępem)

Wyjście: Numery drzwi, które są otwarte, każdy oddzielony pojedynczym odstępem.

Przykład :

Wejście: 3 3

Wyjście: 1 2

Ograniczenia :

0 <N <101

0 <= K <= N

Uwaga :

  • Załóżmy, że N drzwi są ponumerowane od 1 do N, a małpy K są ponumerowane od 1 do K

  • Wygrywa ten z najkrótszym kodem. Wyświetl także dane wyjściowe dla N = 23, K = 21

Kodowanie człowieka
źródło
zainspirowany tą łamigłówką ?
Agregat matematyczny
Mam tylko pytanie, czy N = K, wszystkie drzwi liczb pierwszych są otwarte, prawda?
Fabinout
@ Fabinout no n=k=3wyprowadziłoby 1 2tak źle ... a 5 wyjść 1 2 4ma pewien wzorzec, ale jest to mniej oczywiste.
Agregat matematyczny
@ Fabinout wynika z bardzo dziwnego typu zbioru liczb Fibonacciego, jego bardzo zaawansowanej matematyki abstrakcyjnej.
Agregat matematyczny
@tryingToGetProgrammingStreight masz rację, moje wspomnienia powiedziały mi, że odpowiedzią była lista liczb pierwszych, gdy była to lista liczb kwadratowych.
Fabinout,

Odpowiedzi:

14

APL, 32 28 26

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

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

Wyjaśnienie

  • {+/0=⍺|⍨⍳⍵}to funkcja zwracająca liczbę przełączeń drzwi (lewy argument) w rundzie (prawy argument), co równa się liczbie czynników, która wynosi ≤ :

    • ⍳⍵ Wygeneruj tablicę numeryczną od 1 do

    • ⍺|⍨Oblicz moduł każdego elementu tej tablicy

    • 0= Zmień na 1, gdzie było 0 i 0 dla każdej innej rzeczy

    • +/ Zsumuj wynikową tablicę

  • Funkcja zewnętrzna:

    • (⍳⍺), ⍳⍵Generuj tablice od 1 do N i od 1 do K

    • ∘.{...}Dla każdej pary elementów dwóch tablic zastosuj funkcję. Daje to macierz liczby przełączeń, każdy rząd reprezentuje drzwi, a każda kolumna reprezentuje rundę.

    • +/Zsumuj kolumny. Daje to tablicę liczby przełączeń każdych drzwi we wszystkich rundach.

    • 2|Moduł 2, więc jeśli drzwi są otwarte, jest to 1; jeśli jest zamknięty, to jest 0.

    • (...)/⍳⍺ Na koniec wygeneruj tablicę od 1 do N i wybierz tylko te, w których w poprzednim kroku jest 1.

  • /⎕ Na koniec wstaw funkcję między liczbami z wejścia.


EDYTOWAĆ

{(2|+⌿0=(,↑⍳¨⍳⍵)∘.|⍳⍺)/⍳⍺}/⎕
  • ,↑⍳¨⍳⍵Wygeneruj wszystkie „małpy” (jeśli K = 4, to jest 1 0 0 0 1 2 0 0 1 2 3 0 1 2 3 4)

    • ⍳⍵Tablica od 1 do (K)

    • ⍳¨ Dla każdego z nich wygeneruj tablicę od 1 do tej liczby

    • ,↑Przekształć zagnieżdżoną tablicę w macierz ( ), a następnie rozpakuj do prostej tablicy ( ,)

  • (,↑⍳¨⍳⍵)∘.|⍳⍺Dla każdej liczby od 1 do (N) zmodyfikuj ją dla każdej małpy.

  • 0=Zmień na 1, gdzie było 0 i 0 dla każdej innej rzeczy. Daje to matrycę przełączeń: rzędy są małpami w każdej rundzie, kolumny są drzwiami; 1 oznacza przełącznik, 0 oznacza brak przełączenia.

  • +⌿ Zsumuj rzędy, aby uzyskać tablicę liczby przełączeń każdych drzwi

Inne części nie są zmieniane


EDYTOWAĆ

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

Użyj XOR redukuj ( ≠⌿) zamiast sumy i mod 2 ( 2|+⌿)

TwiNight
źródło
Czy APL został zaprojektowany do skryptu golfowego? ;-)
celtschk
@celtschk Tak, częściowo, w pewien sposób. Został zaprojektowany w celu zwięzłego wyrażania algorytmów.
luser droog
Dlaczego używasz redukcji dfn {}/zamiast tylko wziąć N i K jako argumenty do dfn?
Adám
@ Adám Ponieważ 1) to już przeszłość; 2) to pytanie poprzedza standaryzację „programu lub funkcji” i I / O; 3) OP konkretnie powiedział „oddzielone pojedynczym odstępem”
TwiNight
W porządku, ale przynajmniej możesz zaoszczędzić bajt zi←⍳⍺
Adám
4

GolfScript, 33 znaki

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

Gdyby drzwi były ponumerowane zaczynając od zera, zapisałoby to 3 znaki.

Przykłady ( online ):

> 3 3
1 2

> 23 21
1 2 4 8 9 16 18 23
Howard
źródło
3

Mathematica, 104 znaki

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

Przykład:

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

? 23 21

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

alephalpha
źródło
1
Możesz odrzucić kolejne 15 znaków podczas analizowania danych wejściowych, zakładając strumień wejściowy, np {n,k}=%~Read~{Number,Number}. : .
Marcks Thomas
3

Ruby, 88

Na podstawie odpowiedzi @ manatwork.

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

Te podejrzane globale zawsze przerywają podświetlanie składni!

Paul Prestidge
źródło
Niestety, ale 90 znaków ( wersja 2 ) i 86 znaków ( wersja 3 ) wydaje się być błędna: w wynikach pojawiła się nowa liczba 22.
manatwork
@manatwork dobre połączenie, myślę, że naprawiłem to teraz kosztem dwóch postaci. count#sum
Wydaje
Łał! Naprawdę pod wrażeniem.
manatwork
3

Python 3, 97 84

Jeśli małpa pojawia się w parzystej liczbie rund, nie ma żadnej zmiany. Jeśli małpa pojawia się w parzystej liczbie razy, to tak samo jak w dokładnie jednej rundzie.

W ten sposób niektóre małpy mogą zostać pominięte, a inne muszą tylko raz zmienić drzwi.

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

Dane wyjściowe dla 23 21:

1 2 4 8 9 16 18 23
Przywróć Monikę
źródło
Sprytne użycie ustawionych operacji! Myślę, że można skrócić range(2-K%2,K+1,2)do range(K,0,-2).
xnor
Lub jeszcze lepiej, zamień forpętlę na whilepętlę:while K>0:r^=set(range(K,N+1,K));K-=2
xnor
@xnor: dzięki, to świetnie!
Przywróć Monikę
2

R - 74

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

Symulacja:

> 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
flodel
źródło
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}

tutaj jest (trochę) czytelna wersja:

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

Skrzypce DEMO

powinienem zauważyć, że zaczyna się od zera (technicznie błąd off-by-one)

Agregat matematyczny
źródło
Możesz usunąć swój trzeci wiersz, jeśli zmienisz drugi wiersz na b=Array(n);To inicjalizuje tablicę jako n długości wypełnionej niezdefiniowaną. ! undefined jest prawdą, więc pierwsze przejście małpy zmieni to wszystko w trues.
path411
@ path411 dziękuję bardzo! jestem zaskoczony, że zapomniałem, jak działa „właściwa” deklaracja tablicowa! możesz czuć się swobodnie+1
Matematyczny agregat chłodniczy
Ciekawy. Wygląda na to, że Twoja jedyna, jaką do tej pory widziałem, wydaje się mieć podobną odpowiedź jak moja dla N = 23, K = 21. Jedyną różnicą jest kwestia indywidualna, która obejmuje 0 i wyklucza 23.
Iszi
Zrozumiałem, co jest nie tak z moim, a ten ma ten sam problem. W każdej rundzie wysyłasz tylko jedną małpę przez wszystkie drzwi. Jednak zgodnie ze specyfikacją wyzwania w każdej rundzie muszą znajdować się małpy $ i - gdzie $ i jest liczbą rundy, w której jesteś.
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=' '))

Wyjście dla N = 23, K = 21:

1 2 4 8 9 16 18 23  

Testowany w Chrome, ale nie używa żadnych nowych, ciekawych funkcji ECMAScript, więc powinien działać w dowolnej przeglądarce!

Wiem, że nigdy nie wygram z innymi wpisami i że @tryingToGetProgrammingStrainght przesłał już wpis w JavaScript, ale nie otrzymałem takich samych wyników dla N = 23, K = 21, jak wszyscy inni, więc pomyślałem, że wypróbowałbym własną wersję.

Edycja : źródło z adnotacjami (przeglądając to ponownie, zauważyłem miejsca, w których można zapisać kolejne 3 znaki, więc prawdopodobnie można je jeszcze ulepszyć ...)

(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
Dom Hastings
źródło
dobra robota! jeśli dostarczyłbyś również czytelną i skomentowaną wersję, prawdopodobnie zrobiłbym to+1
Math Schiller
Odpowiedź zaktualizowana! Ponieważ nie mogę skomentować twojej odpowiedzi, aby dodać do komentarza @ path411, możesz ustawić b = [], a puste indeksy są nadal niezdefiniowane, co oszczędza ci kolejne 6 znaków!
Dom Hastings,
już to zrobiłem ....
Chiller matematyczny
1

Ruby - 65 znaków

(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 

Oto obliczenia w pseudokodzie:

  • Niech s (d) będzie liczbą dotknięć drzwi d po k rundach.
  • s (d) = suma (m = 1..m = k) (d% m == 0? (n-m + 1): 0)
  • drzwi d są otwarte po k rundach, jeżeli s (d)% 2 = 1 (lub> 0)

Jeśli nie jesteś przekonany, że wyrażenie dla s (d) jest poprawne, spójrz na to w ten sposób:

  • Niech s (d, r) będzie liczbą dotknięć drzwi d po rundach.
  • s (d, k) - s (d, k-1) = suma (m = 1, .., m = k) (d% m == 0? 1: 0)
  • s (d, k-1) - s (d, k-2) = suma (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
  • zsumuj obie strony, aby uzyskać powyższe wyrażenie dla s (d), które jest równe s (d, k)
Cary Swoveland
źródło
Bardzo zwięzłe! Ale skąd ni skąd kpochodzą? Wydaje się, że wynik jest oddzielony znakiem nowej linii niż spacją.
Paul Prestidge
1

PowerShell: 132

Kod do gry w golfa:

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

Kod bez komentarza:

# 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
Iszi
źródło
Och, rozumiem na czym polega mój problem. Źle zrozumiałem pytanie - to nie jest problem 100 szafek. Właśnie o to! Będzie to wymagało nieco więcej pracy ...
Iszi
1
Słodkie! Naprawienie go w celu spełnienia wymagań wyzwania przyniosło ostatecznie tylko zysk 6 postaci.
Iszi
0

PowerShell, 66 bajtów

Na podstawie Cary Swoveland za odpowiedź .

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

Skrypt testowy:

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

Wynik:

True: 1 2
True: 1 2 4 8 9 16 18 23
mazzy
źródło