Problema de Josefo con tres entradas

22

Hay una pregunta en este sitio que es similar a esta pregunta, pero he agregado un giro.

Tiene tres entradas, el número de personas en el círculo n , la k -ésima persona contada en cada paso y la q -ésima persona que sobrevive. Las personas en el círculo están numeradas del 1 al n .

Por ejemplo, en un círculo de 20 personas, la vigésima persona que sobrevive es la primera persona eliminada, el sobreviviente 19 es la segunda persona eliminada y así sucesivamente. Normalmente, el problema de Josephus es determinar la última persona eliminada, aquí llamada el primer sobreviviente.

Escribir el programa más corto o función que, con esos tres entradas, devuelve el número de la q persona -ésimo para sobrevivir.

Si hay algún problema con la claridad, hágamelo saber.

Algunos ejemplos:

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

Editar: suponga que todas las entradas son válidas. Es decir, nadie pedirá 0 o cualquier número negativo y nadie preguntará por el vigésimo sobreviviente en un círculo de 5 personas (es decir, 1 ≤ q ≤ n)

Editar: aceptaré una respuesta a la medianoche UTC + 7 al comienzo del 2 de diciembre.

Sherlock9
fuente
1
Publique sus propias soluciones como respuestas en lugar de incluirlas en la pregunta.
Pomo de la puerta
Lo tengo. Perdón por eso
Sherlock9
1
Para aclarar, si q=1esto es exactamente lo mismo que la pregunta de Josefo vinculada, ¿verdad?
AdmBorkBork
@TimmyD Exactamente
Sherlock9

Respuestas:

5

Pyth, 16 bytes

eu.<PGvzh-QvwShQ

Pruébelo en línea: Demostración o conjunto de pruebas

La entrada es de la forma k<newline>n<newline>q.

Explicación:

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

Piet, 280 273 codeles

ingrese la descripción de la imagen aquí

Editar: He jugado un poco más en este campo, y creo que puedo jugarlo aún más, pero eso está por venir. Por ahora, me alegro de que funcione, y de que tuviera espacio para firmarlo en la esquina inferior izquierda. Dos ideas que tengo para guardar más codeles son a) para cambiar las instrucciones finales serpop, push 1, add, out num (pop n, salida r + 1) yb) duplicar nuevamente en la esquina inferior izquierda para guardar codeles en la manipulación de la pila más adelante en el ciclo.

La imagen de arriba es mi código a 8 píxeles por codel. En general, es el mismo algoritmo que mi respuesta de Python, pero con las entradas en el orden de k , q , n . En la práctica, también existe una gran cantidad de manipulación de la pila. Puede probarlo aquí abriendo la imagen allí y ejecutando el código con él.

Explicación

Este es un paso a paso ungolfing de la solución.

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
fuente
¿No estás contando el espacio vacío? ¿Hay alguna meta publicación en algún lugar sobre cómo calificar a Piet? Probablemente debería haberlo.
Sparr
@Sparr, estoy contando el espacio vacío. Esa es una imagen de 21 codeles por 13 codeles, por lo que la puntuación es de 273 codeles.
Sherlock9
Ahh, he contado mal. Lo siento.
Sparr
4

CJam, 22 20 19 bytes

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

Esto lee la entrada como q k n. Pruébelo en línea en el intérprete de CJam .

Cómo 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
fuente
3

Golfscript, 58 56 55 35 31 30 bytes

Suponiendo que las tres entradas ya están en la pila, en el orden n , k , q

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

Esa solución supone que necesito deshacerme de todo excepto la respuesta final.

Cómo funciona

Vea j(n,k,q)en mi solución Python 3 para más detalles.

~                                   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

Edición 1: Utilicé la sugerencia de @ Doorknob (Se agregó un + para obtener todas las entradas en la matriz)

Antes,

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

Edición 2: Agregado ~, según las reglas de la wiki, y acortado el código. Gracias @Dennis

Antes,

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

Edición 3: implementado un algoritmo más corto.

Antes,

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

Edición 4: descubrí que podría usarlo %como mapa.

Antes,

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

Edición 5: Edición menor. Cambiado 2$a @hacer [0..q-1]y 3$a 2$recuperar k. Guardado un bocado

Antes,

~1$(1$%3$),2$),-{\3$+\%}%\)])\;
Sherlock9
fuente
1
\;\;\;\;se puede reemplazar con ])\;(wrap in array, right-uncons, swap y pop).
Pomo de la puerta
Edité mi código para mayor claridad @Dennis.
Sherlock9
De acuerdo @ Dennis. Se agregó el ~ y se editó la pregunta para permitir solo programas y funciones. ¿Tiene alguna otra sugerencia?
Sherlock9
No, todo bien. :)
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}

Sin golf

Básicamente, una adaptación de JavaScript de la respuesta Python de @ Sherlock9 .

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

Prueba

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>

usuario81655
fuente
No llamaría a tu versión no golfista: P
Financia la demanda de Mónica el
1

Mathematica, 50 bytes

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

Una función anónima. Toma entradas en el orden q,n,k.

alephalpha
fuente
1

C, 81 73 bytes

Basado en la implementación Javascript de @ user81655 de mi respuesta de Python.

Editar: eliminado i

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

Prueba

#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
fuente
En algunas versiones de C, puede descartar intantes de los nombres de los parámetros.
Financia la demanda de Mónica el
1

Python 3, 72 66 62 bytes

Una función de programación dinámica en 62 bytes. Adaptado del algoritmo en Wikipedia. Solía ​​haber una implementación directa de este algoritmo cuando q = 1 (es decir, i = 1, r = 0) en esa página, pero veo que se ha eliminado ahora.

Edición 1: eliminé ipara guardar 4 bytes. La explicación permanece sin cambios.

Edición 2: Error de cálculo en el recuento de bytes. Estaba usando \r\npara EOL y no me di cuenta cuando eso agregó 3 bytes. He bajado mi recuento de bytes en consecuencia.

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

Como funciona esto

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.

Gracias a @Dennis por recordarme que debería explicar mi código (aunque sea implícitamente, porque incluyó uno en su respuesta). Si algo no está claro, hágamelo saber.

Editar:

Antes,

Una función iterativa adaptada de Concrete Mathematics por Graham, Knuth y Patashnik. Aunque este algoritmo es más largo, es más rápido para n grande y k pequeña .

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
fuente
1
Parece que cortas algo al copiar y pegar, hay un ahorcamiento +.
xnor
1

PHP, 71 bytes

Basado en las respuestas de @ Sherlock9. Vea su respuesta de Python para el algoritmo.

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

Alternativamente, aquí está mi enfoque ingenuo original sin el algoritmo. Esto utiliza una matriz para marcar qué personas se encuentran.

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
fuente
1

Haskell, 48 47 43 bytes

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

Basado en un algoritmo de Haskell en la página de Rosetta Code de la función Josephus con dos entradas. Sugerencias de golf son bienvenidas.

Editar: Mi agradecimiento a nimi por ayudarme a jugar al golf con el primer algoritmo sugiriendo una versión libre de puntos, y por ayudarme a jugar al golf con el segundo algoritmo haciéndome saber que la untilpalabra clave existe.

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

Una versión del algoritmo al final de mi respuesta de Python adaptada de Concrete Mathematics por Graham, Knuth y Patashnik. Aunque este algoritmo es más largo a 62 bytes, y no se ha reducido tanto como el primero, es más rápido para grandes ny pequeños k.

Sin golf:

Primer 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
fuente
Entonces, ¿elegiste esta pregunta para aprender nuevos idiomas? 6/10 de las respuestas son suyas: P
Mego
@Mego mencioné esto en el chat: DI me preguntó si debería publicarlo de todos modos y dijeron que adelante. Además sí. Mis amigos me han dicho que este es mi "¡Hola, mundo!" para nuevos idiomas: D
Sherlock9
No estoy diciendo que esto sea algo malo. Estoy divertido, eso es todo.
Mego
@ Sherlock9: se puede usar untilpara una traducción (más o menos) directa de la versión Python del segundo algoritmo: (n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q).
nimi
Dios te bendiga, @nimi: DI estuvo golpeándome la cabeza con ese problema durante años, intentando foldle infinitas listas y todo tipo de cosas. ¡Gracias por tu ayuda!
Sherlock9
1

GameMaker Language (GML), 88 bytes

Basado en la respuesta 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
fuente
1

Jalea , 14 13 bytes

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

TryItOnline!

¿Cómo?

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
fuente
0

Ruby, 53 48 bytes

Una lambda

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

Cómo 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
fuente