N Puertas, K Monos


14

Hay N puertas y K monos. Inicialmente, todas las puertas están cerradas.

Ronda 1: El 1er mono visita cada puerta y alterna la puerta (si la puerta está cerrada, se abre; si está abierta, se cierra).

Ronda 2 : El 1er mono visita cada puerta y alterna la puerta. Luego, el 2do mono visita cada 2da puerta y alterna la puerta.

. . .

. . .

Ronda k: el 1er mono visita cada puerta y alterna la puerta. . . . . . . . . . El mono k visita cada puerta kth y alterna la puerta.

Entrada: NK (separados por un solo espacio)

Salida: números de puerta que están abiertos, cada uno separado por un solo espacio.

Ejemplo :

Entrada: 3 3

Salida: 1 2

Restricciones :

0 <N <101

0 <= K <= N

Nota :

  • Suponga que las puertas N están numeradas del 1 al N y los monos K están numerados del 1 al K

  • El que tenga el código más corto gana. Además, muestra la salida para N = 23, K = 21



Solo tengo una pregunta, si N = K, cada puerta de número primo está abierta, ¿verdad?
Fabinout

@Fabinout no n=k=3daría salida 1 2así que estás equivocado ... y 5 salidas 1 2 4hay un patrón pero es mucho menos obvio que eso.
Enfriador matemático

@Fabinout sigue un tipo muy extraño de conjunto de números de Fibonacci, sus matemáticas abstractas muy avanzadas.
Enfriador de matemáticas

@tryingToGetProgrammingStraight tienes razón, mis recuerdos me dijeron que la respuesta era la lista de números primos, cuando era la lista de números cuadrados.
Fabinout

Respuestas:


14

APL, 32 28 26

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

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

Explicación

  • {+/0=⍺|⍨⍳⍵}es una función que devuelve el número de veces que la puerta (argumento izquierdo) se alterna en round (argumento derecho), que es igual al número de factores que es ≤ :

    • ⍳⍵ Generar matriz numérica de 1 a

    • ⍺|⍨Calcular el módulo de cada elemento de esa matriz

    • 0= Cambie a 1 donde había un 0, y un 0 para todo lo demás.

    • +/ Suma la matriz resultante

  • La función externa:

    • (⍳⍺), ⍳⍵Generar matrices de 1 a N y 1 a K

    • ∘.{...}Para cada par de elementos de las dos matrices, aplique la función. Esto proporciona una matriz de número de veces activadas, cada fila representa una puerta y cada columna representa una ronda.

    • +/Suma las columnas. Esto proporciona un conjunto de la cantidad de veces que cada puerta se alterna en todas las rondas.

    • 2|Módulo 2, así que si una puerta está abierta, es un 1; si está cerrado, es un 0.

    • (...)/⍳⍺ Finalmente, genere una matriz de 1 a N y seleccione solo aquellas en las que haya un 1 en la matriz en el paso anterior.

  • /⎕ Finalmente, inserte la función entre los números de entrada.


EDITAR

{(2|+⌿0=(,↑⍳¨⍳⍵)∘.|⍳⍺)/⍳⍺}/⎕
  • ,↑⍳¨⍳⍵Genere todos los "monos" (si K = 4, entonces esto es 1 0 0 0 1 2 0 0 1 2 3 0 1 2 3 4)

    • ⍳⍵Matriz de 1 a (K)

    • ⍳¨ Para cada uno de ellos, genere una matriz de 1 a ese número

    • ,↑Convierta la matriz anidada en una matriz ( ) y luego desentrañe en una matriz simple ( ,)

  • (,↑⍳¨⍳⍵)∘.|⍳⍺ Para cada número del 1 al (N), modifíquelo con cada mono.

  • 0=Cambie a 1 donde había un 0, y un 0 para todo lo demás. Esto proporciona una matriz de conmutadores: las filas son cada mono en cada ronda, las columnas son puertas; 1 significa alternar, 0 significa no alternar.

  • +⌿ Suma las filas para obtener una serie de veces que se activa cada puerta

Otras partes no cambian


EDITAR

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

Use XOR reduce ( ≠⌿) en lugar de suma y mod 2 ( 2|+⌿)


¿APL fue diseñado para el script de golf? ;-)
celtschk

@celtschk Sí, en parte, de alguna manera. Fue diseñado para expresar algoritmos de manera concisa.
luser droog

¿Por qué usa una reducción de dfn en {}/lugar de simplemente tomar N y K como argumentos para el dfn?
Adám

@ Adám Porque 1) esto me ha pasado; 2) esta pregunta es anterior al "programa o función" y las estandarizaciones de E / S; 3) el OP dijo específicamente "separados por un solo espacio"
TwiNight

Justo lo suficiente, pero al menos se puede ahorrar un byte coni←⍳⍺
Adám

4

GolfScript, 33 caracteres

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

Si las puertas estuvieran numeradas comenzando con cero, ahorrarían 3 caracteres.

Ejemplos (en línea ):

> 3 3
1 2

> 23 21
1 2 4 8 9 16 18 23

3

Mathematica, 104 caracteres

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

Ejemplo:

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

? 23 21

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


1
Puede golpear otros 15 personajes de analizar la entrada suponiendo un flujo de entrada, por ejemplo: {n,k}=%~Read~{Number,Number}.
Marca Thomas el

3

Ruby, 88

Basado en la respuesta de @ manatwork.

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

¡Esos glotones poco fiables siempre rompen el resaltado de sintaxis!


Lo sentimos, pero los 90 caracteres ( revisión 2 ) y 86 caracteres ( revisión 3 ) parecen tener errores: un nuevo número, 22, apareció en sus resultados.
manatwork

@manatwork buena llamada, creo que lo he arreglado ahora a costa de dos personajes. Siento que ese countbit podría mejorarse aún más, desearía que Ruby tuviera un #summétodo incorporado para cosas como esas:>
Paul Prestidge

¡Guauu! Realmente impresionado.
manatwork

3

Python 3, 97 84

Si un mono aparece en un número par de rondas, eso no cambia en absoluto. Si un mono aparece en un número par de veces, es lo mismo que en una ronda exactamente.

Por lo tanto, algunos monos pueden quedar fuera, y los otros solo tienen que cambiar de puerta una vez.

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

Salida para 23 21:

1 2 4 8 9 16 18 23

¡Uso inteligente de las operaciones de configuración! Creo que se puede acortar range(2-K%2,K+1,2)a range(K,0,-2).
xnor

O mejor aún, reemplace el forbucle con un whilebucle:while K>0:r^=set(range(K,N+1,K));K-=2
xnor

@xnor: gracias, eso es genial!
Vuelva a instalar a Monica el

2

R - 74

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

Simulación:

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

Aquí hay una versión legible (muy pequeña):

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

Violín DEMO

Debo tener en cuenta que comienza a contar desde 0 (técnicamente un error off-by-one)


Puede eliminar su tercera línea si cambia la segunda línea a b=Array(n);Esto inicializa su matriz como n longitud llena de indefinido. ! undefined es cierto, por lo que el primer pase de mono lo convertirá todo en verdad.
path411

@ path411 muchas gracias! ¡Estoy sorprendido de haber olvidado cómo funciona la declaración de matriz "adecuada"! puedes sentirte libre+1
Math chiller

Interesante. Parece que el tuyo es el único que he visto hasta ahora que parece obtener una respuesta similar a la mía para N = 23, K = 21. La única diferencia es el problema off-by-one que incluye 0 y excluye 23.
Iszi

Descubrí lo que está mal con el mío, y este tiene el mismo problema. Para cada ronda, solo estás enviando un mono por todas las puertas. Sin embargo, según las especificaciones del desafío, debe haber $ i monos corriendo en cada ronda, donde $ i es el número de la ronda en la que estás.
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=' '))

Salida para N = 23, K = 21:

1 2 4 8 9 16 18 23  

Probado en Chrome, pero no utiliza ninguna característica nueva de ECMAScript, por lo que debería funcionar en cualquier navegador.

Sé que nunca ganaré contra las otras entradas y que @tryingToGetProgrammingStrainght ya envió una entrada en JavaScript, pero no estaba obteniendo los mismos resultados para N = 23, K = 21 como todos los demás obtenían eso, así que pensé que probaría mi propia versión.

Editar : fuente anotada (al revisar esto nuevamente, vi lugares para guardar otros 3 caracteres, por lo que probablemente aún se pueda mejorar ...)

(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

¡buen trabajo! si también proporcionara una versión legible y comentada, probablemente lo haría+1
Math chiller

Respuesta actualizada! Como no puedo comentar tu respuesta, para agregar al comentario de @ path411, puedes establecer b = [] y los índices vacíos aún no están definidos y eso te ahorra otros 6 caracteres.
Dom Hastings

ya lo hice ...
Math chiller

1

Ruby - 65 caracteres

(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 

Aquí está el cálculo, en pseudocódigo:

  • Sea s (d) el número de veces que se toca la puerta d después de k rondas.
  • s (d) = suma (m = 1..m = k) (d% m == 0? (n-m + 1): 0)
  • la puerta d está abierta después de k rondas si s (d)% 2 = 1 (o> 0)

Si no está convencido de que la expresión para s (d) es correcta, mírela de esta manera:

  • Sea s (d, r) el número de veces que se toca la puerta d después de r rondas.
  • 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
  • suma ambos lados para obtener la expresión anterior para s (d), que es igual a s (d, k)

Muy conciso! ¿De dónde ny de dónde kvienes? Y la salida parece estar separada por nuevas líneas en lugar de espacios.
Paul Prestidge

1

PowerShell: 132

Código de golf:

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

Código no comentado y comentado:

# 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, veo cuál es mi problema. No entendí bien la pregunta: este no es el problema de los 100 casilleros. Es eso, tomado una muesca! Esto requerirá un poco más de trabajo ...
Iszi

1
¡Dulce! Arreglarlo para cumplir los requisitos de desafío correctamente solo obtuvo una ganancia de 6 caracteres al final.
Iszi

0

Powershell, 66 bytes

Basado en la respuesta de Cary Swoveland .

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

Script de prueba:

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

Salida:

True: 1 2
True: 1 2 4 8 9 16 18 23
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.