Problème de Josephus avec trois entrées

22

Il y a une question sur ce site qui est similaire à cette question, mais j'ai ajouté une touche.

Vous disposez de trois entrées, le nombre de personnes dans le cercle n , la k personne -ème compté à chaque étape, et la q personne -ème qui survit. Les personnes dans le cercle sont numérotées de 1 à n .

Par exemple, dans un cercle de 20 personnes, la 20e personne à survivre est la toute première personne enlevée, le 19e survivant est la deuxième personne enlevée et ainsi de suite. Normalement, le problème de Josephus est de déterminer la dernière personne enlevée, appelée ici le premier survivant.

Écrivez le programme ou la fonction la plus courte qui, avec ces trois entrées, renvoie le nombre de la q- ème personne à survivre.

S'il y a des problèmes de clarté, faites-le moi savoir.

Quelques exemples:

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

Modifier: Supposons que toutes les entrées sont valides. Autrement dit, personne ne demandera 0 ou aucun nombre négatif et personne ne demandera le 20e survivant dans un cercle de 5 personnes (c'est-à-dire 1 ≤ q ≤ n)

Edit: j'accepterai une réponse à minuit UTC + 7 début décembre 2.

Sherlock9
la source
1
Veuillez publier vos propres solutions en tant que réponses au lieu de les inclure dans la question.
Poignée de porte
Je l'ai. Désolé pour cela
Sherlock9
1
Pour plus de précision, si q=1c'est exactement la même chose que la question liée de Josephus, non?
AdmBorkBork
@TimmyD Exactement
Sherlock9

Réponses:

5

Pyth, 16 octets

eu.<PGvzh-QvwShQ

Essayez-le en ligne: démonstration ou suite de tests

L'entrée est de la forme k<newline>n<newline>q.

Explication:

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
la source
7

Piet, 280 273 codels

entrez la description de l'image ici

Edit: J'ai encore joué au golf, et je pense que je peux le jouer encore plus loin, mais c'est encore à venir. Pour l'instant, je suis juste content que ça marche, et que j'avais de la place pour le signer dans le coin en bas à gauche. Deux idées que j'ai pour enregistrer plus de codels sont a) pour changer les instructions de fin pop, push 1, add, out num(pop n, sortie r + 1) et b) pour dupliquer à nouveau dans le coin inférieur gauche pour enregistrer les codels dans la manipulation de la pile plus tard dans la boucle.

L'image ci-dessus est mon code à 8 pixels par codel. En général, c'est le même algorithme que ma réponse Python, mais avec les entrées dans l'ordre de k , q , n . En pratique, il y a aussi beaucoup de manipulation de pile. Vous pouvez l' essayer ici en ouvrant l'image là-bas et en exécutant le code avec.

Explication

Il s'agit d'un dégonflage étape par étape de la solution.

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
la source
Vous ne comptez pas d'espace vide? Y a-t-il un meta post quelque part sur la façon de marquer Piet? Il devrait probablement y en avoir.
Sparr
@Sparr, je compte un espace vide. C'est une image de 21 codels par 13 codels, donc le score est de 273 codels.
Sherlock9
Ahh, j'ai mal compté. Désolé.
Sparr
4

CJam, 22 20 19 octets

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

Cela lit l'entrée comme q k n. Essayez-le en ligne dans l' interpréteur CJam .

Comment ça marche

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
la source
3

Golfscript, 58 56 55 35 31 30 octets

En supposant que les trois entrées sont déjà dans la pile, dans l'ordre n , k , q

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

Cette solution suppose que je dois me débarrasser de tout sauf de la réponse finale.

Comment ça marche

Voir j(n,k,q)dans ma solution Python 3 pour plus de détails.

~                                   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: Utilisé la suggestion de @ Doorknob (Ajout d'un + pour obtenir toutes les entrées dans le tableau)

Anciennement,

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

Edit 2: Ajouté ~, selon les règles du wiki, et raccourci le code. Merci @Dennis

Anciennement,

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

Edit 3: implémenté un algorithme plus court.

Anciennement,

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

Edit 4: Compris que je pouvais utiliser %comme carte.

Anciennement,

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

Édition 5: Édition mineure. Changement 2$de @faire [0..q-1]et 3$de 2$récupérer k. Sauvé une bouchée

Anciennement,

~1$(1$%3$),2$),-{\3$+\%}%\)])\;
Sherlock9
la source
1
\;\;\;\;peut être remplacé par ])\;(encapsuler dans un tableau, annuler le droit, swap et pop).
Poignée de porte
Modifié mon code pour plus de clarté @Dennis.
Sherlock9
D'accord @Dennis. Ajout du ~ et modification de la question pour autoriser uniquement les programmes et les fonctions. Avez-vous d'autres suggestions?
Sherlock9
Non, tout va bien. :)
Dennis
2

JavaScript (ES6), 56 octets

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

Non golfé

Fondamentalement, une adaptation JavaScript de la réponse Python de @ Sherlock9 .

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

Tester

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
la source
Je n'appellerais pas votre version non golfée non golfée: P
Fund Monica's Lawsuit
1

Mathematica, 50 octets

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

Une fonction anonyme. Prend les entrées dans l'ordre q,n,k.

alephalpha
la source
1

C, 81 73 octets

Basé sur l' implémentation Javascript de @ user81655 de ma réponse Python.

Modifier: supprimé i

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

Tester

#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
la source
Dans certaines versions de C, vous pouvez supprimer le intavant les noms des paramètres.
Fund Monica's Lawsuit
1

Python 3, 72 66 62 octets

Une fonction de programmation dynamique en 62 octets. Adapté de l'algorithme sur Wikipedia. Il y avait auparavant une implémentation directe de cet algorithme lorsque q = 1 (c'est-à-dire i = 1, r = 0) sur cette page, mais je vois que cela a été supprimé maintenant.

Edit 1: j'ai supprimé ipour enregistrer 4 octets. L'explication reste inchangée.

Édition 2: erreur de calcul dans le nombre d'octets. J'utilisais \r\npour EOL et je n'ai pas remarqué quand cela a ajouté 3 octets. J'ai réduit mon nombre d'octets en conséquence.

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

Comment ça marche

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.

Merci à @Dennis de m'avoir rappelé que je devrais expliquer mon code (ne serait-ce qu'implicitement, car il en a inclus un dans sa réponse). Si quelque chose n'est pas clair, faites-le moi savoir.

Modifier:

Anciennement,

Une fonction itérative qui est adaptée de Concrete Mathematics par Graham, Knuth et Patashnik. Bien que cet algorithme soit plus long, il est plus rapide pour les grands n et les petits 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
la source
1
Il semble que vous ayez coupé quelque chose dans le copier-coller, il y a une pendaison +.
xnor
1

PHP, 71 octets

Basé sur les réponses de @ Sherlock9. Voir sa réponse Python pour l'algorithme.

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

Alternativement, voici mon approche naïve originale sans l'algorithme. Cela utilise un tableau pour marquer les personnes trouvées.

91 octets

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

Haskell, 48 47 43 octets

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

Basé sur un algorithme Haskell sur la page Rosetta Code de la fonction Josephus avec deux entrées. Les suggestions de golf sont les bienvenues.

Edit: Mes remerciements à nimi pour son aide au golf du premier algorithme en suggérant une version sans point, et pour son aide au golf du deuxième algorithme en me faisant savoir que le untilmot - clé existe.

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

Une version de l'algorithme à la fin de ma réponse Python adaptée de Concrete Mathematics par Graham, Knuth et Patashnik. Bien que cet algorithme soit plus long à 62 octets, et qu'il n'ait pas été étudié autant que le premier, il est plus rapide pour les grands net les petits k.

Non golfé:

Premier algorithme

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

Deuxième algorithme

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
la source
Avez-vous choisi cette question pour apprendre de nouvelles langues? 6/10 des réponses sont les vôtres: P
Mego
@Mego, je l'ai mentionné dans le chat: DI a demandé si je devais le publier de toute façon et ils ont dit allez-y. Oui aussi. Mes amis m'ont dit que c'était mon "Bonjour, monde!" pour les nouvelles langues: D
Sherlock9
Je ne dis pas que c'est une mauvaise chose. Je suis juste amusé, c'est tout.
Mego
@ Sherlock9: vous pouvez utiliser untilpour un (plus ou moins) traduction directe de la version Python du 2ème algorithme: (n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q).
nimi
Que Dieu vous bénisse, @nimi: DI me cognait la tête sur ce problème depuis des lustres, essayant foldldes listes infinies et toutes sortes de choses. Merci de votre aide!
Sherlock9
1

GameMaker Language (GML), 88 octets

Basé sur la réponse 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
la source
1

Gelée , 14 13 octets

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

TryItOnline!

Comment?

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
la source
0

Rubis, 53 48 octets

Un lambda.

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

Comment ça marche

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
la source