Quante istanze sono in esecuzione?


13

Scrivi un programma a esecuzione indefinita che riporta quante istanze di se stesso sono attualmente in esecuzione. Ogni istanza del programma dovrebbe inoltre riportare l'ordine in cui è stata aperta da tutte le altre istanze attualmente in esecuzione.

Esempio

L'utente avvia il programma per la prima volta: chiameremo questa istanza 1. 1/1Viene visualizzata l'istanza 1 , poiché è la prima istanza da avviare su un totale di 1 istanze attualmente in esecuzione.

Mentre l'istanza 1 è in esecuzione, l'utente avvia il programma una seconda volta per diventare l'istanza 2. Ora viene visualizzata l'istanza 1 1/2, essendo la prima istanza su un totale di 2 istanze attualmente in esecuzione. 2/2Viene visualizzata l'istanza 2 , poiché è la seconda istanza su un totale di 2 istanze attualmente in esecuzione.

Supponiamo che l'utente continui a generare più istanze fino a quando ce ne sono 5 . In ordine di lancio, le loro uscite sono: 1/5 2/5 3/5 4/5 5/5.

Ora, supponiamo che l'utente decida di chiudere l'istanza 3. L'istanza 4 diventa quindi la nuova istanza 3 e l'istanza 5 la nuova istanza 4, perché sono rispettivamente la terza e la quarta istanza che sono state lanciate da quello che ora è un totale di 4 le istanze. Quindi la modifica di ogni istanza nell'output sarebbe la seguente:

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

Regole

  • È possibile generare i due numeri (numero istanza, istanze totali) in qualsiasi formato ragionevole.
  • Ogni volta che un'istanza viene avviata o terminata, tutte le altre istanze devono aggiornare i rispettivi output entro 100 millisecondi.
  • Se si sceglie di aggiornare l'output stampando su una nuova riga (o in un altro formato di output "accodante", al contrario della sostituzione), è necessario stampare solo quando il numero di istanze cambia e non in qualsiasi altro momento.
  • Questo è il codice golf. Vince il programma più breve in byte.
  • Nella tua risposta, sei invitato a specificare cosa l'utente deve fare per aprire più di un'istanza e / o registrare uno screencast per dimostrare.

Qualcuno ha suggerimenti per i tag da includere?
darrylyeo,

Tale programma sarebbe specifico del sistema operativo.
user202729

È "Ogni volta che un'istanza viene avviata o terminata, tutte le altre istanze devono aggiornare i rispettivi output entro 100 millisecondi" anche sotto il nostro controllo dato che dobbiamo fare affidamento sul sistema operativo per comunicare (e sul fatto che potremmo generare molti, molti processi possono " t aiuto)?
Jonathan Allan,

L'interoperazione dei processi di @Ouros non può essere indipendente dal sistema operativo
edc65, l'

Risposte:


3

APL (Dyalog Unicode) , SBCS da 39 byte

Prefisso anonimo. Chiamare generando sull'argomento fittizio (vettore numerico vuoto), cioè f&⍬. Interroga i thread attualmente in esecuzione con ⎕TNUMSed elimina uno o più thread con ⎕TKILL n. L'output dei thread cambia in [proprio numero, numero totale] non appena ottengono il tempo del processore, cioè praticamente all'istante.

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

Provalo online!

{... } lambda anonima dove si trova l'argomento (inizialmente , il vettore numerico vuoto)

n[] Indice n(da definire) con:

  ⎕TNUMS~0 tutti T hread Num bri tranne numero 0(REPL)

   n← conservare come n

    permutazione che ordinerebbe in ordine crescente

  ora abbiamo i thread attivi in ​​ordine

  ⍵≡ se l'argomento è identico a quello ...

  : poi:

   ∇⍵ attestazione di coda sull'argomento

   altro:

   ⊢/n il numero di thread più a destra

   ⎕TID,ID di  questo T hread (numero di thread) è stato aggiunto a quello

   n⍳ trova il ɩ ndices di quei due

   ⎕← stampalo su STDOUT

   n⊣ scartalo a favore di n

    fare affidamento su questo


2

Python 3, 694 691 byte

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 (abbreviazione di 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")

Perché è così lungo?

Sfortunatamente, questa funzionalità non sembra essere integrata in Python. Sono stato tentato di utilizzare il multiprocessing, ma non mi è sembrato del tutto adatto a ciò che stiamo facendo (lasciando che un utente apra un programma da qualsiasi luogo).

Quindi, ho seguito il consiglio di un post StackOverflow che ho visto (ho smarrito il link) e l'ho implementato usando bottle . (Sono aperto a nuovi suggerimenti).

Ho usato la libreria Bottle per eseguire il mio mini server http in modo che tutte le diverse istanze possano comunicare tra loro. Suppongo che avrei potuto usare un socket, anche se non sono convinto che avrebbe ridotto il conteggio dei byte.

Ho due file separati se main.py. sè a corto di server e poiché appare nel codice, ho pensato che avrei dovuto rendere il nome il più breve possibile.

API di Communication Web Server

Il server Web accetta solo richieste POST e risponde solo all'input all'interno del corpo del POST.

Tutte le richieste passano /(o localhost/).

Input valido:

  • * nel corpo della posta richiederà al server di restituire un nuovo ID per assegnare il client.
  • -<id> nel corpo del post rimuoverà l'id dall'elenco attivo degli id, diminuendo tutti gli id ​​pertinenti e il conteggio totale.
  • Una richiesta vuota nel corpo della posta restituirà semplicemente una stringa vuota. Questo è ciò che viene utilizzato per i test per vedere se il server è online.

Chiusura del programma

Ho implementato il multi-threading quindi chiudere il programma è semplice come premere invio.

Apertura del programma

Se Python non è configurato correttamente all'interno delle variabili ambientali, è sufficiente creare un .batfile e inserirlo nella stessa cartella del main.pye scon il seguente codice (se è stato installato Python per tutti gli utenti, potrebbe trovarsi in una posizione diversa):

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

Titoli di coda

Da 694 a 691 byte Adám .


Non puoi rimuovere :8080/?
Adám,

Se dovessi assegnare la porta alla porta 80, allora sì; altrimenti no. La porta predefinita per i browser web (e le richieste) è la porta 80, ma posso rimuovere il /.
Neil,

@Adám L'ho aggiornato con la modifica della porta, salvato 1 byte in quel modo.
Neil,

1

strumenti sh + linux / unix, 128 byte

se sleep supporta numeri in virgola mobile

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

altrimenti, 159 byte

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

oppure sleep può essere sostituito con :(no-op), ma renderà l'attesa attiva.


Questo è molto vicino: "Devi stampare solo quando il numero di istanze cambia e non in nessun altro momento".
darrylyeo,

@darrylyeo ha appena risolto, ma cercavo una soluzione più breve ma non ho avuto il tempo, anche di dormire 100ms, ho una soluzione ma più a lungo
Nahuel Fouilleul,

0

Java 8, (199 + 301 =) 500 byte

M.jar: (il programma principale)

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: (il server per controllare il flusso del programma)

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);}}}}

Spiegazione del codice:

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

Spiegazione generale:

Tutti i programmi terranno traccia del proprio ID; il numero totale di istanze rimaste; se si è verificata una rimozione; e quali programmi hanno chiuso.

Il server è solo una classe wrapper per avviare e arrestare i programmi. Quando un utente immette 0, avvierà un nuovo programma. Quando l'usato immette un numero intero positivo (es2 ), chiuderà il programma con quell'id. (Nota: S.jar ha M.jar come libreria per accedervi.)

GIF per vederlo in azione:

inserisci qui la descrizione dell'immagine

Pensieri di golf ulteriormente:

Ho appena notato mentre scrivo la spiegazione che uso solo ObservableListper il suo add / remove- ListChangeListenere non uso affatto il suo contenuto. La rimozione di questo e l'utilizzo di un altro tipo di Listener statico potrebbe essere più breve.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.