N Doors, K Monkeys


14

Ci sono N porte e K scimmie. Inizialmente, tutte le porte sono chiuse.

Round 1: La 1a scimmia visita ogni porta e attiva la porta (se la porta è chiusa, viene aperta; se è aperta, viene chiusa).

Round 2 : la 1a scimmia visita ogni porta e attiva la porta. Quindi la seconda scimmia visita ogni seconda porta e attiva la porta.

. . .

. . .

Round k: la 1a scimmia visita ogni porta e attiva la porta. . . . . . . . . . La kth monkey visita ogni kth door e attiva la porta.

Input: NK (separato da un singolo spazio)

Output: numeri di porta che sono aperti, ciascuno separato da un singolo spazio.

Esempio :

Ingresso: 3 3

Uscita: 1 2

Vincoli :

0 <N <101

0 <= K <= N

Nota :

  • Supponiamo che N porte siano numerate da 1 a N e K le scimmie siano numerate da 1 a K

  • Vince quello con il codice più corto. Inoltre, visualizza l'uscita per N = 23, K = 21



Ho solo una domanda, se N = K, ogni porta del numero primo è aperta, giusto?
Fabinout,

@Fabinout no n=k=3avrebbe prodotto un output 1 2così sbagliato ... e 5 output hanno 1 2 4uno schema ma è molto meno ovvio.
Chiller matematico,

@Fabinout segue un tipo molto strano di set di numeri di Fibonacci, la sua matematica astratta molto avanzata.
Chiller matematico,

@tryingToGetProgrammingDa destra hai ragione, i miei ricordi mi hanno detto che la risposta era la lista dei numeri primi, quando era la lista dei numeri quadrati.
Fabinout,

Risposte:


14

APL, 32 28 26

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

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

spiegazione

  • {+/0=⍺|⍨⍳⍵}è una funzione che restituisce il numero di volte in cui la porta (argomento a sinistra) è attivata / disattivata su round (argomento a destra), che equivale al numero di fattori di :

    • ⍳⍵ Genera matrice numerica da 1 a

    • ⍺|⍨Calcola il modulo ogni elemento di quell'array

    • 0= Passa a 1 dove c'erano 0 e 0 per ogni altra cosa

    • +/ Somma l'array risultante

  • La funzione esterna:

    • (⍳⍺), ⍳⍵Genera array da 1 a N e da 1 a K

    • ∘.{...}Per ogni coppia di elementi dei due array, applicare la funzione. Questo dà una matrice di numero di volte alternate, ogni riga rappresenta una porta e ogni colonna rappresenta un giro.

    • +/Somma le colonne. Ciò fornisce una matrice del numero di volte in cui ogni porta viene attivata / disattivata in tutti i round.

    • 2|Modulo 2, quindi se una porta è aperta, è un 1; se è chiuso, è uno 0.

    • (...)/⍳⍺ Infine, genera un array da 1 a N e seleziona solo quelli in cui è presente un array nel passaggio precedente.

  • /⎕ Infine, inserisci la funzione tra i numeri dall'input.


MODIFICARE

{(2|+⌿0=(,↑⍳¨⍳⍵)∘.|⍳⍺)/⍳⍺}/⎕
  • ,↑⍳¨⍳⍵Genera tutte le "scimmie" (Se K = 4, allora questo è 1 0 0 0 1 2 0 0 1 2 3 0 1 2 3 4)

    • ⍳⍵Matrice da 1 a (K)

    • ⍳¨ Per ognuno di questi, genera un array da 1 a quel numero

    • ,↑Converti l'array nidificato in una matrice ( ) e poi svela in una semplice matrice ( ,)

  • (,↑⍳¨⍳⍵)∘.|⍳⍺Per ogni numero compreso tra 1 e (N), modificalo con ogni scimmia.

  • 0=Passa a 1 dove c'erano 0 e 0 per ogni altra cosa. Questo dà una matrice di levette: le righe sono ogni scimmia su ogni round, le colonne sono porte; 1 indica un interruttore, 0 indica nessun interruttore.

  • +⌿ Somma le righe per ottenere una serie di volte in cui ogni porta viene attivata / disattivata

Altre parti non vengono cambiate


MODIFICARE

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

Usa XOR reduce ( ≠⌿) invece di sum e mod 2 ( 2|+⌿)


APL è stato progettato per la sceneggiatura del golf? ;-)
celtschk,

@celtschk Sì, in parte, in un certo senso. È stato progettato per esprimere gli algoritmi in modo conciso.
luser droog,

Perché usi una riduzione di dfn {}/invece di prendere semplicemente N e K come argomenti per il dfn?
Adám,

@Adám Perché 1) questo è passato da me; 2) questa domanda precede il "programma o funzione" e le standardizzazioni I / O; 3) il PO ha detto specificamente "separato da un unico spazio"
TwiNight,

Abbastanza giusto, ma almeno puoi salvare un byte coni←⍳⍺
Adám il

4

GolfScript, 33 caratteri

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

Se le porte fossero numerate a partire da zero, salverebbe 3 caratteri.

Esempi ( online ):

> 3 3
1 2

> 23 21
1 2 4 8 9 16 18 23

3

Mathematica, 104 caratteri

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

Esempio:

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

? 23 21

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


1
Si può battere altri 15 lettere dalla analisi dell'ingresso assumendo un flusso di input, ad esempio: {n,k}=%~Read~{Number,Number}.
Marcks Thomas,

3

Ruby, 88

Basato sulla risposta di @ manatwork.

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

Quei malvagi globi infrangono sempre l'evidenziazione della sintassi!


Siamo spiacenti, ma i 90 caratteri ( revisione 2 ) e 86 caratteri ( revisione 3 ) sembrano essere errati: un nuovo numero, 22, è apparso nei loro risultati.
arte

@manatwork bella chiamata, penso di averlo risolto ora al costo di due personaggi. Sento che quel countpo 'potrebbe essere ulteriormente migliorato, vorrei che Ruby avesse un #summetodo integrato per cose del genere:>
Paul Prestidge

Wow! Davvero colpito.
arte

3

Python 3, 97 84

Se una scimmia appare in un numero pari di round, questo non è affatto un cambiamento. Se una scimmia appare in un numero pari di volte, è esattamente come in un round.

Quindi alcune scimmie possono essere lasciate fuori e gli altri devono solo cambiare porta una volta.

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

Uscita per 23 21:

1 2 4 8 9 16 18 23

Uso intelligente delle operazioni impostate! Penso che si possa ridurre range(2-K%2,K+1,2)a range(K,0,-2).
xnor

O meglio ancora, sostituisci il forloop con un whileloop:while K>0:r^=set(range(K,N+1,K));K-=2
xnor

@xnor: grazie, fantastico!
Ripristina Monica il

2

R - 74

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

Simulazione:

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

ecco una versione (minuscola) leggibile:

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

Violino DEMO

dovrei notare che inizia a contare da 0 (tecnicamente un errore off-by-one)


È possibile rimuovere la terza riga se si modifica la seconda riga in b=Array(n);Questo inizializza l'array come n lunghezza riempita con indefinito. ! undefined è vero, quindi il primo passaggio della scimmia lo trasformerà in veri.
path411

@ path411 grazie mille! Sono sorpreso di aver dimenticato come funziona la dichiarazione di array "corretta"! puoi sentirti libero di+1
Chiller matematico

Interessante. Sembra che il tuo sia l'unico che ho visto finora che sembra avere una risposta simile alla mia per N = 23, K = 21. L'unica differenza è rappresentata dal numero uno-a-uno che include 0 ed esclude il 23.
Iszi,

Ho capito cosa c'è che non va nel mio, e questo ha lo stesso problema. Per ogni round, invii solo una scimmia attraverso tutte le porte. Tuttavia, secondo le specifiche della sfida, ci devono essere $ 1 scimmie che attraversano ogni round - dove $ i è il numero del round in cui ci si trova.
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=' '))

Uscita per N = 23, K = 21:

1 2 4 8 9 16 18 23  

Testato su Chrome, ma non utilizza nuove fantasiose funzionalità ECMAScript, quindi dovrebbe funzionare su qualsiasi browser!

So che non vincerò mai contro le altre voci e che @tryingToGetProgrammingStrainght ha già inviato una voce in JavaScript, ma non ottenevo gli stessi risultati per N = 23, K = 21 di tutti gli altri, quindi ho pensato che proverei con la mia versione.

Modifica : fonte annotata (guardando di nuovo su questo, ho individuato i luoghi in cui salvare altri 3 caratteri, quindi probabilmente può essere ancora migliorato ...)

(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

buon lavoro! se fornissi anche una versione leggibile e commentata, probabilmente lo farei+1
Chiller Math

Risposta aggiornata! Dal momento che non posso commentare la tua risposta, per aggiungere al commento di @ path411, puoi impostare b = [] e gli indici vuoti sono ancora indefiniti e questo ti fa risparmiare altri 6 caratteri!
Dom Hastings,

l'ho già fatto ....
Chiller matematico,

1

Rubino - 65 caratteri

(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 

Ecco il calcolo, in pseudo-codice:

  • Sia s (d) il numero di volte in cui la porta d viene toccata dopo k round.
  • s (d) = somma (m = 1..m = k) (d% m == 0? (n-m + 1): 0)
  • la porta d è aperta dopo k giri se s (d)% 2 = 1 (o> 0)

Se non sei convinto che l'espressione per s (d) sia corretta, guardala in questo modo:

  • Sia s (d, r) il numero di volte in cui la porta d viene toccata dopo il giro di r.
  • s (d, k) - s (d, k-1) = sum (m = 1, .., m = k) (d% m == 0? 1: 0)
  • s (d, k-1) - s (d, k-2) = sum (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
  • sommare entrambe le parti per ottenere l'espressione precedente per s (d), che equivale a s (d, k)

Molto conciso! Da dove viene ne kda dove viene? E l'output sembra essere separato da newline piuttosto che da spazi.
Paul Prestidge,

1

PowerShell: 132

Codice Golfed:

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

Codice non golfato, commentato:

# 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, capisco qual è il mio problema. Ho frainteso la domanda: questo non è il problema dei 100 Locker. È quello, preso un livello! Ciò richiederà un po 'più di lavoro ...
Iszi il

1
Dolce! Risolto il problema per soddisfare correttamente i requisiti della sfida, alla fine aveva solo un guadagno di 6 caratteri.
Iszi,

0

Powershell, 66 byte

Basato sulla risposta di Cary Swoveland .

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

Script di prova:

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

Produzione:

True: 1 2
True: 1 2 4 8 9 16 18 23
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.