N Doors, K Monkeys


13

Existem N portas e K macacos. Inicialmente, todas as portas estão fechadas.

Rodada 1: O primeiro macaco visita cada porta e alterna a porta (se a porta estiver fechada, ela será aberta; se estiver aberta, será fechada).

Rodada 2 : O 1º macaco visita todas as portas e alterna a porta. Então o segundo macaco visita cada segunda porta e alterna a porta.

. . .

. . .

Rodada k: O 1º macaco visita todas as portas e alterna a porta. . . . . . . . . . O k-ésimo macaco visita cada k-ésima porta e alterna a porta.

Entrada: NK (separado por um único espaço)

Saída: números de porta abertos, cada um separado por um único espaço.

Exemplo :

Entrada: 3 3

Saída: 1 2

Restrições :

0 <N <101

0 <= K <= N

Nota :

  • Suponha que N portas sejam numeradas de 1 a N e K macacos sejam numeradas de 1 a K

  • Aquele com o código mais curto vence. Além disso, exiba a saída para N = 23, K = 21



Eu só tenho uma pergunta, se N = K, todas as portas dos números primos estão abertas, certo?
Fabinout

@Fabinout não n=k=3produziria 1 2tão ur errado ... e 5 saídas 1 2 4há um padrão, mas é muito menos óbvio que isso.
Math chiller

@Fabinout segue um tipo muito estranho de conjunto de números de Fibonacci, sua matemática abstrata muito avançada.
Math chiller

@tryingToGetProgrammingStraight você está certo, minhas memórias me disseram que a resposta era a lista de números primos, quando era a lista de números quadrados.
Fabinout

Respostas:


14

APL, 32 28 26

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

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

Explicação

  • {+/0=⍺|⍨⍳⍵}é uma função que retorna o número de vezes que a porta (argumento da esquerda) é alternada na rodada (argumento da direita), que é igual ao número de fatores que é ≤ :

    • ⍳⍵ Gere um array numérico de 1 a

    • ⍺|⍨Calcular o módulo para cada item dessa matriz

    • 0= Mude para 1 onde havia 0 e 0 para todas as outras coisas

    • +/ Soma a matriz resultante

  • A função externa:

    • (⍳⍺), ⍳⍵Gere matrizes de 1 a N e 1 a K

    • ∘.{...}Para cada par de elementos das duas matrizes, aplique a função Isso fornece uma matriz de número de vezes alternada, cada linha representa uma porta e cada coluna representa uma rodada.

    • +/Soma as colunas. Isso fornece uma matriz do número de vezes que cada porta é alternada em todas as rodadas.

    • 2|Módulo 2, portanto, se uma porta está aberta, é 1; se estiver fechado, é um 0.

    • (...)/⍳⍺ Por fim, gere uma matriz de 1 a N e selecione apenas as que contêm 1 na matriz na etapa anterior.

  • /⎕ Por fim, insira a função entre os números da entrada.


EDITAR

{(2|+⌿0=(,↑⍳¨⍳⍵)∘.|⍳⍺)/⍳⍺}/⎕
  • ,↑⍳¨⍳⍵Gere todos os "macacos" (se K = 4, então é isso 1 0 0 0 1 2 0 0 1 2 3 0 1 2 3 4)

    • ⍳⍵Matriz de 1 a (K)

    • ⍳¨ Para cada um deles, gere uma matriz de 1 para esse número

    • ,↑Converta a matriz aninhada em uma matriz ( ) e desdobre-a em uma matriz simples ( ,)

  • (,↑⍳¨⍳⍵)∘.|⍳⍺Para cada número de 1 a (N), modifique-o com cada macaco.

  • 0=Mude para 1 onde havia 0 e 0 para todas as outras coisas. Isso fornece uma matriz de alternância: as linhas são cada macaco em cada rodada, as colunas são as portas; 1 significa uma alternância, 0 significa nenhuma alternância.

  • +⌿ Soma as linhas para obter uma matriz de número de vezes que cada porta é alternada

Outras peças não são alteradas


EDITAR

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

Use XOR reduzir ( ≠⌿) em vez de soma e mod 2 ( 2|+⌿)


O APL foi projetado para roteiro de golfe? ;-)
celtschk 22/06

@celtschk Sim, em parte, de certa forma. Foi projetado para expressar algoritmos de forma concisa.
Luser droog

Por que você usa uma redução dfn em {}/vez de apenas tomar N e K como argumentos para o dfn?
Adám 27/06/17

@ Adám Porque 1) isso já passou de mim; 2) essa pergunta antecede o "programa ou função" e as padronizações de E / S; 3) o OP disse especificamente "separado por um único espaço"
TwiNight

Justo, mas pelo menos você pode salvar um byte com #i←⍳⍺
Adám

4

GolfScript, 33 caracteres

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

Se as portas forem numeradas começando com zero, serão salvos 3 caracteres.

Exemplos ( online ):

> 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~" "

Exemplo:

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

? 23 21

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


1
Você pode bater mais 15 caracteres off analisar a entrada, assumindo um fluxo de entrada, por exemplo: {n,k}=%~Read~{Number,Number}.
Marcks Thomas

3

Ruby, 88

Com base na resposta de @ manatwork.

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

Esses globos desonestos sempre quebram o destaque da sintaxe!


Desculpe, mas os 90 caracteres ( revisão 2 ) e 86 caracteres ( revisão 3 ) parecem estar com erros: um novo número, 22, apareceu em seus resultados.
manatwork

@ manatwork boa chamada, acho que já corrigi-lo agora ao custo de dois caracteres. Eu sinto que esse countbit poderia ser melhorado ainda mais, eu gostaria que o ruby ​​tivesse um #summétodo embutido para coisas assim:>
Paul Prestidge 22/10/2013

Uau! Realmente impressionado.
manatwork

3

Python 3, 97 84

Se um macaco aparecer em um número par de rodadas, isso não muda. Se um macaco aparecer várias vezes, é o mesmo que exatamente em uma rodada.

Assim, alguns macacos podem ficar de fora, e outros apenas precisam trocar de porta uma vez.

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

Saída para 23 21:

1 2 4 8 9 16 18 23

Uso inteligente de operações definidas! Eu acho que você pode reduzir range(2-K%2,K+1,2)para range(K,0,-2).
xnor

Ou melhor ainda, substitua o forloop por um whileloop:while K>0:r^=set(range(K,N+1,K));K-=2
xnor

@xnor: obrigado, isso é ótimo!
Reinstale Monica

2

R - 74

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

Simulação:

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

aqui está uma versão legível (um pouquinho):

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 violino

devo observar que ele começa a contar a partir de 0 (tecnicamente um erro de um por um)


Você pode remover sua 3ª linha se alterar a 2ª linha para b=Array(n);Isso inicializa sua matriz como n comprimento preenchido com indefinido. Como undefined é verdadeiro, o primeiro passe de macaco transformará tudo em verdade.
path411

@ path411 muito obrigado! Estou surpreso, eu esqueci como declaração de matriz "adequada" funciona! você pode sentir livre+1
Math chiller

Interessante. Parece que o seu é o único que vi até agora que parece ter uma resposta semelhante à minha para N = 23, K = 21. A única diferença é a questão off-by-one que inclui 0 e exclui 23.
Iszi

Descobrimos o que há de errado com o meu, e este tem o mesmo problema. Para cada rodada, você está enviando apenas um macaco por todas as portas. No entanto, de acordo com as especificações do desafio, é necessário haver macacos $ i percorrendo cada rodada - onde $ i é o número da rodada em que você está.
Iszi 27/11

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

Saída para N = 23, K = 21:

1 2 4 8 9 16 18 23  

Testado no Chrome, mas não usa nenhum novo recurso sofisticado do ECMAScript, portanto, deve funcionar em qualquer navegador!

Eu sei que nunca vou ganhar contra as outras entradas e que @tryingToGetProgrammingStrainght já enviou uma entrada em JavaScript, mas eu não estava obtendo os mesmos resultados para N = 23, K = 21 que todo mundo estava recebendo com isso, então pensei que teria uma chance na minha própria versão.

Edit : fonte anotada (ao examinar isso novamente, vi lugares para salvar outros 3 caracteres, para que provavelmente possa ser melhorado ainda ...)

(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

bom trabalho! Se você também fornecer uma versão legível e comentou eu provavelmente+1
Math chiller

Resposta atualizada! Como não posso comentar sua resposta, para adicionar ao comentário de @ path411, você pode definir b = [] e os índices vazios ainda são indefinidos, o que economiza outros 6 caracteres!
Dom Hastings

Eu já fiz isso ... #
chiller de matemática 26/10

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 

Aqui está o cálculo, em pseudo-código:

  • Seja s (d) o número de vezes que a porta d é tocada após k rodadas.
  • s (d) = soma (m = 1..m = k) (d% m == 0? (n-m + 1): 0)
  • porta d é aberta após k rodadas se s (d)% 2 = 1 (ou> 0)

Se você não está convencido de que a expressão para s (d) está correta, observe-a desta maneira:

  • Seja s (d, r) o número de vezes que a porta d é tocada após r rodadas.
  • s (d, k) - s (d, k-1) = soma (m = 1, .., m = k) (d% m == 0? 1: 0)
  • s (d, k-1) - s (d, k-2) = soma (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
  • soma os dois lados para obter a expressão acima para s (d), que é igual a s (d, k)

Muito conciso! De onde ne de onde kvem? E a saída parece ser separada por novas linhas, e não por espaços.
Paul Prestidge

1

PowerShell: 132

Código de golfe:

$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 não comentado, 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, eu vejo qual é o meu problema. Eu entendi mal a pergunta - este não é o problema dos 100 cacifos. É isso, tomado um entalhe! Isso vai exigir um pouco mais de trabalho ...
Iszi

1
Doce! Corrigi-lo para atender adequadamente aos requisitos do desafio resultou em um ganho de 6 caracteres no final.
Iszi 27/11

0

Powershell, 66 bytes

Baseado na resposta de Cary Swoveland .

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

Script de teste:

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

Resultado:

True: 1 2
True: 1 2 4 8 9 16 18 23
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.