Josephus Problem mit drei Eingängen

22

Es gibt eine Frage auf dieser Website , die dieser Frage ähnlich ist, aber ich habe eine Wendung hinzugefügt.

Sie haben drei Eingaben, die Anzahl der Personen im Kreis n , die k- te Person, die bei jedem Schritt ausgezählt wird, und die q- te Person, die überlebt. Die Personen im Kreis sind von 1 bis n nummeriert .

In einem Kreis von 20 Personen ist beispielsweise die 20. Person, die überlebt, die erste Person, die entfernt wurde, der 19. Überlebende die zweite Person, die entfernt wurde, und so weiter. Normalerweise besteht das Josephus-Problem darin, die letzte entfernte Person zu bestimmen , die hier als erster Überlebender bezeichnet wird.

Schreiben Sie das kürzeste Programm oder die kürzeste Funktion, die mit diesen drei Eingaben die Nummer der q- ten Person zurückgibt, die überleben soll.

Wenn es Probleme mit der Klarheit gibt, lassen Sie es mich bitte wissen.

Einige Beispiele:

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

Bearbeiten: Angenommen, alle Eingaben sind gültig. Das heißt, niemand fragt nach 0 oder negativen Zahlen und niemand fragt nach dem 20. Überlebenden in einem Kreis von 5 Personen (dh 1 ≤ q ≤ n).

Bearbeiten: Ich akzeptiere eine Antwort um Mitternacht UTC + 7 Anfang Dezember 2.

Sherlock9
quelle
1
Bitte posten Sie Ihre eigenen Lösungen als Antworten, anstatt sie in die Frage aufzunehmen.
Türklinke
Ich habs. Entschuldigung
Sherlock9
1
Zur Verdeutlichung, wenn q=1dies genau das gleiche ist wie die verknüpfte Josephus-Frage, richtig?
AdmBorkBork
@ TimyD Genau
Sherlock9

Antworten:

5

Pyth, 16 Bytes

eu.<PGvzh-QvwShQ

Probieren Sie es online aus: Demo oder Test Suite

Die Eingabe hat die Form k<newline>n<newline>q.

Erläuterung:

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

Piet, 280 273 codels

Bildbeschreibung hier eingeben

Edit: Ich habe das noch ein bisschen runter gespielt, und ich denke, ich kann es noch weiter runter spielen, aber das wird noch kommen. Im Moment bin ich nur froh, dass es funktioniert und dass ich Platz hatte, um es in der linken unteren Ecke zu unterschreiben. Zwei Ideen, die ich mehr Codels speichern muss, sind a) die Endanweisungen zu ändern pop, push 1, add, out num(pop n, output r + 1) und b) in der unteren linken Ecke erneut zu duplizieren, um Codels in der Stapelbearbeitung später in der Schleife zu speichern.

Das Bild oben ist mein Code mit 8 Pixel pro Codel. Im Allgemeinen ist es derselbe Algorithmus wie meine Python-Antwort, jedoch mit Eingaben in der Reihenfolge k , q , n . In der Praxis gibt es auch viel Stapelmanipulation. Sie können es hier versuchen, indem Sie das Bild dort öffnen und den Code damit ausführen.

Erläuterung

Dies ist eine schrittweise Entgolfung der Lösung.

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
quelle
Sie zählen keinen leeren Raum? Gibt es irgendwo einen Meta-Post darüber, wie Piet punkten soll? Da sollte es wohl sein.
Sparr
@Sparr, ich zähle leeren Raum. Das ist ein 21-mal-13-Codel-Bild, die Punktzahl beträgt also 273 Codels.
Sherlock9
Ahh, ich habe falsch gezählt. Es tut uns leid.
Sparr
4

CJam, 22 20 19 Bytes

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

Dies liest die Eingabe als q k n. Probieren Sie es online im CJam-Interpreter aus .

Wie es funktioniert

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
quelle
3

Golfscript, 58 56 55 35 31 30 Bytes

Angenommen, die drei Eingänge befinden sich bereits im Stapel in der Reihenfolge n , k , q

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

Diese Lösung setzt voraus, dass ich alles außer der endgültigen Antwort loswerden muss.

Wie es funktioniert

Weitere j(n,k,q)Informationen finden Sie in meiner Python 3-Lösung.

~                                   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: Verwendet @ Doorknobs Vorschlag (Ein + hinzugefügt, um alle Eingaben in das Array zu bekommen)

Früher,

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

Edit 2: ~ wurde gemäß den Regeln des Wikis hinzugefügt und der Code verkürzt. Danke @Dennis

Früher,

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

Edit 3: Ein kürzerer Algorithmus wurde implementiert.

Früher,

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

Edit 4: Herausgefunden, dass ich %als Karte verwenden könnte.

Früher,

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

Bearbeiten 5: Kleine Bearbeitung. Geändert 2$zu @machen [0..q-1]und abzurufen . Einen Bissen gerettet3$2$k

Früher,

~1$(1$%3$),2$),-{\3$+\%}%\)])\;
Sherlock9
quelle
1
\;\;\;\;kann ersetzt werden durch ])\;(Zeilenumbruch in Array, Rechts-Uncons, Swap und Pop).
Türklinke
Bearbeitet meinen Code für Klarheit @ Tennis.
Sherlock9
Alles klar @Dennis. Fügte das ~ hinzu und bearbeitete die Frage, um nur Programme und Funktionen zuzulassen. Haben Sie noch weitere Vorschläge?
Sherlock9
Nein, alles gut. :)
Dennis
2

JavaScript (ES6), 56 Byte

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

Ungolfed

Grundsätzlich eine JavaScript-Anpassung von @ Sherlock9s Python-Antwort.

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

Prüfung

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
quelle
Ich würde Ihre ungolfed Version nicht als ungolfed bezeichnen: P
Fund Monica's Lawsuit
1

Mathematica, 50 Bytes

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

Eine anonyme Funktion. Nimmt Eingaben in der Reihenfolge vor q,n,k.

Alephalpha
quelle
1

C, 81 73 Bytes

Basierend auf @ user81655s Javascript-Implementierung meiner Python-Antwort.

Bearbeiten: Ich entfernt

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

Prüfung

#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
quelle
In einigen Versionen von C können Sie die intvor den Parameternamen löschen.
Fund Monicas Klage
1

Python 3, 72 66 62 Bytes

Eine dynamische Programmierfunktion in 62 Bytes. Angepasst an den Algorithmus von Wikipedia. Früher gab es eine direkte Implementierung dieses Algorithmus, wenn auf dieser Seite q = 1 (dh i = 1, r = 0) war, aber ich sehe, dass dies jetzt entfernt wurde.

Edit 1: Ich habe entfernt i, um 4 Bytes zu sparen. Erklärung bleibt unverändert.

Edit 2: Fehlberechnung in der Byteanzahl. Ich verwendete \r\nfür EOL und bemerkte nicht, als das 3 Bytes hinzufügte. Ich habe meine Byteanzahl entsprechend gesenkt.

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

Wie das geht

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.

Vielen Dank an @Dennis, der mich daran erinnert hat, dass ich meinen Code erklären soll (wenn auch nur implizit, weil er einen in seine Antwort aufgenommen hat). Wenn etwas unklar ist, lassen Sie es mich bitte wissen.

Bearbeiten:

Früher,

Eine iterative Funktion, die von Graham, Knuth und Patashnik aus der Konkreten Mathematik übernommen wurde. Obwohl dieser Algorithmus länger ist, ist er für großes n und kleines k schneller .

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
quelle
1
Es sieht so aus, als ob Sie beim Kopieren und Einfügen etwas abgeschnitten haben, da hängt etwas +.
25.
1

PHP, 71 Bytes

Basierend auf den Antworten von @ Sherlock9. Siehe seine Python-Antwort für den Algorithmus.

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

Alternativ ist hier mein ursprünglicher naiver Ansatz ohne den Algorithmus. Dies verwendet ein Array, um zu markieren, welche Personen gefunden werden.

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

Haskell, 48 47 43 Bytes

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

Basierend auf einem Haskell-Algorithmus auf der Rosetta-Codepage der Josephus-Funktion mit zwei Eingaben. Golfvorschläge sind willkommen.

Edit: Mein Dank geht an nimi für die Hilfe beim Golfen des ersten Algorithmus, indem sie eine pointfree-Version vorschlägt, und für die Hilfe beim Golfen des zweiten Algorithmus, indem sie mir mitteilt, dass das untilSchlüsselwort existiert.

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

Eine Version des Algorithmus am Ende meiner Python-Antwort, angepasst aus der Konkreten Mathematik von Graham, Knuth und Patashnik. Obwohl dieser Algorithmus mit 62 Bytes länger ist und nicht so viel Golf gespielt hat wie der erste, ist er für große nund kleine schneller k.

Ungolfed:

Erster Algorithmus

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

Zweiter Algorithmus

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
quelle
Hast du diese Frage ausgewählt, um neue Sprachen zu lernen? 6/10 der Antworten gehören dir: P
Mego
@Mego Ich erwähnte dies im Chat: DI fragte, ob ich es trotzdem posten sollte und sie sagten, mach weiter. Auch ja. Meine Freunde haben mir gesagt, dass dies mein "Hallo, Welt!" Ist. für neue Sprachen: D
Sherlock9
Ich sage nicht, dass das eine schlechte Sache ist. Ich bin nur amüsiert, das ist alles.
Mego
@ Sherlock9: Sie verwenden untilfür eine (mehr oder weniger) die direkte Übersetzung der Python - Version des zweiten Algorithmus: (n#k)q|m<-k-1=1+n*k-until(>n*m)(\z-> -div(-z*k)m)(q*k-mod m q).
nimi
Gott segne dich, @nimi: DI hat mich ewig mit diesem Problem konfrontiert, es versucht foldlund unendlich viele Listen und alles Mögliche. Danke für Ihre Hilfe!
Sherlock9
1

GameMaker Language (GML), 88 Byte

Basierend auf der Antwort von @ 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
quelle
1

Jelly , 14 13 Bytes

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

TryItOnline!

Wie?

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

Ruby, 53 48 Bytes

Ein Lambda.

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

Wie es funktioniert

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
quelle