Combien d'instances sont en cours d'exécution?

13

Écrivez un programme à durée indéterminée qui indique le nombre d'instances de lui-même en cours d'exécution. Chaque instance du programme doit également signaler l'ordre dans lequel il a été ouvert par rapport à toutes les autres instances en cours d'exécution.

Exemple

L'utilisateur lance le programme pour la première fois - nous appellerons cette instance 1. L'instance 1 s'affiche 1/1, car il s'agit de la première instance à être lancée sur un total de 1 instances en cours d'exécution.

Pendant que l'instance 1 est en cours d'exécution, l'utilisateur lance le programme une deuxième fois pour devenir l'instance 2. L'instance 1 s'affiche maintenant 1/2, étant la première instance sur un total de 2 instances en cours d'exécution. L'instance 2 s'affiche 2/2, car il s'agit de la deuxième instance sur un total de 2 instances en cours d'exécution.

Supposons que l'utilisateur continue de générer plus d'instances jusqu'à ce qu'il y en ait 5 . Afin de lancement, leurs sorties sont: 1/5 2/5 3/5 4/5 5/5.

Supposons maintenant que l'utilisateur décide de mettre fin à l'instance 3. L'instance 4 devient alors la nouvelle instance 3 et l'instance 5 la nouvelle instance 4, car ce sont respectivement les troisième et quatrième instances à avoir été lancées à partir de ce qui est maintenant un total de 4. instances. Ainsi, le changement de sortie de chaque instance serait le suivant:

  • 1/51/4
  • 2/52/4
  • 3/5 → (Terminé)
  • 4/53/4
  • 5/54/4

Règles

  • Vous pouvez sortir les deux nombres (numéro d'instance, nombre total d'instances) dans n'importe quel format raisonnable.
  • Chaque fois qu'une instance est lancée ou arrêtée, toutes les autres instances doivent mettre à jour leurs sorties respectives dans un délai de 100 millisecondes.
  • Si vous choisissez de mettre à jour la sortie en imprimant sur une nouvelle ligne (ou un autre format de sortie "en ajout", par opposition au remplacement), vous devez imprimer uniquement lorsque le nombre d'instances change, et pas à tout autre moment.
  • C'est le golf de code. Le programme le plus court en octets gagne.
  • Dans votre réponse, nous vous encourageons à spécifier ce que l'utilisateur doit faire pour ouvrir plusieurs instances et / ou enregistrer une capture d'écran à démontrer.
darrylyeo
la source
Quelqu'un a-t-il des suggestions de balises à inclure?
darrylyeo
Un tel programme serait spécifique au système d'exploitation.
user202729
Est «chaque fois qu'une instance est lancée ou arrêtée, toutes les autres instances doivent mettre à jour leurs sorties respectives dans un délai de 100 millisecondes» même sous notre contrôle étant donné que nous devons compter sur le système d'exploitation pour communiquer (et le fait que nous pourrions engendrer de nombreux processus peuvent » t aider)?
Jonathan Allan
L'interopération du processus @Ouros ne peut pas être indépendante du système d'exploitation
edc65

Réponses:

3

APL (Dyalog Unicode) , 39 octets SBCS

Fonction de préfixe anonyme. Appelez en faisant apparaître l'argument factice (vecteur numérique vide), c'est-à-dire f&⍬. Recherchez les threads en cours d'exécution avec ⎕TNUMSet tuez un ou plusieurs threads avec ⎕TKILL n. La sortie des threads change en [nombre propre, nombre total] dès qu'ils obtiennent du temps processeur, c'est-à-dire pratiquement instantanément.

{⍵≡nn[⍋n←⎕TNUMS~0]:∇n⋄∇n⊣⎕←n⍳⎕TID,⊢/n}

Essayez-le en ligne!

{} Lambda anonyme où est l'argument (initialement , le vecteur numérique vide)

n[] Index n(à définir) avec:

  ⎕TNUMS~0 tous les T HLit Num bres sauf le nombre 0(REPL)

   n← stocker sous n

    permutation qui trierait par ordre croissant

  nous avons maintenant les fils actifs afin

  ⍵≡ si l'argument est identique à celui…

  : ensuite:

   ∇⍵ queue recurse sur l'argument

   autre:

   ⊢/n le numéro de fil le plus à droite

   ⎕TID, ce T de HLit ID (numéro de fil) préfixé que

   n⍳ trouver le ɩ ndices de ces deux

   ⎕← l'imprimer sur STDOUT

   n⊣ jeter cela en faveur de n

    recurse sur ce

Adam
la source
2

Python 3, 694 691 octets

main.py

from requests import post as u
from _thread import*
import os
os.system("start cmd /C python s")
def l():
 def p(q):
  while 1:print(u(*q).text,end="\r")
 q=['http://localhost']
 q+=[u(q[0],'*').text]
 start_new_thread(p,(q,))
 input()
 u(q[0],'-'+q[1])
while 1:
 try:l();break
 except:0

s (abréviation de server.py)

from bottle import*
from requests import post as q
try:
 q("http://localhost")
except:
 ids=["0"]
 @post('/')
 def _():
  content = request.body.read().decode('utf-8')
  if len(content)==0:return""
  if content[0]=="*":ids.append(str(int(ids[-1])+1));return str(ids[-1])
  elif content[0]=="-":del ids[ids.index(content[1:])]
  else:return str(ids.index(content)) + "/" + str(len(ids)-1)
 run(port="80")

Pourquoi est-ce si long?

Malheureusement, cette fonctionnalité ne semble pas être intégrée à Python. J'ai été tenté d'utiliser le multitraitement, mais cela ne semblait pas tout à fait adapté à ce que nous faisons (laisser un utilisateur ouvrir un programme de n'importe où).

J'ai donc suivi les conseils d'un post StackOverflow que j'ai vu (j'ai égaré le lien) et je l'ai implémenté en utilisant bottle . (Je suis ouvert à de nouvelles suggestions).

J'ai utilisé la bibliothèque Bottle pour exécuter mon propre mini serveur http afin que toutes les différentes instances puissent communiquer entre elles. Je suppose que j'aurais pu utiliser un socket, même si je ne suis pas convaincu que cela aurait réduit le nombre d'octets.

J'ai deux fichiers séparés, set main.py. sest à court de serveur et parce qu'il apparaît dans le code, j'ai pensé que je devrais rendre le nom aussi court que possible.

API du serveur Web de communication

Le serveur Web accepte uniquement les demandes POST et ne répond qu'aux entrées dans le corps du POST.

Toutes les demandes passent par /(ou localhost/).

Entrée valide:

  • * dans le corps du message demandera au serveur de renvoyer un nouvel identifiant pour affecter le client.
  • -<id> dans le corps du message supprimera l'identifiant de la liste active des identifiants, diminuant tous les identifiants pertinents et le nombre total.
  • Une demande vide dans le corps du message renverra simplement une chaîne vide. C'est ce qui est utilisé pour tester si le serveur est en ligne.

Clôture du programme

J'ai implémenté le multi-threading, donc fermer le programme est aussi simple que d'appuyer sur Entrée.

Ouverture du programme

Si vous n'avez pas configuré correctement Python dans vos variables d'environnement, créez simplement un .batfichier et placez-le dans le même dossier que main.pyet savec le code suivant (si vous avez installé Python pour tous les utilisateurs, il peut se trouver à un emplacement différent):

set PATH=%userprofile%\AppData\Local\Programs\Python\Python36
python main.py

Crédits

De 694 à 691 octets Adám .

Neil
la source
Vous ne pouvez pas supprimer :8080/?
2017 à 8h26
Si je devais affecter le port au port 80, alors oui; sinon, non. Le port par défaut pour les navigateurs Web (et les requêtes) est le port 80, mais je peux supprimer le /.
Neil
@ Adám, je l'ai mis à jour avec le changement de port, sauvé 1 octet de cette façon.
Neil
1

outils sh + linux / unix, 128 octets

si le sommeil prend en charge les nombres à virgule flottante

trap '(flock 9;grep -vw $$ p>t;mv t p)9>l' exit;(flock 9;echo $$>>p)9>l;f(){ echo $(sed -n /^$$\$/= p)/$(wc -l<p);sleep .1;f;};f

sinon, 159 octets

trap '(flock 9;grep -vw $$ p>t;mv t p)9>l' exit;(flock 9;echo $$>>p)9>l;perl -MTime::HiRes=usleep -nE/^$$'$/&&say("$./",$.+(@a=<>)),usleep 1e5,$.=-(@ARGV=p)' p

ou le sommeil peut être remplacé par :(no-op), mais cela rendra l'attente active.

Nahuel Fouilleul
la source
C'est vraiment proche - "Vous ne devez imprimer que lorsque le nombre d'instances change, et pas à tout autre moment."
darrylyeo
@darrylyeo vient de corriger, mais cherchait une solution plus courte mais n'a pas eu le temps, aussi pour dormir 100 ms, j'ai une solution mais plus longue
Nahuel Fouilleul
0

Java 8, (199 + 301 =) 500 octets

M.jar: (le programme principal)

import javafx.collections.*;class M{static ObservableList o=FXCollections.observableArrayList();static int j,F;int i,f;{F=0;ListChangeListener e=(ListChangeListener.Change c)->{if(f<1)System.out.println((F>0&i>F?--i:i)+"/"+j);};o.addListener(e);o.add(i=++j);}public void f(){F=f=i;j--;o.remove(--i);}}

S.jar: (le serveur pour contrôler le déroulement du programme)

import java.util.*;interface S{static void main(String[]a){List<M>l=new Stack();for(Scanner s=new Scanner(System.in);;){Float n=s.nextFloat();if(n%1==0)l.add(new M());else{int t=(int)(n*10-1);l.get(t).f();l.remove(t);}}}}

Explication du code:

import javafx.collections.*;
                  // Required import for ObservableList, FXCollections, and ListChangeListener
class M{          // Program-class
  static ObservableList o=FXCollections.observableArrayList(); 
                  //  Static list to keep record of all instances
  static int j,   //  Static integer (total number of instances)
             F;   //  Static flag (remove occurred?)
  int i,          //  Non-static integer (id of this instance)
      f;          //  Non-static flag (has been removed)
  {               //  Non-static initializer-block (shorter than constructor)
    F=0;          //   Reset the static flag remove_occurred, because we add a new instance
    o.addListener((ListChangeListener.Change c)->{
                  //   Add a change listener for the ObservableList
                  //   This will monitor any additions or removes on the List
       if(f<1)    //    If this instance is not removed yet:
         System.out.println(
                  //     Print:
           (F>0&i>F?
                  //      If a removed occurred and this id is larger than the removed instance
             --i  //       Decrease its id by 1 before printing it
            :     //      Else:
             i)   //       Just print its id
           +"/"+j);
                  //      Plus the total number of instances left
    });
    o.add(        //   Add anything to the Observable list to trigger the listener
     i=++j);      //    Increase the total amount of instances, and set the id of this instance to the last one
  }               //  End of non-static initializer-block
  public void f(){//  Finalize-method
    F=f=i;        //   Set both flags to the current id
    j--;          //   Decrease the total amount of instances
    o.remove(--i);//   Remove the current instance from the list to trigger the listener
  }               //  End of Finalize-method
}                 // End of Program-class

import java.util.*;
                  // Required import for List, Stack and Scanner
interface S{      // Server-class
  static void main(String[]a){
                  //  Mandatory main-method
    List<M>l=new Stack();
                  //   List of programs
    for(Scanner s=new Scanner(System.in);
                  //   Create a STDIN-listener for user input
        ;){       //   Loop indefinitely
      int t=s.nextInt();
                  //    Get the next integer inputted
      if(t<1)     //    If it's 0:
        l.add(new M());
                  //     Startup a new program, and add its instance to the list
      else{       //    Else:
        l.get(t).f();
                  //     Close the program with this integer as id
        l.remove(t);}
                  //     And remove it from the list of programs
    }             //   End of loop
  }               //  End of main-method
}                 // End of Server-class

Explication générale:

Tous les programmes garderont une trace de leur propre identifiant; le nombre total d'instances restantes; si une suppression s'est produite; et quels programmes ont fermé.

Le serveur est juste une classe wrapper pour démarrer et arrêter des programmes. Lorsqu'un utilisateur entre 0, il démarre un nouveau programme. Lorsque l'utilisateur saisit un entier positif (c'est-à-dire 2), il fermera le programme avec cet id. (Remarque: S.jar a M.jar comme bibliothèque pour y accéder.)

Gif pour le voir en action:

entrez la description de l'image ici

Réflexions pour jouer au golf plus loin:

Je viens de remarquer en écrivant l'explication que je n'utilise que ObservableListpour son ajout / suppression ListChangeListener, et que je n'utilise pas du tout son contenu. La suppression et l'utilisation d'un autre type d'écouteur statique peuvent être plus courtes.

Kevin Cruijssen
la source