Josephus problema com três entradas

22

Há uma pergunta neste site que é semelhante a essa pergunta, mas eu adicionei uma reviravolta.

Você tem três entradas, o número de pessoas no círculo n , a k- ésima pessoa contada em cada etapa e a q-é a pessoa que sobrevive. As pessoas no círculo são numeradas de 1 a n .

Por exemplo, em um círculo de 20 pessoas, a 20ª pessoa a sobreviver é a primeira pessoa removida, o 19º sobrevivente é a segunda pessoa removida e assim por diante. Normalmente, o problema de Josephus é determinar a última pessoa removida, aqui chamada de primeiro sobrevivente.

Escreva o programa ou a função mais curta que, com essas três entradas, retorne o número da q- ésima pessoa a sobreviver.

Se houver algum problema com clareza, entre em contato.

Alguns exemplos:

>>> josephus(20, 3, 9)
4
>>> josephus(4, 3, 1)
1
>>> josephus(100, 9, 12)
46

Editar: Assuma que todas as entradas são válidas. Ou seja, ninguém pedirá zero ou nenhum número negativo e ninguém pedirá o vigésimo sobrevivente em um círculo de 5 pessoas (ou seja, 1 ≤ q ≤ n)

Edit: Aceito uma resposta à meia-noite UTC + 7 no início de 2 de dezembro.

Sherlock9
fonte
1
Poste suas próprias soluções como respostas, em vez de incluí-las na pergunta.
Maçaneta
Consegui. Desculpe por isso
Sherlock9
1
Para esclarecimento, se q=1isso é exatamente o mesmo que a questão de Josephus, certo?
AdmBorkBork
@TimmyD Exactly
Sherlock9

Respostas:

5

Pitão, 16 bytes

eu.<PGvzh-QvwShQ

Experimente on-line: Demonstration or Test Suite

Entrada é da forma k<newline>n<newline>q.

Explicação:

eu.<PGvzh-QvwShQ   implicit: z = first input line (string)
                             Q = second input line (integer)
              hQ   Q + 1
             S     the range [1, 2, ..., Q+1]
 u      h-Qvw      apply the following statement (Q-input()+1) times to G=^
    PG                remove the last number of G
  .<  vz              and rotate eval(z) to the left
e                  print the last number of the resulting list  
Jakube
fonte
7

Piet, 280 273 codéis

insira a descrição da imagem aqui

Edit: Eu joguei isso um pouco mais, e acho que posso jogar ainda mais, mas isso ainda está por vir. Por enquanto, estou feliz que funcione e que eu tenha espaço para assiná-lo no canto inferior esquerdo. Duas idéias que tenho para salvar mais codelos são: a) alterar as instruções finaispop, push 1, add, out num (pop n, saída r + 1) eb) duplicar novamente no canto inferior esquerdo para salvar codels na manipulação de pilha posteriormente no loop.

A imagem acima é o meu código de 8 pixels por codel. Em geral, é o mesmo algoritmo da minha resposta Python, mas com as entradas na ordem de k , q , n . Na prática, há também uma grande quantidade de manipulação de pilha. Você pode tentar aqui , abrindo a imagem e executando o código com ele.

Explicação

Esta é uma descrição passo a passo da solução.

in num    get k
dup       Stack: k k
push 1
subtract  Stack: k k-1
in num    get q
dup       Stack: k k-1 q q
dup       Stack: k k-1 q q q
push 4
push 2
roll      Stack: k q q k-1 q
mod       Stack: k q q r
in num    get n
# note: the loop will return to the following codel
dup       Stack: k q q r n n
push 4
push 3
roll      Stack: k q r n n q
greater   1 or 0
pointer   Here the loop begins. If q>n, the pointer moves clockwise.
          Else, it points straight ahead

LOOP:     Stack: k i r n (i=q at the start of the loop)
push 4
push 2
roll      Stack: r n k i
push 1
add       Stack: r n k i=i+1
push 2
push 1
roll      Stack: r n i k
dup       Stack: r n i k k
push 5
push 4
roll      Stack: n i k k r
add       Stack: n i k m=r+k
push 3
push 2
roll      Stack: n k m i
dup       Stack: n k m i i
push 3
# here it turns the corner
push 1
roll      Stack: n k i m i
mod       Stack: n k i r=m%i
push 4
# here it turns the corner and avoids the black codels
push 1
roll      Stack: r n k i
dup       Stack: r n k i i
push 5
push 3
roll      Stack: k i i r n
dup       Stack: k i i r n n
# and we meet up with the dark green codel once more
push 4
push 3
roll      Stack: k i r n n i
greater   Stack: k i r n (0 or 1)
pointer   if else again

# else    Stack: k i r n
push 2    
push 1
roll      Stack: k i n r
# and turn the corner
push 1
add       Stack: k i n r+1
out num   print r+1
# turn the corner into the end pattern (the shape with the black edges)
END
Sherlock9
fonte
Você não está contando espaço vazio? Existe um meta post em algum lugar sobre como marcar Piet? Provavelmente deveria haver.
Sparr
@ Sparr, estou contando espaço vazio. Que é uma imagem de 21 codéis por 13 codéis, então a pontuação é de 273 codéis.
Sherlock9
Ahh, eu contei mal. Desculpe.
Sparr
4

CJam, 22 20 19 bytes

q~_,@a@*{m<)\}%\~=)

Isso lê a entrada como q k n. Experimente online no intérprete CJam .

Como funciona

q~                   Read and evaluate all input. This pushes q, k, and n.
  _,                 Push A := [0 ... n-1].
    @a               Rotate on top of the stack and wrap it in an array.
      @*             Rotate the original n on top and repeat [k] n times.
        {    }%      For each of the n k's:
         m<            Rotate A k units to the left.
           )\          Pop the last element and swap it with A.
               \~    Swap the resulting array with q and apply bitwise NOT.
                 =)  Select the corresponding element and add 1 to it.
Dennis
fonte
3

Golfscript, 58 56 55 35 31 30 bytes

Supondo que as três entradas já estejam na pilha, na ordem n , k , q

~1$(1$%3$),@),-{\2$+\%}%\)])\;

Essa solução pressupõe que eu preciso me livrar de tudo, exceto a resposta final.

Como funciona

Veja j(n,k,q)na minha solução Python 3 para mais detalhes.

~                                   Read the inputs n, k, q
 1$(                                Duplicate k, decrement
    1$                              Duplicate q
      %                             (k-1)%q
       3$),                         Create array [0..n+1]
           @),                      Create array [0..q+1]
              -                     Subtract the second array from the first,
                                        leaving only [q+1..n+1]
               {      }%            Map the following statement onto [q+1..n+1].
                                        The numbers from this array will be denoted i.
                \                   Swap i and r
                 2$+                Duplicate k, add to r
                    \               Swap r and i
                     %              r mod i
                        \)          Swap the leftover array from map with r, increment
                          ]         Put the whole stack into an array
                           )        Remove the last member of the array, r
                            \;      Pop the array, leaving only the result

Edit 1: Used @ Doorknob's sugestão (Adicionado um + para obter todas as entradas na matriz)

Anteriormente,

\.(2$2$*1$4$%-{.5$3$*>!}{~)2$*1$/~)}while 4$3$*\-)\;\;\;\;

Editar 2: Adicionado ~, de acordo com as regras do wiki, e reduziu o código. Obrigado @Dennis

Anteriormente,

[\.(2$2$*1$4$%-{.5$3$*>!}{~)2$*1$/~)}while 4$3$*\-)]+)\;

Edit 3: Implementado um algoritmo mais curto.

Anteriormente,

~\.(2$2$*1$4$%-{.5$3$*>!}{~)2$*1$/~)}while 4$3$*\-)]-1=

Edit 4: Descobri que eu poderia usar %como mapa.

Anteriormente,

~1$(1$%{1$4$<}{\)\2$+1$%}while)])\;

Edição 5: Edição secundária. Mudou 2$para @fazer [0..q-1]e 3$para 2$recuperar k. Salvo uma mordida

Anteriormente,

~1$(1$%3$),2$),-{\3$+\%}%\)])\;
Sherlock9
fonte
1
\;\;\;\;pode ser substituído por ])\;(agrupar na matriz, desconectar à direita, trocar e pop).
Maçaneta da porta
Editou meu código para maior clareza @Dennis.
Sherlock9
Tudo bem, @Dennis. Adicionou ~ e editou a pergunta para permitir apenas programas e funções. Você tem alguma outra sugestão?
Sherlock9
Não, tudo de bom. :)
Dennis
2

JavaScript (ES6), 56 bytes

(n,k,q)=>{r=(k-1)%q;for(i=q;i<n;r=(r+k)%++i);return r+1}

Ungolfed

Basicamente, uma adaptação em JavaScript da resposta Python do @ Sherlock9 .

(n,k,q)=>{
  r=(k-1)%q;
  for(i=q;i<n;r=(r+k)%++i);
  return r+1
}

Teste

n = <input type="number" id="N" value="100" /><br />
k = <input type="number" id="K" value="9" /><br />
q = <input type="number" id="Q" value="12" /><br />
<button onclick="result.innerHTML=(

(n,k,q)=>{r=(k-1)%q;for(i=q;i<n;r=(r+k)%++i);return r+1}

)(+N.value,+K.value,+Q.value)">Go</button><br />
<pre id="result"></pre>

user81655
fonte
Eu não chamaria sua versão não-destruída de golfe: P
Fund Monica's Lawsuit
1

Mathematica, 50 bytes

<<Combinatorica`
Tr@Position[Josephus@##2,1+#2-#]&

Uma função anônima. Recebe entradas na ordem q,n,k.

alefalpha
fonte
1

C, 81 73 bytes

Baseado na implementação Javascript de @ user81655 da minha resposta em Python.

Editar: Removido i

int j(int n,int k,int q){int r=(k-1)%q;for(;q<n;r=(r+k)%++q);return r+1;}

Teste

#include <stdio.h>
int j(int n,int k,int q){int r=(k-1)%q;for(;q<n;r=(r+k)%++q);return r+1;}
int main()
{
    printf("%d\n", j(20,3,9));
    return 0;
}
Sherlock9
fonte
Em algumas versões do C, você pode descartar o intnome dos parâmetros antes.
Fund Monica's Lawsuit
1

Python 3, 72 66 62 bytes

Uma função de programação dinâmica em 62 bytes. Adaptado do algoritmo na Wikipedia. Costumava haver uma implementação direta desse algoritmo quando q = 1 (ie i = 1, r = 0) nessa página, mas vejo que foi removido agora.

Editar 1: removi ipara salvar 4 bytes. A explicação permanece inalterada.

Editar 2: Erro de cálculo na contagem de bytes. Eu estava usando o \r\nEOL e não percebi quando isso adicionou 3 bytes. Reduzi minha contagem de bytes de acordo.

def j(n,k,q):
 r=(k-1)%q
 while q<n:q+=1;r=(r+k)%q
 return r+1

Como isso funciona

def j(n,k,q):
 i=q;r=(k-1)%q              We start with the smallest possible circle to have a q-th
                                survivor, a circle of q people.
 while i<n:i+=1;            Iterate from q to n
                r=(r+k)%i   Every time you add people to the circle, r increases by k, 
                                modulo the current size of the circle i.
 return r+1                 Return the result.

Agradeço ao @Dennis por me lembrar que eu deveria explicar meu código (mesmo que implicitamente, porque ele incluiu um em sua resposta). Se alguma coisa não estiver esclarecida, comunique-me por favor.

Editar:

Anteriormente,

Uma função iterativa que é adaptada de Concrete Mathematics por Graham, Knuth e Patashnik. Embora este algoritmo é mais longo, é mais rápido para grandes n e pequenas k .

def t(n,k,q):
 m=k-1;z=q*k-m%q
 while z<=n*m:z=-(-z*k//m)
 return n*k-z+1
Sherlock9
fonte
1
Parece que você cortou algo em copiar e colar, há um enforcamento +.
Xnor
1

PHP, 71 bytes

Com base nas respostas de @ Sherlock9. Veja sua resposta em Python para o algoritmo.

function a($n,$k,$q){for($r=($k-1)%$q;$q<$n;$r=($r+$k)%++$q);echo$r+1;}

Como alternativa, aqui está minha abordagem ingênua original, sem o algoritmo. Isso usa uma matriz para marcar quais pessoas são encontradas.

91 bytes

function a($n,$k,$q){for($r=--$i;$q<=$n;++$i%$k||$c[$r]=$q++)while($c[$r=++$r%$n]);echo$r;}
Xanderhall
fonte
1

Haskell, 48 47 43 bytes

(n!k)q=1+foldl(mod.(k+))(mod(k-1)q)[q+1..n]

Baseado no algoritmo Haskell na página Código Rosetta da função Josephus com duas entradas. Sugestões de golfe são bem-vindas.

Edit: Meus agradecimentos a nimi pela ajuda com o golfe no primeiro algoritmo, sugerindo uma versão sem pontos, e pela ajuda com o golfe no segundo algoritmo, informando que a untilpalavra - chave existe.

(n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q)

Uma versão do algoritmo no final da minha resposta em Python adaptada de Concrete Mathematics por Graham, Knuth e Patashnik. Embora esse algoritmo tenha mais de 62 bytes e não tenha atingido o máximo do primeiro, é mais rápido para grandes ne pequenos k.

Ungolfed:

Primeiro algoritmo

jos_g num step q = 1 + foldl (\x -> mod (x + step) ) (mod (step-1) q) [q+1..num]

Segundo algoritmo

jos_gkp num step q
    -- ceiling throws a type-related fit with ceiling(z*k/(k-1))
    -- better to use - div (-z * k) (k - 1)
    | m <- step-1 = 1 + num*step - until (>num*m)(\z-> -div (-z*k) m) (q*step - mod m q) 
Sherlock9
fonte
Então você escolheu esta pergunta para aprender novos idiomas? 6/10 das respostas são suas: P
Mego
@Mego eu mencionei isso no chat: DI perguntou se eu deveria postá-lo de qualquer maneira e eles disseram ir em frente. Além disso, sim. Meus amigos me disseram que este é o meu "Olá, mundo!" para novos idiomas: D
Sherlock9:
Não estou dizendo que isso é uma coisa ruim. Só estou divertido, só isso.
Mego19
@ Sherlock9: você pode usar untilpara uma tradução (mais ou menos) direto da versão Python do 2º algoritmo: (n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q).
N20 /
Deus te abençoe, @nimi: o DI estava batendo na minha cabeça com esse problema há séculos, tentando foldle listas infinitas e todo tipo de coisa. Obrigado pela ajuda!
Sherlock9
1

Linguagem GameMaker (GML), 88 bytes

Com base na resposta de @ user81655

r=argument0
k=argument1
q=argument2
r=(k-1)mod q;for(i=q;i<n;r=(r+k)mod ++i){}return r+1
Timtech
fonte
1

Geléia , 14 13 bytes

Rµṙ⁴ṖµL>⁵µ¿⁴ị

TryItOnline!

Quão?

Rµṙ⁴ṖµL>⁵µ¿⁴ị - Main link: n, k, q
 µ            - monadic chain separation
R             - range(n): [1,2,3,...,n] - the circle of people
     µ   µ¿   - while
      L       -     length
       >      -     greater than
        ⁵     -     5th program argument (3rd input), i.e. q
  ṙ           -         rotate left by
   ⁴          -         4th program argument (2nd input) i.e. k
    Ṗ         -         pop - remove the rightmost person
            ị - get index
           ⁴  - 4th program argument (2nd input), i.e. k
Jonathan Allan
fonte
0

Ruby, 53 48 bytes

Uma lambda.

->n,k,q{r=(k-1)%q;(q+=1;r=(r+k)%q)while q<n;r+1}

Como funciona

def j(n,k,q)
  r=(k-1)%q   # r starts at j[q,k,q]
  while q<n
    q+=1
    r=(r+k)%q # Every time you add people to the circle, r increases by k, 
              # modulo the current size of the circle q.
  end
  r+1         # Return the result.
end
Sherlock9
fonte