¿Cuántas instancias se están ejecutando?

13

Escriba un programa que se ejecute indefinidamente y que informe cuántas instancias de sí mismo se están ejecutando actualmente. Cada instancia del programa también debe informar el orden en que se abrió de todas las demás instancias actualmente en ejecución.

Ejemplo

El usuario inicia el programa por primera vez; llamaremos a esta instancia 1. Se muestra la instancia 1 1/1, porque es la primera instancia que se inicia de un total de 1 instancias actualmente en ejecución.

Mientras se ejecuta la Instancia 1, el usuario inicia el programa por segunda vez para convertirse en la Instancia 2. Ahora se muestra la Instancia 1 1/2, siendo la primera instancia de un total de 2 instancias actualmente en ejecución. Se muestra la instancia 2 2/2, porque es la segunda instancia de un total de 2 instancias actualmente en ejecución.

Digamos que el usuario continúa generando más instancias hasta que haya 5 de ellas. Con el fin de lanzamiento, sus salidas son: 1/5 2/5 3/5 4/5 5/5.

Ahora, digamos que el usuario decide terminar la Instancia 3. La Instancia 4 se convierte en la nueva Instancia 3 y la Instancia 5 en la nueva Instancia 4, porque son respectivamente la tercera y cuarta instancias que se han lanzado de lo que ahora es un total de 4 instancias. Entonces, el cambio de salida de cada instancia sería el siguiente:

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

Reglas

  • Puede generar los dos números (número de instancia, instancias totales) en cualquier formato razonable.
  • Cada vez que se inicia o finaliza una instancia, todas las demás instancias deben actualizar sus salidas respectivas dentro de los 100 milisegundos.
  • Si elige actualizar la salida imprimiendo en una nueva línea (u otro formato de salida "anexado"; en lugar de reemplazarla), debe imprimir solo cuando cambie el número de instancias, y no en cualquier otro momento.
  • Este es el código de golf. El programa más corto en bytes gana.
  • En su respuesta, se le recomienda que especifique qué debe hacer el usuario para abrir más de una instancia y / o grabar un screencast para demostrarlo.
Darrylyeo
fuente
¿Alguien tiene sugerencias para incluir etiquetas?
darrylyeo
Tal programa sería específico del sistema operativo.
usuario202729
Es "Cada vez que se inicia o finaliza una instancia, todas las demás instancias deben actualizar sus salidas respectivas dentro de los 100 milisegundos", incluso dentro de nuestro control, dado que debemos confiar en el sistema operativo para comunicarnos (y el hecho de que podamos generar muchos, muchos procesos pueden " t ayuda)?
Jonathan Allan
La interoperación del proceso @Ouros no puede ser independiente del sistema operativo
edc65

Respuestas:

3

APL (Dyalog Unicode) , SBCS de 39 bytes

Función de prefijo anónimo. Llame generando el argumento ficticio (vector numérico vacío), es decir f&⍬. Consulte los hilos que se ejecutan actualmente ⎕TNUMSy elimine uno o más hilos con ⎕TKILL n. Los subprocesos generan cambios en [número propio, número total] tan pronto como obtienen el tiempo del procesador, es decir, casi al instante.

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

Pruébalo en línea!

{... } lambda anónimo donde está el argumento (inicialmente , el vector numérico vacío)

n[] Índice n(por definir) con:

  ⎕TNUMS~0 todo T HRead Num fibras excepto el número 0(de la réplica)

   n← almacenar como n

    permutación que ordenaría ascendente

  ahora tenemos los hilos activos en orden

  ⍵≡ si el argumento es idéntico a eso ...

  : luego:

   ∇⍵ cola recurse en el argumento

   más:

   ⊢/n el número de hilo más a la derecha

   ⎕TID, esta camiseta de HRead ID (número de hilo) antepone al que

   n⍳ encuentra el ɩ nices de esos dos

   ⎕← imprima eso en STDOUT

   n⊣ descartar eso a favor de n

    recurse en eso

Adán
fuente
2

Python 3, 694 691 bytes

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 (abreviatura 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")

¿Por qué es tan largo?

Desafortunadamente, esta funcionalidad no parece estar integrada en Python. Tuve la tentación de usar el multiprocesamiento, pero eso no parecía ser el adecuado para lo que estamos haciendo (dejar que un usuario abra un programa desde cualquier lugar).

Entonces, tomé el consejo de una publicación de StackOverflow que vi (extravié el enlace) y la implementé usando bottle. (Estoy abierto a nuevas sugerencias).

Usé la biblioteca Bottle para ejecutar mi propio mini servidor http para que todas las diferentes instancias puedan comunicarse entre sí. Supongo que podría haber usado un zócalo, aunque no estoy convencido de que hubiera reducido el recuento de bytes.

Tengo dos archivos separados sy main.py. ses corto de servidor y debido a que aparece en el código, pensé que debería hacer el nombre lo más corto posible.

API del servidor web de comunicación

El servidor web solo acepta solicitudes POST y solo responde a las entradas dentro del cuerpo de la POST.

Todas las solicitudes pasan por /(o localhost/).

Entrada válida:

  • * en el cuerpo de la publicación solicitará que el servidor devuelva una nueva identificación para asignar el cliente.
  • -<id> en el cuerpo de la publicación eliminará la identificación de la lista activa de identificaciones, disminuyendo todas las identificaciones relevantes y el recuento total.
  • Una solicitud vacía en el cuerpo de la publicación simplemente devolverá una cadena vacía. Esto es lo que se usa para las pruebas para ver si el servidor está en línea.

Cerrando el programa

Implementé múltiples subprocesos, por lo que cerrar el programa es tan simple como presionar enter.

Abriendo el programa

Si no tiene la configuración de Python correctamente dentro de sus variables de entorno, simplemente cree un .batarchivo y colóquelo en la misma carpeta main.pyy scon el siguiente código (si instaló Python para todos los usuarios, puede estar en una ubicación diferente):

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

Créditos

De 694 a 691 bytes Adám .

Neil
fuente
¿No puedes eliminar :8080/?
Adám
Si tuviera que asignar el puerto al puerto 80, entonces sí; De otra manera no. El puerto predeterminado para los navegadores web (y solicitudes) es el puerto 80, pero puedo eliminar el /.
Neil
@ Adám Lo actualicé con el cambio de puerto, guardado 1 byte de esa manera.
Neil
1

Herramientas sh + linux / unix, 128 bytes

si el sueño admite números de coma flotante

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

de lo contrario, 159 bytes

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

o el sueño se puede reemplazar con :(no-op), pero hará que la espera sea activa.

Nahuel Fouilleul
fuente
Esto está muy cerca: "Debe imprimir solo cuando cambie el número de instancias, y no en cualquier otro momento".
darrylyeo
@darrylyeo solo solucionó, pero estaba buscando una solución más corta pero no tuve el tiempo, también para dormir 100 ms, tengo una solución pero más tiempo
Nahuel Fouilleul
0

Java 8, (199 + 301 =) 500 bytes

M.jar: (el programa 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: (el servidor para controlar el flujo del programa)

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

Explicación del código:

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

Explicación general:

Todos los programas mantendrán un registro de su propia identificación; el número total de instancias restantes; si ocurrió un retiro; y qué programas han cerrado.

El servidor es solo una clase de contenedor para iniciar y detener programas. Cuando un usuario ingresa 0, iniciará un nuevo programa. Cuando el usado ingresa un entero positivo (es decir 2), cerrará el programa con esa identificación. (Nota: S.jar tiene M.jar como biblioteca para acceder a ella).

Gif para verlo en acción:

ingrese la descripción de la imagen aquí

Pensamientos para jugar más al golf:

Al escribir la explicación, me di cuenta de que solo utilizo ObservableListpara agregar / quitar ListChangeListener, y no uso su contenido en absoluto. Eliminar esto y usar otro tipo de escucha estática podría ser más corto.

Kevin Cruijssen
fuente